我正在开发一个API来缓存用C ++编写的GDI对象,我在其中实现了模仿win32 API的不同Create方法。一种这样的方法是CreateDIBPatternBrushPt()
,它将VOID*
输入到打包的DIB中。 VOID*
包含BITMAPINFO
结构,紧接着是定义位图像素的字节数组。我对打包的DIB进行了一些研究。根据书籍编程Windows,以及维基百科,长度等于行长度biHeight
(BITMAPINFOHEADER
的成员)的乘积,其中:
RowLength = 4 * ((bmi.bcWidth * bmi.bcBitCount + 31) / 32) ;
所以,目前我的想法是做这样的事情:
//copy BIMAPINFO to access width and height
//lpPackedDIB is the VOID* parameter of CreateDIBPatternBrushPt()
BITMAPINFO tmpBitmapInfo;
std::memcpy(&tmpBitmapInfo, lpPackedDIB, sizeof(BITMAPINFO));
//copy entire packed DIB
int rowLength = 4 * ((tmpBitmapInfo.bmiHeader.biWidth * tmpBitmapInfo.bmiHeader.biBitCount + 31) / 32);
std::memcpy(m_pPackedDIB, lpPackedDIB, sizeof(BITMAPINFO) + rowLength * std::abs(bitmapInfo.bmiHeader.biHeight));
这看起来像是一种有效的方法吗?我还想知道使用lpPackedDIB
的人来自哪里CreateDIBPatternBrushPt()
,以便我可以正确地测试这个逻辑。
编辑:
参考文献: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183493(v=vs.85).aspx https://en.wikipedia.org/wiki/BMP_file_format#File_structure https://www-user.tu-chemnitz.de/~heha/petzold/ch15b.htm(特别是“The DIB Pixel Bits”部分)
答案 0 :(得分:0)
此答案之前已发布,但由于某种原因被删除。它并没有直接解决这个问题,但它可以很好地洞察我所面临的问题。感谢用户:Barmak Shemirani。
您只需使用
获取CreatePatternBrush
从HBRUSH
HBITAMP
即可或使用
CreateDIBPatternBrushPt
。但请注意,打包的dib只有14个字节,因为它不需要BITMAPFILEHEADER
。这使得它非常适用于非常小的刷子。例如2x1绿/黑刷:typedef struct { BITMAPINFOHEADER header; unsigned char bits[2 * 1 * 4]; } DIBSTRUCT; const DIBSTRUCT dib = { { sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }, { 0,0xff,0,0, 0,0,0,0 } }; HBRUSH hbrush = CreateDIBPatternBrushPt(&dib, DIB_RGB_COLORS);
您也可以从位图文件制作画笔。分配dib,为
BITMAPINFOHEADER
和颜色表添加空间。然后复制BITMAPINFOHEADER
,然后复制颜色表(如果有),然后复制像素。例如:HBRUSH getbrush(HBITMAP hbitmap) { BITMAP bm; GetObject(hbitmap, sizeof(bm), &bm); int colorCount = 0; if (bm.bmBitsPixel == 1) colorCount = 2; if (bm.bmBitsPixel == 4) colorCount = 16; if (bm.bmBitsPixel == 8) colorCount = 256; RGBQUAD rgb[256]; if (colorCount) { HDC memdc = CreateCompatibleDC(NULL); HGDIOBJ oldbitmap = SelectObject(memdc, hbitmap); GetDIBColorTable(memdc, 0, colorCount, rgb); SelectObject(memdc, oldbitmap); DeleteDC(memdc); } BITMAPINFOHEADER bminfo = { sizeof(BITMAPINFOHEADER), bm.bmWidth, bm.bmHeight, 1, bm.bmBitsPixel, BI_RGB, 0, 0, 0, 0, 0 }; DWORD size = ((bm.bmWidth * bm.bmBitsPixel + 31) / 32) * 4 * bm.bmHeight; char *dib = new char[sizeof(BITMAPINFOHEADER) + colorCount * 4 + size]; memcpy(dib, &bminfo, sizeof(BITMAPINFOHEADER)); memcpy(dib + sizeof(BITMAPINFOHEADER), rgb, colorCount * 4); memcpy(dib + sizeof(BITMAPINFOHEADER) + colorCount * 4, bm.bmBits, size); HBRUSH hbrush = CreateDIBPatternBrushPt(dib, DIB_RGB_COLORS); //clearnup DeleteObject(hbitmap); delete[]dib; return hbrush; }