ついてつらつらとこの広告は、90日以上更新していないブログに表示しています。Paint内部の画像データ形式について話したいと思います。Paintがどんな風にメモリを使うのかを知ることで、限られたメモリ内で大きな画像や多数のレイヤーを扱う場合のヒントになるかもしれません。ピクセルデータRGBA各チャネル毎に16bit幅のデータで持っています。1ピクセル=16bit*4=64bit=8バイトになります。各チャンネルの階調は14bit=1.0にしているので16384段階です。あまった2bitは将来的に合成等で計算途中に負数や多少のオーバーフローを許す中間値保存が必要になる可能性を考えてバッファを取っています。ユーザーに見せているのは一般的な0~255の256段階=8bitですがブラシ効果による色の変化や合成で作成される内部的な演算結果の精度としては最大14bitということです。Paintは画像データを小さい順にPixel→Cell→Tile→全体画像というように複数段階に分けて管理しています。Paintは自動拡張キャンバスを採用しているため、こういう構造をとらざるを得ません。上の白枠がキャンバスイメージ全体で、内部の青い枠に(0,0)とか(5,0)などと表記されていますが、これはTile単位の座標値です。Paintではこの座標値は符号付き16bitなので、x座標、y座標それぞれ-32768~32767までの数値をとります。Tileは内部にCellを横16個、縦16個固定で持っていて、16x16=256個のCellを持つことになります。最後にCellは内部に8x8pixelを持ちます。16個のセルぞれぞれが8pixel幅なので、Tileは縦横16*8=128pixelサイズということになります。Tileの座標値が-32768~32767でそのそれぞれが128pixelなので、キャンバスのとれる座標はおよそ-400万Pixel~+400万Pixelとなります。浮動小数点を内部で使っているのでその演算精度の問題や、そもそもメモリが足りないのでそんなキャンバスを現実的に使うことは不可能ですが、仕様上はそうなります。これだけだと、ただデータの持ち方をややこしくしただけの話なので、いろいろと例外があります。イメージプレーン(プログラム内部ではこう名付けています。要するにビットマップ形式のレイヤー)一枚毎にディフォルト色を1つ持てます。ディフォルト色は何に使うかというと、あるTile座標を調べて、Tileデータが存在しない場合、そのTile座標が本来占める128x128Pixelの矩形領域はディフォルト色で埋め尽くされていると判断する...というルールを設定してあります。何も画像がないただ一色で塗りつぶされたレイヤーは、どんなに大きな領域を占めているように見えても実際には1ピクセル分のデータしか使われないということです。(正確にはブレンド情報その他もあるため、数百バイトくらいは使ってると思われますが)次にCellにも実は2種類あって、64ピクセルを全て独立して持つタイプと、1ピクセル分のデータで64ピクセル全てを表現するという、Cellが同じ色で塗りつぶされている時に使えるタイプがあります。データサイズが1/64に圧縮されるわけです。この2種類のCellはいつでも交換可能で、Tileの16x16のCellにはどちらかが入っています。上のルールを守りながら、画面上にペンを走らせるとどうなるのか?ということですが、このようになります。黄色はCellの存在するTileのうち、先ほど説明した1Pixelだけを含むCellです。面倒なので描いていませんが、実際には小さなCellの集合です。赤い四角はペンが通った部分で、8x8Pixel=64Pixelを持つCellに変化しています。青い部分はペンが通っていないので影響がなく、セルを作る必要がないのでそもそもTileすら存在しない部分です。このように、ペンが通った部分だけ完全なデータを持つようになっています。Paintで、各描画ツールやその他操作がどうなっているかというと、現状は時間がないため、かなり手を抜いた処理になっています。アニメ風の絵をロードした時は、背景に透明部分等が広くあれば、それは存在しないTileや1ピクセルだけを含むCellとして表現してデータを節約できるはずですが、何もしません。太い二値ペンでは最適化しようと思えばストローク後に調べて一部のCellを1ピクセルにまとめることも可能ですが、やっていません。セーブ・ロード時にも特に何もしていません。将来的には対応したいのですが、目に見えない、特にこのままでも致命的な支障はない部分なので後回しになっています。バケツ処理だけは最適化を行うので、塗潰しは太い筆よりもできるだけバケツを使うことを意識すれば多少はデータを節約できます。レイヤー全体の塗潰しも、内部データをしっかり消してくれます。そのうちこの辺はちゃんと書いてメモリを節約したいところですね。v1.16以降ではPSD画像とネイティブ画像フォーマットの読み込み時に完全な最適化を行うようになりました。Paint開発の経緯とEfTについて月別アーカイブはてなブログをはじめよう!CloverPaintさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。