Вывод графики с использованием отображаемых файлов
Спору нет – объект TBitmap удобен и универсален. Программисты Borland шагают в ногу с разработчиками графического API Windows, и исходный код модуля GRAPHICS.PAS от версии к версии совершенствуется. Но в ряде случаев возможностей, предоставляемых стандартным компонентом, недостаточно. Один из таких случаев – работа с большими и очень большими изображениями (до сотен Мбайт). С ними приходится иметь дело в полиграфии, медицине, при обработке изображений дистанционного зондирования Земли из космоса и т. п. Здесь класс TBitmap не подходит, т. к. запрашивает для хранения и преобразования картинки слишком много ресурсов.
Что делать? На помощь следует призвать Windows API, поддерживающий файлы, отображаемые в память (Memory Mapped Files). У них много полезных свойств, но здесь важно только одно из них. При создании битовой карты Windows распределяет для нее часть виртуального адресного пространства. А оно не безгранично – для выделения 50-100 Мбайт может не хватить размеров файла подкачки, не говоря уже об ОЗУ. Но можно напрямую отобразить файл в виртуальную память, сделав его частью виртуального адресного пространства. В этом случае нашему файлу с изображением будет просто выделен диапазон адресов, которые можно использовать для последующей работы.
Процедура отображения файла в память и присвоения адреса его данным выглядит следующим образом:
Var Memory: pByteArray; ес: Integer; procedure TForml.OpenlClick(Sender: TObject); var i: integer; bmFile: pBitmapFileHeader; bmlnfo: pBitmapInfoHeader; begin if not OpenDialogl.execute then Exit; hf: = CreateFile(pChar(OpenDialogl.FileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0); if hf=INVALID_HANDLE_VALUE then begin ec: = GetLastError; ShowMessage(' File opening error Ч-IntTostr (ec)); Exit; end; hm: = CreateFileMapping(hf,' nil, PAGE_READONLY, 0.0,nil); if hm=0 then begin ShowMessage(' File Mapping error %d',[GetLastError]); Expend; pb: = MapViewOfFile(hm, FILE_MAP_READ, 0.0.0); if pb=nil then begin ec: = GetLastError; ShowMessage('Mapping error '+IntTostr(ec)); Exit; end; bmFile: = pBitmapFileHeader(pb); if (bmFile".bfTypeO$4D42) then BEGIN Exit; end; Memory: = @(рb^[bmFile^.bfOffBits]); bmlnfo: = @(рb^[SizeOf(TBitmapFileHeader)]); StrLen: = (((bmInfo~.biWidth*bmInfoA.biBitCount) +31) div 32}*4; PaintMe(Self); end;
В этом коде последовательно получены дескрипторы файла (hf, с использованием функции CreateFile), его отображения в память (hm, с помощью функции CreateFileMapping) и указатель на отображенные данные (pb, посредством MapviewOfFile). He будем вдаваться в детали внутренней реализации битовой карты – графический формат BMP известен достаточно хорошо. Отметим только, что результатом проделанных операций являются структура bminfo типа TBitmapinfo, полностью характеризующая битовую карту, и указатель Memory на данные битовой карты.