2010-10-26 19 views
1

HI, 我使用的LoadImage加載一個24位BMP文件,然後試圖讓BMP信息的LoadImage的工作不同的基於win顏色設置

hBitmap = (HBITMAP)LoadImage(NULL, "logo.bmp", IMAGE_BITMAP, 0, 0, 
       LR_LOADFROMFILE | LR_DEFAULTSIZE) 
GetObject(hBitmap, sizeof(BITMAP), &bm); 

當我做窗戶彩色顯示屏相同的操作設置32喜顏色比我得到了下面的值 bmBitsPixel = 32,但如果我設置窗口的顏色顯示,以16比我得到 bmBitsPixel = 16

任何一個可以請解釋這是什麼意思。 我如果我使用下面的公式來計算bmp的大小比bmp的大小取決於窗口的顏色設置。

尺寸= bmWidth * bmHeight * bmBitsPixel/8

感謝和問候

+0

聽起來你不想使用LoadImage()。使用''進行位圖操作。雖然需要C++。或者只是從文件中讀取BITMAPFILEHEADER + BITMAPINFO。 – 2010-10-26 11:02:06

回答

1

一個HBITMAPdevice-dependent bitmap:其內部表示取決於屏幕的顏色格式。

因此,如果您將顯示顏色格式設置爲每像素(bpp)32位,那麼您的位圖將使用32 bpp。如果您將顏色格式切換爲16 bpp,則位圖將隨後使用16 bpp。

您的公式是正確的,在計算位圖大小時必須考慮bmBitsPixel

0

當使用LoadImage API時,通過指定LR_CREATEDIBSECTION標誌以及其他標誌(如果沒有它,Windows正在轉換爲設備相關位圖),可以將HBITMAP作爲設備無關位圖進行加載。這隻有在源圖像是32BPP位圖時纔有效。較低比特率(8BPP,16BPP,24BPP等)將裝載EXACT位平面/顏色深度 - 必須將其轉換爲顯示器的顏色深度以實際顯示它。

因爲沒有進行處理,所以您可能會得到一個32BPP BMP,它不是用於alpha渲染(AlphaBlend()函數)的預乘,所以會出現色邊和其他不需要的工件。對於這些情況,您需要對每個像素進行預乘。以下是一小段代碼 - 但不會做太多的錯誤檢查......您需要在允許此代碼執行之前測試BITMAP具有正確的平面/顏色深度。有幾種方法可以優化下面的代碼(例如使用查找表),但這主要是爲了解釋目的。

這個密碼只能工作,如果bm.bmBits指針不爲NULL,bm.bmPlanes等於1,和bmBitsPixel等於32:

RGBQUAD* lprgbSrc = (RGBQUAD*)bm.bmBits; 
if(lprgbSrc) 
{ 
    RGBQUAD* lprgbEnd = (RGBQUAD*)((size_t)lprgbSrc + (size_t)bm.bmHeight*bm.bmWidthBytes); 
    while(lprgbSrc != lprgbEnd) 
    { 
    switch(lprgbSrc->rgbReserved) 
    { 
    case 255: // Pixel at full opacity - no color shift required... 
     break; 
    case 0: // Pixel at full transparency - must go full black 
     *(DWORD*)lprgbSrc = 0; 
     break; 
    // Need to pre-multiply by the alpha (rgbReserved) and 
    // divide by 255 to get a correct brightness level for correct 
    // rendering of the color when mixed on top of the background 
    default: 
     lprgbSrc->rgbRed = ((size_t)lprgbSrc->rgbRed * (size_t)lprgbSrc->rgbReserved) /255; 
     lprgbSrc->rgbBlue = ((size_t)lprgbSrc->rgbBlue * (size_t)lprgbSrc->rgbReserved) /255; 
     lprgbSrc->rgbGreen = ((size_t)lprgbSrc->rgbGreen * (size_t)lprgbSrc->rgbReserved) /255; 
     break; 
    } 
    lprgbSrc++; 
    } 
} 

注意,某些Windows GDI函數接受非預乘HBITMAP(ImageList中例如)應用某些標誌時。

0

LoadImage函數不起作用,因爲它需要一個正高度。一些位圖圖像以高度值保存,以便圖像將從左下角開始。 LoadImage函數VC++ 6.0 MFC未被編程爲負高度,因此失敗並僅返回NULL。只需將結構BITMAPINFOHEADER中的biheight更改爲正值即可。然後,LoadImage將打開幾乎任何位圖8位,24位或32位,正向雙高。

BITMAPFILEHEADER m_bmfHeader; 
BITMAPINFOHEADER m_bi; 

HANDLE hFile = CreateFile(image_filename, 
       GENERIC_READ, 
       0, 
       NULL,OPEN_EXISTING, 
       FILE_ATTRIBUTE_NORMAL, NULL); 

if(hFile == INVALID_HANDLE_VALUE) 
{ 
    AfxMessageBox("Cannot Open a New File"); 
    return; 
} 

DWORD dwBytesWritten = 0; 

ReadFile(hFile, (LPSTR)&m_bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 

ReadFile(hFile, (LPSTR)&m_bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 

int m_nSizeImage = m_bi.biSizeImage; 
BYTE *lpbitmap; 
lpbitmap = (BYTE*)malloc(m_nSizeImage); 

ReadFile(hFile, (LPSTR)lpbitmap, m_nSizeImage, &dwBytesWritten,NULL); 
CloseHandle(hFile); 

hFile = CreateFile(image_filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 

DWORD dwBytesWritten = 0; 
m_bi.biHeight = (int)fabs(m_bi.biHeight); //Height Always Positive!!! 

WriteFile(hFile, (LPSTR)&m_bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 
WriteFile(hFile, (LPSTR)&m_bi, sizeof(BITMAPINFOHEADER),&dwBytesWritten, NULL); 

WriteFile(hFile, (LPSTR)lpbitmap, m_bi.biSizeImage, &dwBytesWritten, NULL); 
CloseHandle(hFile); 
free(lpbitmap); // Now you can use the LoadImage(...) 
相關問題