ビットマップの作成について – 固定ページ 2 – プログラミング – Home

ビットマップの作成について
 
通知
すべてクリア

[解決済] ビットマップの作成について

固定ページ 2 / 2

aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

> 180度回転する件ですが、BITMAPINFOHEADER を作成する際
> biHeight の値をマイナス掛けすればうまくいきました。
> ( って、こんな修正でいいのでしょうかとやや不安 )

そんな修正でよかったりします。
biHeight が正の値の場合はボトムアップですが、負の値の場合はトップダウンとなりま
す。
ただし、場合によるとトップダウンビットマップを解釈しないビューワがあるかもしれ
ませんので、より確実を期するならボトムアップがいいでしょう。
biHeight を負にするだけでも、間違いではありません。

なお、biWidth を負にしても左右反転にはなりませんので注意。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 22年前
投稿: 160
 

いちお~補足ですが…
「上下反転」であって「180度回転」ではないです。
意味が変わりますので注意された方がよろしいかと。


返信引用
Air
 Air
(@Air)
ゲスト
結合: 20年前
投稿: 33
Topic starter  

ご返答ありがとうございます。

ゆうさん >
とりあえず、言われたとおり、HBITMAP や hDC 等をメンバ変数にし
ビットマップ作成は画像を読み込んだ時のみ行い
BitBlt() は毎割り込み行う方法でやってみようと思います。
結果はまた報告させていただきます。

シャノンさん、瀬戸っぷさん >
なるほど。少し不安だったので安心しました。
新たな忠告も肝に命じておきます。

ちょっと表題からははずれるのですが、
現在ピクチャボックスを 160 x 136 の大きさで配置しています。
これはダイアログエディタ上のサイズです。
そこに 128 x 128 のビットマップを表示してみたのですが
かなり小さいというか左右などはちょうど半分ぐらいに収まっています。
ダイアログ座標というものを考えても予想以上に小さかったので
ん??と思いました。
このサイズについての違いといいますか、その辺りを少し詳しく
教えていただければと思います。

よろしくお願い致します。


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

ダイアログ座標での何ポイントがピクセル単位での何ポイントに相当するかは
ダイアログのフォントの大きさに依存しますので、フォントがデカければデカいほど
ダイアログ座標では同じ値でも、ピクセル単位では差が大きくなりますが。

ちなみに、デザイン時にダイアログ座標をいくつにすればピクセル単位で望みの
値になるのかはわかりません。
ご存知でしたらぜひ教えていただけないでしょうか。


返信引用
Air
 Air
(@Air)
ゲスト
結合: 20年前
投稿: 33
Topic starter  

ご返答ありがとうございます。

シャノンさん >
なるほど。なんとなく納得しました。
自分なりに色々調整してみようと思います。

ピクチャボックスへの描画の件ですが、例のメンバ変数を用意し
BitBlt() だけ毎割り込み行う方法で、うまくいってるっぽいです。
ありがとうございました。

ここでささいなしつもんなのですが、

HDC とか HBITMAP は最後に DeleteObject なり ReleaseDC を行うと思います。
私の場合は

// ビットマップ作成部分より抜粋
p_pic = (CWnd *)GetDlgItem(IDC_PICTURE);
hDC = p_pic->GetDC()->GetSafeHdc();

hCompatiDC = CreateCompatibleDC(hDC);

myDIB = CreateDIBSection( (HDC)0, (BITMAPINFO *)(&p_tex->m_bi),       
         DIB_RGB_COLORS, (void **)&pBitsDib, NULL, 0 );

-------------------------------------------------------------------
// 解放部分
DeleteObject( myDIB );
DeleteObject(hCompatiDC);
ReleaseDC(hWnd, hDC);

こういう感じなのですが (かなり省略して書いていますが)
仮にこの hDC, hCompatiDC, myDIB が一度も使われないまま
解放処理(削除処理)を行った場合というのは大丈夫なのでしょうか?

素人丸出しの質問で恐縮ですが
よろしくお願いします。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 22年前
投稿: 160
 

> ちなみに、デザイン時にダイアログ座標をいくつにすればピクセル単位で望みの
> 値になるのかはわかりません。
> ご存知でしたらぜひ教えていただけないでしょうか。

ピクセル単位で処理したことはありませんが…

とりあえず、下記のページ辺りが参考になるでしょうか?(Delphiのページだったりしますが)
http://homepage2.nifty.com/Mr_XRAY/Halbow/Chap23.html
「ダイアログ単位」ってヤツですね。
変換式が書かれているので参考になるかと。

> こういう感じなのですが (かなり省略して書いていますが)
> 仮にこの hDC, hCompatiDC, myDIB が一度も使われないまま
> 解放処理(削除処理)を行った場合というのは大丈夫なのでしょうか?

作成と解放をドコに記述したかによるのではないでしょうか?
MFCは詳しくないのでドコに書くのが適切なのか判りませんが。
(コンストラクタとデストラクタ? OnInitDialogとOnDestory?)


