Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C LoadImage的工作方式因win颜色设置而异_C_Windows_Gdi - Fatal编程技术网

C LoadImage的工作方式因win颜色设置而异

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执行相同的操作时,我得到了以下值

嗨, 我正在使用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执行相同的操作时,我得到了以下值 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。