-1

我正在开发一个用 C++ 编写的用于缓存 GDI 对象的 API,我在其中实现了模仿 win32 API 的不同 Create 方法。一种这样的方法是CreateDIBPatternBrushPt(),它将 a 接收VOID*到打包的 DIB 中。VOID*包含一个结构,BITMAPINFO后面紧跟一个定义位图像素的字节数组。我对打包的 DIB 进行了一些研究。根据这本书,Programming Windows 以及 Wikipedia,长度等于行长度和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(特别是“DIB 像素位”部分)

4

1 回答 1

1

此答案之前已发布,但由于某种原因被删除。它没有直接解决这个问题,但它很好地洞察了我所面临的问题。归功于用户:Barmak Shemirani

你可以简单地使用CreatePatternBrushHBRUSHHBITAMP

或使用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;
}
于 2016-04-25T20:43:08.663 回答