LoadImage基于win颜色设置工作不同

嗨,我正在使用loadImage加载一个24位的BMP文件,然后尝试获取BMP信息

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

当我做相同的操作与Windows彩色显示设置32喜颜色比我有以下值bmBitsPixel = 32但如果我设置窗口颜色显示为16比我得到bmBitsPixel = 16

任何人都可以解释一下是什么意思。 我如果我用下面的公式来计算的bmp的大小比bmp的大小取决于窗口的颜色设置。

size = bmWidth * bmHeight * bmBitsPixel / 8

感谢致敬

HBITMAP是一个依赖于设备的位图 :其内部表示取决于屏幕的颜色格式。

因此,如果将显示颜色格式设置为每像素(bpp)32位,则位图将使用32 bpp。 如果您将颜色格式切换为16 bpp,则位图将随后使用16 bpp。

你的公式是正确的,你必须在计算位图大小时考虑bmBitsPixel

当使用LoadImage API时,HBITMAP可以通过指定LR_CREATEDIBSECTION标志和其他标志来加载为设备无关位图 – 如果没有它,Windows将转换为设备相关的位图。 这只有在源图像是32BPP位图时才起作用。 较低的比特率(8BPP,16BPP,24BPP等)将被装载EXACT位平面/颜色深度 – 必须转换为显示器的颜色深度才能实际显示。

因为没有处理发生,你可能会得到一个32BPP的BMP不预先乘alpha-rendering(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)。

LoadImage函数不起作用,因为它需要一个正高度。 一些位图图像以高度值保存,以便图像将从左下角开始。 LoadImage函数VC ++ 6.0 MFC没有编程负高度,所以它失败,只是返回NULL。 只要将结构BITMAPINFOHEADER中的biheight更改为正值即可。 然后LoadImage将打开几乎任何位图8位,24位或32位与积极biheight。

 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(...)