フォーマットによってパレット形式とビットマップ形式がある。 どちらも独自形式
+--------------------------------------------------------------------+---
| tag & length | length | image_id | format | width | height | ...
| 20 , 0x3f | | | | | |
+--------------------------------------------------------------------+---
<-- 2 bytes --><- 4 bytes -><-2 bytes-><-1 byte-><-2 bytes-><-2 bytes->
<------------------ length ---(最後まで)
----------------------------------------------+
共通 |colormap_count| (colormap & indices) |
部分 | | zlib compressed |
----------------------------------------------+
<-- 1 byte -><-- contents 残り全部 -->
RGBの順で並ぶ↓ ↑ zlib compress ↑
------------------------------------------------+
| colormap | indices |
------------------------------------------------+
<-- colormap --><-((width + 3) & -4) * height->
count * 3
----------------------------------------------+
共通 |colormap_count| (colormap & indices) |
部分 | | zlib compressed |
----------------------------------------------+
<-- 2 bytes -><-- contents 残り全部 -->
↑ zlib compress ↑
------------------------------------------------+
| colormap | indices |
------------------------------------------------+
<-- colormap --><-((width + 3) & -4) * height->
count * 2
colormap を 0RRRRRGGGGGBBBBB の 16bit (BigEndian)で表現する
----------------------------+
共通 | (bitmap) |
部分 | zlib compressed |
----------------------------+
<- contents 残り全部 ->
↑ zlib compress ↑
-----------------------------+
...| bitmap | ← XRGB の順で並ぶ (X は padding)
-----------------------------+
<-- width * height * 4 -->
DefineBitsLossless に透明度がついたもの。
+--------------------------------------------------------------------+---
| tag & length | length | image_id | format | width | height | ...
| 36 , 0x3f | | | | | |
+--------------------------------------------------------------------+---
<-- 2 bytes --><- 4 bytes -><-2 bytes-><-1 byte-><-2 bytes-><-2 bytes->
<------------------ length ---(最後まで)
----------------------------------------------+
共通 |colormap_count| (colormap & indices) |
部分 | | zlib compressed |
----------------------------------------------+
<-- 1 byte -><-- contents 残り全部 -->
ARGBの順で並ぶ↓ ↑ zlib compress ↑
------------------------------------------------+
| colormap | indices |
------------------------------------------------+
<-- colormap --><-((width + 3) & -4) * height->
count * 4
----------------------------+
共通 | (bitmap) |
部分 | zlib compressed |
----------------------------+
<- contents 残り全部 ->
↑ zlib compress ↑
-----------------------------+
...| bitmap | ← ARGB の順で並ぶ
-----------------------------+
<-- width * height * 4 -->
colormap_number には実際に使われる色数から 1 を引いた値が入る。(つまり 0 数えのカウント)
1byte で 1色~256色 を表したいので。(そのままだと255色までしか届かない)
A が 0 でも 255 でもない時は、RGB はズバリ入ってなくて、A に応じて補正されてます。
BitmapPixelData ARGB[image data size] Array of pixel colors. Number of entries is BitmapWidth * BitmapHeight. The RGB data must already be multiplied by the alpha channel value.なので、PNG 画像を DefineBitsLossless2 に落とす場合は、 PNG の (R, G, B, A) を (R*A/255, G*A/255, B*A/255, A) に変換する必要があります。
実行時の透明pixelの重ね合わせは以下の計算式になる
output = alpha * foreground + (1-alpha) * backgroundなので、この (alpha * ) の処理を端折れるように、はじめから補正してあると。
((width + 3) & -4) * height
って何じゃらほい。という感じだけど、witdh を4の倍数で合わせるという意味 ほら、-4 って 2 の補数だと二進数で 11(略)1100 じゃないですか。
witdh = 1 の場合 => ((1 + 3) & -4) = 4 & 11(略)1100 = 4 witdh = 2 の場合 => ((2 + 3) & -4) = 5 & 11(略)1100 = 4 witdh = 3 の場合 => ((3 + 3) & -4) = 6 & 11(略)1100 = 4 witdh = 4 の場合 => ((4 + 3) & -4) = 7 & 11(略)1100 = 4 witdh = 5 の場合 => ((5 + 3) & -4) = 8 & 11(略)1100 = 8つまり、4の倍数への繰り上げ処理。Windows BMP もピクセルデータはこんな並びだし、普通。
% 4 とか mod 4 とか書いても良いけど、alexref にリスペクトして、あえてそのまま。(実コードに、この演算使うと処理速そうだし)