アプリ版:「スタンプのみでお礼する」機能のリリースについて

GetPixel関数を使って画像のCOLORREF値を取得しているのですが処理に数十秒かかってしまいます。
もっと高速で処理するにはどうすればいいのでしょうか?

環境
 Windows Vista HomePremium
 Visual C++ EE

A 回答 (2件)

 こんばんは。

御礼頂きました。

>>その内容はDDBになっていると思うのですが、これを直接操作することはできないのでしょうか?
 はい。
 残念ながらも、DDBからグラフィックスのポインタを取り出す事は出来ないのです(ただ、Vistaではどうか分かりません・・・)。

 実験として、以下を実行して、bitmap.bmBits メンバを確認して見ると良いでしょう。
 ココがNULLであった場合、グラフィックスへのポインタが取れなかった事を意味します。
 もしVistaに置いて、認められているのであるならば、グラフィックスへのポインタが帰って来る筈です。
 
 BITMAP bitmap = {0};
 ::GetObject(hBitmap, sizeof(bitmap), &bitmap);

>>DIBに変換しなければならないのでしょうか?
 はい。
 直にグラフィックスのポインタへアクセスする為には、「DIBへの変換が必要」と言う事に成ります。
 此れに関しては、幾つかの選択肢が有りますが、手っ取り早くDIBのビットマップハンドルを作成する事でしょうか。
 DIBのヘッダの初期化が面倒程度で、左程難しい事は有りません。
 DIBを作成し、DDBからDIBに向かってBitBlt()API等で描写すれば、互換コピーが出来ます。後はDIBに対してお目当ての処理をするだけです。

 例えば、こんな感じです。

 ※InitHDR32BIT()/InitBitFields32BIT()は参考URLのNo3を引用

//DDBからDIBへの互換コピー
static HBITMAP ConvertToDIB(HBITMAP hDDB)
{
//変換元DDBの情報を取る
BITMAP bitmap = {0};
::GetObject(hDDB, sizeof(bitmap), &bitmap);
//ヘッダのサイズ(RGBQUAD * 3は、ビットフィールド用に必要です)
const int nHDRSize = sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 3);
LPBITMAPINFO pbmi = static_cast<LPBITMAPINFO>(::calloc(nHDRSize, 1));
//32ビット用のヘッダを作成する
::InitHDR32BIT(pbmi->bmiHeader, bitmap.bmWidth, bitmap.bmHeight);
//32ビット用のフィールドを設定する
::InitBitFields32BIT(pbmi->bmiColors);

//DIBセクションの作成
LPVOID pBits = NULL;
HBITMAP hDIB = ::CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, NULL);
//動的に割り当てたヘッダを解放する
::free(pbmi);

//DIB用HDC
HDC hDCDIB = ::CreateCompatibleDC(NULL);
//DDB用HDC
HDC hDCDDB = ::CreateCompatibleDC(NULL);
//それぞれをHDCに選択
::SelectObject(hDCDIB, hDIB);
::SelectObject(hDCDDB, hDDB);
//DDBからDIBへ互換コピー
::BitBlt(hDCDIB, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hDCDDB, 0, 0, SRCCOPY);
//それぞれのHDCを解放
::DeleteDC(hDCDIB);
::DeleteDC(hDCDDB);
//出来上がり
return hDIB;
}

 //この様にして変換する
 HBITMAP hDIB = ::ConvertToDIB(hBitmap/*お目当てのDDB*/);
 ::GetObject(hDIB, sizeof(bitmap), &bitmap);
 //ココでグラフィックのポインタが取れる筈
 bitmap.bmBits

 その他、例えば、2Dグラフィックス系で言えば、DirectDrawやDirect3Dのテクスチャ等がありますが、何れも「ビデオメモリ側」と「システムメモリ側」に分かれており、グラフィックスのポインタを取り出して処理する際には、「ビデオメモリ側からシステムメモリ側へ互換複写」をした後、システムメモリ側のモノを操作する、と言った事に成ります(勿論、編集後はシステムメモリ側からビデオメモリ側へ複写しなおす)。

 そう言った意味では、似たり寄ったりだと思います。
    • good
    • 0
この回答へのお礼

非常に丁寧な説明をありがとうございます。
おかげで目的を達成することができそうです。

お礼日時:2009/02/07 23:38

 こんにちは。


 SetPixel()/GetPixel()はどうしようもない程重たい物です。
 高速化を計るのであるならば、DIBイメージにして、グラフィックデータへのポインタにアクセスするのが手っ取り早いと思います。
 また、プログラム内にて、取り扱うフォーマットを決めておかないと大変な事になってしまいます(32ビットを前提にすると楽です)。

 以下のリンクは似た様な事例です。
 http://oshiete1.goo.ne.jp/qa4431353.html
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
質問ですがスクリーン画面のビットマップ構造体を取得したとき、その内容はDDBになっていると思うのですが、
これを直接操作することはできないのでしょうか?
DIBに変換しなければならないのでしょうか?

画像処理についての知識が全くないので的外れな質問かもしれませんがよろしくお願いします。

お礼日時:2009/02/07 20:19

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!