Other

アイコン・ファイルのフォーマット

アイコンには悩まされた。いろいろ不可解だった。

アイコン・ファイルの構造
fig.1: アイコンファイルの構造; 配列で示した箇所は添え字が1となっているが、要素数が1とは限らない。この書き方は構造体の定義に由来する。

ICONDIRENTRYについて

bWidthやbHeightが0の場合、それらは256を意味する。

8ビットカラー以上の場合、bColorCountは0。28 = 256はBYTEの範囲を超えているので、しかたない。アイコンのカラーのビット数は1, 4, 8, 16, 24, 32のいずれかなので、bColorCountは0, 2, 16のいずれか。

[不思議1] 値としては明らかにビット数より色数のほうが大きいのに、bColorCountはBYTE、wBitCountはWORDで定義されている。

dwImageOffsetは、対応のICONIMAGEの位置であり、ファイル先頭からのオフセット。

BITMAPINFOHEADERについて

BITMAPINFOHEADERで使用するのはbiSize, biWidth, biHeight, biPlanes, biBitCount, biSizeImageだけで、他はmust be 0。

[不思議2] biHeightはXORマスクとANDマスクをくっつけた高さ。ANDマスクはXORマスクと同じ幅と高さでなので、結局、XORマスクの2倍の高さになる。これがなかなかわからなかった。ちなみに“くっつける(combine)”とは上下にくっつけることらしい。前後にも左右にもくっつけない。

biSizeImageはXORマスクのバイト数だが、この値は無視されるような気がする。アイコン・ファイルを読み込むときも、自分でバイト数を計算したほうが良さそうだ。

WidthBytes = 4 * ((biBitCount * biWidth + 31) / 32);
biSizeImage = WidthBytes * biHeight;

ICONIMAGEについて

カラーテーブルが必要ない場合、つまり16ビットカラー以上の場合、icColorsはない。

icXORは“XORマスク”と説明されているが、マスクではないと思う。DIBのビットマップデータ。各行ごとに4バイト境界に合わせる。アイコンの大きさはだいたい決まっているので、たいていピッタリだと思う。

icANDは1ビットカラーのDIBのビットマップデータ。icXORと同様に、各行ごとに4バイト境界に合わせる。32ビットカラーならicXORがアルファ値を含んでいるのでicANDは不要と思うが、ないとは限らない。また、24ビットカラーでもicANDはあるべきだと思うが、ない場合もあり、よくわからない。アイコン・ファイルを保存するときは、必要なくても0で埋めておいたほうが良いような気がする。

※「4バイト境界に合わせる」というのは、バイト数を4で割った余り(剰余)が0になるように0~3バイトを追加すること。実際は上の例示のように、ビット数から計算する。

(参照)http://msdn.microsoft.com/en-us/library/ms997538.aspx

(2016/05/14 初稿)
(2016/05/25 更新)