2010-10-26 3 views
1

HI, Я использую LoadImage загрузить файл 24bit BMP, а затем попытаться получить ВМР INFO выиграть цветLoadImage исправна разному в зависимости от настройки

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 из файла. –

ответ

1

HBITMAP является device-dependent bitmap: его внутреннее представление зависит от формата цвета экрана.

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

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

0

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

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

0

Функция LoadImage не работает, потому что ей нужна положительная высота. Некоторые растровые изображения сохраняются с -высоким значением, чтобы изображение начиналось в левом нижнем углу. Функция 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(...) 
Смежные вопросы