3

Windows API GetPixel() 関数と同等の関数を作成しようとしていますが、画面のビットマップを作成してからそのバッファーを読み取りたいと考えています。

これは私が持っているものです (ほとんどの場合、Google 検索からコピーして貼り付けたものです)。実行すると、0 のみが出力されます。私はそれのほとんどを正しく理解していると思います。私の問題は、BYTE変数の読み方がわからないことです。

私の質問は、 for ループでランダムな色 (R、G、または B) を印刷するにはどうすればよいですか?

#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>

using namespace std;

int main() {

    HDC hdc,hdcMem;

    hdc = GetDC(NULL);
    hdcMem = CreateCompatibleDC(hdc); 

    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 1680, 1050);

    BITMAPINFO MyBMInfo = {0};
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); 
    // Get the BITMAPINFO structure from the bitmap
    if(0 == GetDIBits(hdcMem, hBitmap, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) {
        cout << "error" << endl;
    }

    // create the bitmap buffer
    BYTE* lpPixels = new BYTE[MyBMInfo.bmiHeader.biSizeImage];

    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
    MyBMInfo.bmiHeader.biBitCount = 32;  
    MyBMInfo.bmiHeader.biCompression = BI_RGB;  
    MyBMInfo.bmiHeader.biHeight = abs(MyBMInfo.bmiHeader.biHeight); 

    // get the actual bitmap buffer
    if(0 == GetDIBits(hdc, hBitmap, 0, MyBMInfo.bmiHeader.biHeight, (LPVOID)lpPixels, &MyBMInfo, DIB_RGB_COLORS)) {
        cout << "error2" << endl;
    }

    for(int i = 0; i < 100; i++) {
        cout << (int)lpPixels[i] << endl;
    }

    return 0;
}
  • ウィンドウズ7
  • C::B 13.12 (コンソール アプリケーション)
  • コンパイラ: mingw32-gcc
  • ライブラリ gdi32 リンク
4

3 に答える 3

3

基本的に、0 以外の結果を得るには、いくつかのピクセルを描画する必要があります。

現在、メインのコードの 4 行目は、空の (空の、0 で初期化された) イメージを作成します。次に、 への最初の呼び出しで、このイメージのサイズに関する情報を取得しますGetDIBits。次に、 への 2 回目の呼び出しで実際の (空白の) ピクセルを取得しますGetDIBits

修正するには、ビットマップ ファイルをディスクから にロードし、hBitmapこのビットマップをhdcMem.

つまり、変更

HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 1680, 1050);

このようなものに。

HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "xpButton.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);
HBITMAP old = (HBITMAP) SelectObject(hdcMem, hBitmap);

(有効な bmp ファイル名を使用していることを確認してください。私のファイルは .cpp ファイルと同じフォルダーにあります。これは、IDE 経由で実行する場合、これが「現在の」ディレクトリであるためです。エクスプローラー経由で実行する場合は、別のコピーを配置します。 exe と同じフォルダー内の bmp)

これが私が使用したbmpです(SOへのアップロード後にpngに変換されています):

ここに画像の説明を入力

これがループの最初の 10 回の繰り返しです。

255
5
253
0
255
5
253
0
255
5

0,0 のピクセルの色は rgb(253,5,255) であり、8 ビット イメージであるため、アルファ チャネルがないため、値は 0 です。ピクセルは [BGRA]、[BGRA] として保存されます。 、[BGRA] など。あなたのプログラムの (存在しない) クリーンアップ セクションを修正するのはあなたに任せます。Windows は、ここで使用したメモリの割り当てを解除しますが、割り当てたメモリを解放しないという習慣を絶対に身につけるべきではありません。:)

于 2014-10-07T11:23:32.683 に答える
2

あなたのコードは少し混乱しているようです。スニペットが多すぎると思います:)。それでも、あなたはかなり近づいています: 最初の GetDIBits() 呼び出しは、コード内のコメントが示唆するように、ビットマップのプロパティを取得するためのものです。これには不要な MemDC を使用しています。これはおそらく、画面で BitBlt を実行したいスニペットからのものです。

その後、2 番目の GetDIBits() 呼び出しで実際のビットマップ ピクセルを取得するために、塗りつぶされた構造体を使用できます。

そのため、MemDC を削除し (必要ありません)、GetDIBits() の最初の呼び出しで hdcMem を hdc に置き換えます。次に、最初の GetDIBits 呼び出しの後に bmiHeader メンバーを上書きするすべてのステートメントを削除すると、ピクセルを取得する必要があります。

ああ、もちろん、DC とビットマップで ReleaseDC()/DeleteObject() を呼び出し、バッファを削除することを忘れないでください :)

于 2014-10-07T11:08:32.527 に答える