はじめまして。初めて投稿させていただきます。
環境はwin2000 .NET win32アプリで作成しています。
8bitのビットマップを読込みビットマップ構造体より2倍のサイズを持つ
ビットマップを作成しようとしています。
CBitmap cbmp1,cbmp2;
HBITMAP hBmp = (HBITMAP)LoadImage( AfxGetApp()->m_hInstance, bit08.bmp,
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
cbmp1.Attach(hBmp);
cbmp1.GetBitmap( &bmp ); // ビットマップの詳細を取得
bmp.bmHeight = bmp.bmHeight << 1; // 2倍
bmp.bmWidth = bmp.bmWidth << 1; // 2倍
bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;
cbmp2.CreateBitmapIndirect(&bmp);
を実行するとCreateBitmapIndirectで0が返ってきます。
LoadImageのLR_CREATEDIBSECTIONフラグを消すと正常に0以外が返ってきます。
LR_CREATEDIBSECTIONフラグを追加した時の処理はどうすればいいのでしょうか?
ご教授おねがいします。
すいません。
環境間違えました。MFCダイアログベースです。
> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;
この計算じゃダメじゃないですか?
WidthBytes は4の倍数に揃えなければなりません。
例えば、BitsPixel が 24 で Width が 5 だったら、上の式では 24 / 8 * 5 = 15 ですが、
最寄の4の倍数に揃えるため、実際には 16 にしなければなりません。
シャノンさん、ご返答ありがとうございます。
BitsPixel = 8; Width = 160; 一定なのですがエラーが返ってきます。
どうもbmHeightかbmWidthで読込んだbmp値より1pixelでも大きく指定すると
CreateBitmapIndirectでエラーが返るみたいです。
読込んだビットマップより2倍の領域を確保したい場合は
CreateBitmapIndirect関数を使用するのではないのでしょうか…?
> bmp.bmHeight = bmp.bmHeight << 1; // 2倍
> bmp.bmWidth = bmp.bmWidth << 1; // 2倍
> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;
これらを修正しておいて、
bmp.bmBits ほったらかしなのがマズいような...
dairygoodsさん ご返答ありがとうございます。
bmp.bmBitsは変更無しでいいかと思ってました…。
調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりません…。
宜しかったらご教授お願いします。
> 調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりませ
ん…。
長さが、bmHeight × bmWidthBytes × (BitsPixel/8) で、
各ピクセルの値が、左上から順番に格納されます。
dairygoodsさんありがとうございます。
LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes * (bmp.bmBitsPixel/8)];
bmp.bmBits = bmByte;
で0以外が返るようになりました。
しかし作成したCBitmapに画像をセットし保存するとモノクロ1bitで表現されています。
LR_CREATEDIBSECTIONフラグを消すと正常?にOS/2形式で保存されるのでソースが間違って
いるわけではないと思うのですが…。
読込む画像が8bitなのにwindow形式8bitとして保存する為にはやはりRGBQUADを使うしか
ないのでしょうか?
すいません。8bitで保存できました。
がやはり画像が表示されません。
LR_CREATEDIBSECTIONフラグを消すとOS/2形式で正常に保存されるのは
変わらないのですが…
LR_CREATEDIBSECTIONフラグを入れることでなにか別の処理が必要になるのでしょうか?
> LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes *
(bmp.bmBitsPixel/8)];
> bmp.bmBits = bmByte;
これでは、ピクセルデータを格納するためのメモリ領域を確保しただけで、その中身は不定で
す。
これに、ビットマップのピクセルデータを格納してやらなければなりません。
シャノンさんご返答有難うございます。
ピクセルデータですか…調べてもピンとこない…
まだまだ勉強不足ですね。
理解できるように頑張ってみます。
> ピクセルデータですか…調べてもピンとこない…
点の色情報が配列に入ってるだけですよ。
例えば、1つの点の情報が8ビットの2x2のビットマップなら、
char bits[4];
bits[0] = 0; // 左上(0,0)の点は、0番目の色
bits[1] = 1; // 右上(1,0)の点は、1番目の色
bits[2] = 0; // 左下(0,1)の点は、0番目の色
bits[3] = 3; // 右下(1,1)の点は、3番目の色
dairygoodsさん、ご返答有難うございます。
> 例えば、1つの点の情報が8ビットの2x2のビットマップなら
>char bits[4];
>bits[0] = 0; // 左上(0,0)の点は、0番目の色
>bits[1] = 1; // 右上(1,0)の点は、1番目の色
ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
配列に入れるということなんでしょうか?
> ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
> 配列に入れるということなんでしょうか?
そうです。ただし、2点注意。
1.今回、2倍に拡大したビットマップを作るのですから、ピクセルのマップ先の座標を計算する
必要があります。
つまり、元ピクセルがこう
■□
□■
だったら、これを
■×□×
××××
□×■×
××××
にしなければなりません
(×は拡大によって新たに生まれたピクセル。どうにかして補完する必要があります)。
例えばこう。
■■□□
■■□□
□□■■
□□■■
2.あまり気にとめなくていいことだと思いますが、
> 読込んだビットマップの左上から
一般にビットマップはボトムアップ、つまり、下から上へと描画されます。
ファイルの先頭にあるデータは、画像の左下ピクセルのものになります。
シャノンさん、分かりやすい説明有難うございます。
領域を2倍にして読込んだビットマップを縦横斜めに同じ画像を計4枚を表示させる場合の
bmBits はこんな感じになるのでしょうか?
LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes * (bmp.bmBitsPixel/8)];
LPBYTE pBuff = new BYTE[bmp.bmHeight * bmp.bmWidthBytes];
for( nCnt=0; nCnt < 4; nCnt++ ){
cbmp2.GetBitmapBits(bmp.bmWidthBytes * bmp.bmWidth, pBuff);
for( int i=0; i< bmp.bmHeight; i++ ){
::memcpy( &(bmByte[ (i * bmp.bmWidthBytes * 2) +
((nCnt%2)*bmp.bmWidthBytes) + ((nCnt/2)*bmp.bmHeight*2*bmp.bmWidthBytes) ]),
&(pBuff[i * bmp.bmWidthBytes]), bmp.bmWidthBytes );
}
}
bmp.bmBits = bmByte;
cbmp2.CreateBitmapIndirect(&bmp);