Здравствуйте всем!
Необходимо из bmp извлечь пиксели (RGB) в массив (С++).
Уже весь день лазил по форумам, вот что получилось: (чтобы упростить себе задачу решил считать хотябы первую линию bmp (1024 пикселя в картинке 1024х768))
void LoadBmpInMemory(LPCWSTR szFileName) //name пока что не использую { static HBITMAP hbitmap; BITMAP BitMap; HANDLE hObj = LoadImage( NULL,L"Desert.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); if ( ( HBITMAP)hObj == NULL) { ::MessageBox( NULL, __T( "LoadImage Failed"), __T( "Error"), MB_OK); //это сообщение не выбивается } HDC hdc = CreateCompatibleDC( NULL); SelectObject( hdc, ( HBITMAP)hObj); GetObject( ( HBITMAP)hObj, sizeof( BITMAP), &BitMap); BITMAPINFO bInfo; WIDTH=BitMap.bmWidth; HEIGHT=BitMap.bmHeight; bInfo.bmiHeader.biSize =sizeof( bInfo.bmiHeader); //эта штука 40 байт bInfo.bmiHeader.biWidth = BitMap.bmWidth*4; //это ширина в байтах изображения bInfo.bmiHeader.biHeight = BitMap.bmHeight*4; //это высота в байтах bInfo.bmiHeader.biBitCount = 32; //это количество бит на пиксель bInfo.bmiHeader.biPlanes = 1; bInfo.bmiHeader.biCompression = BI_RGB; bInfo.bmiHeader.biSizeImage = BitMap.bmHeight * BitMap.bmWidth * 4; //это общий размер растра BYTE tempScanLine[1024*4]; //тут уже менял 3 на 4 тоже эффекта нету int LineCopy = GetDIBits( hdc, ( HBITMAP)hObj, 0, 1, tempScanLine, &bInfo, DIB_RGB_COLORS); // delete [] tempScanLine; //тут кстати крешится }
В итоге в tempScanLine одинаковые значения - видимо ничего и не присваивалось.
А GetDIBits возвратила 0 - то есть ошибка. =(
Кто хоть что-нибудь подскажет - буду очень признателен. У меня windows 7 x 64
Вот когда то делал загрузку текстур из bmp файлов:
BOOL load_texture(char* filename,GLuint num_tex) { BITMAPFILEHEADER bfh; //Заголовок BMP файла BITMAPINFOHEADER bih; //Заголовок BMP файла GLubyte *TxBits,*buf; // массивы для цветов DWORD nBytesRead; // сколько данных прочтено с файла HANDLE FileHandle; // хендл, открываемого для чтения, файла int width,height; // ширина и высота файла // открываем файл для чтения FileHandle=CreateFile( filename, // имя файла GENERIC_READ, // открыт для чтения 0, // совместного использования нет NULL, // защита по умолчанию OPEN_EXISTING, // только существующий файл FILE_ATTRIBUTE_NORMAL, // атрибуты обычного файла NULL); // шаблона атрибутов нет if ( FileHandle == INVALID_HANDLE_VALUE) // если ошибка при открытии то сообщаем { MessageBox( NULL,"Файл отсутствует!","Ошибка",MB_OK | MB_ICONINFORMATION); return FALSE; } ReadFile( FileHandle,&bfh,sizeof( bfh),&nBytesRead,NULL); //считываем первый заголовок, вообще то он не нужен ReadFile( FileHandle,&bih,sizeof( bih),&nBytesRead,NULL); //считываем второй заголовок // записываем размер рисунка width=bih.biWidth; height=bih.biHeight; buf = new GLubyte[width*height*3]; // выделяем память для исходного рисунка TxBits = new GLubyte[width*height*3]; // выделяем память для получаемого рисунка ReadFile( FileHandle,buf,( width*height*3),&nBytesRead,NULL); //считываем данные о цветах пикселей // в этом цикле меняем структуру цвета, т.к. BMP файл имеет структуру BGR, а нам нужен RGB for ( int i=0;i<( width*height*3);i+=3) { //переписываем массив цветов TxBits[i]= buf[i+2]; TxBits[i+1]= buf[i+1]; TxBits[i+2]= buf[i]; } // тут инициализируется текстура (это место стерто) // ... CloseHandle( FileHandle); // закрываем файл // освобождаем памяти delete [] TxBits; delete [] buf; return TRUE; // возвражаем TRUE если все успешно }
В итоге получаем массив цветов пикселей TxBits в формате [ R ] [ G ] [ B ] [ R ] [ G ] [ B ]... Красивее смотрелось бы со структурами, но для текстур нужен был такой формат.
Правда это работает только для 24-х битных bmp изображений без сжатия.
Посмотри, может чего и полезного вытянешь из этого кода
yamilramilev
Спасибо!
Если не решу первое - придется использовать это.)
По форумам полазил - проблема у многих. Именно с GetDIBits =( Надеюсь найду в чем проблема...чувствую уже близко.
Порылся у себя, вот что нашел, может пригодится:
... mM_Bitmap = (HBITMAP)LoadImage(NULL, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); ... GetObject(mM_Bitmap ,sizeof(BITMAP), &bmp); .... mM_Width = bmp.bmWidth; mM_Height = bmp.bmHeight; mM_Bits = (BYTE*)bmp.bmBits; ... BYTE* byte = mM_Bits + y*mM_Width*3; byte += x*3; // кажется x это координата картинки COLORREF color = (byte[0]) | (byte[1] << 8) | (byte[2] << 16); // RGB, это то что надо? ...
к сожалению код старый, не могу ничего ни вспомнить ни прокомментировать (может даже картинка читается сверху вниз или вообще черно-белая)
=)
Ну так у тебя в GetDIBits явно же указана одна строка. Почитай внимательно про этот метод
И высота должна быть не в байтах, а в пикселях
Sergio
rAmpArk
yamilramilev
BITMAP BitMap; HDC hdc = CreateCompatibleDC(NULL); SelectObject( hdc, hBitmap); GetObject( hBitmap, sizeof( BITMAP), &BitMap); BITMAPINFOHEADER bInfo; bInfo.biSize =sizeof( bInfo); //эта штука 40 байт bInfo.biWidth = BitMap.bmWidth; bInfo.biHeight = BitMap.bmHeight; bInfo.biBitCount = 32; //это количество бит на пиксель bInfo.biPlanes = 1; bInfo.biCompression = BI_RGB; BYTE * tempScanLine=new BYTE[1024*768*4]; int LineCopy = GetDIBits( hdc,hBitmap, 0,BitMap.bmHeight , tempScanLine,( LPBITMAPINFO) &bInfo, DIB_RGB_COLORS);
Всем спасибо! Вот так грузит. Ещё заметил, если в GetDIBits вместо hdc ставить NULL- не записывает.
На форумах очень по-разному заполняются параметры BITMAPINFO. В некоторых biHeight вообще отрицательное число, в некоторых пишут что это вообще величина в байтах растра. Непонятно.
Надеюсь кому-нибудь код поможет :)
2 LeeSwagger
Тут кагбэ
BYTE * tempScanLine=new BYTE[bInfo.biWidth*bInfo.biHeight*(bInfo.biBitCount/4)];
А ещё и delete [] tempScanLine; не забыть
За информацию о BITMAPINFO
читай MSDN от мелкософта по ссылям от Гоголя, думаю там подробно расписаны поля структуры.
LeeSwagger
> В некоторых biHeight вообще отрицательное число,
Это значит - изображение отражено по горизонтали, "перевернуто"
LeeSwagger
> в некоторых пишут что это вообще величина в байтах растра
Неверно. Это biSizeImage - размер в байтах, причем если изображение сжатое.
В уроках NeHe была функция, понимающая сразу jpg, bmp и gif. Тоже использует функции Windows.
Тема в архиве.