我有一个调用,GetDIBits它在32位完美工作,但在64位上失败.尽管手柄的值不同,但bitmapinfo结构的内容是相同的.
这是我可以用来重现错误的最小(至少是结构稍微)代码示例.我使用Delphi 10 Seattle Update 1进行了测试,但是即使使用其他Delphi版本,也会出现错误.
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Winapi.Windows,
System.SysUtils,
Vcl.Graphics;
type
TRGBALine = array[Word] of TRGBQuad;
PRGBALine = ^TRGBALine;
type
{ same structure as TBitmapInfo, but adds space for two more entries in bmiColors }
TMyBitmapInfo = record
bmiHeader: TBitmapInfoHeader;
bmiColors: array[0..2] of TRGBQuad;
public
constructor Create(AWidth, AHeight: Integer);
end;
constructor TMyBitmapInfo.Create(AWidth, AHeight: Integer);
begin
FillChar(bmiHeader, Sizeof(bmiHeader), 0);
bmiHeader.biSize := SizeOf(bmiHeader);
bmiHeader.biWidth := AWidth;
bmiHeader.biHeight := -AHeight; //Otherwise …Run Code Online (Sandbox Code Playgroud) 我有一个HBITMAP包含alpha通道数据.我可以使用::AlphaBlendGDI函数成功渲染它.
但是,当我调用::GetPixelGDI函数时,我永远不会使用alpha组件返回值.文档确实说它返回像素的RGB值.
有没有办法检索一个像素的alpha通道值HBITMAP?
我希望能够检测何时使用:: AlphaBlend,以及何时使用旧式方法将源HBITMAP中的特定颜色视为透明.
HDC sourceHdc = ::CreateCompatibleDC(hdcDraw);
::SelectObject(sourceHdc, m_hbmp);
// This pixel has partial transparency, but ::GetPixel returns just RGB.
COLORREF c = ::GetPixel(sourceHdc, 20, 20);
// Draw the bitmap to hdcDraw
BLENDFUNCTION bf1;
bf1.BlendOp = AC_SRC_OVER;
bf1.BlendFlags = 0;
bf1.SourceConstantAlpha = 0xff;
bf1.AlphaFormat = AC_SRC_ALPHA;
::AlphaBlend(di.hdcDraw, x, 10, 64, 64, sourceHdc, 0, 0, 64, 64, bf1);
::DeleteDC(sourceHdc);
Run Code Online (Sandbox Code Playgroud)
使用GetDIBits检索图像的第一个(或更多)扫描线:
byte* bits[1000];// = new byte[w * 4];
BITMAPINFO bmi;
memset(&bmi, …Run Code Online (Sandbox Code Playgroud) 我抓住屏幕的一部分并扫描像素以获得特定的颜色范围.
我查看了MSDN的Capturing a Image示例,并了解如何使用这些函数.
我可以把这些位放到一个数组中,但是我不知道如何以这样的方式进行操作,我可以像运用图像一样循环它.一个伪示例(我肯定是这样的):
for ( x = 1; x <= Image.Width; x += 3 )
{
for ( y = 1; y <= Image.Height; y += 3 )
{
red = lpPixels[x];
green = lpPixels[x + 1];
blue = lpPixels[x + 2];
}
}
Run Code Online (Sandbox Code Playgroud)
这基本上就是我想做的事情,所以如果红色,蓝色和绿色是某种颜色,我会知道图像中(x,y)的坐标是什么.
我只是不知道如何以这种方式使用GetDIBits,以及如何适当地设置数组以便能够实现这一点.
我GetDIBits用来将屏幕兼容设备上下文中的位图数据转换为某种格式的DIB.我的印象是,当源位图为每像素8位或更少时,DC仅用于合成色表.由于我的源位图是一个完整的32位彩色图像,这是一个一次性的程序,我没有屏幕DC方便,我将HDC参数设置为NULL.这没用.一旦我抓住屏幕DC并将其传入,它就开始工作了.
这让我想知道为什么GetDIBits需要设备上下文.它是干什么用的?
我编写了以下代码(C++ Win32)来捕获游戏窗口屏幕并从图像中获取像素颜色数组。函数 autoB() 可以完成这项工作。
然后我将结果数组绘制到我的窗口中,以直观地检查我得到了什么。
问题是这个程序在我启动计算机后只运行一次,在它第一次“缓存”从游戏中截取的第一个屏幕截图之后,我总是得到相同的像素数组。即使我关闭并重新启动程序,我也会得到相同的屏幕截图。
游戏没有使用 DirectX 在屏幕上绘图,我总是可以使用 Alt+PrtSc 截取屏幕截图。
任何帮助理解为什么会以这种方式发生的帮助表示赞赏。
int getPixels(HDC *eClientHdcMem, HBITMAP *eClientBmp, unsigned char **lp) {
BITMAP bmpScreen;
BITMAPINFOHEADER bi;
GetObject(*eClientBmp, sizeof(BITMAP), &bmpScreen);
LONG bW = bmpScreen.bmWidth, bH = bmpScreen.bmHeight;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bW;
bi.biHeight = -bH;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dw = ((bW * bi.biBitCount + 31) / 32) * 4 …Run Code Online (Sandbox Code Playgroud) MSDN表示GetDiBits在调用此函数之前,不应将用于的位图选择为DC.但是从我的经验来看,BitBlt我知道除非选择了位图,否则我无法绘制位图.
GetDiBits绕过这个?我可以使用未选择的,新创建的位图作为此函数的参数吗?GetDiBits并CreateDibSection返回一个数组.但是MSDN谈到了第一个功能:
"指定的兼容位图的位"
我认为DI代表DeviceIndependent.为什么会出现矛盾?这意味着,根据MSDN,GetDiBits只能用CreateCompatibleBitmap(哪个是DD)?然后我不能将这个数组发送到另一台机器来显示它,对吗?
CreateDibSection真的是DIndependent为什么它需要一个hDC?所有需要的信息都是通过bitmapinfoheader提供的......我正在尝试创建一个与 windows API GetPixel() 函数等效的函数,但我想创建屏幕的位图,然后读取该缓冲区。
这就是我所得到的(主要是从谷歌搜索中复制粘贴的),当我运行它时,它只打印出 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 …Run Code Online (Sandbox Code Playgroud)