PC上でのビットマップ表示の処理速度を向上させる方法

このQ&Aのポイント
  • PC上でのLCDデータのビットマップ表示処理が重たい問題について、処理速度を上げる方法を知りたいです。
  • 現在、PC上でタバコサイズのLCDデータを表示させるために、ビットマップファイルを数百枚貼り付けています。
  • ビットマップファイルのサイズを削減するためにFireWorksを使用しましたが、画面が化けてしまいました。CreateDIBitmap関数の設定をいじる必要があるのでしょうか?
回答を見る
  • ベストアンサー

ビットマップ(表示速度とサイズ)

タバコサイズのLCDのデータを取り込んでPC上に描写させています。 小さくて見難いLCDを、PCの画面上で大きく表示させています。 私はSHでファームを作っていて、アプリはVCで作られた既存のもので動かしています。 SHから送られたセグメントの情報をもとに、ビットマップファイルを数百枚貼り付けて表示しているようです。 それで、このLCDデータを表示させている(ビットマップを貼り付けている)処理が重たいくて困っています。 PCの環境にも依存するのかもしれませんが、たとえばLCD全点灯させたときなどは、表示させるのに約2秒くらいかかっています。 各ビットマップファイルのサイズをみると600kバイトくらいあります。 そこでFireWorksをつかって8bitサイズにしたところ、200k位になったのですが・・いざ動かしたら、画面が化けて原型をとどめていませんでした。 VCは無知なのでよくわからないのですが、CreateDIBitmapという関数の設定とかをいじる必要があるのでしょうか? 長々とわかりにくい文章になってしまいましたが、要は処理速度を上げる方法を知りたいです。 よろしくお願いします<(_ _)>

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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); } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

dora40
質問者

お礼

何度もご回答していただいて本当にありがとうございます。 本当に感謝いたします。 machongolaさんのソースを参考にちょっと実験してみます。 ただVC自体不慣れなもので、少々時間かかると思われます^^; 結果は、後ほどご報告させていただきます。

dora40
質問者

補足

いろいろと試みたのですが、結局挫折しました。 外注に出すことになると思います。 VCは見えない部分が多くて大変です。 そもそもまともに作ったことがない私が手を出したことが間違いですよね^^; machongolaさん、ほんとうにありがとうございました!

その他の回答 (2)

回答No.2

 こんにちは。御礼頂きました。  前回の回答が不完全で間違えもあった為、改めて回答しなおさせていただきます。  ええと、先ず、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()を使用して、プログラム中でビットマップに着色操作をしていないか。  必要になる色違いのビットマップは、予めファイルとして準備して置く様にする。

dora40
質問者

お礼

こんにちは。 ありがとうございます。本当に感謝です^^ >描写にはBitBlt関数を使用する。第九パラメータにSRCCOPY以外は極力使用しない。 BitBlt関数を使用し、SRCCOPYをつかっているようです。 >必要になる色違いのビットマップは、予めファイルとして準備して置く様にする。 着色操作はしていないと思います。 色は1色でファイルとして用意しています。 >CreateDIBitmap()の第一パラメータに渡しているデバイスコンテクストは、ウィンドウハンドルから取って来たモノであるか これがよくわかりません。 いろいろ本を読みあさってはいるんですが。。。 ソースを補足に掲載しますので、なにかアドバイスいただけるとうれしいです。 図々しくてすみません。 時間が有るときで結構ですので、よろしくお願いします。

dora40
質問者

補足

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 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 ); } ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

回答No.1

 こんにちは。  CreateDIBitmap()APIを使用していて、イメージファイルを8bitにしたら、表示が可笑しくなったという事でしょうか。  ファイルからどの様にして、読み込んでいるのかにもよりますが、恐らくCreateDIBitmap()の呼び出し以前に、特定フォーマット以外のイメージファイルを読み込む事は、想定されていないコーディングになっているのではないでしょうか。  また、8bitにしたからと言って、特別に早くなる訳ではありません。  イメージの描写に関しては、どの様な取り扱いをしたいのかによって、DDB又はDIBのどちらを選択するかが変ってきます。  画像編集的な取り扱いをするのならばDIB、用意されたイメージをいち早く描写しなければならないならDDBを選択します。  この事例の場合、DDBを選択した方が良いと思います。  尚、DDBである以上、デスクトップとビット数が一致していないといけないので要注意です。

dora40
質問者

お礼

こんにちは。 さっそくのご回答ありがとうございます。 >CreateDIBitmap()APIを使用していて、イメージファイルを8bitにしたら、表示が可笑しくなったという事でしょうか。 はい。そのとおりです。 >また、8bitにしたからと言って、特別に早くなる訳ではありません。 そうなんですね。 単純にファイルサイズが三分の一になれば、そのぶん早くなるかと思ってました。 DDBというものを少し調べてみます。 大変参考になりました。ありがとうございました。

