Jump to content

Новые возможности TfgBitmap


Viktor Akselrod

203 views

 Share

Здравствуйте.

Еще одним нововведением в релизе 1.11.2.0, помимо TfgPopup, является работа с пикселями ("сырыми данными") TfgBitmap. Доступ к пикселям открывает практически неограниченные возможности для обработки и анализа изображений. Так же в новом релизе будет добавлена возможность поворота изображения.

 

Воможность работы с пикселями TfgBitmap.

Общие сведения.

Обращение к сырым данным возможно только между парными вызовами TfgBitmap.MapData и TfgBitmap.UnmapData, которые могут быть знакомы пользователям FMX. Однако, важным отличием от FMX, является отсутствие уровня доступа (только чтение/только запись/чтение и запись). Это сделано с целью ускорения доступа, т. к. работа осуществляется непосредственно с данными нативного изображения без создания промежуточного буфера.

В результате вызова TfgBitmap.MapData вы получаете интерфейс IFGXBitmapData (более подробно рассмотрен ниже), который предоставляет доступ к пикселям изображения.

Важно! Актуальность объекта IFGXBitmapData гарантирована только между вызовами TfgBitmap.MapData и TfgBitmap.UnmapData, т.к. используется "натуральный" интерфейс без подсчета ссылок.

Важно! Во время доступа к сырым данным операции по изменению TfgBitmap запрещены (например загрузка из различных источников, изменение размера, масштаба, поворота и тд).

Типичный пример работы с сырыми данными изображения:

var
  LBitmapData: IFGXBitmapData;
begin  
  if LBitmap.MapData(LBitmapData) then
    try
      // Работа с пикселями изображения.
    finally
      LBitmap.UnmapData;
    end;
end;

Важно! Всегда проверяйте результат выполнения TfgBitmap.MapData во избежание непредвиденных последствий. Повторный вызов TfgBitmap.MapData для уже спроецированных данных вернет ложь.

Интерфейс IFGXBitmapData.

Интерфейс IFGXBitmapData предоставляет информацию об изображении (Info, Width, Height), а так же позволяет манипулировать пикселями изображения (RawData, Scanlines, Pixels, Colors).

Информация о битмапе TfgBitmapInfo:

  1. BitsPerPixel — количество бит на один пиксель изображения. К примеру, для одного из самых распространенных вариантов ARGB, этот параметр будет равен 32-ум битам.
  2. BytesPerRow — количество байт на одну строку изображения. Обычно это Width * BitsPerPixel, но, в случае применения выравнивания для ускорения доступа к данным, значение может быть иным.
  3. PixelFormat — формат пикселя изображения. В отличии от фиксированного формата ARGB присущего стандартному типу TAlphaColor, нативные изображения могут иметь различный состав и порядок следования цветовых компонентов. Возможные комбинации этих параметров отражает тип  TfgBitmapPixelFormat.
    TfgBitmapPixelFormat = (Unknown, Alpha, Gray, ARGB, RGBA, RGB, RGB24);
  4. IsAlphaPremultiplied — флаг, показывающий являются ли компоненты пикселя предварительно помноженными на компоненту прозрачности.

Интерфейс IFGXBitmapData содержит несколько вариантов доступа к самим данным, которые отличаются по степени абстракции:

  1. RawData — самый низкий уровень. Возвращает указатель на начало данных. Размер данных можно узнать из свойства RawDataSize.
  2. Scanlines — указатель на переданную в аргументе строку. Размер данных строки в байтах можно получить из Info.BytesPerRow, количество пикселей в строке — Width.
  3. Pixels — указатель на пиксель. В аргументах передаются координаты пикселя. Размер пикселя в битах можно получить из Info.BitsPerPixel.
  4. Colors — цвет пикселя в стандартном формате TAlphaColor. В аргументах передаются координаты пикселя.

Как правило, для достижения максимальной скорости при последовательном сканировании пикселей изображения, вместо индексного доступа (Pixels, Colors) используют инкрементный перебор начиная с некой точки отсчёта (начало изображения RawData, начало определенной строки Scanlines[Y], определенный пиксель Pixelsх[X, Y]) . В этом случае вы получаете указатель, вместо привычного TAlphaColor.  Для преобразования данных по указателю в тип TAlphaColor вам могут пригодиться готовые варианты для конвератции, которые находятся в хэлпере TAlphaColorHelper из модуля FGX.Types.Color.

Для формирования TAlphaColor из сырых данных используйте перегруженный конструктор:

constructor Create(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean); overload;

Для обратной операции подойдет метод:

/// <summary>Записывает текущий цвет по адресу <c>APixel</c> с учетом опций <c>APixelFormat</c> и <c>AIsAlphaPremultiplied</c>.</summary>
procedure ToPixel(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean);

Реальный пример работы с сырыми данными.

Ниже приведен кусок кода из нового демонстрационного примера "Графика" -> "TfgBitmap - работа с "сырыми" данными" в котором изображение преобразуется из цветного в оттенки серого.

uses
  FGX.Types.Color, FGX.Canvas.Types, FGX.Canvas.Types, FGX.Assets, FGX.Assets.BitmapSet;

procedure TFormMain.fgButton1Tap(Sender: TObject);
var
  LBitmapSet: TfgAssetBitmapSet;
  LBitmap: TfgBitmap;
  LBitmapData: IFGXBitmapData;
  I, J: Integer;
begin
  if not TfgAssetsManager.Current.Find<TfgAssetBitmapSet>('Image', LBitmapSet) then
    Exit;
  LBitmap := LBitmapSet.GetBitmap;
  if LBitmap.MapData(TfgBitmapDataAccessMode.ReadWrite, LBitmapData) then
    try
      for J := 0 to LBitmap.Height - 1 do
        for I := 0 to LBitmap.Width - 1 do
          LBitmapData.Colors[I, J] := LBitmapData.Colors[I, J].ToGrayscale;
    finally
      LBitmap.UnmapData;
    end;
  fgPaintBox1.Invalidate;
end;

Повороты изображения.

Благодаря добавлению работы с сырыми данными появилась возможность с легкостью вращать изображения.

Поворот осуществляется с помощью метода TfgBitmap.Rotate:

/// <summary>Поворачивает изображение на указанный угол.</summary>
procedure Rotate(const AAngle: TfgRotation);

В качестве аргумента передается одно из предустановленных значений угла поворота.

TfgRotation = (Rotation0 = 0, Rotation90 = 90, Rotation180 = 180, Rotation270 = 270);

Поворот осуществляется по часовой стрелке.

 

Благодарим за внимание и приятного коддинга 🙂.

  • Like 9
  • Thanks 3
 Share

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...