2010-06-29 69 views
0

我一直試圖在8bpp灰度位圖上繪製沒有成功。這是我的一些嘗試。也許有人可以指出我做錯了什麼。使用8bpp灰度位圖(非託管C++)

============================================== =====

嘗試1:創建,選擇和繪製:

在構造:

CBitmap bm; 
bm.CreateBitmap (200, 200, 1, 8, NULL); 

在OnDraw中:

CDC *mdc=new CDC(); 
HGDIOBJ tmp = mdc->SelectObject(bm); 

結果:TMP是NULL,指示失敗。

============================================== =====

嘗試2:CreateDIBSection

在構造:

HBITMAP hbm; 
BITMAPINFOHEADER bih; 
BITMAPINFO bi; 
HANDLE hb; 
CDC* myDc = new CDC(); 
HDC hdc = myDc->GetSafeHdc(); 
void* bits; 
RGBQUAD rq [256]; 

initBi(); 
hbm = CreateDIBSection (hdc, &bi, DIB_RGB_COLORS, &bits, NULL, 0); 

... 

void CEightBitDrawingView::initBi() 
{ 
bih.biSize = sizeof (BITMAPINFOHEADER); 
bih.biWidth = 200; 
bih.biHeight = -200; 
bih.biPlanes = 1; 
bih.biBitCount = 8; 
bih.biCompression = BI_RGB; 
bih.biSizeImage = 0; 
bih.biXPelsPerMeter = 14173; 
bih.biYPelsPerMeter = 14173; 
bih.biClrUsed = 0; 
bih.biClrImportant = 0; 

memset ((void *) rq, 0, 256 * sizeof (RGBQUAD)); 

bi.bmiHeader = bih; 
bi.bmiColors = rq; 
} 

結果:該甚至不編譯,因爲BITMAPINFO bmiColors構件被定義爲: RGBQUAD bmiColors [1] ;

所以不會接受多個RGB顏色。實際上,我沒有分配給這個成員編譯! (他們可能會使它更復雜!?)

任何建議,將不勝感激!謝謝!

============================================== =====

+1

您是否試過GDI +?或者有任何業務不需要? – 2010-06-29 15:47:22

+0

我將我在GDI +中的工作示例轉換爲非託管C++/GDI以提高速度。在GDI中獲取8bpp位圖非常困難。 – user20493 2010-06-29 16:02:26

+0

GDI +不受管理。這是一個建立在win32上的C++庫。託管將是WinForms或WPF。 – Cogwheel 2010-06-29 16:11:37

回答

0

您的位圖需要與您要渲染的顯示上下文兼容(相同的顏色深度)。此外,8位/像素位圖不一定是灰度 - 這是您使用的調色板的功能。

+0

8bpp位圖將包含另一個應用程序的CYMK位圖的組件,所以我不希望它們與顯示器兼容。 我不在乎調色板,但Windows迫使我處理它以獲取8bpp位圖。 – user20493 2010-06-29 15:59:15

4

這裏。演示如何在未管理的世界中的代碼在堆棧中分配動態大小的結構,並將其填充並傳遞給CreateDIBSection。

#include <malloc.h> 

HBITMAP CreateGreyscaleBitmap(int cx, int cy) 
{ 
    BITMAPINFO* pbmi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256); 
    pbmi->bmiHeader.biSize = sizeof (pbmi->bmiHeader); 
    pbmi->bmiHeader.biWidth = cx; 
    pbmi->bmiHeader.biHeight = cy; 
    pbmi->bmiHeader.biPlanes = 1; 
    pbmi->bmiHeader.biBitCount = 8; 
    pbmi->bmiHeader.biCompression = BI_RGB; 
    pbmi->bmiHeader.biSizeImage = 0; 
    pbmi->bmiHeader.biXPelsPerMeter = 14173; 
    pbmi->bmiHeader.biYPelsPerMeter = 14173; 
    pbmi->bmiHeader.biClrUsed = 0; 
    pbmi->bmiHeader.biClrImportant = 0; 

    for(int i=0; i<256; i++) 
    { 
    pbmi->bmiColors[i].rgbRed = i; 
    pbmi->bmiColors[i].rgbGreen = i; 
    pbmi->bmiColors[i].rgbBlue = i; 
    pbmi->bmiColors[i].rgbReserved = 0; 
    } 

    PVOID pv; 
    return CreateDIBSection(NULL,pbmi,DIB_RGB_COLORS,&pv,NULL,0); 
} 
+0

「BITMAPINFO」結構大小的計算錯誤。由於任何特定平臺/體系結構的對齊規則,它沒有考慮填充。編譯器可以使用[offsetof](https://msdn.microsoft.com/en-us/library/dz4y9b9a.aspx)宏來計算正確的大小:'alloca(offsetof(BITMAPINFO,bmiColors [256])); '。這個博客條目解釋了基本原則:[爲什麼某些結構以大小爲1的數組結尾?](https://blogs.msdn.microsoft.com/oldnewthing/20040826-00/?p=38043)。 – IInspectable 2016-09-24 11:36:33

2

在這兩個你的例子,你創建了一個新CDC與以下行:

CDC* pDC = new CDC(); 

但有若有所失:這將只需要創建一個新的CDC對象,但沒有有效的HDC柄連接到它。您需要先調用CDC :: CreateCompatibleDC,否則試圖選擇任何對象到此DC將失敗。

關於bmiColors:該成員被定義爲1大小的數組,因爲它後面的數據取決於位圖的顏色深度和類型。這在MSDN中有記錄。舉例來說,如果你有一個128×128像素的8位位圖,你就必須分配MEM的數額如下:

128 * 128 * sizeof(WORD) + sizeof(BITMAPINFOHEADER) 
0

我終於祭出使用.NET的圖形工具(Aurigma)來創建一個8bpp的位圖,將其句柄傳遞給非託管C++。

然後在C++:

HDC memDc = CreateCompatibleDC (NULL);  
HGDIOBJ Obmp = ::SelectObject(memDc, varLayer); // Handle to 8-bit bitmap. 

我能選擇位圖到CDC和借鑑它。不是100%不受管理的,但是這允許我在非託管代碼中進行繪圖,這給出了可接受的速度。