デバッグ用画像ファイルを作成する(8,24,32)
どのような環境、どのような言語でプログラミングするにしろ、デバッグ用の画像ファイルが必要です。お気に入りの風景画像やポートレート画像を使ってもいいですが、厳密な意味でのデバッグには使用できません。
下記のような画像を簡単に取得できるコードを下記に紹介します。
32bpp の場合 BMP は透明度の指定ができないので PNG だけにしています。32bpp では透明度 0xff で完全不透明としてあります。
下記コードのコンパイルするためには、VisualStudio のビルドオプションで「アンセーフコードの許可」を実施してください。ビルドオプションの設定方法は下記の記事をごらんください。
下記の using 追加をお忘れなく.
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
// この using 追加を忘れずに. Don't forget to add this sentence.
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
namespace aaa
{
public partial class Form1 : Form
{
// WindowsAPI を定義する、memcpy() と同じ動作をする.
[DllImport("Kernel32.Dll")]
public static unsafe extern void CopyMemory( byte* dst, byte* src, int bytes );
// 24ビットパックのデータ構造体の宣言.
[StructLayout( LayoutKind.Explicit)]
public struct GY_IMG_BPP24
{
[FieldOffset(0)] public byte B;
[FieldOffset(1)] public byte G;
[FieldOffset(2)] public byte R;
}
// 32ビットパックのデータ構造体の宣言.
[StructLayout( LayoutKind.Explicit)]
public struct GY_IMG_BPP32
{
[FieldOffset(0)] public byte B;
[FieldOffset(1)] public byte G;
[FieldOffset(2)] public byte R;
[FieldOffset(3)] public byte A;
}
const int INI_W = 512;
const int INI_H = 256;
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
Directory.CreateDirectory( "c:/tmp" );
}
private void button1_Click( object sender, EventArgs e )
{
Bitmap bmp;
byte [] data008;
// ビットマップに書き込みたい8ビットデータの領域を確保する.
int w = INI_W;
int h = INI_H;
int numpix = w * h;
data008 = new byte[ numpix ];
// 上が黒くて、下が白いグラデーションの画像データを格納する.
for ( int j = 0; j < h; j++ )
{
int adrs = w * j;
byte level = (byte)(j);
for ( int i = 0; i < w; i++ )
{
data008[ adrs ] = level;
adrs++;
}
}
// 8ビットインデックスパレットのビットマップを生成する.
PixelFormat pixfmt = PixelFormat.Format8bppIndexed;
bmp = new Bitmap( w, h, pixfmt );
// いったんデフォルトのパレットを盗む.
ColorPalette pal = bmp.Palette;
// 盗んだパレットの中身をいじる.
for ( int k = 0; k < 256; k++ )
{
pal.Entries[k] = Color.FromArgb( k, k, k );
}
// いじったパレットを戻す.
bmp.Palette = pal;
// グラデーションデータをビットマップにコピーする.
unsafe
{
BitmapData bmdt = new BitmapData();
// ビットマップをロックする.
Rectangle rct = new Rectangle( 0, 0, w, h );
ImageLockMode mode = ImageLockMode.ReadWrite;
bmdt = bmp.LockBits( rct, mode, pixfmt );
// ワンスキャンぶんのバイト数を計算する.
// ビットマップの幅ピクセル数が4の倍数でなかったときは、
// one_scan_bytes_dst と one_scan_bytes_src は、
// 違う値になる可能性が高いので別々に扱う.
int one_scan_bytes_src = w * sizeof( byte);
int one_scan_bytes_dst = bmdt.Stride;
// ここで byte[] データを Bitmap に書き込む.
fixed( byte* src = data008 )
{
byte* pt_scan_src = src;
byte* pt_scan_dst = (byte*)( bmdt.Scan0 );
for ( int j = 0; j < h; j++ )
{
byte* pt_src = pt_scan_src;
byte* pt_dst = pt_scan_dst;
for ( int i = 0; i < w; i++ )
{
*pt_dst = *pt_src;
pt_src++;
pt_dst++;
}
pt_scan_src += one_scan_bytes_src;
pt_scan_dst += one_scan_bytes_dst;
}
}
// ビットマップをアンロックする.
bmp.UnlockBits( bmdt );
}
// ビットマップファイルを保存する.
String fp_img0 = "c:/tmp/debug_sample_bpp08.bmp";
ImageFormat imgfmt0 = ImageFormat.Bmp;
bmp.Save( fp_img0, imgfmt0 );
// ピングファイルを保存する.
String fp_img1 = "c:/tmp/debug_sample_bpp08.png";
ImageFormat imgfmt1 = ImageFormat.Png;
bmp.Save( fp_img1, imgfmt1 );
// ビットマップは生成したら Dispose しなければならない.
bmp.Dispose();
bmp = null;
// 「フォト」や「ペイントブラシ」などで保存した画像ファイルを開く
Process.Start( fp_img0 );
Process.Start( fp_img1 );
}
private void button2_Click( object sender, EventArgs e )
{
Bitmap bmp;
GY_IMG_BPP24 [] data024;
int w = INI_W;
int h = INI_H;
int numpix = w * h;
data024 = new GY_IMG_BPP24[ numpix ];
int quarter_w = w >> 2;
// 左から順に、Gray, Blue, Green, Red のグラデーションを作成したい.
int xs0 = quarter_w * 0;
int xs1 = quarter_w * 1;
int xs2 = quarter_w * 2;
int xs3 = quarter_w * 3;
int xe0 = xs0 + quarter_w - 1;
int xe1 = xs1 + quarter_w - 1;
int xe2 = xs2 + quarter_w - 1;
int xe3 = xs3 + quarter_w - 1;
for ( int j = 0; j < h; j++ )
{
byte level = (byte)(j);
// Gray のグラデーション.
for ( int i = xs0; i <= xe0; i++ )
{
data024[ i + w * j ].B = level;
data024[ i + w * j ].G = level;
data024[ i + w * j ].R = level;
}
// Blue のグラデーション.
for ( int i = xs1; i <= xe1; i++ )
{
data024[ i + w * j ].B = level;
data024[ i + w * j ].G = 0x00;
data024[ i + w * j ].R = 0x00;
}
// Green のグラデーション.
for ( int i = xs2; i <= xe2; i++ )
{
data024[ i + w * j ].B = 0x00;
data024[ i + w * j ].G = level;
data024[ i + w * j ].R = 0x00;
}
// Red のグラデーション.
for ( int i = xs3; i <= xe3; i++ )
{
data024[ i + w * j ].B = 0x00;
data024[ i + w * j ].G = 0x00;
data024[ i + w * j ].R = level;
}
}
// 24bpp のビットマップを作成する.
PixelFormat pixfmt = PixelFormat.Format24bppRgb;
bmp = new Bitmap( w, h, pixfmt );
// グラデーションデータをビットマップにコピーする.
unsafe
{
BitmapData bmdt = new BitmapData();
Rectangle rct = new Rectangle( 0, 0, w, h );
ImageLockMode mode = ImageLockMode.ReadWrite;
// ビットマップをロックする.
bmdt = bmp.LockBits( rct, mode, pixfmt );
// ワンスキャンぶんのバイト数を計算する.
// ビットマップの幅ピクセル数が4の倍数でなかったときは、
// one_scan_bytes_dst と one_scan_bytes_src は、
// 違う値になる可能性が高いので別々に扱う.
int one_scan_bytes_src = w * sizeof( GY_IMG_BPP24 );
int one_scan_bytes_dst = bmdt.Stride;
// ここで24bitsパックドデータを Bitmap に書き込む.
fixed( void* src = &( data024[0] ))
{
byte* pt_src = (byte*)( src );
byte* pt_dst = (byte*)( bmdt.Scan0 );
for ( int j = 0; j < h; j++ )
{
CopyMemory( pt_dst, pt_src, one_scan_bytes_src );
pt_src += one_scan_bytes_src;
pt_dst += one_scan_bytes_dst;
}
}
// ビットマップをアンロックする.
bmp.UnlockBits( bmdt );
}
// ビットマップファイルを保存する.
String fp_img0 = "c:/tmp/debug_sample_bpp24.bmp";
ImageFormat imgfmt0 = ImageFormat.Bmp;
bmp.Save( fp_img0, imgfmt0 );
// ピングファイルを保存する.
String fp_img1 = "c:/tmp/debug_sample_bpp24.png";
ImageFormat imgfmt1 = ImageFormat.Png;
bmp.Save( fp_img1, imgfmt1 );
// ビットマップは生成したら Dispose しなければならない.
bmp.Dispose();
bmp = null;
// 「フォト」や「ペイントブラシ」などで保存した画像ファイルを開く.
Process.Start( fp_img0 );
Process.Start( fp_img1 );
}
private void button3_Click( object sender, EventArgs e )
{
Bitmap bmp;
GY_IMG_BPP32 [] data032;
int w = INI_W;
int h = INI_H;
int numpix = w * h;
data032 = new GY_IMG_BPP32[ numpix ];
int quarter_w = w >> 2;
// 左から順に、Gray, Blue, Green, Red のグラデーションを作成したい.
int xs0 = quarter_w * 0;
int xs1 = quarter_w * 1;
int xs2 = quarter_w * 2;
int xs3 = quarter_w * 3;
int xe0 = xs0 + quarter_w - 1;
int xe1 = xs1 + quarter_w - 1;
int xe2 = xs2 + quarter_w - 1;
int xe3 = xs3 + quarter_w - 1;
// 0xff で不透明、0x80 で半透明、0x00 で透明.
const byte LEVEL_ALPHA = 0xff;
for ( int j = 0; j < h; j++ )
{
byte level = (byte)(j);
// Gray のグラデーション.
for ( int i = xs0; i <= xe0; i++ )
{
data032[ i + w * j ].B = level;
data032[ i + w * j ].G = level;
data032[ i + w * j ].R = level;
data032[ i + w * j ].A = LEVEL_ALPHA;
}
// Blue のグラデーション.
for ( int i = xs1; i <= xe1; i++ )
{
data032[ i + w * j ].B = level;
data032[ i + w * j ].G = 0x00;
data032[ i + w * j ].R = 0x00;
data032[ i + w * j ].A = LEVEL_ALPHA;
}
// Green のグラデーション.
for ( int i = xs2; i <= xe2; i++ )
{
data032[ i + w * j ].B = 0x00;
data032[ i + w * j ].G = level;
data032[ i + w * j ].R = 0x00;
data032[ i + w * j ].A = LEVEL_ALPHA;
}
// Red のグラデーション.
for ( int i = xs3; i <= xe3; i++ )
{
data032[ i + w * j ].B = 0x00;
data032[ i + w * j ].G = 0x00;
data032[ i + w * j ].R = level;
data032[ i + w * j ].A = LEVEL_ALPHA;
}
}
// 32bpp のビットマップを作成する.
PixelFormat pixfmt = PixelFormat.Format32bppArgb;
bmp = new Bitmap( w, h, pixfmt );
// グラデーションデータをビットマップにコピーする.
unsafe
{
BitmapData bmdt = new BitmapData();
Rectangle rct = new Rectangle( 0, 0, w, h );
ImageLockMode mode = ImageLockMode.ReadWrite;
// ビットマップをロックする.
bmdt = bmp.LockBits( rct, mode, pixfmt );
// ワンスキャンぶんのバイト数を計算する.
// ビットマップの幅ピクセル数が4の倍数でなかったときは、
// one_scan_bytes_dst と one_scan_bytes_src は、
// 違う値になる可能性が高いので別々に扱う.
int one_scan_bytes_src = w * sizeof( GY_IMG_BPP32 );
int one_scan_bytes_dst = bmdt.Stride;
// ここで32bitsパックドデータを Bitmap に書き込む.
fixed( void* src = &( data032[0] ))
{
byte* pt_src = (byte*)( src );
byte* pt_dst = (byte*)( bmdt.Scan0 );
for ( int j = 0; j < h; j++ )
{
CopyMemory( pt_dst, pt_src, one_scan_bytes_src );
pt_src += one_scan_bytes_src;
pt_dst += one_scan_bytes_dst;
}
}
// ビットマップをアンロックする.
bmp.UnlockBits( bmdt );
}
// BMPファイルは透明度の定義がないのでPNGファイルで保存する.
// ピングファイルを保存する.
String fp_img1 = "c:/tmp/debug_sample_bpp32.png";
ImageFormat imgfmt1 = ImageFormat.Png;
bmp.Save( fp_img1, imgfmt1 );
// ビットマップは生成したら Dispose しなければならない.
bmp.Dispose();
bmp = null;
// 「フォト」や「ペイントブラシ」などで保存した画像ファイルを開く.
Process.Start( fp_img1 );
}
}
}
サンプルソースを用意しました。よろしければご利用ください。
デバッグ用画像ファイルを作成する(8,24,32)
1 ファイル 13 KB
出来上がったソフトを実行すると Form1_Load()に記述してあるとおり c:/tmp というディレクトリを作成し、Button1, Button2, Button3 を押すと、c:/tmp の中に画像ファイルが配置されます。