Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Inf_2.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
265 Кб
Скачать
☆

Вывод графики с использованием отображаемых файлов

Спору нет, объект TBitmap удобен и универсален. Программисты Inprise шагают в ногу с разработчиками графического API Windows, и исходный код модуля graphics. pas от версии к версии совершенствуется. Но в ряде случаев возможностей, предоставляемых стандартным компонентом, недостаточно. Один из таких случаев — работа с большими и очень большими изображениями (до сотен мегабайт). С ними приходится иметь дело в полиграфии, медицине, обработке изображений дистанционного зондирования Земли из космоса и т. п. Здесь TBitmap не подходит, так как запрашивает для хранения и преобразования картинки слишком много ресурсов.

Что делать? На помощь следует призвать Windows API, поддерживающий файлы, отображаемые в память (Memory Mapped Files). У них много полезных свойств, но здесь важно только одно из них. При создании битовой карты Windows распределяет для нее часть виртуального адресного пространства. А оно не безгранично — для выделения пятидесяти — ста мегабайт может не хватить размеров файла подкачки, не говоря уже об ОЗУ. Но можно напрямую отобразить файл в виртуальную память, сделав его частью виртуального адресного пространства. В этом случае нашему файлу с изображением будет просто выделен диапазон адресов, которые можно использовать для последующей работы.

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

Var Memory: pByteArray;

ес : Integer-procedure TFormI.OpenlClick(Sender: TObject);

var

i: integer;

bmFile : pBitmapFileHeader;

bmlnfo : pBitmapInfoHeader;

begin if not OpenDialogI.execute then Exit;

hf := CreateFile(pChar(OpenDialogI.FileName), GENERIC_READ or GENERIC WRITE,

FILE_SHARE_READ, nil, OPENJ5XISTING, 0, 0);

if hf=INVALID_HANDLE_VALUE then begin

ec:=GetLastError;

ShowMessage(' File opening error '+IntTostr(ec));

Exit;

end;

hm := CreateFileMappingfhf, nil, PAGE_READONLY, 0,0,nil);

if пт=0 then begin ShowMessage(' File Mapping error %d',[GetLastError]);

Exit;

end;

pb := MapViewOfFile(hm, FTLK_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:=@(pb^[bmFile^.bfOffBits]);

bmlnfo := @(pb^[SizeOf(TBitmapFileHeader)]);

StrLen:=(((bmlnfo^.biWidth*bm!nfo^

.biBitCount)+31) div 32)*4;

PaintMe(Self);

end;

В этом коде последовательно получены дескрипторы файла (hf, с помощью функции createFile), его отображения в память (hm, с помощью функции createFiieMapping) и указатель на отображенные данные (pb, посредством MapViewOfFile). He будем вдаваться в детали внутренней реализации битовой карты — графический формат BMP известен достаточно хорошо. Отметим только, что результатом проделанных операций являются структура bminfo типа TBitmapinfo, полностью характеризующая битовую карту, и указатель Memory на данные битовой карты. Теперь загруженные данные нужно суметь нарисовать на канве, в данном случае на канве объекта paintBox. Делается это следующим образом:

procedure TFormI.PaintMe(Sender: TObj ect);

var OldP : hPalette;i : integer;

begin

if Memory=nil then Exit;

OldP := SelectPalette(PaintBox.Canvas.Handle, Palette, False);

RealizePalette(PaintBox.Canvas.Handle);

SetStretchBltMode(PaintBox.Canvas.Handle, STRETCH_DELETESCANS);

case ViewMode of vmStretch:

with bminfo^ do

i := Stretch DIBits(PaintBox.Canvas.Handle,0,0,

PaintBox.Height,PaintBox.Width,

0,0,biWidth,Abs(biHeight),

Memory, pBitmapInfo(hminfo)^,

DIB_RGB_COLORS,

PaintBox.Canvas.CopyMode);

vmlxl:

with bminfo^,PaintBox.ClientRect do

i:=SetDIBitsToDevice(PaintBox.Canvas.

Handle,Left,Top,Right-Left,Bottom-Top,

Left,Top,Top,Bottom-top, Memory, pBitmapInfo(bminfo)", DIB_RGB_COLORS) ;

vmZoom:

begin

with bminfo'"', PaintBox. ClientRect do

i := StretchDIBits(PaintBox.Canvas.Handle,Left,Top,Right-Left,Bottom-Top,

0,0,biWidth,Abs(biHeight), Memory, pBitmapInfo (bminfo)^, DIB_RGB_COLORS,

PaintBox.Canvas.CopyMode);

end;

end;

if (i=0) or (i=GDI_ERROR) then

begin

ec :=GetLastError;

Formi.Caption := 'Error code '+IntToStr(ec);

end;

SelectPalette(PaintBox.Canvas.Handle, OldP, False);

end;

В зависимости от установленного режима отображения (vmstretch, vmzoom или vmlxl) применяются разные функции Windows API: StretchDiBits или SetDiBitsToDevice. Выигрыш в скорости работы приложения особенно ощущается, если загружаемые файлы становятся велики и должны размещаться в файле подкачки. Наше же приложение не использует его и отображает данные прямо из файла на экран (рис. 8.3).

Рис. 8.3. Этот снимок с метеорологического спутника имеет размер десятки мегабайт

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]