Сохранение независимого от устройства битмапа



 

Для сохранения битмапа необходимо разобраться со всеми необходимыми структурами данных, заполнить их, а затем записать в файл. Задачу можно существенно упростить, если считать, что битмап загружен в виде «Packed DIB», что существенно позволяет сохранение битмапа свести, аналогично чтению, к нескольким функциям.

В ранее приводимых примерах я использовал собственную структуру _DIB, описывающую загруженный в память DIB. Она определена в примере на странице 52, вместе с включением необходимых заголовочных файлов и определением вспомогательных символов. Помимо этого она будет применяться в данном примере, а также с ее помощью будут выполнены операции по преобразованию DIB в DDB (стр. 63) и наоборот — DDB в DIB (стр. 64).

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

BOOL StoreDIBtoFile (LPSTR lpszFileName, LP_DIB lpDib) {

BITMAPFILEHEADER bmfh; // заголовок файла битмапа

HFILE hf;

BOOL a = FALSE;

DWORD dwSize;

hf = _lcreat (lpszFileName, 0);

if (hf != HFILE_ERROR) {

// заполняем и записываем заголовок файла

bmfh.bfType = DIB_SIGNATURE;

bmfh.bfSize = 0L;

bmfh.bfReserved1 = bmfh.bfReserved2 = 0;

bmfh.bfOffBits =

sizeof (BITMAPFILEHEADER) +

(LPSTR) (lpDib->lpImage) - (LPSTR) (lpDib->lpDibHdr);

// в нашем случае это всегда «Packed DIB», поэтому разница двух указателей

// возвратит расстояние между ними.

if (lpDib->lpDibHdr.biSize == sizeof (BITMAPCOREHEADER)) {

// определяем размер изображения

#define lpbmch ((LPBITMAPCOREHEADER) (lpDib->lpDibHdr))

dwSize = ( (lpbmch->bcWidth * lpbmch->bcBitCount + 31) >> 3) & ~3L;

dwSize *= lpbmch->bcHeight;

#undef lpbmch

// прибавляем размер заголовков и палитры

dwSize += bmfh.bfOffBits;

} else {

// размер изображения можно получить из BITMAPINFOHEADER

dwSize = bmfh.bfOffBits + lpDib->lpDibHdr.biSizeImage;}

_hwrite (hf, (LPVOID)&bmfh, sizeof (bmfh));

// записываем собственно DIB

_hwrite (hf, (LPVOID) (lpDib->lpDibHdr), dwSize - sizeof (BITMAPFILEHEADER));

_lclose (hf);

a = TRUE;}

return a;}

Большая часть трудностей, связанных с анализом информации о битмапе, переносится на функции, осуществляющие загрузку битмапа (LoadDIBfromFile, стр. 52, LoadDIBfromResources, стр. 52) и преобразование из DDB в DIB (ConvertDDBtoDIB, стр. 64)

 

Отображение независимого от устройства битмапа

 

Для отображения DIB существует несколько возможных способов. Два из них аналогичны функциям BitBlt и StretchBlt, но используют в качестве исходных данных не контекст устройства, а независимый от устройства битмап.

Эти функции используют указатель на структуру BITMAPINFO (или BITMAPCOREINFO), задающую характеристики битмапа и таблицу определения цветов, а также указатель на данные изображения. Эти указатели могут указывать на разные части одного блока данных, содержащего весь битмап, или вообще на разные блоки данных, если вам так удобнее.

Сначала мы рассмотрим функцию, осуществляющую перенос изображения из битмапа на устройство, не изменяющее размеров изображения.

int SetDIBitsToDevice (

hDC, nDestX, nDestY, nDestWidth, nDestHeight,

nSrcX, nSrcY, nStartScan, nCountScan, lpImage, lpDibInfo, nColorUse);

Параметры hDC, nDestX, nDestY, nDestWidth и nDestHeight указывают устройство, на котором осуществляется отображение битмапа, положение и размер выводимого изображения. Существенно отметить, что в данном случае используется система координат устройства.

