C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: byte配列を使った画像加工と透過色の指定


(過去ログ 127 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■75452 / inTopicNo.1)  byte配列を使った画像加工と透過色の指定
  
□投稿者/ pod (34回)-(2015/03/26(Thu) 12:19:04)

分類:[C#] 

VS 2013 C# で画像処理を行うプログラムを作っています。
getPixel, setPixel を使う方法では時間がかかるので、
Bitmap を byte[] に変え、加工をした後で Bitmap に戻すという方法を
とっています。

具体的にはJPEGの一部を透過し、PNGに変換するもので、
試しにRGB全て100(灰色)、透明度127(半分)に書き換えて保存した所、
透過を持つPNGを読み込んでbyte[]に変換したものは正しく半透明なグレーで
保存され、JPEGを元にbyte[]にしたものは不透明なグレー画像で保存されました。
保存にはどちらも img2.Save(保存先, ImageFormat.Png) を使用しています。

どのようにすれば読み込み元のファイル形式に関係なく透明度を持つPNG
ファイルを書き出すことができるのでしょうか?

書き換えは byte[] を4バイト飛ばしでループさせ、次のようにしています。

Bitmap bmp = new Bitmap(ファイル);
byte[] buf = bitmapToBytes(bmp);
for(int i=0;i<buf.Length;i += 4){
    b = buf[i];
    g = buf[i + 1];
    r = buf[i + 2];
    a = buf[i + 3];

    buf[i] = 100;
    buf[i + 1] = 100;
    buf[i + 2] = 100;
    buf[i + 3] = 127;
}
bmp.Dispose();
Bitmap bmp2 = bytesToBitmap(buf);

変換に用いている関数は次です。

public byte[] bitmapToBytes(Bitmap bmp)
{
	BitmapData bmpdat = (bmp).LockBits(
			 new Rectangle(Point.Empty, bmp.Size),
			 ImageLockMode.ReadWrite,
			 PixelFormat.Format32bppArgb);

	byte[] pixels = new byte[bmpdat.Stride * bmpdat.Height];
	Marshal.Copy(bmpdat.Scan0, pixels, 0, pixels.Length);
	return pixels;
}

public Bitmap bytesToBitmap(byte[] buf, int width, int height)
{
	Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
	BitmapData bd = bmp.LockBits(
		new Rectangle(0, 0, width, height),
		ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
	Marshal.Copy(buf, 0, bd.Scan0, buf.Length);
	bmp.UnlockBits(bd);
	return bmp;
}

引用返信 編集キー/
■75463 / inTopicNo.2)  Re[1]: byte配列を使った画像加工と透過色の指定
□投稿者/ Azulean (459回)-(2015/03/26(Thu) 22:17:59)
提示のコードはコンパイルエラーになると思いますが、単に書き写す際の間違いと考えて差し支えないでしょうか?
コンパイルエラーのまま実行を強行していた場合、以前のコードで実行されている可能性があるためです。

理由:bytesToBitmap の引数が一致しない。
引用返信 編集キー/
■75467 / inTopicNo.3)  Re[2]: byte配列を使った画像加工と透過色の指定
□投稿者/ pod (35回)-(2015/03/27(Fri) 12:19:52)
すみません、書き間違えていました。実際には関数にwidthやheightが渡されています。
今のところコンパイルエラーは発生していないようです。
引用返信 編集キー/
■75468 / inTopicNo.4)  Re[3]: byte配列を使った画像加工と透過色の指定
□投稿者/ とっちゃん (296回)-(2015/03/27(Fri) 13:20:00)
とっちゃん さんの Web サイト
No75467 (pod さん) に返信
> すみません、書き間違えていました。実際には関数にwidthやheightが渡されています。
> 今のところコンパイルエラーは発生していないようです。

うまくいってるかどうかが正しく判断できていない気がしたので
誰が見てもよくわかるような変化を加えて画像を出力させてみました。

> int width = 256;
> int height = 256;
> byte[] buf = new byte[width * height * 4];
> int pos = 0;
> for( int y = 0 ; y < height ; y++ )
> {
> for( int x = 0 ; x < width ; x++ )
> {
> buf[pos++] = 255;
> buf[pos++] = 0;
> buf[pos++] = 0;
> buf[pos++] = (byte)y; // 縦方向に少しずつ色が混ざっていく
> }
> }
> var bmp = bytesToBitmap( buf, width, height );
> bmp.Save( "Test.png", ImageFormat.Png );

bytesToBitmap() は、そのままコピペして、試しています。

あとは、実際のコードと比較して、どこに問題があるかを探してみてください。

消しちゃった部分に問題があるか、単純に透過していることを目で見て判断できていないかのどちらかだと思います。


引用返信 編集キー/
■75469 / inTopicNo.5)  Re[4]: byte配列を使った画像加工と透過色の指定
□投稿者/ とっちゃん (297回)-(2015/03/27(Fri) 13:25:13)
とっちゃん さんの Web サイト
No75468 (とっちゃん さん) に返信

書き忘れた。

透過がうまくいっているかどうかは、透過しているはずの画像を単にプレビュー表示するのではなく
背景が市松模様(黒と白など)になるようなツールを使って表示させてみることをお勧めします。

VisualStudio でPNGを開けば、そういう風に表示してくれるので、それで確認すれば透過しているか判断できると思います。


引用返信 編集キー/
■75477 / inTopicNo.6)  Re[5]: byte配列を使った画像加工と透過色の指定
□投稿者/ pod (36回)-(2015/03/27(Fri) 18:25:05)
No75469 (とっちゃん さん) に返信

サンプルやアドバイスありがとうございます。
上記サンプルを最低限のソースで実行した場合は正しくグラデーションのかかった画像として保存されました。
自分が最初に提示したソース以外の部分で問題が発生しているようですので、
ひとまずこのトピックはクローズして再度念入りに流れを追ってみようと思います。
失礼致しました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -