前回、作成したアイコンは背景が透過されていません。
アイコンファイルをフルカラーで保存する 自作アイコンエディタ(その6)
では背景が透過されたアイコンをファイルとして保存するにはどうすればいいのでしょうか?
アイコンファイルのフォーマットは
アイコンヘッダ……ICOファイルに関する包括的情報を格納している。
ディレクトリ[1..n]……個々の画像に関する包括的情報を格納している。
アイコン画像データ[1..n]……AND/XORビットマップ形式か、PNG形式
このようになっています。
最後のAND/XORビットマップ形式は背景を透過する画像を作成することに使えます。前回のプログラムではANDビットマップをすべて0にしてしまったので背景を透過させることができませんでしたが、適切な処理をすることで背景透過のアイコンをつくることができます。
まずどのようなときに背景を透過させるかを決める必要があります。
今回はパネルの背景色がColor.FromName(“Control”)のときに背景は透明にすることにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
List<Byte> bytes = new List<byte>(); // アイコンヘッダーを取得(前回と同じなので省略) // アイコンディレクトリを取得(前回と同じなので省略) // ビットマップヘッダーを取得(前回と同じなので省略) for(int row = 31; row >= 0; row--) { for(int colum = 0; colum < 32; colum++) { Color color = panels[colum, row].BackColor; bytes.Add(color.B); bytes.Add(color.G); bytes.Add(color.R); bytes.Add(0); if(color == Color.FromName("Control")) { // 背景を透明にするための処理 } } } for(int i = 0; i < 128; i++) { bytes.Add(?);// 背景を透明にするために適切な値をいれる } |
XORビットマップが1ピクセル4バイトであるのに対してANDビットマップは1ピクセル1ビット(8ピクセル1バイト)というのが問題をややこしくしています。
ここはこう考えます。
背景を透過にする部分をリストの格納して、ANDビットマップを設定するときにリストのなかの値に対象部分があるかどうかで判断します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
List<Byte> bytes = new List<byte>(); // アイコンヘッダーを取得(前回と同じなので省略) // アイコンディレクトリを取得(前回と同じなので省略) // ビットマップヘッダーを取得(前回と同じなので省略) List<int> vs = new List<int>(); int bit = 0; for(int row = 31; row >= 0; row--) { for(int colum = 0; colum < 32; colum++) { Color color = panels[colum, row].BackColor; bytes.Add(color.B); bytes.Add(color.G); bytes.Add(color.R); bytes.Add(0); // 以下のときは透過させる if(color == Color.FromName("Control")) { vs.Add(bit); } bit++; } } for(int i = 0; i < 128; i++) { // i * 8 + 0 i ~ i * 8 + 7 を調べる int value = 0; if(vs.Any(x => x == i * 8)) value += 128; if(vs.Any(x => x == i * 8 + 1)) value += 64; if(vs.Any(x => x == i * 8 + 2)) value += 32; if(vs.Any(x => x == i * 8 + 3)) value += 16; if(vs.Any(x => x == i * 8 + 4)) value += 8; if(vs.Any(x => x == i * 8 + 5)) value += 4; if(vs.Any(x => x == i * 8 + 6)) value += 2; if(vs.Any(x => x == i * 8 + 7)) value += 1; bytes.Add((byte)value); } File.WriteAllBytes("保存するファイルのパス", bytes.ToArray()); |
これで背景が透明なアイコンを保存することができるようになります。ただこのアイコンはVisualStudioのアイコンエディタでは編集できません(編集可能なのは16色のものだけ)。編集はできませんが、表示はされます。もちろん使用することも可能です。
ただアイコンは一つのファイルで複数サイズに対応できるものもあります。今回作成したものは32×32ピクセルのものだけです。複数サイズに対応するためには
アイコンヘッダ
ディレクトリ[1]
ディレクトリ[2]
ディレクトリ[n]
アイコン画像データ[1]
アイコン画像データ[2]
アイコン画像データ[n]
とすればできます。長くなるのでまた次回。
アイコンを複数のサイズに対応できるファイルとして保存する方法 自作アイコンエディタ(その9)
16×16ピクセルのアイコンを作成しようとしてはまった件 自作アイコンエディタ(その8)
鳩でも分かるC#管理人からのお願い
できる仕事であれば請け負います。鳩でもわかるC#管理人はクラウドワークスに在宅ワーカーとして登録しています。お仕事の依頼もお待ちしております。
⇒ 仕事を依頼する
コメントについて
コメントで英語などの外国語でコメントをされる方がいますが、管理人は日本語以外はわからないので基本的に内容が理解できず、承認することもありません。それからへんな薬を売っているサイトやリンク先のサイトが存在しないというスパムコメントも多々あります。
Some people make comments in foreign languages such as English, but since the manager does not understand anything other than Japanese, he basically cannot understand the content and does not approve it. Please use Japanese when making comments.
そんななか日本語のコメントもいただけるようになりました。「○○という変数はどこで宣言されているのか?」「××というメソッドはどこにあるのか」「例外が発生する」「いっそのことソース丸ごとくれ」という質問ですが、管理人としては嬉しく思います。「自分が書いた記事は読まれているんだな」と。疑問点には可能な限り答えます。記事に問題があれば修正いたします。
そのうえでお願いがあります。「匿名」という味も素っ気もない名前ではなく、捨てハンでいいのでなにかハンドルネームをつくってほしいと思います。
管理人のモチベーションアップのために
よろしければご支援お願いします。
⇒ 管理人の物乞いリスト