- ベストアンサー
PC上でのビットマップ表示の処理速度を向上させる方法
- PC上でのLCDデータのビットマップ表示処理が重たい問題について、処理速度を上げる方法を知りたいです。
- 現在、PC上でタバコサイズのLCDデータを表示させるために、ビットマップファイルを数百枚貼り付けています。
- ビットマップファイルのサイズを削減するためにFireWorksを使用しましたが、画面が化けてしまいました。CreateDIBitmap関数の設定をいじる必要があるのでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。拝見させて頂きました。 ああ、MFCでしたか。 見た所、デバイスコンテクストはm_pict(恐らくピクチャーボックス)のウィンドウから取って来ている様です(問題は無いと思います)。 で、肝心な速度落ちの問題ですが、幾つも候補があります。 描画する度にCreateDIBitmap()を呼び出してDDBに変換している事自体が相当なタイムロスに繋がって良そうです。 更に、 void CDataSetDialog::paint_BMP(int i) と言う事ですが、此れはもしかして、 for(int i = 0; i < ???; ++i) paint_BMP(i); と言った具合で複数回呼び出されるのでしょうか。此れもチョッと重たい一因の様な気がします。 何処までいじって構わないのかが、不明瞭なのですが、兎に角、ビットマップファイルを読み込んだら、直にCreateDIBitmap()を使用してDDBに変換して、HBITMAP型の配列を保有して置いた方が良いと思います。 そうすれば、ワザワザ、描写直前でDDBの作成をする必要も無くなって来ます。 再描画に関係なく、HDCを渡しさえすれば、描画してくれる共用のメソッドを一つ準備しておき、別の場所から、其れを利用した方が効率は良くなります。 色々アラも有ると思いますので、以下は参考程度として下さい(テストしていません)。 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ //ファイルを読み込む場所でビットマップハンドルを作成してしまう m_hBitmap[i] = ::CreateDIBitmap(hDC, &pInfo->bmiHeader, CBM_INIT, pBits, pInfo, DIB_RGB_COLORS); ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ void CDataSetDialog::draw_BMP(HDC hDC, int i) { // hDC と互換性のある メモリーデバイスコンテキスト を作成 HDC hCompatiDC = ::CreateCompatibleDC( hDC ); // メモリーデバイスコンテキストにビットマップを選択 ::SelectObject(hCompatiDC, m_hBitmap[i]); // ビットマップハンドルから高さや幅などの情報を取り出す BITMAP bitmap = {0}; ::GetObject(m_hBitmap[i], sizeof(bitmap), &bitmap); // 描画する if( i==0 ){ BitBlt( hDC, 0,0, bitmap.bmWidth, bitmap.bmHeight, hCompatiDC, 0,0, SRCCOPY ); }else{ BitBlt( hDC, 0,0,bitmap.bmWidth, bitmap.bmHeight, hCompatiDC, 0,0,DSTINVERT ); BitBlt( hDC, 0,0,bitmap.bmWidth, bitmap.bmHeight, hCompatiDC, 0,0,MERGEPAINT ); BitBlt( hDC, 0,0,bitmap.bmWidth, bitmap.bmHeight, hCompatiDC, 0,0,DSTINVERT ); } // メモリーデバイスコンテキストの解放 ::DeleteDC(hCompatiDC); } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ void CDataSetDialog::paint_BMP(int i) { PAINTSTRUCT ps; // クライアント領域の描画に使う情報を保持 //** 描画の準備をする ::BeginPaint( m_hWnd, &ps ); // ピクチャーボックスのデバイスコンテキストを取る CDC* pDC = m_pict.GetDC(); // hDCにiを描写する this->draw_BMP(pDC->GetSafeHdc(), i); //** 後始末 ::EndPaint(m_hWnd, &ps); ::ReleaseDC(pDC); } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
その他の回答 (2)
- machongola
- ベストアンサー率60% (434/720)
こんにちは。御礼頂きました。 前回の回答が不完全で間違えもあった為、改めて回答しなおさせていただきます。 ええと、先ず、CreateDIBitmap()はDIBからDDBを作成するものでした。 http://msdn.microsoft.com/ja-jp/library/cc428343.aspx なので、CreateDIBitmap()で作成したビットマップは根本的にDDBと言う事に成ります。 ただ、CreateDIBitmap()の第一パラメータに渡したデバイスコンテクストに、DIBが選択されていたりすると、この関数は暗黙でDIBを作成する様です。 その時の処理速度落ちは1000倍近くです。 以下の事を確認して見て下さい。 ・CreateDIBitmap()の第一パラメータに渡しているデバイスコンテクストは、ウィンドウハンドルから取って来たモノであるか(デスクトップウィンドウからでもOKだと思う)。 ・描写にはBitBlt関数を使用する。第九パラメータにSRCCOPY以外は極力使用しない。 http://msdn.microsoft.com/ja-jp/library/cc428307.aspx ・色違いのビットマップを作りたいが為に、SetPixel()/GetPixel()を使用して、プログラム中でビットマップに着色操作をしていないか。 必要になる色違いのビットマップは、予めファイルとして準備して置く様にする。
お礼
こんにちは。 ありがとうございます。本当に感謝です^^ >描写にはBitBlt関数を使用する。第九パラメータにSRCCOPY以外は極力使用しない。 BitBlt関数を使用し、SRCCOPYをつかっているようです。 >必要になる色違いのビットマップは、予めファイルとして準備して置く様にする。 着色操作はしていないと思います。 色は1色でファイルとして用意しています。 >CreateDIBitmap()の第一パラメータに渡しているデバイスコンテクストは、ウィンドウハンドルから取って来たモノであるか これがよくわかりません。 いろいろ本を読みあさってはいるんですが。。。 ソースを補足に掲載しますので、なにかアドバイスいただけるとうれしいです。 図々しくてすみません。 時間が有るときで結構ですので、よろしくお願いします。
補足
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ void CDataSetDialog::paint_BMP(int i) { HBITMAP myDIB; HBITMAP oldDIB; HDC hDC; // デバイスコンテキスト のハンドル HDC hCompatiDC; // メモリーデバイスコンテキスト のハンドル PAINTSTRUCT ps; // クライアント領域の描画に使う情報を保持 hDC = m_pict.GetDC()->GetSafeHdc(); //** 描画の準備をする ::BeginPaint( m_hWnd, &ps ); // hDC と互換性のある メモリーデバイスコンテキスト を作成 hCompatiDC = ::CreateCompatibleDC( hDC ); // DIB形式ビットマップ から DDB(デバイス依存)形式ビットマップ へ変換する myDIB = ::CreateDIBitmap( hDC, &m_BmpInfo[i]->bmiHeader, CBM_INIT, m_BmpImage[i], m_BmpInfo[i], DIB_RGB_COLORS ); oldDIB = (HBITMAP)::SelectObject( hCompatiDC, myDIB ); // hCompatiDC にある画像を hDC に表示する if( i==0 ){ BitBlt( hDC, 0,0, m_BmpInfo[i]->bmiHeader.biWidth, m_BmpInfo[i]->bmiHeader.biHeight, hCompatiDC, 0,0, SRCCOPY ); }else{ BitBlt( hDC, 0,0,m_BmpInfo[i]->bmiHeader.biWidth, m_BmpInfo[i]->bmiHeader.biHeight, hCompatiDC, 0,0,DSTINVERT ); BitBlt( hDC, 0,0,m_BmpInfo[i]->bmiHeader.biWidth, m_BmpInfo[i]->bmiHeader.biHeight, hCompatiDC, 0,0,MERGEPAINT ); BitBlt( hDC, 0,0,m_BmpInfo[i]->bmiHeader.biWidth, m_BmpInfo[i]->bmiHeader.biHeight, hCompatiDC, 0,0,DSTINVERT ); } //** 後始末 ::EndPaint( m_hWnd, &ps ); ::SelectObject( hCompatiDC, oldDIB ); ::DeleteObject( myDIB ); ::DeleteObject( hCompatiDC ); ::ReleaseDC( m_hWnd, hDC ); } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
- machongola
- ベストアンサー率60% (434/720)
こんにちは。 CreateDIBitmap()APIを使用していて、イメージファイルを8bitにしたら、表示が可笑しくなったという事でしょうか。 ファイルからどの様にして、読み込んでいるのかにもよりますが、恐らくCreateDIBitmap()の呼び出し以前に、特定フォーマット以外のイメージファイルを読み込む事は、想定されていないコーディングになっているのではないでしょうか。 また、8bitにしたからと言って、特別に早くなる訳ではありません。 イメージの描写に関しては、どの様な取り扱いをしたいのかによって、DDB又はDIBのどちらを選択するかが変ってきます。 画像編集的な取り扱いをするのならばDIB、用意されたイメージをいち早く描写しなければならないならDDBを選択します。 この事例の場合、DDBを選択した方が良いと思います。 尚、DDBである以上、デスクトップとビット数が一致していないといけないので要注意です。
お礼
こんにちは。 さっそくのご回答ありがとうございます。 >CreateDIBitmap()APIを使用していて、イメージファイルを8bitにしたら、表示が可笑しくなったという事でしょうか。 はい。そのとおりです。 >また、8bitにしたからと言って、特別に早くなる訳ではありません。 そうなんですね。 単純にファイルサイズが三分の一になれば、そのぶん早くなるかと思ってました。 DDBというものを少し調べてみます。 大変参考になりました。ありがとうございました。
お礼
何度もご回答していただいて本当にありがとうございます。 本当に感謝いたします。 machongolaさんのソースを参考にちょっと実験してみます。 ただVC自体不慣れなもので、少々時間かかると思われます^^; 結果は、後ほどご報告させていただきます。
補足
いろいろと試みたのですが、結局挫折しました。 外注に出すことになると思います。 VCは見えない部分が多くて大変です。 そもそもまともに作ったことがない私が手を出したことが間違いですよね^^; machongolaさん、ほんとうにありがとうございました!