Delphi для профессионалов

         

Класс TBitmap


Класс TBitmap является основой растровой графики в Delphi. В первых версиях среды этот класс соответствовал битовой карте, зависимой от устройства (Device Dependent Bitmap, DDB). Этот формат хорош для деловой графики — отображения небольших картинок с малой глубиной цвета, например, на кнопках. Формат DDB появился во времена первых версий Windows, когда еще не было графических ускорителей и кое-где еще помнили о EGA. Поэтому и форматы хранения были привязаны к определенным видеорежимам.

Со временем аппаратура совершенствовалась, росло и количество поддерживаемых видеорежимов. Появились режимы High Color (15—16 бит на точку) и True Color (24 бита на точку). Все это привело к тому, что картинка стала храниться в аппаратно-независимом формате (Device Independent Bitmap, DIB), а проблемы ее быстрого отображения легли на аппаратуру и драйверы.

За формат битовой карты — DIB или DDB — отвечает свойство:

type TBitraapHandleType = (bmDIB, bmDDB);

 property HandleType: TBitmapHandleType;

По умолчанию устанавливается режим bmDIB. Впрочем, можно заставить приложение, написанное на Delphi, вернуться к старому типу. Для этого нужно установить глобальную переменную DOBsOnly (модуль GRAPHICS.PAS) в значение True. Впрочем, необходимость этого сомнительна. Все новые видеокарты и драйверы к ним, а также графические интерфейсы (такие, как DirectX) оптимизированы для использования DIB.

Желаемую глубину цвета битовой карты можно узнать и переустановить, меняя значение свойства:

TPixelFormat = (pfDevice, pflbit, pf4bit, pfSbit, pflSbit, pf!6bit, pf24bit, pf32bit, pfCustom); 

property PixelFormat: TPixelFormat;

Режим pfDevice соответствует битовой карте DDB. Глубина цвета в 1, 4 и 8 бит на пиксел — традиционная и предусматривает наличие у изображения палитры. Другие режимы заботятся о хранении непосредственных яркостей точек в каждом из трех основных цветов — красном (R), зеленом (G) и синем (В). Разрядность 15 бит соответствует распределению бит 5-5-5 (RGB555), 16 бит - RGB 565, 24 бит - RGB888. Режим 32 бит похож на 24-битный, но в нем дополнительно добавлен четвертый канат (альфа-канал), содержащий дополнительную информацию о прозрачности каждой точки. Режим pfCustom предназначен для реализации программистом собственных графических конструкций. В стандартном классе TBitmap установка свойства PixelFormat в режим pfCustom приведет к ошибке — поэтому использовать его нужно только в написанных вами потомках TBitmap.

Битовая карта является одним из видов ресурсов. Естественно, что класс TBitmap поддерживает загрузку из ресурсов приложения:

procedure LoadFromResourcelD(Instance: THandle; ResID: Integer);

 procedure LoadFromResourceName(Instance: THandle; const ResName: string);

Здесь instance — это глобальная переменная модуля System, хранящая уникальный идентификатор запущенной копии приложения (или динамической библиотеки).

Канва битовой карты доступна через свойство:

property Canvas: TCanvas;

С ее помощью можно рисовать на поверхности растрового изображения. Обратите внимание, что никакие другие потомки TGraphic канвы не имеют.

Дескрипторы битовой карты и ее палитры доступны как свойства:

property Handle: HBITMAP; 

property Palette: HPALETTE;

Имея дело с классом TBitmap, учитывайте, что принцип "один объект — один дескриптор" из-за наличия механизма кэширования неверен. Два метода:

function ReleaseHandle: HBITMAP; 

function ReleasePalette: HPALETTE;

возвращают дескрипторы битовой карты и палитры соответственно, а после этого обнуляют дескрипторы, т. е. как бы "отдают" их пользователю.

При любом внешнем обращении к дескриптору битовой карты и любой попытке рисовать на ее канве разделение одной картинки несколькими объектами прерывается, и объект получает собственную копию содержимого дескриптора. Для этого есть методы:

  •  procedure Dormant — выгружает изображение в поток и уничтожает дескрипторы битовой карты и палитры;
  •  procedure Freeimage — "освобождающий" дескриптор битовой карты для дальнейшего использования и внесения изменений. Это означает, что если на данный дескриптор есть ссылки, то он дублируется; поток очищается.

Битовая карта может быть монохромной и цветной, что определено свойством:

property Monochrome: Boolean;

Значение True соответствует монохромной битовой карте. При его изменении происходит преобразование содержимого к требуемому виду.

За прозрачность битовой карты отвечают следующие свойства:

property TransparentColor: TColor;

type TTransparentMode = (tmAuto, tmFixed);

property TransparentMode: TTransparentMode;

Если свойство TransparentMode установлено в режим tmAuto, то за прозрачный (фоновый) принимается цвет верхнего левого пиксела. В противном случае этот цвет берется из свойства Transparentcolor.

Битовая карта может использоваться в качестве маски для других битовых карт. В этом случае она превращается в двухцветную, где в белый цвет окрашиваются точки фона (см. свойство Transparentcolor), а в черный — все остальные. Для поддержки этого режима служат следующие методы и свойства:

