我的纯Win32项目中有一个HBITMAP(没有使用外部库).我可以仅使用Winapi和/或CRT函数将其导出到*.bmp文件,因此我不会产生任何额外的依赖关系吗?
我有一个应用程序,它从数据库中加载一些blob数据,可以表示各种位图和图标的png格式或原始二进制数据.这是存储在std::vector<unsigned char>
我正在使用CImageList对象在树视图,工具栏图像等中显示各种图像,但问题是从内存中的数据创建位图会变得模糊,好像它在执行如下操作时缺少像素:
std::vector<unsigned char> bits;
HBITMAP hbitmap = CreateBitmap(16, 16, 1, 32, bits.data());
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我现在只需将向量中的data()写入临时文件,然后使用LoadImage将其读回并从中创建HBITMAP.这是完美的,但无可否认,这是一个无耻的黑客,我希望完全没必要.
我在网上环顾四周,但没有找到任何关于如何"正确"从内存创建hbitmaps的好例子.我希望能够创建这些位图,以便添加到图像列表中,而无需任何文件i/o和有限数量的复制数据(如果可能).
寻找最好的方法来做到这一点,显然Windows特定的代码是好的.
更新:
根据jdv的回答,我开始使用CreateCompatibleBitmap,CreateDIBitmap,最后是CreateDIBSection.所有这些最终创建了可爱的黑色位图,而不是之前的模糊位图,所以我必须再次做错了我的猜测是因为这个位图创建是在一个没有屏幕直流或窗口概念的对象中完成的,使用GetDC(NULL)和CreateCompatibleDC(NULL)不好.示例代码:
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biHeight = 16;
bmi.bmiHeader.biWidth = 16;
bmi.bmiHeader.biPlanes = 1;
HDC dc = CreateCompatibleDC(NULL);
HBITMAP hbitmap = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, (void**)blobData.GetMember<FILEDATAFIELD_DATA>().data(), NULL, 0);
Run Code Online (Sandbox Code Playgroud)
我现在当然认为必须有一个更简单的方法来解决这个问题,或许完全避免使用HBITMAP并直接与CBitmap班级合作?当它归结为将图像添加到CImageList我正在使用CBitmap::FromHandle(HBITMAP hbitmap, COLORREF mask)的时候.有谁知道CBitmap从一个初始化对象的简单方法std::vector<unsigned char>?
既然不推荐使用QPixmap :: toWinHBITMAP(),我找不到从QPixmap(或QImage)获取HBITMAP的方法.
谷歌搜索,我发现有一个名为qt_pixmapToWinHBITMAP()的函数似乎可以做我需要的,但我找不到我应该启用的模块-if any-在我的.pro文件中或者我应该包含哪些标题来使用它,或者也许别的东西.
我需要HBITMAP的原因是使用VFW创建视频.当然,我很乐意只使用Qt来做到这一点.有QtMultimedia模块,但据我所知,它不会导出视频,所以我想我一直坚持使用windows api.
任何帮助,将不胜感激.
我有一个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) 有谁知道如何使用HBITMAP变量来编写png或jpeg文件?
我首先考虑用GDI +做这个,但是它给我错误告诉我min/max还没有被定义(定义它们只会带来更多问题),然后我查看了libpng的C++绑定(png ++)并且无法得到示例编译.
谢谢,
米奇
是否可以仅使用WINAPI函数将*.bmp文件加载到Win32项目中的HBITMAP中?
我试图将hBitmap转换为字节数组,但我不想使用单位Graphics的TBitmap.我的输入图像是128x64x32bit.
var TheBits: array of array of Cardinal;
begin
with info.bmiHeader do begin
biWidth:=131;
biHeight:=64;
biSize:=SizeOf(TBITMAPINFOHEADER);
biCompression:=BI_RGB;
biBitCount:=32;
biPlanes:=1;
biSizeImage:=0;
end;
DC := CreateCompatibleDC(0);
SetLength(TheBits, 128, 64);
GetDIBits(DC, BmpHandle, 0, 64,@TheBits[0][0],Info,DIB_RGB_COLORS);
Run Code Online (Sandbox Code Playgroud)
这给了我一个很好的形象(当然是颠倒的),但我不得不把131放入biWidth,这对我来说并没有多大意义.为什么不能是128?
使用位图对我来说是一个很新的事情,所以我一直在努力学习我已经阅读过的在线教程和策略.基本上我的目标是扫描屏幕上的特定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, …Run Code Online (Sandbox Code Playgroud) 我有一些处理,我需要关闭它.代码中有一些地方可以关闭句柄.那么,这是一个正确的关闭方式吗?
HANDLE h;
....
if ( h != INVALID_HANDLE_VALUE ) {
::CloseHandle(h);
h = INVALID_HANDLE_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
关于位图句柄有一个相同的问题:
HBITMAP hb;
....
if ( hb != INVALID_HANDLE_VALUE ) {
::DeleteObject(hb);
hb = INVALID_HANDLE_VALUE;
}
Run Code Online (Sandbox Code Playgroud)
编辑:我想,有一些误解.我知道CloseHandle是关闭手柄.我想知道关闭手柄的正确方法.删除指针时会出现类似的情况.
Foo *foo = new Foo();
// for example there is 2 functions that can delete foo
void bar() {
....
delete foo;
}
void duck() {
....
delete foo;
}
Run Code Online (Sandbox Code Playgroud)
因此,以下代码意味着问题:
bar();
duck();
Run Code Online (Sandbox Code Playgroud)
这种情况有一些解决方法.我们需要定义bar和这样的duck函数:
void bar() {
....
if (foo) …Run Code Online (Sandbox Code Playgroud) 在我的仅限Windows的程序中,我使用第三方库,它返回一个HBITMAP.
有没有办法QImage从其内容初始化a ,即将其转换为QImage?