从压缩的DIB无效指针

时间:2016-03-28 14:03:51

标签: c++ winapi gdi dib

我正在开发一个API来缓存用C ++编写的GDI对象,我在其中实现了模仿win32 API的不同Create方法。一种这样的方法是CreateDIBPatternBrushPt(),它将VOID*输入到打包的DIB中。 VOID*包含BITMAPINFO结构,紧接着是定义位图像素的字节数组。我对打包的DIB进行了一些研究。根据书籍编程Windows,以及维基百科,长度等于行长度biHeightBITMAPINFOHEADER的成员)的乘积,其中:

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”部分)

1 个答案:

答案 0 :(得分:0)

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

  

您只需使用CreatePatternBrushHBRUSH

获取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;
}