ImagingFmx.pas 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. {
  2. Vampyre Imaging Library
  3. by Marek Mauder
  4. https://github.com/galfar/imaginglib
  5. https://imaginglib.sourceforge.io
  6. - - - - -
  7. This Source Code Form is subject to the terms of the Mozilla Public
  8. License, v. 2.0. If a copy of the MPL was not distributed with this
  9. file, You can obtain one at https://mozilla.org/MPL/2.0.
  10. }
  11. { Functions and classes for interoperability between Imaging and
  12. FireMonkey framework.}
  13. unit ImagingFmx;
  14. {$I ImagingOptions.inc}
  15. {$IF not Defined (DCC) or (CompilerVersion < 25.0)}
  16. {$MESSAGE FATAL 'Needs at least Delphi XE4'}
  17. {$IFEND}
  18. interface
  19. uses
  20. Types,
  21. SysUtils,
  22. ImagingTypes,
  23. Imaging,
  24. ImagingFormats,
  25. ImagingClasses,
  26. ImagingUtility,
  27. UITypes,
  28. Fmx.Types,
  29. Fmx.Utils,
  30. Fmx.Graphics;
  31. { Converts image from TImageData record to FMX bitmap. Bitmap must be already instantiated.}
  32. procedure ConvertImageDataToFmxBitmap(const Image: TImageData; Bitmap: TBitmap);
  33. { Converts FMX bitmap to TImageData. Image Data must already instantiated.}
  34. procedure ConvertFmxBitmapToImageData(const Bitmap: TBitmap; Image: TImageData);
  35. { Converts image from TBaseImage instance to FMX bitmap. Bitmap must be already instantiated.}
  36. procedure ConvertImageToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap);
  37. { Copies rectangular area of pixels from TImageData record to existing FMX bitmap.}
  38. procedure CopyRectToFmxBitmap(const Image: TImageData; Bitmap: TBitmap;
  39. SrcX, SrcY, Width, Height, DstX, DstY: LongInt); overload;
  40. { Copies rectangular area of pixels from TBaseImage instance to existing FMX bitmap.}
  41. procedure CopyRectToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap;
  42. SrcX, SrcY, Width, Height, DstX, DstY: LongInt); overload;
  43. implementation
  44. procedure ConvertFmxBitmapToImageData(const Bitmap: TBitmap; Image: TImageData);
  45. var
  46. Color32: TColor32Rec;
  47. MapData: TBitmapData;
  48. SourceData: PAlphaColorRec;
  49. TargetData: PByte;
  50. X, Y, Bpp, SrcWidthBytes: Integer;
  51. TargetInfo: TImageFormatInfo;
  52. begin
  53. Bitmap.Map(TMapAccess.maRead, MapData);
  54. GetImageFormatInfo(Image.Format, TargetInfo);
  55. Bpp := TargetInfo.BytesPerPixel;
  56. SrcWidthBytes := Image.Width * Bpp;
  57. TargetData := @PByteArray(Image.Bits)[0];
  58. for Y := 0 to Bitmap.Height - 1 do
  59. for X:= 0 to Bitmap.Width - 1 do
  60. begin
  61. SourceData:= @PAlphaColorRecArray(MapData.Data)[Y * (MapData.Pitch div 4) + X];
  62. case TargetInfo.Format of
  63. ifIndex8:
  64. begin
  65. Image.Palette[TargetData^].R := SourceData^.R;
  66. Image.Palette[TargetData^].G := SourceData^.G;
  67. Image.Palette[TargetData^].B := SourceData^.B;
  68. Image.Palette[TargetData^].A := SourceData^.A;
  69. end;
  70. ifGray8:
  71. TargetData^ := SourceData.R;
  72. ifA8Gray8:
  73. begin
  74. TargetData^ := SourceData.R;
  75. PWordRec(TargetData).High := SourceData.A;
  76. end;
  77. ifGray16:
  78. PWord(TargetData)^ := SourceData.R;
  79. ifR8G8B8:
  80. begin
  81. PColor24Rec(TargetData)^.R := SourceData.R;
  82. PColor24Rec(TargetData)^.G := SourceData.G;
  83. PColor24Rec(TargetData)^.B := SourceData.B;
  84. end;
  85. ifA8R8G8B8:
  86. begin
  87. PColor32Rec(TargetData)^.A := SourceData^.B;
  88. PColor32Rec(TargetData)^.G := SourceData^.R;
  89. PColor32Rec(TargetData)^.R := SourceData^.G;
  90. PColor32Rec(TargetData)^.B := SourceData^.A;
  91. end;
  92. ifR16G16B16:
  93. begin
  94. PColor48Rec(TargetData).R := Round(SourceData.R * $FFFF / 255);
  95. PColor48Rec(TargetData).G := Round(SourceData.G * $FFFF / 255);
  96. PColor48Rec(TargetData).B := Round(SourceData.B * $FFFF / 255);
  97. end;
  98. ifA16R16G16B16:
  99. begin
  100. PColor64Rec(TargetData).R := Round(SourceData.R * $FFFF / 255);
  101. PColor64Rec(TargetData).G := Round(SourceData.G * $FFFF / 255);
  102. PColor64Rec(TargetData).B := Round(SourceData.B * $FFFF / 255);
  103. PColor64Rec(TargetData).A := Round(SourceData.A * $FFFF / 255);
  104. end;
  105. else
  106. Color32.R := SourceData^.R;
  107. Color32.G := SourceData^.G;
  108. Color32.B := SourceData^.B;
  109. Color32.A := SourceData^.A;
  110. TargetInfo.SetPixel32(TargetData,@TargetInfo, Image.Palette,Color32);
  111. end;
  112. Inc(TargetData, Bpp);
  113. end;
  114. Bitmap.Unmap(MapData);
  115. end;
  116. procedure ConvertImageDataToFmxBitmap(const Image: TImageData; Bitmap: TBitmap);
  117. begin
  118. Assert(TestImage(Image));
  119. Bitmap.SetSize(Image.Width, Image.Height);
  120. CopyRectToFmxBitmap(Image, Bitmap, 0, 0, Image.Width, Image.Height, 0, 0);
  121. end;
  122. procedure ConvertImageToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap);
  123. begin
  124. ConvertImageDataToFmxBitmap(Image.ImageDataPointer^, Bitmap);
  125. end;
  126. procedure ConvertToAlphaColorRec(SrcPix: PByte; DestPix: PAlphaColorRec;
  127. const SrcInfo: TImageFormatInfo; SrcPalette: PPalette32);
  128. var
  129. Color32:TColor32Rec;
  130. begin
  131. case SrcInfo.Format of
  132. ifIndex8:
  133. begin
  134. DestPix^.R := SrcPalette[SrcPix^].R;
  135. DestPix^.G := SrcPalette[SrcPix^].G;
  136. DestPix^.B := SrcPalette[SrcPix^].B;
  137. DestPix^.A := SrcPalette[SrcPix^].A;
  138. end;
  139. ifGray8:
  140. begin
  141. DestPix.R := SrcPix^;
  142. DestPix.G := SrcPix^;
  143. DestPix.B := SrcPix^;
  144. DestPix.A := 255;
  145. end;
  146. ifA8Gray8:
  147. begin
  148. DestPix.R := SrcPix^;
  149. DestPix.G := SrcPix^;
  150. DestPix.B := SrcPix^;
  151. DestPix.A := PWordRec(SrcPix).High;
  152. end;
  153. ifGray16:
  154. begin
  155. DestPix.R := PWord(SrcPix)^ shr 8;
  156. DestPix.G := DestPix.R;
  157. DestPix.B := DestPix.R;
  158. DestPix.A := 255;
  159. end;
  160. ifR8G8B8:
  161. begin
  162. DestPix.R := PColor24Rec(SrcPix)^.R;
  163. DestPix.G := PColor24Rec(SrcPix)^.G;
  164. DestPix.B := PColor24Rec(SrcPix)^.B;
  165. DestPix.A := 255;
  166. end;
  167. ifA8R8G8B8:
  168. begin
  169. DestPix^.R := PColor32Rec(SrcPix)^.R;
  170. DestPix^.G := PColor32Rec(SrcPix)^.G;
  171. DestPix^.B := PColor32Rec(SrcPix)^.B;
  172. DestPix^.A := PColor32Rec(SrcPix)^.A;
  173. end;
  174. ifR16G16B16:
  175. begin
  176. DestPix.R := PColor48Rec(SrcPix).R shr 8;
  177. DestPix.G := PColor48Rec(SrcPix).G shr 8;
  178. DestPix.B := PColor48Rec(SrcPix).B shr 8;
  179. DestPix.A := 255;
  180. end;
  181. ifA16R16G16B16:
  182. begin
  183. DestPix.R := PColor64Rec(SrcPix).R shr 8;
  184. DestPix.G := PColor64Rec(SrcPix).G shr 8;
  185. DestPix.B := PColor64Rec(SrcPix).B shr 8;
  186. DestPix.A := PColor64Rec(SrcPix).A shr 8;
  187. end;
  188. else
  189. Color32:=SrcInfo.GetPixel32(SrcPix, @SrcInfo, SrcPalette);
  190. DestPix^.R := Color32.R;
  191. DestPix^.G := Color32.G;
  192. DestPix^.B := Color32.B;
  193. DestPix^.A := Color32.A;
  194. end;
  195. end;
  196. procedure CopyRectToFmxBitmap(const Image: TImageData; Bitmap: TBitmap;
  197. SrcX, SrcY, Width, Height, DstX, DstY: LongInt);
  198. var
  199. TempImage: TImageData;
  200. X, Y, Bpp, SrcWidthBytes, MoveBytes: Integer;
  201. SrcPtr: PByte;
  202. Info: TImageFormatInfo;
  203. MapData: TBitmapData;
  204. DstPtr: PAlphaColorRec;
  205. ARGB: TAlphaColorRec;
  206. begin
  207. Assert(TestImage(Image) and not Bitmap.IsEmpty);
  208. ClipCopyBounds(SrcX, SrcY, Width, Height, DstX, DstY, Image.Width, Image.Height,
  209. Rect(0, 0, Bitmap.Width, Bitmap.Height));
  210. GetImageFormatInfo(Image.Format, Info);
  211. if not Info.IsSpecial then
  212. begin
  213. Bpp := Info.BytesPerPixel;
  214. SrcWidthBytes := Image.Width * Bpp;
  215. MoveBytes := Width * Bpp;
  216. SrcPtr := @PByteArray(Image.Bits)[SrcY * SrcWidthBytes + SrcX * Bpp];
  217. Bitmap.Map(TMapAccess.maReadWrite, MapData);
  218. for Y := 0 to Height - 1 do
  219. begin
  220. if Info.Format = ifA8R8G8B8 then
  221. begin
  222. for X := 0 to Width - 1 do
  223. begin
  224. DstPtr := @PColor32RecArray(MapData.Data)[Y * (MapData.Pitch div 4) + X];
  225. Move(SrcPtr^, ARGB, 4);
  226. if MapData.PixelFormat = TPixelFormat.RGBA then
  227. SwapValues(ARGB.R, ARGB.B);
  228. DstPtr^.A := ARGB.A;
  229. DstPtr^.R := ARGB.R;
  230. DstPtr^.G := ARGB.G;
  231. DstPtr^.B := ARGB.B;
  232. Inc(SrcPtr, 4);
  233. end;
  234. end
  235. else
  236. begin
  237. for X := 0 to Width - 1 do
  238. begin
  239. DstPtr := @PColor32RecArray(MapData.Data)[Y * (MapData.Pitch div 4)+X];
  240. ConvertToAlphaColorRec(SrcPtr, DstPtr, Info, Image.Palette);
  241. Inc(SrcPtr, Bpp);
  242. end;
  243. end;
  244. end;
  245. end
  246. else
  247. begin
  248. InitImage(TempImage);
  249. CloneImage(Image, TempImage);
  250. ConvertImage(TempImage, ifA8R8G8B8);
  251. try
  252. CopyRectToFmxBitmap(TempImage, Bitmap, SrcX, SrcY, Width, Height, DstX, DstY);
  253. finally
  254. FreeImage(TempImage);
  255. end;
  256. end;
  257. Bitmap.UnMap(MapData);
  258. end;
  259. procedure CopyRectToFmxBitmap(Image: TBaseImage; Bitmap: TBitmap;
  260. SrcX, SrcY, Width, Height, DstX, DstY: LongInt);
  261. begin
  262. CopyRectToFmxBitmap(Image.ImageDataPointer^, Bitmap,
  263. SrcX, SrcY, Width, Height, DstX, DstY);
  264. end;
  265. {
  266. File Notes:
  267. -- 0.77.1 Changes/Bug Fixes ---------------------------------
  268. - Removed support for old FMX versions (XE2 etc.)
  269. - Support for current FMX version (XE4+) contributed by Ken Schafer.
  270. -- 0.77 Changes/Bug Fixes -----------------------------------
  271. - Unit created with initial stuff, working with FMX1 in Delphi XE2.
  272. }
  273. end.