我有一个像素数组,我需要转换为HBITMAP才能在窗口中显示它.我尝试使用CreateDIBitmap()但我没有BMP标头.我尝试根据MSDN文档手动构建它们,但这不起作用.
这是我的代码看起来如何
HBITMAP hBitmap
char pixels[160*120]; // White grayscale image of size 160x120
memset(pixels,255,sizeof(pixels));
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = 160;
bmih.biHeight = -120;
bmih.biPlanes = 1;
bmih.biBitCount = 8;
bmih.biCompression = BI_RGB ;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 10;
bmih.biYPelsPerMeter = 10;
bmih.biClrUsed =0;
bmih.biClrImportant =0;
BITMAPINFO dbmi;
dbmi.bmiHeader = bmih;
dbmi.bmiColors->rgbBlue = 0;
dbmi.bmiColors->rgbGreen = 0;
dbmi.bmiColors->rgbRed = 0;
dbmi.bmiColors->rgbReserved = 0;
void* bits = (void*)&(pixels[0]);
hBitmap = CreateDIBitmap(localDC, &bmih, CBM_INIT, qB.bmBits, &dbmi, DIB_RGB_COLORS);
Run Code Online (Sandbox Code Playgroud)
现在我得到一个非NULL的hBitmap,它很好,但它总是显示黑色图像,好像它没有指向像素数组.我使用代码检查了它
BITMAP qB; …Run Code Online (Sandbox Code Playgroud) 我正在从具有以下内容的文件加载 DIBSection:
HBITMAP bmpIn = (HBITMAP) LoadImage(NULL, _T("c:\\Temp\\Temp.bmp"), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
Run Code Online (Sandbox Code Playgroud)
根据经验,我发现加载的位图和我过去使用的位图之间存在以下差异,但我找不到任何文档说明应该存在差异。
CreateDIBSection当您使用从头开始创建 DIBSection时,我还发现了一个已记录的差异。
GetObject将为 NULL。前两个差异的文档在哪里,我是否遗漏了什么?这是 Windows 7 的情况,但我无法想象其他版本的 Windows 会有什么不同。
编辑:一些额外的细节。这是一个十六进制转储temp.bmp;它是一个 7x7 的图像,右侧有白色条纹,蓝色值沿左侧递增(0x10、0x20 等)。您可以看到底线 (00,00,70) 位于第一行,并且有 3 个字节的填充。
00: 42 4d de 00 00 00 00 00 00 00 36 00 00 00 28 00
10: 00 00 07 00 00 00 07 00 00 00 01 …Run Code Online (Sandbox Code Playgroud) 我只是在论坛中讨论是否有一个替代的Windows图形库到GDI和Direct X. 有人提到WinDIB.可悲的是,他没有解释更多.
现在我搜索了谷歌.
Windows DIB似乎没有维基百科的文章.
似乎某些图形库(如SDL)使用WinDIB后端.
那究竟什么是WinDIB?它有任何文件吗?我在哪里可以了解更多信息?
我创建了一个可消耗的 COM 类库。
类库获取相机的图像。它的类型为图像/位图。
我在VB6中使用类库,我需要在VB6中显示这个图像。
如何将此 System.Drawing.Image 转换为 VB6 可以显示的内容?
我可以使用 DIB(使用 CreateDIBSection 等)吗?
如果是,System.Drawing.Image 究竟能转换成 DIB 吗?
谢谢!
我有一个位图存储为BGRA字节数组.这是我用来绘制位图的代码:
CDC *dispDC = new CDC();
dispDC->CreateCompatibleDC(pDC);
CBitmap *dispBMP = new CBitmap();
dispBMP->CreateCompatibleBitmap(pDC, sourceImage->GetWidth(), sourceImage->GetHeight());
dispDC->SelectObject(this->dispBMP);
Run Code Online (Sandbox Code Playgroud)
实际复制translatedImage数组中的像素时会发生以下情况:
dispBMP->SetBitmapBits(sourceImage->GetArea() * 4, translatedImage);
Run Code Online (Sandbox Code Playgroud)
经过一些处理之后,我打电话pDC->StretchBlt给dispDC作为源CDC.这在本地登录时工作正常,因为显示也设置为32bpp.
一旦我使用远程桌面登录,显示屏将变为16bpp并且图像被破坏.罪魁祸首是SetBitmapBits; 即为了它的工作,我必须正确填写translatedImage我想要显示的16bpp版本.我没有自己这样做,而是搜索了文档,发现SetDIBits它听起来像我想要的那样:
SetDIBits函数使用在指定DIB中找到的颜色数据设置兼容位图(DDB)中的像素.
在我的例子中,DIB是32bpp RGBA数组,而DDB是dispBMP我创建的CreateCompatibleBitmap.
所以不是我的号召SetBitmapBits,这就是我所做的:
BITMAPINFO info;
ZeroMemory(&info, sizeof(BITMAPINFO));
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biBitCount = 32;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = sourceImage->GetArea()*4;
info.bmiHeader.biWidth = sourceImage->GetWidth();
info.bmiHeader.biHeight = sourceImage->GetHeight();
info.bmiHeader.biClrUsed = 0;
int r = SetDIBits(pDC->GetSafeHdc(), (HBITMAP)dispBMP,
0, …Run Code Online (Sandbox Code Playgroud) 好吧,整个故事是,我试图在C++中使用Leptonica + Tesseract OCR截取屏幕截图,将其保存为*.bmp文件,然后将其加载回OCR.我不需要经常这样做,但由于我似乎无法将屏幕截图数据直接复制到Leptonica PIX结构中,我需要先将其保存到文件中......实际上,最好是解决这个问题.
这是我在网上找到的一些代码,试图帮助我.
屏幕上限:
HBITMAP ScreenCapture(){
int width=100;
int height=100;
// get the device context of the screen
HDC hScreenDC = CreateDC(L"DISPLAY", NULL, NULL, NULL);
// and a device context to put it in
HDC hMemoryDC = CreateCompatibleDC(hScreenDC);
int x = GetDeviceCaps(hScreenDC, HORZRES);
int y = GetDeviceCaps(hScreenDC, VERTRES);
// maybe worth checking these are positive values
HBITMAP hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);
// get a new bitmap
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, width, height, …Run Code Online (Sandbox Code Playgroud) 我正在开发一个程序,该程序将有许多 DIB 位图(由 创建CreateDIBSection),并且必须使用 Win API 在它们上绘制大量文本。
为了在位图上绘图,Windows 需要由CreateCompatibleDC.
现在有两种方法:
我可以为每个位图创建一次 DC,用它来绘制并在释放位图时将其删除。
或者,只有当我需要绘制位图、调用绘制函数并删除 DC 时,我才可以创建 DC。
更好的方法是什么?我更喜欢第一个,因为调用较少 - 这将使我的代码更小并且速度更快一些。
但是为每个位图持有一个长期存在的 DC 是不是太昂贵了?
Edit1:该应用程序实际上是一个 GUI 工具包库,将来可以以不同且不可预测的方式使用,因此我需要一个平衡的决策,以实现最大可能的性能和最小的系统资源使用。
MSDN表示GetDiBits在调用此函数之前,不应将用于的位图选择为DC.但是从我的经验来看,BitBlt我知道除非选择了位图,否则我无法绘制位图.
GetDiBits绕过这个?我可以使用未选择的,新创建的位图作为此函数的参数吗?GetDiBits并CreateDibSection返回一个数组.但是MSDN谈到了第一个功能:
"指定的兼容位图的位"
我认为DI代表DeviceIndependent.为什么会出现矛盾?这意味着,根据MSDN,GetDiBits只能用CreateCompatibleBitmap(哪个是DD)?然后我不能将这个数组发送到另一台机器来显示它,对吗?
CreateDibSection真的是DIndependent为什么它需要一个hDC?所有需要的信息都是通过bitmapinfoheader提供的......我有一个实时OpenGL应用程序渲染一些纹理对象.我已经构建了一个函数来通过PFD_DRAW_TO_BITMAP将它渲染到DIB并将其复制到图像来制作渲染场景的内部屏幕截图.除了一种纹理外,它的效果非常好.这些是具有24bpp的JPG(因此每个R,G,B为8位).我可以加载它们并实时正确渲染,但不能渲染到DIB.对于其他纹理,效果很好.在虚拟机上测试我的应用程序时,我有相同的行为(WinXP,没有硬件加速!).这些特定的纹理甚至没有在实时渲染中显示.如果没有硬件加速,我猜WinXP使用自己的OpenGL软件实现,并回归到OpenGL 1.1.那么有没有3D硬件加速不能绘制的纹理?还是有一个常见的陷阱?