Вопрос № 82944: Добрый день.
Тут столкнулся с проблемкой при работе с битмапами. Мне надо получить биты битмапа из HBITMAP. Кроме функции GetDIBits ничего не нашел... (а загружать с помощью GetPixel цвета себе дороже). Об изображении изначально ничего неизвестно...
Вопрос № 82.944
Добрый день.
Тут столкнулся с проблемкой при работе с битмапами. Мне надо получить биты битмапа из HBITMAP. Кроме функции GetDIBits ничего не нашел... (а загружать с помощью GetPixel цвета себе дороже). Об изображении изначально ничего неизвестно, поэтому получаем о нем инфу:
BITMAPINFO bmpi = {};
bmpi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
if(GetDIBits(GetWindowDC(0), bitmap, 0, 0, NULL, &bmpi, DIB_RGB_COLORS) == 0){ //Ошибка
}
Тут все работает норм, он заполняет структуру. Теперь пытаемся получить биты:
char* buffer = new char[BitmapInfo.bV5SizeImage];
if(GetDIBits(GetWindowDC(0), bitmap, 0, BitmapInfo.bV5Height, (void*)buffer, &bmpi, DIB_RGB_COLORS) == 0){/*Ошибка*/}
Запускаю. В итоге получаю сообщение следующего содержания: Run-Time Check Failure #2 - Stack Around the variable 'bmpi' was corrupted. (при выходе из функции, естественно). В режиме Debug смотрю: биты он загрузил нормально, все в порядке, но вот только переменная bmpi, которую он теоретически не должен трогать вообще, почему-то изменила содержание. Как функция WinAPI могла испортить переменную bmpi? Или я все-таки что-то не так сделал?
Приложение:
Отправлен: 17.04.2007, 13:10
Вопрос задал: Mystic (статус: 6-ой класс)
Всего ответов: 1 Мини-форум вопроса >>> (сообщений: 5)
Отвечает: Gremlin
Здравствуйте, Mystic!
Во первых, не правильно используется функция GetDIBits, первый её параметр должен содержать девайс, в который выбран битмап(второй параметр).
Во вторых, использование такого кода вообще недопустимо:
GetDIBits(GetWindowDC(0), ...)
Функции GetWindowDC должна вызываться парная ей ReleaseDC
В третьих, буфер, заполняемый GetDIBits, должен быть достаточно большой, чтобы вместить все линии(scan-lines) битмапа, это довольно просто посчитать:
bits_per_line = width*bpp;
dwords_per_line = bits_per_line/32;
if(bits_per_line%32){
dwords_per_line++;
}
bytes_per_line = dwords_per_line*4;
где
width - ширина битмапа в пикселах
bpp - количество бит на пиксел(1, 4, 8, 16, 24 или 32, в зависимости от формата битмапа)
теперь размер буфера можно считать равным lines*bytes_per_line байт, где lines - это четвертый параметр функции GetDIBits
Run-Time Check Failure #2 - Stack Around the variable 'bmpi' was corrupted - эта ошибка говорит о том, что в переменную 'bmpi', расположенную в стеке была произведена несанкционированная запись. В данном случае это, скорее всего значит, что bmpi не BITMAPINFO, а нечто меньшее, т.е. здесь следует обратить внимание на biSize и число битов на пиксел: если оно не равно 24 или 32, то GetDIBits считает, что после заголовка должна идти таблица цветов, определяемая членом biClrUsed и biClrImportant.
Ответ отправил: Gremlin (статус: 2-ой класс)
Ответ отправлен: 17.04.2007, 19:44 Оценка за ответ: 4 Комментарий оценки: Читаем МСДН: 1)GetWindowDC(0) возвращает хэндл окна приложения. 2)Буфер выделяется в достаточном объеме (функция даже все нормально возвращает) Проблема только в том, что функция почему-то портит переменную при втором вызове. В общем, все правильно вроде