FC2ブログ

C#でgifの透過情報を簡単に扱う[むー]

C#
03 /22 2009
C#で透過付きgif89aを簡単に扱う方法を紹介します。


読み込んだ段階でbitmapクラスに黒く変更された色情報の復旧について書かれている事が少なかった為、覚書。


Bitmap img = Bitmap("image.gif");

とするとPixelFormatはFormat8bppIndexedでは無く
Format32bppArgbでBitmapオブジェクトがインスタンスされます。
その際、透過色に指定されている色が元の色に関係なく黒に変換されてしまいます。

そのため、何らかの処理を経て、透過の表示を行おうとすると、
透過部分が黒く塗りつぶされた状態になってしまいます。

それを回避するためには、途中の処理で使うbitmapクラスをすべて
Format32bppArgbで処理を行えば下記の状態で透過を残すことが出来ます。


すでに読み込んで有るデータの通常の黒は
Color.FromArgb(255, 0, 0, 0);
読み込み時に変更された黒が
Color.FromArgb(0, 0, 0, 0);
であるため、通常の黒と見分けることが出来ます。


ほとんどの画像処理を高速化するサンプルが、unsafeコードで一旦Format24bppRgbに変換を行っているために、そのまま処理を行うとアルファ情報が落ちていると思います。

Format32bppArgb版のサンプルは『続き』を参照してください。


また、読み込んだままFormat8bppIndexedに無理やり戻してもアルファ情報が落ちます。
Format8bppIndexedに戻すには一旦アルファ値が0の黒を元のパレットの透過色に戻してから変換する必要が有ります。

ColorPaletteを使ったパレットデータを変更する方法はあちこちで記されていますが、読み込んだ段階でFormat32bppArgbに変更されているため、この変更された色はパレットデータのアルファを0から255に書き換えて適用しても復元できませんでした。


通常黒と透過で変更された黒が見分けられれば、
保存やサイズ変更への応用も出来ると思います。


『続きを読む』に読み込んだgifでフォームを切り取るサンプルを置きましたので、ご参考になればと思います。


どなたかの助けになれば幸いです。

write by むー

読み込んだgifでウィンドウを切り取るサンプル
(たぶんpngでも同様に可)


//画像を読む
Bitmap img = new Bitmap("img.gif");

//フォームを非短径で表示する
System.Drawing.Drawing2D.GraphicsPath gpath =
new System.Drawing.Drawing2D.GraphicsPath();

BitmapData bmpData = img.LockBits(
new Rectangle(0, 0, img.Width, img.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);

int stride = bmpData.Stride;
int nResidual = stride - img.Width * 4;

unsafe {
byte* p = (byte*)(void*)bmpData.Scan0;

for (int y = 0; y < img.Height; ++y) {
for (int x = 0; x < img.Width; ++x) {

// アルファ:p[3] 赤:p[2] 緑:p[1] 青:p[0]
if (p[3] != 0) {
gpath.AddRectangle(new Rectangle(x, y, 1, 1));
}

p += 4;
}

p += nResidual;
}

} //unsafe終わり

img.UnlockBits(bmpData);

//フォームにパスを適用
this.Region = new Region(gpath);

コメント

非公開コメント