Новые возможности TfgBitmap
Здравствуйте.
Еще одним нововведением в релизе 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:
- BitsPerPixel — количество бит на один пиксель изображения. К примеру, для одного из самых распространенных вариантов ARGB, этот параметр будет равен 32-ум битам.
- BytesPerRow — количество байт на одну строку изображения. Обычно это Width * BitsPerPixel, но, в случае применения выравнивания для ускорения доступа к данным, значение может быть иным.
-
PixelFormat — формат пикселя изображения. В отличии от фиксированного формата ARGB присущего стандартному типу TAlphaColor, нативные изображения могут иметь различный состав и порядок следования цветовых компонентов. Возможные комбинации этих параметров отражает тип TfgBitmapPixelFormat.
TfgBitmapPixelFormat = (Unknown, Alpha, Gray, ARGB, RGBA, RGB, RGB24);
- IsAlphaPremultiplied — флаг, показывающий являются ли компоненты пикселя предварительно помноженными на компоненту прозрачности.
Интерфейс IFGXBitmapData содержит несколько вариантов доступа к самим данным, которые отличаются по степени абстракции:
- RawData — самый низкий уровень. Возвращает указатель на начало данных. Размер данных можно узнать из свойства RawDataSize.
- Scanlines — указатель на переданную в аргументе строку. Размер данных строки в байтах можно получить из Info.BytesPerRow, количество пикселей в строке — Width.
- Pixels — указатель на пиксель. В аргументах передаются координаты пикселя. Размер пикселя в битах можно получить из Info.BitsPerPixel.
- 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);
Поворот осуществляется по часовой стрелке.
Благодарим за внимание и приятного коддинга 🙂.
- 9
- 3
0 Comments
Recommended Comments
There are no comments to display.