DOBON.NET DOBON.NETプログラミング掲示板過去ログ

BMPモノクロ画像の結合

環境/言語:[C#2008 .NET ver3.5]
分類:[.NET]

BMPモノクロ2色の画像を読み込んで、固定サイズの画像の中央に配置して
BMPモノクロ2色で保存したいのですが、思うようにいかずご教授いただけ
ないでしょうか?

・画像1…入力ファイル(BMPモノクロ2色)
・画像2…1000pix×1000pixの画像
・画像3…画像1と画像2を結合したもの(BMPモノクロ2色で保存したい)

下記のようなロジックを作成しましたが、作成された画像が24bitのBMP
で作成されてしまいます。

画像2を作成する際にpixellFormatを指定していない事が原因と考えていますが
PixelFormat.Format1bppIndexed としてしまいますと、
「インデックス付きのピクセル形式をもつイメージからグラフィックス オブジェクトを作成することはできません。」とエラーが出てしまいます。

-------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace Sample01
{
class Program
{


static void Main(string[] args)
{
//画像1(BMPモノクロ2色)
PictureBox pictureBox1 = new PictureBox();
pictureBox1.Image = System.Drawing.Image.FromFile(@"C:\\sample.bmp");

Rectangle rect = new Rectangle(0 , 0 , pictureBox1.Image.Width , pictureBox1.Image.Height);

//画像2(1000×1000)
Bitmap bitmap = new Bitmap(1000, 1000);
Graphics gfx = Graphics.FromImage(bitmap);

//画像2を白で塗りつぶす
Region rgn = new Region(new Rectangle(0 , 0 , 1000 , 1000));
gfx.FillRegion(Brushes.White, rgn);

//画像2の中央に画像1を張り付ける
gfx.DrawImage(pictureBox1.Image, new Rectangle((1000 - rect.Width) / 2, (1000 - rect.Height) / 2, rect.Width, rect.Height), rect, GraphicsUnit.Pixel);

//リソース解放
gfx.Dispose();

//結合後の画像を保存する。
PictureBox pictureBox2 = new PictureBox();

pictureBox2.Image = bitmap;

pictureBox2.Invalidate();

//BMP形式で保存
pictureBox2.Image.Save("C:\\temp\\Save1.bmp" , System.Drawing.Imaging.ImageFormat.Bmp);

}
}
}



-------------------------------------------
■No29128に返信(たろうさんの記事)
> BMPモノクロ2色の画像を読み込んで、固定サイズの画像の中央に配置して
> BMPモノクロ2色で保存したいのですが、思うようにいかずご教授いただけ
> ないでしょうか?
>
> ・画像1…入力ファイル(BMPモノクロ2色)
> ・画像2…1000pix×1000pixの画像
> ・画像3…画像1と画像2を結合したもの(BMPモノクロ2色で保存したい)
>
> 下記のようなロジックを作成しましたが、作成された画像が24bitのBMP
> で作成されてしまいます。
>
> 画像2を作成する際にpixellFormatを指定していない事が原因と考えていますが
> PixelFormat.Format1bppIndexed としてしまいますと、
> 「インデックス付きのピクセル形式をもつイメージからグラフィックス オブジェクトを作成することはできません。」とエラーが出てしまいます。
>

Graphics.FromImage例外について
http://msdn.microsoft.com/ja-jp/library/system.drawing.graphics.fromimage.aspx

上記のとおりFormat1bppIndexedでは Graphics.FromImage(bitmap)はできません。

LockBitsをつかいPixelFormat.Format1bppIndexedでBitmapDataにして、そのBitmapDataを使って新たなBitmapを作成してください。Bitmapのコンストラクタは

public Bitmap(
int width,
int height,
int stride,
PixelFormat format,
IntPtr scan0 ←ここにBitmapData.Scan0が入る
)
Bitmapコンストラクタ(詳しくは)
http://msdn.microsoft.com/ja-jp/library/zy1a2d14%28v=VS.90%29.aspx

を使ってください。
そしてこの作成したBitmapを保存すれば2値化されているはずです。
あとUnlockBitsは忘れずに。
コメント頂きありがとうございます。

Format1bppIndexedでは Graphics.FromImage(bitmap)はできないのですね。
ドキュメントにもその通り記載が確認できました。
LockBitsをつかい新たなBitmapデータを作成して対応したいと思います。
ありがとうございました。



■No29129に返信(itiさんの記事)
> ■No29128に返信(たろうさんの記事)
>>BMPモノクロ2色の画像を読み込んで、固定サイズの画像の中央に配置して
>>BMPモノクロ2色で保存したいのですが、思うようにいかずご教授いただけ
>>ないでしょうか?
>>
>>・画像1…入力ファイル(BMPモノクロ2色)
>>・画像2…1000pix×1000pixの画像
>>・画像3…画像1と画像2を結合したもの(BMPモノクロ2色で保存したい)
>>
>>下記のようなロジックを作成しましたが、作成された画像が24bitのBMP
>>で作成されてしまいます。
>>
>>画像2を作成する際にpixellFormatを指定していない事が原因と考えていますが
>>PixelFormat.Format1bppIndexed としてしまいますと、
>>「インデックス付きのピクセル形式をもつイメージからグラフィックス オブジェクトを作成することはできません。」とエラーが出てしまいます。
>>
>
> Graphics.FromImage例外について
> http://msdn.microsoft.com/ja-jp/library/system.drawing.graphics.fromimage.aspx
>
> 上記のとおりFormat1bppIndexedでは Graphics.FromImage(bitmap)はできません。
>
> LockBitsをつかいPixelFormat.Format1bppIndexedでBitmapDataにして、そのBitmapDataを使って新たなBitmapを作成してください。Bitmapのコンストラクタは
>
> public Bitmap(
> int width,
> int height,
> int stride,
> PixelFormat format,
> IntPtr scan0 ←ここにBitmapData.Scan0が入る
> )
> Bitmapコンストラクタ(詳しくは)
> http://msdn.microsoft.com/ja-jp/library/zy1a2d14%28v=VS.90%29.aspx
>
> を使ってください。
> そしてこの作成したBitmapを保存すれば2値化されているはずです。
> あとUnlockBitsは忘れずに。
>
解決済み!
■No29135に返信(たろうさんの記事)
> コメント頂きありがとうございます。
>
> Format1bppIndexedでは Graphics.FromImage(bitmap)はできないのですね。
> ドキュメントにもその通り記載が確認できました。
> LockBitsをつかい新たなBitmapデータを作成して対応したいと思います。
> ありがとうございました。
>

一応補足しておきます。(わかっていたらすいません。)
BitmapDataを使い新たなBitmapを作ってもGraphics.FromImageを行えるわけではありません。
画像の表示、加工の段階では24ビットBitmap(まぁ加工できるなら何ビットでもいいですが)のまま行い。
保存の段階で対象Bitmapを2値化するということです。


bitmap ← 加工済み
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format1bppIndexed);
Bitmap bmp = new Bitmap(1000, 1000, bitmapData.Stride,PixelFormat.Format1bppIndexed,bitmapData.Scan0);
bmp.Save(@"C:\UserSamp\Samp\Desktop\samp\Save1.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
bitmap.UnlockBits(bitmapData);


なお、これでは2値化の閾値を調整できないので、もし閾値調整が必要な場合は上記保存処理の前に、自分で閾値を設定しRGB値を自分で2値化しておいてください。
以上 補足でした。

DOBON.NET | プログラミング道 | プログラミング掲示板