Создание индексного растрового изображения, процесс чтения и записи C++

В отличие от обычных 16-, 24- и 32-битных цветовых форматов BMP, индексированное растровое изображение — это формат растрового изображения, в котором используется палитра + 8-битный цвет, каждый пиксель занимает только один байт, а значение пикселя составляет индекс 0–255. цвет сохраняется в соответствующей позиции данных палитры

Создание индексированных растровых изображений в Photoshop

Используйте Photoshop, чтобы открыть существующее изображение, а затем выберите меню [Изображение], [Режим], [Индексированный цвет...]. Затем
во всплывающем диалоговом окне вы можете выбрать соответствующий алгоритм для сортировки индексированного цвета и суммировать цвета текущего изображения в один из 256 цветов.После подтверждения в середине
вставьте сюда описание изображенияизображение становится индексным растровым изображением.Через меню [Изображение],[Режим],[Таблица цветов...] снова можно изменить содержимое палитры, а затем [Сохранить как...], чтобы сохранить его в
вставьте сюда описание изображенияформате 8-битного цветного изображения BMP.

GIMP делает индексированные растровые изображения

Через меню 【Изображение】, 【Режим】, 【Индекс...】
всплывающее диалоговое окно преобразует изображение в индексированный цвет,
вставьте сюда описание изображения
а затем через меню 【Окно】, 【Прикрепляемое диалоговое окно】, 【Таблица цветов 】
чтобы открыть панель цветной поверхности, вы можете использовать ее в дальнейшем Укажите цвет и значение индекса в операции.После
вставьте сюда описание изображения
редактирования вам нужно выбрать изображение Windows BMP через меню [Файл], [Экспорт... ] и может быть сгенерирован 8-битный битовый индекс

Представьте растровое изображение индекса просмотра и таблицу цветов

Imagine — это легкий бесплатный браузер изображений, который может легко просматривать различные форматы изображений, официальный сайт: https://www.nyam.pe.kr/dev/imagine/
. При открытии индексного растрового изображения вы можете использовать 【Edit Palette】. кнопка вставьте сюда описание изображениядля открытия окна палитры
вставьте сюда описание изображения

Формат файла индексированного растрового изображения

Обратитесь к документу msdn: https://docs.microsoft.com/zh-cn/windows/win32/gdi/bitmap-storage , видно, что формат хранения растрового изображения
вставьте сюда описание изображения

Формат BITMAPFILEHEADER

Заявлено в заголовочном файле Wingdi.h

член иллюстрировать
бфТип 0x4D42, что указывает на BM
bfSize Общий размер файла, включая размер BITMAPFILEHEADER.
бфрезервед1 0
bfReserved2 0
бфоффбитс Начальная позиция данных изображения (массив цветовых индексов) относительно заголовка файла.

Формат BITMAPINFHEADER

Заявлено в заголовочном файле Wingdi.h

член иллюстрировать
биразмер Размер структуры BITMAPINFOHEADER 40
biWidth ширина изображения
биВысота высота изображения
бипланы 1
бибиткаунт растровое изображение индекса равно 8
бикомпрессия BI_RGB означает несжатый
biSizeImage Размер данных изображения, обычно шаг x biHeight,
шаг: 4-байтовая выровненная версия biWidth * sizeof(pixel)
biXPelsPerMeter пикселей на метр
biYPelsPerMeter пикселей на метр
biClrUsed Битовая карта индекса равна 0, что указывает на то, что палитра имеет 256 цветов.
biClrВажно 0

Чтение растрового изображения индекса в C++

Предположим, вам нужно прочитать растровое изображение в двумерный массив boost::multi_array<byte, 2> img

std::ifstream ifs("aaa.bmp", std::ios::binary);

//-		bfh	{bfType=19778 bfSize=787512 bfReserved1=0 ...}	tagBITMAPFILEHEADER
//		bfType	19778	unsigned short
//		bfSize	787512	unsigned long
//		bfReserved1	0	unsigned short
//		bfReserved2	0	unsigned short
//		bfOffBits	1078	unsigned long
BITMAPFILEHEADER bfh;
ifs.read((char*)&bfh, sizeof(bfh));
if (bfh.bfType != 0x4D42)
	return;

