LoadImageのLR_CREATEDIBSECTION時の処理 – プログラミング – Home

通知
すべてクリア

LoadImageのLR_CREATEDIBSECTION時の処理


メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

はじめまして。初めて投稿させていただきます。
環境は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フラグを追加した時の処理はどうすればいいのでしょうか?
ご教授おねがいします。


引用解決済
トピックタグ
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

すいません。
環境間違えました。MFCダイアログベースです。


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;

この計算じゃダメじゃないですか?
WidthBytes は4の倍数に揃えなければなりません。
例えば、BitsPixel が 24 で Width が 5 だったら、上の式では 24 / 8 * 5 = 15 ですが、
最寄の4の倍数に揃えるため、実際には 16 にしなければなりません。


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

シャノンさん、ご返答ありがとうございます。
BitsPixel = 8; Width = 160; 一定なのですがエラーが返ってきます。
どうもbmHeightかbmWidthで読込んだbmp値より1pixelでも大きく指定すると
CreateBitmapIndirectでエラーが返るみたいです。
読込んだビットマップより2倍の領域を確保したい場合は
CreateBitmapIndirect関数を使用するのではないのでしょうか…?


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> bmp.bmHeight = bmp.bmHeight << 1; // 2倍
> bmp.bmWidth = bmp.bmWidth << 1; // 2倍
> bmp.bmWidthBytes = (bmp.bmBitsPixel/8)*bmp.bmWidth;

これらを修正しておいて、
bmp.bmBits ほったらかしなのがマズいような...


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

dairygoodsさん ご返答ありがとうございます。
bmp.bmBitsは変更無しでいいかと思ってました…。
調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりません…。
宜しかったらご教授お願いします。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> 調べてみましたが領域が2倍時のピクセルビットの配列の変更の仕方がよく分かりませ
ん…。

長さが、bmHeight × bmWidthBytes × (BitsPixel/8) で、
各ピクセルの値が、左上から順番に格納されます。


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

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を使うしか
ないのでしょうか?


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

すいません。8bitで保存できました。
がやはり画像が表示されません。
LR_CREATEDIBSECTIONフラグを消すとOS/2形式で正常に保存されるのは
変わらないのですが…
LR_CREATEDIBSECTIONフラグを入れることでなにか別の処理が必要になるのでしょうか?


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> LPBYTE bmByte =new BYTE[bmp.bmHeight * bmp.bmWidthBytes *
(bmp.bmBitsPixel/8)];
> bmp.bmBits = bmByte;

これでは、ピクセルデータを格納するためのメモリ領域を確保しただけで、その中身は不定で
す。
これに、ビットマップのピクセルデータを格納してやらなければなりません。


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

シャノンさんご返答有難うございます。
ピクセルデータですか…調べてもピンとこない…
まだまだ勉強不足ですね。
理解できるように頑張ってみます。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> ピクセルデータですか…調べてもピンとこない…

点の色情報が配列に入ってるだけですよ。

例えば、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番目の色


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

dairygoodsさん、ご返答有難うございます。
> 例えば、1つの点の情報が8ビットの2x2のビットマップなら
>char bits[4];
>bits[0] = 0; // 左上(0,0)の点は、0番目の色
>bits[1] = 1; // 右上(1,0)の点は、1番目の色

ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
配列に入れるということなんでしょうか?


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> ということは読込んだビットマップの左上から1ドットづつの色を取得して順番に
> 配列に入れるということなんでしょうか?

そうです。ただし、2点注意。

1.今回、2倍に拡大したビットマップを作るのですから、ピクセルのマップ先の座標を計算する
必要があります。
つまり、元ピクセルがこう

■□
□■

だったら、これを

■×□×
××××
□×■×
××××

にしなければなりません
(×は拡大によって新たに生まれたピクセル。どうにかして補完する必要があります)。

例えばこう。

■■□□
■■□□
□□■■
□□■■

2.あまり気にとめなくていいことだと思いますが、

> 読込んだビットマップの左上から

一般にビットマップはボトムアップ、つまり、下から上へと描画されます。
ファイルの先頭にあるデータは、画像の左下ピクセルのものになります。


返信引用
メアリ
 メアリ
(@メアリ)
ゲスト
結合: 19年前
投稿: 9
Topic starter  

シャノンさん、分かりやすい説明有難うございます。
領域を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);


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました