Visual studio メモ 3 --CImage で bmp jpeg png tifを読む (2012/08/14)--
環境 : Visual Studio 2010 + Windows 7
参考url :
http://msdn.microsoft.com/ja-jp/library/bwea7by5
Load (CImage::GetPixelを使う(遅い))
static bool t_loadImg1(const char *fname, int &W, int &H, byte* rgba)
{
CImage pic;
if( !SUCCEEDED( pic.Load( _T(fname) ) ) ) return false;//bmp jpeg png tiff画像の読み込み(bmp jpegのみ動作確認済み)
W = pic.GetWidth ();
H = pic.GetHeight();
rgba = new byte[W*H*4];
for( int y=0, i=0; y<H; ++y )
for( int x=0 ; x<W; ++x, ++i)
{
COLORREF c = pic.GetPixel( x, y );//画素値get (ここが非常に遅い)
rgba [ i*4 + 0] = GetRValue(c); //画素値コピー
rgba [ i*4 + 1] = GetGValue(c); //画素値コピー
rgba [ i*4 + 2] = GetBValue(c); //画素値コピー
rgba [ i*4 + 3] = 128;
}
return true;
}
やってる事は
1)CImage::Load()で画像を読み込んで
2)CImage::GetWidth() / GetHeight()で画像サイズをもらって
3)CImage::GetPixel()で画素値をCOLORREFでもらう
Load (CImage::GetPixelAddressを使う)
GetPixelが遅いので、PixelのAddressに直接アクセスした方が良い。
画素が24bitsのときのみ、Addressから直接RGBを得るよう書き直したのが以下。
static bool t_loadImg2(const char *fname, int &W, int &H, byte* rgba)
{
CImage pic;
if( !SUCCEEDED( pic.Load( _T(fname) ) ) ) return false;//bmp jpeg png tiff画像の読み込み(bmp jpegのみ動作確認済み)
int pitch = pic.GetPitch();
if( pitch < 0) pitch *= -1;
//↑メージのピッチ(行方向のバイト数)を返します。
//戻り値が負の値の場合、ビットマップは左下隅を起点とする逆方向 (下から上) の DIB です。
//戻り値が正の値の場合、ビットマップは左上隅を起点とする順方向 (上から下の向き) の DIB です
W = pic.GetWidth ();
H = pic.GetHeight();
rgba = new byte[W*H*4];
int byteNum = pitch / W; //これが1pixelあたりのバイト数
if( byteNum == 3 ) //24bit color
{
for( int y=0, i=0; y<H; ++y )
for( int x=0 ; x<W; ++x, ++i)
{
//RGB(24bit)に対するアドレスをbyteにキャストしてるので, R G B順の一番下位のBを指すものになる
byte *c = (byte*)pic.GetPixelAddress( x, y );
rgba[ i*4 + 3] = 128;
rgba[ i*4 + 2] = *c ; ++c;
rgba[ i*4 + 1] = *c ; ++c;
rgba[ i*4 + 0] = *c ;
}
}
else //その他
{
for( int y=0, i=0; y<H; ++y )
for( int x=0 ; x<W; ++x, ++i)
{
COLORREF c = pic.GetPixel( x, y );
rgba[ i*4 + 3] = 128;
rgba[ i*4 + 0] = GetRValue(c);
rgba[ i*4 + 1] = GetGValue(c);
rgba[ i*4 + 2] = GetBValue(c);
}
}
return true;
}
このコードは、jpeg/bmpで動作確認済み。
24bitでない画像や、Color table付きのtifなどはもう少し細かな処理が必要になる。
以下は、GetPixelAddressの(私の)イメージ。24bitで1ブロック(RGB)なので、
例えばCOLORREF(32bit)とかにキャストすると(e.g. (COLORREF*)GetPixelAddress(x,y))、
端っこで1byte分踏み越えて、不正アクセスが発生して、最悪落ちる。
下図では、隣の画素値が、メモリ上でも隣にあるように書いてあるが、それがいつも保障されているかは不明。
このページにあるコードの動作の保証はできません。自己責任で使ってください。ライセンスは
NYSL Version 0.9982です。