//-		bih	{biSize=40 biWidth=1024 biHeight=768 ...}	tagBITMAPINFOHEADER
//		biSize	40	unsigned long
//		biWidth	1024	long
//		biHeight	768	long
//		biPlanes	1	unsigned short
//		biBitCount	8	unsigned short
//		biCompression	0	unsigned long
//		biSizeImage	786434	unsigned long
//		biXPelsPerMeter	11808	long
//		biYPelsPerMeter	11808	long
//		biClrUsed	0	unsigned long
//		biClrImportant	0	unsigned long
BITMAPINFOHEADER bih;
ifs.read((char*)&bih, sizeof(bih));
if (bih.biCompression != BI_RGB || bih.biBitCount != 8)
	return;

// 位图每一行的数据字节长度是4的倍数
int pitch = (bih.biWidth * bih.biBitCount + 31) / 32 * 4;

// 逐行将数据读入二维数组
boost::multi_array<unsigned char, 2> img(boost::extents[bih.biHeight][bih.biWidth]);
for (int i = 0; i < bih.biHeight; i++)
{
    
    
	// Windows位图数据从下往上存储,所以需要反着读取
	long offset = bfh.bfOffBits + (bih.biHeight - i - 1) * pitch;
	ifs.seekg(offset, SEEK_SET);

	ifs.read((char*)&img[i][0], bih.biWidth * sizeof(unsigned char));
}

Написать растровое изображение индекса на C++

После чтения bfh и bih растрового изображения данные уже были видны в памяти, поэтому следуйте тому же шаблону, а затем запишите данные обратно в файл, но поскольку данные ширины растрового изображения должны быть кратны 4, это рекомендуется сохранить исходный массив соответственно расширить

// boost::multi_array<unsigned char, 2> img(...);
// 需要将二维数组img的宽度扩大到4的倍数
img.resize(boost::extents[img.shape()[0]][boost::alignment::align_up(img.shape()[1], 4)]);

std::ofstream ofs(path, std::ios::binary, _SH_DENYRW);

BITMAPFILEHEADER bfh = {
    
     0 };
BITMAPINFOHEADER bih = {
    
     0 };
bfh.bfType = 0x4D42;
bfh.bfOffBits = sizeof(bfh) + sizeof(bih) + sizeof(RGBQUAD) * 256;
bfh.bfSize = bfh.bfOffBits + img.num_elements() * sizeof(unsigned char);
bih.biSize = sizeof(bih);
bih.biWidth = img.shape()[1];
bih.biHeight = img.shape()[0];
bih.biPlanes = 1;
bih.biBitCount = 8;
bih.biCompression = BI_RGB;
bih.biSizeImage = img.num_elements() * sizeof(unsigned char);
bih.biXPelsPerMeter = 11808;
bih.biYPelsPerMeter = 11808;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

ofs.write((char*)&bfh, sizeof(bfh));
ofs.write((char*)&bih, sizeof(bih));

// 这里写入灰度数据到调色板数据,可在Photoshop面板中更改
for (int p = 0; p < 256; p++)
{
    
    
	RGBQUAD q = {
    
     p, p, p, 0 };
	ofs.write((char*)&q, sizeof(q));
}

for (int i = 0; i < img.shape()[0]; i++)
{
    
    
	ofs.write((char*)&img[img.shape()[0] - i - 1][0], img.shape()[1] * sizeof(unsigned char));
}

Ссылка:
https://docs.microsoft.com/zh-cn/windows/win32/gdi/bitmap-storage
https://blog.csdn.net/Wintalen/article/details/1014820
https://sunriver2000.blog. csdn.net/статья/детали/104251831

Supongo que te gusta

Origin blog.csdn.net/tangyin025/article/details/126175940
Recomendado
Clasificación