| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- {
- Vampyre Imaging Library
- by Marek Mauder
- https://github.com/galfar/imaginglib
- https://imaginglib.sourceforge.io
- - - - - -
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at https://mozilla.org/MPL/2.0.
- }
- {
- Functions and classes for interoperability between Imaging and
- FireMonkey framework.
- Currently has conversion functions between FMX TBitmap (RGBA and BGRA pixel formats)
- and Imaging's TImageData and TBaseImage.
- }
- unit ImagingFmx;
- {$I ImagingOptions.inc}
- {$IF not Defined (DCC) or (CompilerVersion < 25.0)}
- {$MESSAGE FATAL 'Needs at least Delphi XE4, probably higher'}
- {$IFEND}
- interface
- uses
- Types,
- SysUtils,
- ImagingTypes,
- Imaging,
- ImagingFormats,
- ImagingClasses,
- ImagingUtility,
- UITypes,
- UIConsts,
- FMX.Types,
- FMX.Utils,
- FMX.Graphics;
- { Converts image from TImageData record to FMX bitmap. Bitmap must be already instantiated.}
- procedure ConvertImageDataToFmxBitmap(const Image: TImageData; Bitmap: TBitmap);
- { Converts FMX bitmap to TImageData. Image must be already initialized.}
- procedure ConvertFmxBitmapToImageData(const Bitmap: TBitmap; Image: TImageData);
- { Converts image from TBaseImage instance to FMX bitmap. Bitmap must be already instantiated.}
- procedure ConvertImageToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap);
- { Converts FMX bitmap to TBaseImage. Image must be already instantiated.}
- procedure ConvertFmxBitmapToImage(const Bitmap: TBitmap; Image: TBaseImage);
- { Copies rectangular area of pixels from TImageData record to existing FMX bitmap.}
- procedure CopyRectToFmxBitmap(const Image: TImageData; Bitmap: TBitmap;
- SrcX, SrcY, Width, Height, DstX, DstY: LongInt); overload;
- { Copies rectangular area of pixels from TBaseImage instance to existing FMX bitmap.}
- procedure CopyRectToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap;
- SrcX, SrcY, Width, Height, DstX, DstY: LongInt); overload;
- implementation
- procedure ConvertFmxBitmapToImageData(const Bitmap: TBitmap; Image: TImageData);
- var
- Color32: TColor32Rec;
- MapData: TBitmapData;
- SourceData: PAlphaColorRec;
- TargetData: PByte;
- X, Y, Bpp, SrcWidthBytes: Integer;
- TargetInfo: TImageFormatInfo;
- begin
- Assert(TestImage(Image) and not Bitmap.IsEmpty);
- Bitmap.Map(TMapAccess.Read, MapData);
- GetImageFormatInfo(Image.Format, TargetInfo);
- Bpp := TargetInfo.BytesPerPixel;
- SrcWidthBytes := Image.Width * Bpp;
- TargetData := @PByteArray(Image.Bits)[0];
- for Y := 0 to Bitmap.Height - 1 do
- for X := 0 to Bitmap.Width - 1 do
- begin
- SourceData:= @PAlphaColorRecArray(MapData.Data)[Y * (MapData.Pitch div 4) + X];
- case TargetInfo.Format of
- ifIndex8:
- begin
- Image.Palette[TargetData^].R := SourceData^.R;
- Image.Palette[TargetData^].G := SourceData^.G;
- Image.Palette[TargetData^].B := SourceData^.B;
- Image.Palette[TargetData^].A := SourceData^.A;
- end;
- ifGray8:
- TargetData^ := SourceData.R;
- ifA8Gray8:
- begin
- TargetData^ := SourceData.R;
- PWordRec(TargetData).High := SourceData.A;
- end;
- ifGray16:
- PWord(TargetData)^ := SourceData.R;
- ifR8G8B8:
- begin
- PColor24Rec(TargetData)^.R := SourceData.R;
- PColor24Rec(TargetData)^.G := SourceData.G;
- PColor24Rec(TargetData)^.B := SourceData.B;
- end;
- ifA8R8G8B8:
- begin
- PColor32Rec(TargetData)^.A := SourceData^.B;
- PColor32Rec(TargetData)^.G := SourceData^.R;
- PColor32Rec(TargetData)^.R := SourceData^.G;
- PColor32Rec(TargetData)^.B := SourceData^.A;
- end;
- ifR16G16B16:
- begin
- PColor48Rec(TargetData).R := Round(SourceData.R * $FFFF / 255);
- PColor48Rec(TargetData).G := Round(SourceData.G * $FFFF / 255);
- PColor48Rec(TargetData).B := Round(SourceData.B * $FFFF / 255);
- end;
- ifA16R16G16B16:
- begin
- PColor64Rec(TargetData).R := Round(SourceData.R * $FFFF / 255);
- PColor64Rec(TargetData).G := Round(SourceData.G * $FFFF / 255);
- PColor64Rec(TargetData).B := Round(SourceData.B * $FFFF / 255);
- PColor64Rec(TargetData).A := Round(SourceData.A * $FFFF / 255);
- end;
- else
- Color32.R := SourceData^.R;
- Color32.G := SourceData^.G;
- Color32.B := SourceData^.B;
- Color32.A := SourceData^.A;
- TargetInfo.SetPixel32(TargetData,@TargetInfo, Image.Palette,Color32);
- end;
- Inc(TargetData, Bpp);
- end;
- Bitmap.Unmap(MapData);
- end;
- procedure ConvertFmxBitmapToImage(const Bitmap: TBitmap; Image: TBaseImage);
- begin
- ConvertFmxBitmapToImageData(Bitmap, Image.ImageDataPointer^);
- end;
- procedure ConvertImageDataToFmxBitmap(const Image: TImageData; Bitmap: TBitmap);
- begin
- Assert(TestImage(Image));
- Bitmap.SetSize(Image.Width, Image.Height);
- CopyRectToFmxBitmap(Image, Bitmap, 0, 0, Image.Width, Image.Height, 0, 0);
- end;
- procedure ConvertImageToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap);
- begin
- ConvertImageDataToFmxBitmap(Image.ImageDataPointer^, Bitmap);
- end;
- procedure ConvertToAlphaColorRec(SrcPix: PByte; DestPix: PAlphaColorRec;
- const SrcInfo: TImageFormatInfo; SrcPalette: PPalette32);
- var
- Color32: TColor32Rec;
- begin
- case SrcInfo.Format of
- ifIndex8:
- begin
- DestPix.R := SrcPalette[SrcPix^].R;
- DestPix.G := SrcPalette[SrcPix^].G;
- DestPix.B := SrcPalette[SrcPix^].B;
- DestPix.A := SrcPalette[SrcPix^].A;
- end;
- ifGray8:
- begin
- DestPix.R := SrcPix^;
- DestPix.G := SrcPix^;
- DestPix.B := SrcPix^;
- DestPix.A := 255;
- end;
- ifR8G8B8:
- begin
- PColor24Rec(DestPix)^ := PColor24Rec(SrcPix)^;
- DestPix.A := 255;
- end;
- ifA8R8G8B8:
- PColor32Rec(DestPix)^ := PColor32Rec(SrcPix)^;
- else
- PColor32Rec(DestPix)^ := SrcInfo.GetPixel32(SrcPix, @SrcInfo, SrcPalette);
- end;
- end;
- procedure CopyRectToFmxBitmap(const Image: TImageData; Bitmap: TBitmap;
- SrcX, SrcY, Width, Height, DstX, DstY: LongInt);
- var
- TempImage: TImageData;
- X, Y, Bpp, SrcLineBytes: Integer;
- SrcPtr: PByte;
- Info: TImageFormatInfo;
- MapData: TBitmapData;
- DstPtr: PAlphaColorRec;
- BGRA: TAlphaColorRec;
- begin
- Assert(TestImage(Image) and not Bitmap.IsEmpty);
- if not (Bitmap.PixelFormat in [TPixelFormat.RGBA, TPixelFormat.BGRA]) then
- raise Exception.CreateFmt('Unsupported FMX TBitmap pixel format "%s"', [PixelFormatToString(Bitmap.PixelFormat)]);
- ClipCopyBounds(SrcX, SrcY, Width, Height, DstX, DstY, Image.Width,
- Image.Height, Rect(0, 0, Bitmap.Width, Bitmap.Height));
- GetImageFormatInfo(Image.Format, Info);
- if not Info.IsSpecial then
- begin
- Bpp := Info.BytesPerPixel;
- SrcLineBytes := Image.Width * Bpp;
- Bitmap.Map(TMapAccess.Write, MapData);
- for Y := 0 to Height - 1 do
- begin
- SrcPtr := @PByteArray(Image.Bits)[(SrcY + Y) * SrcLineBytes + SrcX * Bpp];
- DstPtr := @PAlphaColorRecArray(MapData.GetScanline(DstY + Y))[DstX];
- for X := 0 to Width - 1 do
- begin
- if Info.Format = ifA8R8G8B8 then
- BGRA := PAlphaColorRec(SrcPtr)^
- else
- ConvertToAlphaColorRec(SrcPtr, @BGRA, Info, Image.Palette);
- if MapData.PixelFormat = TPixelFormat.RGBA then
- SwapValues(BGRA.R, BGRA.B);
- // Alpha premultiplication is needed for FMX bitmaps to display correctly in TImage etc.
- DstPtr.Color := PremultiplyAlpha(BGRA.Color);
- Inc(SrcPtr, Bpp);
- Inc(DstPtr);
- end;
- end;
- end
- else
- begin
- InitImage(TempImage);
- CloneImage(Image, TempImage);
- ConvertImage(TempImage, ifA8R8G8B8);
- try
- CopyRectToFmxBitmap(TempImage, Bitmap, SrcX, SrcY, Width, Height, DstX, DstY);
- finally
- FreeImage(TempImage);
- end;
- end;
- Bitmap.Unmap(MapData);
- end;
- procedure CopyRectToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap;
- SrcX, SrcY, Width, Height, DstX, DstY: LongInt);
- begin
- CopyRectToFmxBitmap(Image.ImageDataPointer^, Bitmap,
- SrcX, SrcY, Width, Height, DstX, DstY);
- end;
- end.
|