C++ 从 hBitmap 获取 RGB

2023-11-22

使用位图对我来说是非常陌生的,所以我一直在努力阅读我读过的在线教程和策略。基本上我的目标是扫描屏幕以获取特定的 RGB 值。我相信执行此操作的步骤是在 hBitmap 中捕获屏幕,然后从中生成一个我可以扫描的 RGB 值数组。

我最初从 GetPixel 开始,但速度非常慢。解决方案是使用 GetDIBits 生成 RGB 值数组。问题是它返回奇怪且可能随机的 RGB 值。

我正在使用从另一个教程中找到的以下代码:

/* Globals */
int ScreenX = GetDeviceCaps(GetDC(0), HORZRES);
int ScreenY = GetDeviceCaps(GetDC(0), VERTRES);
BYTE* ScreenData = new BYTE[3*ScreenX*ScreenY];

void ScreenCap() {
    HDC hdc = GetDC(GetDesktopWindow());
    HDC hdcMem = CreateCompatibleDC (hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, ScreenX, ScreenY);
    BITMAPINFOHEADER bmi = {0};
    bmi.biSize = sizeof(BITMAPINFOHEADER);
    bmi.biPlanes = 1;
    bmi.biBitCount = 24;
    bmi.biWidth = ScreenX;
    bmi.biHeight = -ScreenY;
    bmi.biCompression = BI_RGB;
    bmi.biSizeImage = ScreenX * ScreenY;
    SelectObject(hdcMem, hBitmap);
    BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hdc, 0, 0, SRCCOPY);
    GetDIBits(hdc, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);

    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdc);
}

inline int PosR(int x, int y) {
    return ScreenData[3*((y*ScreenX)+x)+2];
}

inline int PosG(int x, int y) {
    return ScreenData[3*((y*ScreenX)+x)+1];
}

inline int PosB(int x, int y) {
    return ScreenData[3*((y*ScreenX)+x)];
}

我用下面的代码对此进行测试。我按 Shift 键调用 ScreenCap,然后将光标移动到所需位置并按 Space 键查看该位置的 RGB 值。我完全疯了吗?

int main() {

while ( true ) {

   if (GetAsyncKeyState(VK_SPACE)){  

      // Print out current cursor position
      GetCursorPos(&p);
      printf("X:%d Y:%d \n",p.x,p.y);
      // Print out RGB value at that position
      int r = PosR(p.x, p.y);
      int g = PosG(p.x, p.y);
      int b = PosB(p.x, p.y);
      printf("r:%d g:%d b:%d \n",r,g,b);

   } else if (GetAsyncKeyState(VK_ESCAPE)){
      printf("Quit\n");
      break;
   } else if (GetAsyncKeyState(VK_SHIFT)){
      ScreenCap();
      printf("Captured\n");
   }
}

system("PAUSE");
return 0;
}

问题是你的屏幕实际上是 32 位深度而不是 24 位。下面的代码将为你提供你需要的结果:

/* Globals */
int ScreenX = 0;
int ScreenY = 0;
BYTE* ScreenData = 0;

void ScreenCap() 
{
    HDC hScreen = GetDC(NULL);
    ScreenX = GetDeviceCaps(hScreen, HORZRES);
    ScreenY = GetDeviceCaps(hScreen, VERTRES);

    HDC hdcMem = CreateCompatibleDC(hScreen);
    HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, ScreenX, ScreenY);
    HGDIOBJ hOld = SelectObject(hdcMem, hBitmap);
    BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hScreen, 0, 0, SRCCOPY);
    SelectObject(hdcMem, hOld);

    BITMAPINFOHEADER bmi = {0};
    bmi.biSize = sizeof(BITMAPINFOHEADER);
    bmi.biPlanes = 1;
    bmi.biBitCount = 32;
    bmi.biWidth = ScreenX;
    bmi.biHeight = -ScreenY;
    bmi.biCompression = BI_RGB;
    bmi.biSizeImage = 0;// 3 * ScreenX * ScreenY;

    if(ScreenData)
        free(ScreenData);
    ScreenData = (BYTE*)malloc(4 * ScreenX * ScreenY);

    GetDIBits(hdcMem, hBitmap, 0, ScreenY, ScreenData, (BITMAPINFO*)&bmi, DIB_RGB_COLORS);

    ReleaseDC(GetDesktopWindow(),hScreen);
    DeleteDC(hdcMem);
    DeleteObject(hBitmap);
}

inline int PosB(int x, int y) 
{
    return ScreenData[4*((y*ScreenX)+x)];
}

inline int PosG(int x, int y) 
{
    return ScreenData[4*((y*ScreenX)+x)+1];
}

inline int PosR(int x, int y) 
{
    return ScreenData[4*((y*ScreenX)+x)+2];
}

bool ButtonPress(int Key)
{
    bool button_pressed = false;

    while(GetAsyncKeyState(Key))
        button_pressed = true;

    return button_pressed;
}

