HLFX.Ru Forum
Показать все 37 сообщений этой темы на одной странице

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:

Где изображение этого "странного"?
Ты ж не думаешь всеръез, что мы будем программу запускать?

__________________

xaerox on Vivino


Отправлено 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:

Очень похоже на то, что ты что-то в формате файла начудил.

__________________

xaerox on Vivino


Отправлено 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 )
2
{
3
  if( Palette.rgbRed + maxvalue < pRgbData.r || Palette.rgbRed - maxvalue > pRgbData.r )
4
  {
5
    return false;
6
  }
7
 
8
  if( Palette.rgbGreen + maxvalue < pRgbData.g || Palette.rgbGreen - maxvalue > pRgbData.g )
9
  {
10
    return false;
11
  }
12
 
13
  if( Palette.rgbBlue + maxvalue < pRgbData.b || Palette.rgbBlue - maxvalue > pRgbData.b )
14
  {
15
    return false;
16
  }
17
 
18
  return true;
19
}

__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей


Отправлено Дядя Миша 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... =\

__________________

xaerox on Vivino


Отправлено 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
4
....
5
free(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!


Отправлено 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;
3
 
4
int countpixels = bih.biWidth * bih.biHeight;
5
int countbytesalignment = relimgsize - optimgsize;
6
int alignmentsize = 0;
7
 
8
int pixeloffset = 0;
9
 
10
if( relimgsize == optimgsize )
11
{
12
  pixeloffset = 3;
13
}
14
else
15
{
16
  alignmentsize = countbytesalignment / countpixels;
17
 
18
  pixeloffset = 3 + alignmentsize;
19
}


Теперь все изображения успешно сохраняются.

__________________
Вся сила лысого кощея,
Сокрыта в башне из костей
Воздвигнутой, под небесами
На месте похорон людей


Отправлено Дядя Миша 13-01-2011 в 12:53:

C++ Source Code:
1
qboolean Image_SaveBMP( const char *name, rgbdata_t *pix )
2
{
3
  file_t		*pfile = NULL;
4
  BITMAPFILEHEADER	bmfh;
5
  BITMAPINFOHEADER	bmih;
6
  RGBQUAD		rgrgbPalette[256];
7
  dword		cbBmpBits;
8
  byte*		pbBmpBits;
9
  byte		*pb, *pbPal = NULL;
10
  dword		cbPalBytes;
11
  dword		biTrueWidth;
12
  int		i, rc = 0;
13
 
14
  if( FS_FileExists( name, false ) && !(image.cmd_flags & IL_ALLOW_OVERWRITE ))
15
    return false; // already existed
16
 
17
  // bogus parameter check
18
  if( !pix->palette || !pix->buffer )
19
    return false;
20
 
21
  switch( pix->type )
22
  {
23
  case PF_INDEXED_24:
24
    case PF_INDEXED_32:
25
        break;
26
    default:
27
        MsgDev( D_WARN, "Image_SaveBMP: unsupported image type %s\n", PFDesc[pix->type].name );
28
      return false;
29
    }
30
 
31
  pfile = FS_Open( name, "wb", false );
32
  if( !pfile ) return false;
33
 
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 );
39
 
40
  // Bogus file header check
41
  bmfh.bfType = MAKEWORD( 'B', 'M' );
42
  bmfh.bfSize = sizeof(bmfh) + sizeof(bmih) + cbBmpBits + cbPalBytes;
43
  bmfh.bfReserved1 = 0;
44
  bmfh.bfReserved2 = 0;
45
  bmfh.bfOffBits = sizeof(bmfh) + sizeof(bmih) + cbPalBytes;
46
 
47
  // write header
48
  FS_Write( pfile, &bmfh, sizeof(bmfh));
49
 
50
  // size of structure
51
  bmih.biSize = sizeof(bmih);
52
  bmih.biWidth = biTrueWidth;
53
  bmih.biHeight = pix->height;
54
  bmih.biPlanes = 1;
55
  bmih.biBitCount = 8;
56
  bmih.biCompression = BI_RGB;
57
  bmih.biSizeImage = 0;
58
  bmih.biXPelsPerMeter = 0;
59
  bmih.biYPelsPerMeter = 0;
60
  bmih.biClrUsed = 256;
61
  bmih.biClrImportant = 0;
62
 
63
  // Write info header
64
  FS_Write( pfile, &bmih, sizeof(bmih));
65
  pb = pix->palette;
66
 
67
  // copy over used entries
68
  for( i = 0; i < (int)bmih.biClrUsed; i++ )
69
  {
70
    rgrgbPalette[i].rgbRed = *pb++;
71
    rgrgbPalette[i].rgbGreen = *pb++;
72
    rgrgbPalette[i].rgbBlue = *pb++;
73
 
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;
79
  }
80
 
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 ))
83
  {
84
    rgrgbPalette[255].rgbRed = 0x00;
85
    rgrgbPalette[255].rgbGreen = 0x00;
86
    rgrgbPalette[255].rgbBlue = 0xFF;
87
    rgrgbPalette[255].rgbReserved = 0x00;
88
  }
89
 
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
95
 
96
  pb = pix->buffer;
97
  pb += (pix->height - 1) * pix->width;
98
 
99
  for( i = 0; i < bmih.biHeight; i++ )
100
  {
101
    Mem_Copy( &pbBmpBits[biTrueWidth * i], pb, pix->width );
102
    pb -= pix->width;
103
  }
104
 
105
  // write bitmap bits (remainder of file)
106
  FS_Write( pfile, pbBmpBits, cbBmpBits );
107
  FS_Close( pfile );
108
  Mem_Free( pbBmpBits );
109
 
110
  return true;
111
}

__________________
My Projects: download page

F.A.Q по XashNT
Блог разработчика в телеграме

Цитата:

C:\DOCUME~1\C4C5~1\LOCALS~1\Temp\a33328if(72) : see declaration of 'size_t'


Временная зона GMT. Текущее время 20:20.
Показать все 37 сообщений этой темы на одной странице

На основе vBulletin версии 2.3.0
Авторское право © Jelsoft Enterprises Limited 2000 - 2002.
Дизайн и программирование: Crystice Softworks © 2005 - 2024