M Y D E L P H I 7 . R U Самоучитель программирования  
 
  • Главная
  •  

     

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