首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++用GetDIBits()读取像素

c++用GetDIBits()读取像素
EN

Stack Overflow用户
提问于 2014-10-07 10:24:03
回答 3查看 11.6K关注 0票数 6

我正在尝试创建一个与windows ()函数等价的函数,但我希望创建屏幕的位图,然后读取该缓冲区。

这就是我所得到的(主要是从谷歌搜索中粘贴的拷贝),当我运行它时,它只打印0。我认为我的大部分都是正确的,我的问题是我不知道如何读取字节变量。

所以我的问题是,我需要做什么才能让它用我的for循环打印出一些随机的颜色(R,G或B)?

代码语言:javascript
复制
#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;
}
  • Windows 7
  • C:B 13.12 (控制台应用程序)
  • 编译器: mingw32-gcc
  • 库gdi32链接
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-07 14:27:49

按照约定,我将使用工作代码片段添加一个新的答案(我添加了缺少的lpPixels清理)。请参阅我先前回答的讨论和@enhzflep所做的讨论。

代码语言:javascript
复制
#include <Windows.h>
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;

HBITMAP GetScreenBmp( HDC hdc) {
    // Get screen dimensions
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);

    // Create compatible DC, create a compatible bitmap and copy the screen using BitBlt()
    HDC hCaptureDC  = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    HGDIOBJ hOld = SelectObject(hCaptureDC, hBitmap); 
    BOOL bOK = BitBlt(hCaptureDC,0,0,nScreenWidth, nScreenHeight, hdc,0,0,SRCCOPY|CAPTUREBLT); 

    SelectObject(hCaptureDC, hOld); // always select the previously selected object once done
    DeleteDC(hCaptureDC);
    return hBitmap;
}

int main() {
    HDC hdc = GetDC(0);

    HBITMAP hBitmap = GetScreenBmp(hdc);

    BITMAPINFO MyBMInfo = {0};
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); 

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

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

    // Better do this here - the original bitmap might have BI_BITFILEDS, which makes it
    // necessary to read the color table - you might not want this.
    MyBMInfo.bmiHeader.biCompression = BI_RGB;  

    // 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];
    }

    DeleteObject(hBitmap);
    ReleaseDC(NULL, hdc);
    delete[] lpPixels;
    return 0;
}
票数 7
EN

Stack Overflow用户

发布于 2014-10-07 11:23:32

基本上,您需要绘制一些像素才能返回除0以外的结果。

目前,主目录中的第4行代码创建了一个空(空白,0初始化)映像。然后,在第一次调用GetDIBits时,您将获得有关此映像大小的信息。然后,通过第二次调用GetDIBits获得实际(空白)像素。

要修复,只需将一个位图文件从磁盘加载到您的hBitmap中,并选择此位图到您的hdcMem中。

即改变

代码语言:javascript
复制
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 1680, 1050);

像这样的事。

代码语言:javascript
复制
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "xpButton.bmp", IMAGE_BITMAP, 0,0, LR_LOADFROMFILE);
HBITMAP old = (HBITMAP) SelectObject(hdcMem, hBitmap);

(确保使用有效的bmp文件名。我的目录与.cpp文件存在于同一个文件夹中,因为这是通过IDE运行时的“当前”目录。如果希望通过资源管理器运行,请将bmp的另一份副本放在与exe相同的文件夹中)

下面是我使用过的bmp (上传到SO后已转换为png ):

下面是循环的前10次迭代。

代码语言:javascript
复制
255
5
253
0
255
5
253
0
255
5

注意,0,0像素的颜色为: rgb(253,5,255),它是一个8位的图像,因此没有alpha通道,因此它的值为0。像素存储为BGRA等,我将留给您来修复程序的(不存在的)清理部分。Windows将取消您在这里使用的内存,但是您绝对不应该养成不释放任何已分配内存的习惯。:)

票数 3
EN

Stack Overflow用户

发布于 2014-10-07 11:08:32

你的代码似乎有点混乱。太多的片段,我猜:)。尽管如此,您仍然非常接近:第一个GetDIBits()调用是为了得到填充位图的属性,正如代码中的注释所示。为此,您将使用一个不必要的MemDC --这可能是来自一个希望在屏幕上执行BitBlt的片段。

然后,您可以使用填充结构获得第二个GetDIBits()调用的实际位图像素,但是您要做的是再次用硬编码值替换属性,从而使第一个GetDIBits()调用变得无用。

因此:删除MemDC --您不需要它--并在第一个对GetDIBits()的调用中用hdc替换hdcMem,然后删除在第一个GetDIBits调用之后覆盖bmiHeader成员的所有语句,然后得到像素。

哦,当然,不要忘记在dc上调用ReleaseDC()/DeleteObject(),并在位图上调用delete[]缓冲区:)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26233848

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档