返信引用
Air
 Air
(@Air)
ゲスト
結合: 20年前
投稿: 33
Topic starter  

> 作成と解放をドコに記述したかによるのではないでしょうか?
> MFCは詳しくないのでドコに書くのが適切なのか判りませんが。
> (コンストラクタとデストラクタ? OnInitDialogとOnDestory?)

変数自体は、基本となるビュークラスのメンバとして宣言しています。
で、画像の読み込みが一度でも行われれば使われるといった感じです。
解放は同じビュークラスのデストラクタで行っています。

なので、画像を一度も読み込まずにアプリを終了すれば
一度も使ってはいないけど解放ということになります。


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

ダイアログ単位について語るスレではないでしょうから、それに関してはこの辺で打ち
止めにして、あとは別スレを立てるなりした方がよいかと。

参考までに、以前この掲示板でダイアログ単位について質問したスレ。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200312/03120064.txt

問題点としては、
・GetDialogBaseUnits で取得した値は、ダイアログのフォントが「System」だと
 想定している
・ダイアログのプロパティで「Use System Font」を TRUE にしても、フォントは
 「System」ではなく「MS Shell Dlg」になってしまう。
の2点。

で、今やって見た所、わりとすんなりできたので変換関数を掲載。

// フォントを考慮した GetDialogBaseUnits 改良版
void CHogeDlg::GetDialogBaseUnits2( LONG & baseUnitX, LONG & baseUnitY )
{
  DWORD dwStyle = GetStyle();
  if( ( dwStyle & ( DS_SETFONT | DS_SHELLFONT ) ) == 0 )
  {
    DWORD dwBaseUnits = GetDialogBaseUnits();
    baseUnitX = LOWORD( dwBaseUnits );
    baseUnitY = HIWORD( dwBaseUnits );
  }
  else
  {
    CDC * pDC = GetDC();

    CDC dc;
    dc.CreateCompatibleDC( pDC );

    CFont * pOldFont = dc.SelectObject( GetFont() );

    TEXTMETRIC metric;
    dc.GetTextMetrics( &metric );
    baseUnitX = metric.tmAveCharWidth;
    baseUnitY = metric.tmHeight;

    dc.SelectObject( pOldFont );
    dc.DeleteDC();

    ReleaseDC( pDC );
  }
}

// MapDialogRect に相当する関数
void CDLUDlg::DialogUnitToPixel( RECT & rect )
{
  LONG baseUnitX = 0;
  LONG baseUnitY = 0;
  GetDialogBaseUnits2( baseUnitX, baseUnitY );

  rect.left = MulDiv( rect.left, baseUnitX, 4 );
  rect.top = MulDiv( rect.top, baseUnitY, 8 );
  rect.right = MulDiv( rect.right, baseUnitX, 4 );
  rect.bottom = MulDiv( rect.bottom, baseUnitY, 8 );
}

// MapDialogRect の逆変換(ピクセル→ダイアログ単位)を行う関数
void CDLUDlg::PixelToDialogUnit( RECT & rect )
{
  LONG baseUnitX = 0;
  LONG baseUnitY = 0;
  GetDialogBaseUnits2( baseUnitX, baseUnitY );

  rect.left = MulDiv( rect.left, 4, baseUnitX );
  rect.top = MulDiv( rect.top, 8, baseUnitY );
  rect.right = MulDiv( rect.right, 4, baseUnitX );
  rect.bottom = MulDiv( rect.bottom, 8, baseUnitY );
}


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

ごめん。この関数じゃうまく行かない場合あり。原因究明中。


返信引用
Air
 Air
(@Air)
ゲスト
結合: 20年前
投稿: 33
Topic starter  

表題とかなり内容が変わってきておりますので、一旦解決とし
別スレを立てさせていただこうと思います。

ちなみに、ピクチャボックスのサイズに関しては
以前シャノンさんの立てられたスレにありました
MapDialogRect() を使い、何とかうまくいきそうです。

だらだらと引っ張ってすいませんでした。
ご返答くださった皆様、ありがとうございました。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

既に解決してしまっているようですが、一つだけアドバイスを。

ビットマップのラインスキャンの方向を反転するために高さをマイナス値にする
件ですけれど、
仕様上は正しいのですが、ドライバによってはこの辺の解釈が怪しい物もあるようです。
グラフィックボードのドライバ多分大丈夫だと思うのですが、
プリンタドライバに関しては結構手抜きをしている物もあるみたいで
高さをマイナスにするよりも自分で逆にたどるようにした方がトラブルが少ないです。
描画に関してはドライバが絡むので苦労させられます。
特に印刷周りはグラフィックドライバよりも手抜きをしていたり、
独自の実装をしていたりで苦しめられる事が多いのでなるべくプログラム側で
対処してあわせてしまう方が無難です。

半分愚痴ですが、ご参考になれば。


返信引用
固定ページ 2 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

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