HLFX.Ru Forum (https://hlfx.ru/forum/index.php)
- Half-Life SDK (https://hlfx.ru/forum/forumdisplay.php?forumid=8)
-- C++ Конвертирование BMP 24 -> 8 bit (https://hlfx.ru/forum/showthread.php?threadid=2468)
Отправлено fire64 26-11-2010 в 18:35:
 C++ Конвертирование BMP 24 -> 8 bit
Написал код для конвертирования  24 битных BMP в 8 битные.
В чем суть: считываем из пикселей цвета и заполняем ими палитру, а вместо цветов ставим индекс цвета из палитры.
Потом записываем заголовки + палитра + пиксели.
По неизвестной мне причине, вместо нормального 8 битного изображения получается что-то странное.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено XaeroX 26-11-2010 в 18:40:
 
Где изображение этого "странного"?
Ты ж не думаешь всеръез, что мы будем программу запускать?
__________________
Отправлено fire64 26-11-2010 в 18:41:
 
Посмотри в папке Debug
test.bmp - оригинал
new.bmp - конвертированная версия.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 26-11-2010 в 19:34:
 
Цитата:
fire64 писал:
 считываем из пикселей цвета и заполняем ими палитру, а вместо цветов ставим индекс цвета из палитры.
плакал. Ты всеръез думаешь что палитру можно заполнить тупым копированием цветов из RGB24 ?__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено XaeroX 26-11-2010 в 19:41:
 
fire64 
У меня new.bmp не открывается, пишет, что ошибка в файле. Ты что, не мог как следовает изучить bmp-формат? 
Добавлено 27-11-2010 в 01:41:
Очень похоже на то, что ты что-то в формате файла начудил.
__________________
Отправлено fire64 26-11-2010 в 19:55:
 
Дядя Миша, хм.
А разве цвет в палитре не задается с помощью 4 байт r, g, b, reserve ?
Вроде бы в 24 битном формате цвет пикселя задается также.
Логично, что палитра имеет 255 слотов под цвета.
А в самом изображении RGBRes заменяется на индекс идентичного цвета в палитре.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 26-11-2010 в 20:01:
 
fire64 на вот тебе для затравки
Почему картинка смещается - ищи сам. Ненавижу эту фишку бмп.
Добавлено 26-11-2010 в 23:01:
Цитата:
fire64 писал:
Логично, что палитра имеет 255 слотов под цвета.
ну хорошо, твой метод проканает для ч\б картинок и рисунков, нарисованных фпаинте. Но для боле-мене полноцветной картинки - никогда.__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 26-11-2010 в 20:23:
 
Дядя Миша, если в оригинале, количество цветов больше чем 256, то тогда надо будет менять код GetOrAddPixeltoPallet.
Нужно будет работать с областью значений и подбирать наиболее схожие цвета.
Кстати, почему
C++ Source Code:
| for( int i = 0; i < countpixel * 3; i+=3 ) | 
 
Мы же по логике должны смещаться на 4 байта.
Ведь пиксель в 24 битном формате имеет вида:
byte r
byte g
byte b
byte reserve__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 26-11-2010 в 20:29:
 
Цитата:
fire64 писал:
Нужно будет работать с областью значений и подбирать наиболее схожие цвета.
ну и на выходе получится гамно, можешь быть уверен.
Квантизатор цветового пространства - это архи-сложная вещь, сравнимая с кодированием звукового сигнала в мп3 с учетом психо-акустических особенностей человеческого организма. Для завтравки - посмотри квантизатор из хл2 бетки.
Согласись, что он "слегка" сложнее тупого подбора похожего цвета.
И это еще не самый лучший квантизатор.
Добавлено 26-11-2010 в 23:29:
Цитата:
fire64 писал:
Мы же по логике должны смещаться на 4 байта.
ну смещайся, кто тебе запрещает? Только потом не жалуйся, что картинку вьювер не открывает.
Цитата:
fire64 писал:
Ведь пиксель в 24 битном формате имеет вида:
byte r
byte g
byte b
byte reserve
Удивительные открытия - каждый день! Это ктож тебя так обманул?
Покажи пальцем, я его сам забаню за распространение ложных слухов.__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 26-11-2010 в 20:40:
 
Насчет 4 байт для пикселей, кажется читал в вики.
Мда, все оказывается намного сложней.
Я надеялся, что можно просто в GetOrAddPixeltoPallet заменить
C++ Source Code:
| if( Palette[i].rgbRed == pRgbData.r && Palette[i].rgbGreen == pRgbData.g && Palette[i].rgbBlue == pRgbData.b ) | 
 
на
C++ Source Code:
| if( CompareColor( Palette[i], pRgbData, 30 ) ) | 
 
C++ Source Code:
| 1 | bool CompareColor( RGBQUAD Palette, rgbdata_t pRgbData, int maxvalue ) | 
| 3 |   if( Palette.rgbRed + maxvalue < pRgbData.r || Palette.rgbRed - maxvalue > pRgbData.r ) | 
| 8 |   if( Palette.rgbGreen + maxvalue < pRgbData.g || Palette.rgbGreen - maxvalue > pRgbData.g ) | 
| 13 |   if( Palette.rgbBlue + maxvalue < pRgbData.b || Palette.rgbBlue - maxvalue > pRgbData.b ) | 
 __________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 26-11-2010 в 20:45:
 
Цитата:
fire64 писал:
Насчет 4 байт для пикселей, кажется читал в вики.
это для 32-битных картинок.
Цитата:
fire64 писал:
Я надеялся, что можно просто в GetOrAddPixeltoPallet заменить
можно, но
Цитата:
Дядя Миша писал:
на выходе получится гамно, можешь быть уверен.
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено XaeroX 26-11-2010 в 20:47:
 
Цитата:
fire64 писал:
Насчет 4 байт для пикселей, кажется читал в вики.
А в наше время молодежь читала MSDN... =\__________________
Отправлено fire64 26-11-2010 в 20:52:
 
Только что, взял свой аватар и сохранил в 24 битном bmp.
Изображение нормально сконвертировалось, но перепутались цветовые каналы.
вместо RGB, BGR
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 26-11-2010 в 21:04:
 
Здрасти. Ну BMP это и есть BGR.
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено SiPlus 27-11-2010 в 12:36:
 
fire64, в 24-х битном BMP для покраски пикселов надо 3 байта (b,g,r). Никаких реверсов там нет. Да и из количества битов все понятно. Это тебе не 32-битный BMP.
Отправлено Дядя Миша 27-11-2010 в 12:52:
 
Цитата:
SiPlus писал:
Никаких реверсов там нет
что за реверсы-то?__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено SiPlus 27-11-2010 в 15:06:
 
Цитата:
Дядя Миша писал:
что за реверсы-то?
Цитата:
fire64 писал:
byte r
byte g
byte b
byte reserve
Добавлено 27-11-2010 в 18:06:
Ой, не реверсы, а резервы. Кстати, зачем они вообще нужны?
Отправлено Дядя Миша 27-11-2010 в 16:59:
 
нету там никакого резерва. Это ты со структурой RGBQUAD перопутал.
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 28-11-2010 в 08:18:
 
Новая версия.
Кажется во всех вьюверах теперь открывается.
добавил небольшие изменение, для увеличения количества настоящих цветов за счет принудительного превращения в черные и белы цвета
Добавлено 28-11-2010 в 11:18:
Держите новую версию.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено CrazyRussian 28-11-2010 в 08:20:
 
По поводу краша с RGBQUAD FullImageColors[16777216];
C++ Source Code:
| 1 | RGBQUAD*FullImageColors; | 
| 2 | FullImageColors=(RGBQUAD*)malloc(sizeof(RGBQUAD)*16777216); | 
| 3 | //работаем с FullImageColors | 
 __________________
Трагическая новость: Пятеро инженеров Casio умерли от смеха, узнав что Samsung анонсировали часы с заявленным временем работы в 25 часов
Отправлено fire64 28-11-2010 в 09:48:
 
Добавил "смешивание цветов", а так же переменные для настройки конвертирования.
Добавлено 28-11-2010 в 12:48:
Новая версия.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 28-11-2010 в 09:53:
 
fire64 ну это не смешно, честное слово.
твоя картинка должна выглядеть вот так (см. аттач)
иначе всё это просто никому не нужно.
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 10-01-2011 в 16:46:
 
Дядя Миша, возобновляю старую тему.
Новый алгоритм заполнения палитры 
Результат конечно не как от хорошего квантоватора, но имхо все же лучше чем ничего 
Добавлено 10-01-2011 в 19:46:
Да и результаты вполне вменяемые.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено fire64 11-01-2011 в 14:11:
 
Я решил пойти дальше и написать конвертер Vtf2WAD.
Однако столкнулся со странной проблемой.
DevIL.dll сохраняет изображение в какой-то нестандартный тип BMP.
И в результате мой конвертер 24->8bpp просто падает.
cкачать исходники и программу
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Ku2zoff 11-01-2011 в 14:26:
 
fire64 а ты в BMP не сохраняй, сохраняй в TGA или DDS  Зачем нужен vtf2wad? Много текстур размером 2048x1024 наконвертируешь в хл вад? Нужен wad2vtf!
 Зачем нужен vtf2wad? Много текстур размером 2048x1024 наконвертируешь в хл вад? Нужен wad2vtf!
Отправлено fire64 11-01-2011 в 14:42:
 
Все разобрался.
DevIL сохраняет BMP файл с bih.biSizeImage равным 0
Пришлось вместо 
bih.biSizeImage
использовать
bfh.bfSize -  bfh.bfOffBits
Теперь vtf нормально конвертится и сохраняет в 8 битный bmp
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 11-01-2011 в 15:16:
 
fire64 ты конвертируй с учетом всех сторон кубимапы и вообще многокадровые изображения распаковывай нормально.
Дать загрузчик VTF из ксаша?
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 11-01-2011 в 15:26:
 
Пипец.
Qlumpy отказывается жрать файл размером 512x512.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 11-01-2011 в 15:37:
 
Цитата:
fire64 писал:
Qlumpy отказывается жрать файл размером 512x512.
зато xwad - прекрасно кушает 
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 11-01-2011 в 16:19:
 
А исходники у xwad есть ?
Добавлено 11-01-2011 в 19:19:
Исправил "фичу" из-за которой приходилось в скрипте указывать полный путь до BMP файла и добавил поддержку больших текстур.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 11-01-2011 в 17:09:
 
Цитата:
fire64 писал:
А исходники у xwad есть ?
а как жы.
Добавлено 11-01-2011 в 20:09:
Загрузчик VTF для нашего друга 
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 13-01-2011 в 11:01:
 
В общем все прекрасно за исключением того, что половина BMP файлов получаются кривыми.
__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 13-01-2011 в 11:36:
 
fire64 дать сохранялку бмп? Правда у меня только для 8-бит. но сохраняет жылезна.
__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 13-01-2011 в 11:56:
 
Разобрался.
Дело в том, что в BMP есть такое понятие как выравнивание.
То есть, дополнительные байты в конце каждой строки.
C++ Source Code:
| int optimgsize = bih.biWidth * bih.biHeight * 3; | 
| int relimgsize = bfh.bfSize -  bfh.bfOffBits; | 
 
Соответственно если optimgsize и relimgsize равны, то пустых байтов нет и изображение нормально сохраняется.
Если же relimgsize больше optimgsize, то нужно дополнительно производить смещение в конце строки на relimgsize / optimgsize.__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 13-01-2011 в 12:30:
 
Цитата:
fire64 писал:
Дело в том, что в BMP есть такое понятие как выравнивание.
Я не понял, это ты мне рассказываешь?  
 
твой код, кстати неправильный.__________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'
Отправлено fire64 13-01-2011 в 12:32:
 
Короче сделал так:
C++ Source Code:
| 1 | int optimgsize = bih.biWidth * bih.biHeight * 3; | 
| 2 | int relimgsize = bfh.bfSize -  bfh.bfOffBits; | 
| 4 | int countpixels = bih.biWidth * bih.biHeight; | 
| 5 | int countbytesalignment = relimgsize - optimgsize; | 
| 10 | if( relimgsize == optimgsize ) | 
| 16 |   alignmentsize = countbytesalignment / countpixels; | 
| 18 |   pixeloffset = 3 + alignmentsize; | 
 
Теперь все изображения успешно сохраняются.__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей
Отправлено Дядя Миша 13-01-2011 в 12:53:
 
C++ Source Code:
| 1 | qboolean Image_SaveBMP( const char *name, rgbdata_t *pix ) | 
| 6 |   RGBQUAD		rgrgbPalette[256]; | 
| 9 |   byte		*pb, *pbPal = NULL; | 
| 14 |   if( FS_FileExists( name, false ) && !(image.cmd_flags & IL_ALLOW_OVERWRITE )) | 
| 15 |     return false; // already existed | 
| 17 |   // bogus parameter check | 
| 18 |   if( !pix->palette || !pix->buffer ) | 
| 27 |         MsgDev( D_WARN, "Image_SaveBMP: unsupported image type %s\n", PFDesc[pix->type].name ); | 
| 31 |   pfile = FS_Open( name, "wb", false ); | 
| 32 |   if( !pfile ) return false; | 
| 34 |   // NOTE: align transparency column will sucessfully removed | 
| 35 |   // after create sprite or lump image, it's just standard requiriments | 
| 36 |   biTrueWidth = ((pix->width + 3) & ~3); | 
| 37 |   cbBmpBits = biTrueWidth * pix->height; | 
| 38 |   cbPalBytes = 256 * sizeof( RGBQUAD ); | 
| 40 |   // Bogus file header check | 
| 41 |   bmfh.bfType = MAKEWORD( 'B', 'M' ); | 
| 42 |   bmfh.bfSize = sizeof(bmfh) + sizeof(bmih) + cbBmpBits + cbPalBytes; | 
| 45 |   bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + cbPalBytes; | 
| 48 |   FS_Write( pfile, &bmfh, sizeof(bmfh)); | 
| 51 |   bmih.biSize = sizeof(bmih); | 
| 52 |   bmih.biWidth = biTrueWidth; | 
| 53 |   bmih.biHeight = pix->height; | 
| 56 |   bmih.biCompression = BI_RGB; | 
| 58 |   bmih.biXPelsPerMeter = 0; | 
| 59 |   bmih.biYPelsPerMeter = 0; | 
| 61 |   bmih.biClrImportant = 0; | 
| 64 |   FS_Write( pfile, &bmih, sizeof(bmih)); | 
| 67 |   // copy over used entries | 
| 68 |   for( i = 0; i < (int)bmih.biClrUsed; i++ ) | 
| 70 |     rgrgbPalette[i].rgbRed = *pb++; | 
| 71 |     rgrgbPalette[i].rgbGreen = *pb++; | 
| 72 |     rgrgbPalette[i].rgbBlue = *pb++; | 
| 74 |     // bmp feature - can store 32-bit palette if present | 
| 75 |     // some viewers e.g. fimg.exe can show alpha-chanell for it | 
| 76 |     if( pix->type == PF_INDEXED_32 ) | 
| 77 |       rgrgbPalette[i].rgbReserved = *pb++; | 
| 78 |     else rgrgbPalette[i].rgbReserved = 0; | 
| 81 |   // make last color is 0 0 255, xwad expect this (but ignore decals) | 
| 82 |   if( com.strrchr( name, '{' ) && pix->flags & IMAGE_HAS_ALPHA && !( pix->flags & IMAGE_COLORINDEX )) | 
| 84 |     rgrgbPalette[255].rgbRed = 0x00; | 
| 85 |     rgrgbPalette[255].rgbGreen = 0x00; | 
| 86 |     rgrgbPalette[255].rgbBlue = 0xFF; | 
| 87 |     rgrgbPalette[255].rgbReserved = 0x00; | 
| 90 |   // write palette( bmih.biClrUsed entries ) | 
| 91 |   cbPalBytes = bmih.biClrUsed * sizeof( RGBQUAD ); | 
| 92 |   FS_Write( pfile, rgrgbPalette, cbPalBytes ); | 
| 93 |   pbBmpBits = Mem_Alloc( Sys.imagepool, cbBmpBits ); | 
| 94 |   Mem_Set( pbBmpBits, 0xFF, cbBmpBits );	// fill buffer with last palette color | 
| 97 |   pb += (pix->height - 1) * pix->width; | 
| 99 |   for( i = 0; i < bmih.biHeight; i++ ) | 
| 101 |     Mem_Copy( &pbBmpBits[biTrueWidth * i], pb, pix->width ); | 
| 105 |   // write bitmap bits (remainder of file) | 
| 106 |   FS_Write( pfile, pbBmpBits, cbBmpBits ); | 
| 108 |   Mem_Free( pbBmpBits ); | 
 __________________
My Projects: download page
F.A.Q по XashNT
Блог разработчика в телеграме
Цитата:
C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'