|
Класс 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;
|