LoadImage работает по-разному в зависимости от настройки цвета win - PullRequest
1 голос
/ 26 октября 2010

HI, Я использую 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 зависит от настройки цвета окна.

размер = bmWidth * bmHeight * bmBitsPixel / 8

Спасибо и всего наилучшего

Ответы [ 3 ]

1 голос
/ 26 октября 2010

HBITMAP - это зависящее от устройства растровое изображение : его внутреннее представление зависит от цветового формата вашего экрана.

Соответственно, если вы установите цветовой формат отображения 32 бита на пиксель (bpp), то ваше растровое изображение будет использовать 32 bpp. Если вы переключите формат цвета на 16 бит / с, растровое изображение будет следовать и использовать 16 бит / с.

Ваша формула верна, необходимо учитывать bmBitsPixel при расчете размера растрового изображения.

0 голосов
/ 23 апреля 2015

Функция LoadImage не работает, потому что ей нужна положительная высота. Некоторые растровые изображения сохраняются со значением -height, поэтому изображение начинается в левом нижнем углу. Функция LoadImage VC ++ 6.0 MFC не была запрограммирована для отрицательных высот, поэтому она не работает и просто возвращает NULL. Просто измените biheight в структуре BITMAPINFOHEADER на положительное значение. После этого 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(...)
0 голосов
/ 21 февраля 2015

HBITMAP может быть загружен как независимая от устройства битовая карта при использовании API-интерфейса LoadImage, указав флаг LR_CREATEDIBSECTION вместе с другими флагами - без него Windows преобразуется в зависимую от устройства битовую карту. Это будет работать только тогда, когда исходное изображение является растровым изображением 32BPP. Более низкие битовые скорости (8BPP, 16BPP, 24BPP и т. Д.) Будут загружаться с EXACT-битовыми плоскостями / глубинами цвета - которые необходимо будет преобразовать в глубину цвета монитора, чтобы фактически отобразить ее.

Поскольку никакой обработки не происходит, вы можете получить BMP 32BPP, который предварительно не умножается для альфа-рендеринга (функция 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), когда применяются определенные флаги.

...