int main() 
{
    while (true) 
    {
       if (ButtonPress(VK_SPACE))
       {  

          // Print out current cursor position
          POINT p;
          GetCursorPos(&p);
          printf("X:%d Y:%d \n",p.x,p.y);
          // Print out RGB value at that position
          std::cout << "Bitmap: r: " << PosR(p.x, p.y) << " g: " << PosG(p.x, p.y) << " b: " << PosB(p.x, p.y) << "\n";

       } else if (ButtonPress(VK_ESCAPE))
       {
          printf("Quit\n");
          break;
       } else if (ButtonPress(VK_SHIFT))
       {
          ScreenCap();
          printf("Captured\n");
       }
    }

    system("PAUSE");
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 从 hBitmap 获取 RGB 的相关文章

随机推荐

  • 如何使 text-shadow 和 box-shadow 在所有浏览器上使用文本颜色?

    我正在尝试为带有与其文本颜色相同的阴影的框创建样式 因为我有几个框 每个框都有不同的文本颜色 所以我想避免在每个框的每个规则集中重复相同的颜色 现在 背景和边框模块指出 对于box shadow 这也适用于text shadow Where
  • Spring boot 2.6.0 创建名为“webSecurityConfig”的 bean 时出错

    我无法将我的 Spring Boot 应用程序从 2 5 7 更新到 2 6 0 它抛出以下错误 2021 12 07T08 40 22 311 ERROR restartedMain o s b SpringApplication rep
  • SwipeRefreshLayout 片段创建时没有动画

    我在用着android support v4 widget SwipeRefreshLayout with android support v7 widget RecyclerView 关于片段视图创建我需要显示SwipeRefreshLa
  • 在具有非静态片段的布局上有效使用布局编辑器

    凭借所有 Android 开发工具的强大功能 尤其是从版本 21 开始 图形布局编辑器是一个功能强大的工具 可以通过针对每个配置和区域设置的片段对布局进行可视化控制 我知道一个典型的Activity的布局 XML 将包含 staticfra
  • 如何禁用 Delphi 2010 中的格式化程序

    Delphi 2010 中的格式化程序对我来说确实是一件烦人的事情 我更喜欢手动格式化我的代码 我相信我会做得更好 我怎样才能禁用它 注意 关于我为什么不首先使用它的答案将不会被接受 我需要将其关闭 不多不少 Install DDev扩展来
  • pdo-odbc 不适用于绑定值,nvarchar 和文本在等于运算符中不兼容

    有一个专栏url nvarchar 200 not null
  • 使用 NLTK 提取关系

    这是一个我的问题的后续行动 我正在使用 nltk 来解析人 组织及其关系 使用这个例子 我能够创造出大量的人和组织 但是 我在 nltk sem extract rel 命令中收到错误 AttributeError Tree object
  • 如何在 Linux 上从 python 调用 Wine dll?

    我正在 Linux 中编写 python 脚本 需要调用 Wine 中可用的一些 Windows 函数 具体来说 AllocateAndInitializeSid and LookupAccountSidW 以确定谁登录到远程 Window
  • 在 ASP.NET MVC 中将 .html 文件呈现为视图

    我希望在我的 ASP NET MVC 项目中将 html 文件与其他 cshtml 视图一起用作视图 这样做的主要原因是 在我的操作中 html 文件受到与其他视图所遵守的相同的自定义安全规则的约束 我不想使用 cshtml 或 aspx
  • 我可以告诉编译器考虑关于返回值的控制路径关闭吗?

    假设我有以下功能 Thingy getThingy int id for int i 0 i lt something i normal execution guarantees that the Thingy we re looking
  • 具有复杂键的 Spring @Cacheable 仍然执行

    我对 spring 3 1 中 Cacheable 的使用有以下内容 spring
  • 你能在一条语句中访问MySQL中的自动增量值吗?

    我有一个 MySQL 数据库 其中包含一个用户表 表的主键是 userid 设置为自增字段 我想做的是 当我将新用户插入表中时 使用自动增量在不同字段 default assignment 的 userid 字段中创建的相同值 e g 我想
  • C++:声明一个全局类并从其他类访问它?

    我有一个类应该从 main 全局声明并从程序中的其他声明的类访问 我该怎么做 class A int i int value return i class B global A a or extern int calc return a v
  • Python 中 Tesseract OCR 的 UnicodeDecodeError

    我正在尝试使用 Python 中的 Tesseract OCR 从图像文件中提取文本 但我遇到了一个错误 我可以弄清楚如何处理它 我的所有环境都很好 因为我用 python 中的 ocr 测试了一些示例图像 这是代码 from PIL im
  • 更改 MySQL 错误消息语言

    我的 MySQL 错误语言有问题 当查询出现错误时 该错误不是英文的 就像下面的消息 Le champ id ne peut tre vide null 我已经运行此查询来更改语言 但仍然出现相同的错误 SET lc messages en
  • 本地 ffmpeg 输出到 S3 Bucket

    这是我的设置 我有一台运行 ffmpeg 的本地 PC 输出配置为 h 264 和 aac 以及在AWS创建的S3存储桶 我需要做的是 使用 ffmpeg local 输出将文件直接上传到 s3 存储桶 附 计划将 s3 存储桶与 clou
  • DOM/Javascript:获取标签后的文本

    如何获取 html 文档中标签后面的文本 there p a hello a there p 我发现有一种方法可以用 xpath 做到这一点 从下一个标签获取文本 但我没有使用 xpath 并且希望不必为此而开始 我意识到我可以获取 p 标
  • 如何在Java.time中将LocalDateTime的精度设置为纳秒?

    根据java time 文档 java time应该能够以纳秒精度呈现 LocalDateTime 或 LocalTime 但是当我运行时LocalDateTime now 打印出来 只显示3位数字 而不是9位 像这样 2016 08 11
  • 怎么去掉这些点啊!

    我正在 VS2008 的一个项目上编码 我试图按 CTR R E 将字段封装为属性 resharper 的功能 但我摸索着 现在我到处都是点 我有空格 我不知道如何摆脱它 例如 using System Namespace EgNamesp
  • C++ 从 hBitmap 获取 RGB

    使用位图对我来说是非常陌生的 所以我一直在努力阅读我读过的在线教程和策略 基本上我的目标是扫描屏幕以获取特定的 RGB 值 我相信执行此操作的步骤是在 hBitmap 中捕获屏幕 然后从中生成一个我可以扫描的 RGB 值数组 我最初从 Ge