Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Сохранение изображения в файле




 

Для того чтобы сохранить изображение в файл, как минимум необходимо знать дескриптор сохраняемого изображения. После того как дескриптор нам известен, требуется заполнить структуру BITMAPINFOHEADER, которая содержит информацию о размере и формате цвета изображения, не зависящего от устройства (device-independent bitmap (DIB)). Для этих целей используется дескриптор нашего изображения и дескриптор контекста устройства. Контекст устройства удобно взять от окна рабочего стола.

 

hwndScreen=GetDesktopWindow();

hdcScreen = GetDC( hwndScreen );

 

Для заполнения структуры потребуется несколько раз вызвать функцию GetDIBits. Эта функция применяется для выборки двоичных данных указанного растрового изображения в буфер с использованием указанного формата. В неё мы передаем дескрипторы контекста устройства и изображения, и основываясь на из данных заполняем поля нашей структуры. В качестве массива для данных изображения указываем NULL, так как первоначально нам требуется определить свойства самого изображения заносимого в структуру BITMAPINFO.

 

GetDIBits( hdcScreen, // дескриптор контекста устройства

bitmap, // дескриптор изображения

0, // первая строка развертки, которая должна

// быть выбрана

0, // число копируемых линий

NULL, // адрес массива для битов изображения

(BITMAPINFO*)info, // адрес структуры для данных изображения

DIB_RGB_COLORS // RGB или индекс палитры

);

После того как структура будет заполнена, требуется определить количество бит приходящихся на один пиксель. Если это число не является 4, 8 или 24, то устанавливаем количество бит в 24, и указываем, что изображение не сжато. После этого определяем размер изображения основываясь на данных полученных в предыдущем шаге. После того как размер изображения будет определен, необходимо заполнить массив битов изображения, путем вторичного вызова функции GetDIBits. Если массив успешно заполнен, следует инициализировать структуру содержащую информацию о типе, размере и местоположении файла в котором будет сохранено изображение. Для этого потребуется заполнить поле bfOffBits, характеризующее сдвиг от начала структуры BITMAPFILEHEADER до массива бит и bfSize – характеризующее размер в байтах файла изображения.

 

//Сдвиг от начала структуры BITMAPFILEHEADER до массива бит

finfo.bfOffBits=sizeof(BITMAPFILEHEADER)+

sizeof(BITMAPINFOHEADER)+

(sizeof(RGBQUAD)*ctsize);

// Размер файла изображения в байтах

finfo.bfSize=finfo.bfOffBits+imgsize;

finfo.bfReserved1=0;

finfo.bfReserved2=0;

Когда все манипуляции со структурами и данными будут завершены, потребуется создать файл для изображения и последовательно записать в него структуру содержащую заголовок файла, затем структуру с информацией о изображении и в завершении массив бит этого изображения. Ну и соответственно не забыть закрыть открытые дескрипторы и освободить контекст устройства. Ниже приведен исходный код, позволяющий сохранить изображение окна в файл.

 

void PrintWindow(HWND hWnd)

{

HDC hDCMem = CreateCompatibleDC(NULL);

RECT rect;

GetWindowRect(hWnd, & rect);

 

HBITMAP hBmp = NULL;

HDC hDC = GetDC(hWnd);

hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);

ReleaseDC(hWnd, hDC);

 

HGDIOBJ hOld = SelectObject(hDCMem, hBmp);

SendMessage(hWnd, WM_PRINT, (WPARAM) hDCMem, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED);

 

SelectObject(hDCMem, hOld);

DeleteObject(hDCMem);

 

OpenClipboard(hWnd);

 

EmptyClipboard();

SetClipboardData(CF_BITMAP, hBmp);

CloseClipboard();

}

 

 

BOOL SaveBitmap(char *name,HBITMAP bitmap)

