2016-03-28 70 views
-1

我正在開發一個API來緩存用C++編寫的GDI對象,其中我實現了模仿win32 API的不同Create方法。一種這樣的方法是CreateDIBPatternBrushPt(),其將VOID*接入打包的DIB。 VOID*包含一個BITMAPINFO結構,緊接着是一個定義位圖像素的字節數組。我對打包的DIB做了一些研究。根據這本書,Windows程序設計,以及維基百科的長度等於行長度的產品和biHeight(的BITMAPINFOHEADER成員),其中:從打包的DIB void pointer複製

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像素的位數」 部分)

+1

的'VOID *'肯定不包含但地址,可能是一個'BITMAPINFO'的。所以,你的問題歸結爲如何解釋打包的DIB,對吧?如果是這樣,請相應地調整標題和問題。現在,關於您的進一步問題,該方法看起來有效。關於最後一個問題,你定義了邏輯,你定義了它的工作原理,爲什麼你不能爲它定義測試數據?一個建議:不要試圖一次解決太多問題。你放鬆焦點,只會變得更加困惑。 –

+0

@UlrichEckhardt VOID *只是一個指向BITMAPINFO的指針,儘管緊接着是一串字節數組,其大小我不確定。這個等式是有道理的,但我沒有辦法驗證它會成功複製所有提供的字節,因爲我沒有任何示例數據可用。我發現由邏輯定義的測試數據會使其通過是反生產的。 謝謝你的關注,我絕對覺得我在這方面有點太過於費勁,但這一切都在這個非常具體的任務範圍之內。 :) –

回答

0

這個答案之前發佈,但取下來出於某種原因。它並沒有直接解決這個問題,但它對我所面臨的問題提供了很好的見解。授予用戶:Barmak Shemirani

您可以簡單地使用CreatePatternBrushHBITAMP

得到HBRUSH或者使用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); 

您也可以使用位圖文件進行畫筆。分配二進制,爲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; 
}