2010-10-26 20 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(...) 
相关问题