Параметры nSrcX и nSrcY задают положение исходного прямоугольного изображения в битмапе. Если вы задаете эти координаты не 0, то помните, что у независимых от устройства битмапов начало отсчета системы координат помещается в левый–нижний угол, что несколько необычно.

Параметр lpDibInfo является указателем на структуру BITMAPINFO (BITMAPCOREINFO), определяющую характеристики битмапа, а параметр lpImage указывает на область памяти, содержащую данные изображения.

Еще два параметра nStartScan и nCountScan указывают на фрагмент битмапа, определенный в области lpImage. nStartScan указывает номер строки развертки, с которой начинается изображение, а nCountScan указывает число строк, отображаемых этой операцией. С помощью этих параметров можно разбить процесс вывода одного большого битмапа на несколько вызовов функции SetDIBitsToDevice, каждый из которых перенесет только небольшую часть строк изображения. Это может существенно сократить требуемое для отображения битмапа количество памяти (полная картинка 1280 x 1024, 24 бита/пиксель занимает более 3M).

Последний параметр nColorUse определяет применение цветов битмапом. Он может быть DIB_RGB_COLORS, если таблица определения цветов содержит записи RGBQUAD; или он может быть DIB_PAL_COLORS, если таблица определения цветов содержит массив 16ти разрядных номеров цветов в текущей палитре.

В Windows требуется, что бы таблица определения цветов содержала записи RGBQUAD[10], если битмап сохранен в виде файла, в виде ресурсов приложения, или если он каким–либо способом передается другому приложению. Таким образом DIB_PAL_COLORS может применяться, только если вы сами создаете и используете DIB, не сохраняя его и никому не передавая, и при этом текущая системная палитра полностью удовлетворяет вашим требованиям, что весьма и весьма редкий случай. Более того, при использовании DIB_PAL_COLORS вы обязаны проследить, что бы количество цветов, определяемых индексами было четным. Это связано с тем, что строки растра в DIB выравниваются на границу двойного слова и, одновременно, должны начинаться на такой границе. Размер заголовка (BITMAPINFOHEADER) кратен 4, одна запись RGBQUAD тоже имеет длину 4 байта; таким образом при использовании DIB_RGB_COLORS строка растра всегда начнется на границе двойного слова. А вот в случае DIB_PAL_COLORS одна запись в таблице определения цветов — 16ти разрядное число, тогда вам необходимо проследить, что бы таблица содержала четное число записей и ее длина была бы кратна 4 байтам.

Функция возвращает число строк развертки, перенесенных данной операцией.

Следующая рассматриваемая нами функция осуществляет перенос изображения с одновременным изменением размеров изображения:

int StretchDIBits (

hDC, nDestX, nDestY, nDestWidth, nDestHeight,

nSrcX, nSrcY, nSrcWidth, nSrcHeight, lpImage, lpDibInfo,

nColorUse, dwROP);

Параметры hDC, nDestX, nDestY, nDestWidth, nDestHeight задают устройство, на котором осуществляется отображение, положение и размеры изображения, как оно должно быть отображено.

Параметры nSrcX, nSrcY, nSrcWidth, nSrcHeight задают положение и размеры исходного изображения в битмапе. Начало отсчета системы координат битмапа находится в левом–нижнем углу битмапа, единицы соответствуют пикселям битмапа.

Параметр lpDibInfo указывает на структуру BITMAPINFO (BITMAPCOREINFO), а lpImage на буфер, содержащий данные изображения.

Параметр nColorUse указывает на способ задания таблицы определения цветов, обычно DIB_RGB_COLORS, а параметр dwROP задает индекс растровой операции, выполняемой при переносе изображения.

Так как при переносе может изменяться размер изображения, то функция использует текущий режим сжатия изображения, заданный функцией SetStretchBltMode.

Функция возвращает число строк развертки, перенесенных данной операцией.

 


Дата добавления: 2019-02-12; просмотров: 215; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!