C LoadImage的工作方式因win颜色设置而异
嗨, 我正在使用loadImage加载24位bmp文件,然后尝试获取bmp信息C LoadImage的工作方式因win颜色设置而异,c,windows,gdi,C,Windows,Gdi,嗨, 我正在使用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 hi color执行相同的操作时,我得到了以下值
hBitmap = (HBITMAP)LoadImage(NULL, "logo.bmp", IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_DEFAULTSIZE)
GetObject( hBitmap, sizeof(BITMAP), &bm );
当我对windows颜色显示设置32 hi color执行相同的操作时,我得到了以下值
bmBitsPixel=32,但如果我将windows颜色显示设置为16,则得到
bmBitsPixel=16
谁能解释一下这是什么意思吗。
如果我使用以下公式计算bmp的大小,则bmp的大小取决于窗口颜色设置
大小=bmWidth*bmHeight*bmBitsPixel/8
感谢并问候一个
HBITMAP
是一个:它的内部表示取决于屏幕的颜色格式
因此,如果将显示颜色格式设置为每像素32位(bpp),则位图将使用32 bpp。如果将颜色格式切换为16 bpp,位图将跟随并使用16 bpp
公式正确,计算位图大小时必须考虑
bmBitsPixel
。一个HBITMAP
是一个:其内部表示取决于屏幕的颜色格式
因此,如果将显示颜色格式设置为每像素32位(bpp),则位图将使用32 bpp。如果将颜色格式切换为16 bpp,位图将跟随并使用16 bpp
如果公式正确,则在计算位图大小时必须考虑
bmBitsPixel
。使用LoadImage API时,可以通过指定LR_CREATEDIBSECTION标志以及其他标志将HBITMAP加载为与设备无关的位图-如果没有它,Windows将转换为与设备相关的位图。这仅在源图像为32BPP位图时有效。较低的比特率(8BPP、16BPP、24BPP等)将加载精确的位平面/颜色深度-必须将其转换为显示器的颜色深度才能实际显示
由于不进行任何处理,您可能会得到一个32BPP的BMP,该BMP不会在alpha渲染(AlphaBlend()函数)中进行预乘,因此您将获得彩色条纹和其他不需要的瑕疵。对于这些情况,您需要对每个像素进行预乘。下面是一个小片段的代码-但不做太多的错误检查。。。在允许执行此代码之前,需要测试位图的平面/颜色深度是否正确。下面有几种方法可以优化代码(例如使用查找表),但这主要是出于解释目的
此代码仅在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 API时,HBITMAP可以作为设备独立位图加载,方法是指定LR_CREATEDIBSECTION标志以及其他标志-不指定它,Windows正在转换为设备相关位图。这仅在源图像为32BPP位图时有效。较低的比特率(8BPP、16BPP、24BPP等)将加载精确的位平面/颜色深度-必须将其转换为显示器的颜色深度才能实际显示 由于不进行任何处理,您可能会得到一个32BPP的BMP,该BMP不会在alpha渲染(AlphaBlend()函数)中进行预乘,因此您将获得彩色条纹和其他不需要的瑕疵。对于这些情况,您需要对每个像素进行预乘。下面是一个小片段的代码-但不做太多的错误检查。。。在允许执行此代码之前,需要测试位图的平面/颜色深度是否正确。下面有几种方法可以优化代码(例如使用查找表),但这主要是出于解释目的 此代码仅在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函数不工作,因为它需要正高度。某些位图图像以-height值保存,以便图像从左下角开始。LoadImage函数VC++6.0 MFC未针对负高度进行编程,因此它将失败并返回NULL。只需将结构BitMapInfo标头中的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(...)
LoadImage函数不工作,因为它需要正高度。某些位图图像以-height值保存,以便图像从左下角开始。LoadImage函数VC++6.0 MFC未针对负高度进行编程,因此它将失败并返回NULL。只需将结构BitMapInfo标头中的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(...)
听起来您不想使用LoadImage()。使用
进行位图操作。但是需要C++。或者从文件中读取BITMAPFILEHEADER+BITMAPINFO。听起来您不想使用LoadImage()。使用
进行位图操作。但是需要C++。或者从文件中读取BITMAPFILEHEADER+BITMAPINFO。