関連するQ&A

  •  (・_・) ビットマップ表示とは?(Windows98)

     いまだにWindows98を愛用してます。  「アクセサリ」から「ペイント」を開き、「ファイル」を「開く」として、マイドキュメントに保存してる写真(JPEG形式)を貼り付けました。  次に「表示」→「ビットマップ表示」とクリックすると、画面がパッと大きくなりました。  この「ビットマップ表示」というのは、なんでしょうか?  この表示にすると、なにかとくべつの作業ができるんでしょうか?

  • ビットマップの表示ができません。

    Visual Studio.net 2003 MFCを使用しています。 ビットマップの表示とフォームのサイズ変更はできたのですが、 以下のソースのように フォームのサイズをビットマップのサイズに変更すると ビットマップが表示されません。 一瞬表示はされているようですが、 真っ白になります。 フォームをきちんとビットマップのサイズに変更し、 ビットマップを表示するにはどうすればいいでしょうか? int num=35; void CProject1View::OnLButtonUp(UINT nFlags, CPoint point) {   // TODO : ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。   char str[128];   wsprintf(str,"c:\\test\\%d.bmp",num);num++;   HBITMAP hbm = (HBITMAP)LoadImage(NULL, str, IMAGE_BITMAP,0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION );   CBitmap *pBmp = CBitmap::FromHandle( hbm );   BITMAP bmp;   GetObject(hbm,sizeof(bmp),&bmp );   CDC bmpdc;   CDC *mydc=GetDC();   bmpdc.CreateCompatibleDC(mydc);   CBitmap *pOldBmp = bmpdc.SelectObject(pBmp);   GetParentFrame()->SetWindowPos(&wndTop,0,0,bmp.bmWidth,bmp.bmHeight,SWP_NOMOVE);   mydc->BitBlt( 0, 0,bmp.bmWidth, bmp.bmHeight, &bmpdc, 0, 0, SRCCOPY );   bmpdc.SelectObject(pOldBmp);   DeleteObject(hbm);   CView::OnLButtonUp(nFlags, point); }

  • ビットマップのコピーについて

    はじめまして。 ビットマップ操作について勉強をしております。 現在、ビットマップファイルを読み込んでメモリDC上でコピーし、新しいファイルを生成するプログラムを作っております。 手順としては 1. LoadImageでBMPファイルを読み込み、ハンドルを取得。 hdcmem_old = CreateCompatibleDC ( NULL ); SelectObject( hdcmem_old , hBitmap_old ); 2. hdcmem_new = CreateCompatibleDC ( NULL ); hBitmap_new = CreateDIBSection( hdcmem_new , (BITMAPINFO*)&bmpInfoHeader , DIB_PAL_COLORS , (void **) &Pixel , NULL , 0 ); SelectObject( hdcmem_new, hBitmap_new ); 3. BitBlt( hdcmem_new , 0 , 0 , LCD_WIDTH , LCD_HEIGHT , hdcmem_old , 0 , 0 , SRCCOPY ) でデータを転送後、ビットマップファイルのヘッダを取り出し、&Pixelからビットデータを加えて新たなファイルを生成しているのですが、生成された画像を見ると全黒になっております。 メモリDCを完全に理解してないせいか、解決策がみあたりません。 もしよろしければ、解決策、またはヒントをご教授していただければと思います。 よろしくお願いします。

  • 【VC++2005】複数ビットマップの表示方法

    【VC++2005】複数ビットマップの表示方法 BMPファイルを読み込み、ピクチャーコントロールに表示する方法を以下を参考に作成しました。 →http://www-higashi.ist.osaka-u.ac.jp/~k-maeda/vcpp/sec4-1bmpfile.html そこから今度は、複数のBMPを読み込み、画面に連結して表示させたいと思いましたが、どのように行えば実現可能なのか検討もつきません・・・。 参考になりそうなサイト等、ご存知の方がおられましたらご教授お願いいたしますm(__)m

  • ビットマップボタンを押したときの処理についてなんですが

    環境はVC++6.0 MFC ダイアログベースです。 MFC初心者なんですが、 HBITMAP hBitmap; hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), (LPCTSTR)csBMPFile,      IMAGE_BITMAP, 0, 0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); を使いビットマップハンドルをし取得しました。 ビットマップの貼り付けは出来たのですが、ボタンを押したときにビットマップの画像を変える処理の仕方がわかりません>< loadbitmapsなら容易に出来るのですが、どうしてもloadimageを使って表示したいのですが、どのようにすれば良いでしょうか? 御教授よろしくお願いします><

  • ビットマップの画像処理について自由度を得る最適方法

    以下、長文かつ具体性に欠ける質問で済みません。画像処理についてやりたいことは決まっているのですが、やり方がわからなくて長年困っています。 【やりたいこと】:ビットマップ形式による写真画像があります。その画像上に例えば、何らかのデータに基づいて線を引いたり、写真画像を数値化して計測したり、自由に加工したりするものです。そのためにはビットマップファイルを自由に操作出来なければなりません。 【これまでにやったこと】 ○Windows VC++ 6.0, Borland C++, Visual Basicなどの勉強 WindowsAPIなど。 ○既成ソフトでの操作(Adobe系,ImageMagik,など) ○科学技術系ソフト(Matlab, Octaveなど) どれも何となくイメージと違うのです。画像ファイルというのはバイナリで、ヘッダ部とデータがあり、(500×500)などの2次元ラスターファイルに過ぎないと私は考えています(色もあるのでさらにそれが何枚かあるのかも知れませんが、基本構造は同じ?)。WindowsAPIなど勉強していると難しいクラスの説明ばかりですが、もっと簡単に処理できるだろうと思っています。画像処理ソフトでは、感覚に頼って見た目に応じてマウスで処理するので正確ではありません。どうしても数値のデータとして処理したいのです。 テキストとして取り出されたビットマップファイル(500×500)の処理はループを回してアレコレ処理すればよい(自由度無限大、だからいろいろあって難しいが)わけですね。要するにビットマップファイルを数値データとして自由に読み書きできるスキルを最も最速で習得するにはどうしたらよいかということなのです。 前提となる画像フォーマットはWindows Bitmapです。そうでないものはペイントショップなどで(質はともかく)変換できるので、その問題はクリアしています。 やはり、WindowsAPIの勉強が不可欠なのでしょうか。 プログラムのスキルとしてはFortranによる科学技術計算プログラムを10年以上作成しています。Fortran95ぐらいだったらポインタなどもあるようなのでビットマップのエディットはひょっとしたら簡単なのかも知れませんが。 以上、長文で失礼します。よろしくお願いします。

  • JPGデータが表示されない。

    いつもお世話になっています。 デジカメで撮った写真をパソコンにコピーしたのですが、表示ができません。 デジカメではプレビュー画面で見れます。 見れないのはJPGファイルです。データ自体は1M程度のサイズです。 過去の質問を見て、以下の3つの方法をしたのですが、見れません。 1)ファイルをダブルクリックすると、 「プレビューを利用できません。」と表示される。 2)ペイントで開くと以下のようなエラーが出ます。 「このファイルは読み取れません。 このビットマップファイルは無効であるか、または現在サポートされていない形式です。」 3)IEは画像が表示されません。 4)フォトショップで開くと、以下のようなエラーが出ます。 「書類を開くことができません。JPEGマーカーセグメントが短すぎます(ファイルが完全でない場合があります)。」 パソコンでの表示の仕方を教えてください。 ちなみに、使用パソコンはWINDOWS XPです。 よろしくお願いします。

  • 640×480のWindiwsビットマップファイル?

    お世話になります。 手持ちのDVDレコーダーで(TOSHIBA RD-XS40)、DVDを作成する際にネットでナビという機能を使うとメニュー画面を自分で色々自作できるという事を知り、試しているのですが上手くいきません。 説明によるとメニュー画面の背景にUP出来る画像が「640×480のWindiwsビットマップファイル」となっていたのですが、そういう画像はどこで手に入るのでしょうか? フリーの素材やさんなどをのぞいてみたりしましたが、大きさが125×125だったりで一応保存してみるものの、Picture Managerという元々パソコンに入っているソフトでサイズ変更しようとしても正方形のまま大きくなったりして上手くいきません。 どなたか、この大きさのビットマップファイルが手に入るサイトや、小さなサイズの物をこの640×480の大きさに拡大できる方法など分かりましたら教えて頂きたいです。 画像は、水玉とかストライプとかよく素材やさんで目にする様なかわいい感じの物を探しています。 なにぶんPC初心者なので、分かり易く説明していただけましたら嬉しいです。 宜しくお願い致します。

  • バッファサイズについて

    今画像データについて勉強しています。ビットマップファイルについてなんですが大きさを240×320の場合の時 #define WSIZE 320 /*ビットマップの幅*/ #define HSIZE 240 /*ビットマップの高さ*/ #define BSIZE 1024 /*バッファサイズ*/ と書くんですがなぜBSIZE 1024 となるかわかりません。教えてください。

  • 表示サイズが違う件について

    たとえばこのページ(まだ途中なんですが)を自宅のPCで開くと画面ぴったりサイズで表示されます。 http://homepage2.nifty.com/syukujek/top.htm (幅750、高さ900) しかし違うPCでみるとかなり小さく表示されます。 幅750なので小さくみえるのが当たり前なのでしょうけどこの表示サイズのそれぞれ違う2台のPCは液晶の画面はまったく同じサイズなんです。 なのになぜ表示サイズが違うのでしょうか。 色々なサイトを2台のPCで見比べてみても私の作ったHP(上記URL)のようにはならず表示されるサイズは一緒です。 何かPC画面に合わせてぴったりに表示させるようなタグはあるのでしょうか。よろしくおねがいします。

    • ベストアンサー
    • HTML

専門家に質問してみよう