{

HDC hdcScreen; // Контекст устройства экрана

HWND hwndScreen; // Дескриптор окна рабочего стола

int i; // Количество выбираемых линий

BYTE *bits; // Указатель0020на массив битов изображения

BITMAPINFOHEADER *info; // Информационная структура изображения

HANDLE fp; // Дескриптор файла

BITMAPFILEHEADER finfo; // Заголовок файла изображения

long ctsize,imgsize,pixels;// Различные размерности для записи файла

DWORD dw; // Код возврата

char *ptr; // Указатель используемый для записи открытого BM

 

// Получаем дескриптор рабочего стола

hwndScreen=GetDesktopWindow();

// Получаем контекст устройства рабочего стола

hdcScreen = GetDC( hwndScreen );

 

// Выделяем память под структуру с информацией о изображении

info = (BITMAPINFOHEADER*)GlobalAlloc(GMEM_FIXED,sizeof(BITMAPFILEHEADER)+(1024*sizeof(RGBQUAD)));

info->biSize = sizeof(BITMAPINFOHEADER);

info->biBitCount = 0;

 

// Заполняем структуру информацией о изображении

i = GetDIBits( hdcScreen, // дескриптор контекста устройства

bitmap, // дескриптор изображения

0, // первая строка развертки, которая должна быть выбрана

0, // число копируемых линий

NULL, // адрес массива для битов изображения

(BITMAPINFO*)info, // адрес структуры для данных изображения

DIB_RGB_COLORS // RGB или индекс палитры

);

// Определяем количество бит на пиксель.

if( (info->biBitCount!=4) &&

(info->biBitCount!=8) &&

(info->biBitCount!=24) )

info->biBitCount=24;

// Указываем что изображение не сжато

info->biCompression=BI_RGB;

 

// Получаем количество пикселей

pixels=info->biWidth*info->biHeight;

switch(info->biBitCount)

{

case 4:ctsize=16;imgsize=pixels/2;break;

case 8:ctsize=256;imgsize=pixels;break;

case 16:ctsize=0;imgsize=pixels*2;break;

case 24:ctsize=0;imgsize=pixels*3;break;

case 32:ctsize=0;imgsize=pixels*4;break;

default:

ReleaseDC( hwndScreen,hdcScreen );

return FALSE;

}

 

// Инициализируем массив для битов изображения

bits = (unsigned char*)GlobalAlloc(GMEM_FIXED,imgsize);

 

//Заполняем массив битов изображения

i = GetDIBits( hdcScreen, // дескриптор контекста устройства

bitmap, // дескриптор изображения

0, // первая выбираемая линия для изображения назначения

info->biHeight, // количество выбираемых линий

bits, // адрес массива битов изображения

(BITMAPINFO*)info,// адрес структуры с данными изображения

DIB_RGB_COLORS // RGB или индекс палитры

);

 

// Формируем заголовок файла

ptr = (char *)&finfo.bfType;

ptr[0]='B';

ptr[1]='M';

 

//Определяем сдвиг от начала структуры BITMAPFILEHEADER до массива бит

finfo.bfOffBits=sizeof(BITMAPFILEHEADER)+

sizeof(BITMAPINFOHEADER)+

(sizeof(RGBQUAD)*ctsize);

// Размер файла изображения в байтах

finfo.bfSize=finfo.bfOffBits+imgsize;

finfo.bfReserved1=0;

finfo.bfReserved2=0;

 

//Создаем файл для изображения

fp = CreateFile(name, // указатель с именем файла

GENERIC_WRITE, // режим доступа

0, // режим использования

NULL, // указатель на параметры безопасности

CREATE_ALWAYS, // метод создания

FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,// атрибуты файла

NULL

);

// Записываем структуру заголовка файла

WriteFile(fp,&finfo,sizeof(BITMAPFILEHEADER),&dw,NULL);

// Записываем структуру информации изображения

WriteFile(fp,info,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*ctsize,&dw,NULL);

// Записываем биты изображения

WriteFile(fp,bits,imgsize,&dw,NULL);

// Закрываем файл

CloseHandle(fp);

//Освобождаем память с информацией изображения

GlobalFree(info);

// Освобождаем память с битами изображения

GlobalFree(bits);

// Освобождаем контекст устройства

ReleaseDC(hwndScreen,hdcScreen);

return TRUE;

}

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 534.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...