procedure Mask(Transparentcoior: TColor); 

property MaskHandle: HBitmap; 

function ReleaseMaskHandle: HBitmap;

Наконец, последним по счету будет рассмотрено очень важное свойство битовой карты TBitmap. Если формат ее хранения — DIB, то есть возможность получить доступ к данным самой битовой карты:

property ScanLine[Row: Integer]: Pointer;

Это свойство представляет собой массив указателей на строки с данными битовой карты. Параметр ROW содержит номер строки. Следует помнить, что в большинстве случаев строки в битовой карте упорядочены в памяти снизу вверх и фактически первой после заголовка хранится нижняя строка. Код, возвращающий значение свойства ScanLine, это учитывает; поэтому не удивляйтесь, если с ростом параметра ROW значение свойства уменьшается.

Внутри строки данные упорядочены в соответствии с форматом (pixelFormat). Для формата pfsbit все просто — каждый байт в строке соответствует одному пикселу. Для форматов pfisbit и pfiebit пикселу соответствуют два байта (в этих 16 битах упакованы данные о трех каналах), pf24bit — три байта (по байту на канал).

Примерно так может выглядеть обработчик события onMouseMove, выводящий на панель состояния информацию о яркости в данной точке (подразумевается, что формат битовой карты — 8 или 24 бита):

procedure TMainForm.ImagelMouseMove(Sender: TObject; Shift: TShiftState;

X, Y: Integer);

begin

if not Assigned(Imagel. Picture.Bitmap) then Exit;

with Imagel.Picture.Bitmap, 

do case PixelFormat of

pfSbit: Statusbarl.SimpleText := Format('x: %d y: %d b: %d',[x, y, pByteArray(ScanLine[у])^[x] ]);

pf24bit: Statusbarl.SimpleText := Format('x: %d y: %d R: %d,G: %d, B: %d', 

[x,y, pByteArray(ScanLine[y])л[3*х], pByteArray(ScanLine[у])^[ 3*x+l], pByteArray(ScanLine[у])^[ 3*х+2]]); 

end;

Само значение свойства ScanLine изменить нельзя (оно доступно только для чтения). Но можно изменить данные, на которые оно указывает. Вот так можно получить негатив 24-битной картинки:

Var line : pByteArray;

For i:=0 to Imagel.Picture.Bitmap.Height — 1 do

 Begin

Line := Imagel.Picture.Bitmap.ScanLine[i];

 For j:=0 to Imagel.Picture.Bitmap.Width * 3 - 1 do

 Line^[j] := 255 - Line^[j];

 End;

Если вы хотите решать более серьезные задачи — на уровне профессиональных средств — на помощь может прийти библиотека обработки изображений фирмы Intel (Intel Image Processing Library). Этот набор инструментов позволяет разработчику включать в программы алгоритмы обработки изображений, написанные и оптимизированные специально для процессоров фирмы Intel. Библиотека является свободно распространяемой, и последняя ее версия располагается на Web-сайте фирмы. Интерфейсы к функциям библиотеки для Delphi разработаны авторами этой книги и вместе с примерами находятся на прилагаемой к книге дискете.

 Примечание 

В Delphi можно столкнуться с "тезкой" рассматриваемого объекта — структурой TBitmap, описанной в файле WINDOWS.PAS. Поскольку обе они относятся к одной и той же предметной области, часто возникают коллизии, приводящие к ошибкам. Напомним, чтобы отличить структуры-синонимы, следует использовать имя модуля, в котором они описаны. Поэтому если в вашей программе есть модули Windows и Graphics, то описывайте и употребляйте типы Windows.TBitmap И Graphics.TBitmap.

В состав Windows входят карточные игры (точнее, пасьянсы), которые черпают ресурсы из динамической библиотеки cards.dll. Если вы откроете эту библиотеку в редакторе ресурсов, то увидите там изображения всех пятидесяти двух карт и десятка вариантов их рубашек (оборотных сторон). Используем эту возможность для рисования карт. Так загружается битовая карта для рубашки:

var CardsDll : THandle;

BackBitmap : Graphics.TBitmap; 

initialization

CardsDll := LoadLibraryEx('cards.dll',0, LOAD_LIBRARY__AS_DATAFILE) ;

BackBitmap := Graphics.TBitmap.Create;

BackBitmap.LoadFromResourcelD(CardsDll, 64) ;

finalization

BackBitmap.Free;

FreeLibrary(CardsDll); 

end.

 Примечание

В Windows 95/98 эта динамическая библиотека — 16-разрядная, и работать так, как описано, не будет. Используйте библиотеку Cards.dll из состава Windows NT, 2000.

Аналогичным образом можно загрузить битовые карты для всей колоды. При показе карты, в зависимости от того, открыта она или закрыта, отрисовывается один из объектов TBitmap:

if Known then // карта открыта

Canvas.StretchDraw(ClientRect, FaceBitmap) 

else

Canvas.StretchDraw(ClientRect,BackBitmap) 

end;

 

Содержание раздела