GR32.ImageFormats.TPicture.pas 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. unit GR32.ImageFormats.TPicture;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is image format support for Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Anders Melander <[email protected]>
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2008-2022
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * ***** END LICENSE BLOCK ***** *)
  31. interface
  32. {$include GR32.inc}
  33. implementation
  34. uses
  35. Classes,
  36. {$ifdef FPC}
  37. LCLType, // LCLType must be after Classes so we get the correct THandle
  38. {$endif FPC}
  39. Graphics,
  40. Clipbrd,
  41. GR32,
  42. GR32.ImageFormats;
  43. //------------------------------------------------------------------------------
  44. //
  45. // TImageFormatAdapterTPicture
  46. //
  47. //------------------------------------------------------------------------------
  48. // Implements IImageFormatAdapter for the TPicture class.
  49. //------------------------------------------------------------------------------
  50. type
  51. TImageFormatAdapterTPicture = class(TCustomImageFormatAdapter,
  52. IImageFormatAdapter)
  53. strict protected
  54. // IImageFormatAdapter
  55. function CanAssignFrom(Source: TPersistent): boolean; override;
  56. function AssignFrom(Dest: TCustomBitmap32; Source: TPersistent): boolean; override;
  57. function CanAssignTo(Dest: TPersistent): boolean; override;
  58. function AssignTo(Source: TCustomBitmap32; Dest: TPersistent): boolean; override;
  59. end;
  60. //------------------------------------------------------------------------------
  61. // IImageFormatAdapter
  62. //------------------------------------------------------------------------------
  63. function TImageFormatAdapterTPicture.CanAssignFrom(Source: TPersistent): boolean;
  64. begin
  65. Result := (Source is TPicture) and (TPicture(Source).Graphic <> nil) and
  66. ImageFormatManager.Adapters.CanAssignFrom(TPicture(Source).Graphic);
  67. end;
  68. function TImageFormatAdapterTPicture.AssignFrom(Dest: TCustomBitmap32; Source: TPersistent): boolean;
  69. begin
  70. Result := (Source is TPicture) and (TPicture(Source).Graphic <> nil) and
  71. // Recurse and try to assign from the TGraphic
  72. ImageFormatManager.Adapters.AssignFrom(Dest, TPicture(Source).Graphic);
  73. end;
  74. //------------------------------------------------------------------------------
  75. function TImageFormatAdapterTPicture.CanAssignTo(Dest: TPersistent): boolean;
  76. begin
  77. if (Dest is TPicture) then
  78. begin
  79. // Try to assign to TPicture.Graphic, fallback to TBitmap
  80. Result := ((TPicture(Dest).Graphic <> nil) and ImageFormatManager.Adapters.CanAssignTo(TPicture(Dest).Graphic)) or
  81. ImageFormatManager.Adapters.CanAssignTo(TPicture(Dest).Bitmap); // Note: This potentially modifies the TPicture
  82. end else
  83. Result := False;
  84. end;
  85. function TImageFormatAdapterTPicture.AssignTo(Source: TCustomBitmap32; Dest: TPersistent): boolean;
  86. begin
  87. if (Dest is TPicture) then
  88. begin
  89. // Try to assign to TPicture.Graphic, fallback to TBitmap
  90. Result := (TPicture(Dest).Graphic <> nil) and
  91. // Recurse and try to assign to the TGraphic
  92. ImageFormatManager.Adapters.AssignTo(Source, TPicture(Dest).Graphic);
  93. if (not Result) then
  94. // Recurse and try to assign to TBitmap
  95. Result := ImageFormatManager.Adapters.AssignTo(Source, TPicture(Dest).Bitmap);
  96. end else
  97. Result := False;
  98. end;
  99. //------------------------------------------------------------------------------
  100. //
  101. // TImageFormatReaderTPicture
  102. //
  103. //------------------------------------------------------------------------------
  104. // Implements IImageFormatReader for the TPicture class.
  105. // Basically this reader will support all TGraphic implementations that can
  106. // read from a stream.
  107. // Additionally IImageFormatFileReader is implemented to allow TPicture to
  108. // determine the image format based on the file type.
  109. //------------------------------------------------------------------------------
  110. type
  111. TImageFormatReaderTPicture = class(TCustomImageFormat,
  112. IImageFormatReader,
  113. IImageFormatFileReader,
  114. IImageFormatClipboardFormat)
  115. strict private
  116. // IImageFormatReader
  117. function CanLoadFromStream(AStream: TStream): boolean;
  118. function LoadFromStream(ADest: TCustomBitmap32; AStream: TStream): boolean;
  119. strict private
  120. // IImageFormatFileReader
  121. function LoadFromFile(ADest: TCustomBitmap32; const AFilename: string): boolean;
  122. strict private
  123. // IImageFormatClipboardFormat
  124. function SupportsClipboardFormat(AFormat: TClipboardFormat): Boolean;
  125. function PasteFromClipboard(ADest: TCustomBitmap32): boolean;
  126. function LoadFromClipboardFormat(ADest: TCustomBitmap32; AFormat: TClipboardFormat; AData: THandle; APalette: THandle): boolean;
  127. end;
  128. //------------------------------------------------------------------------------
  129. // IImageFormatReader
  130. //------------------------------------------------------------------------------
  131. function TImageFormatReaderTPicture.CanLoadFromStream(AStream: TStream): boolean;
  132. begin
  133. // TPicture does not have a CanLoadFromStream so this is a last-ditch effort.
  134. Result := True;
  135. end;
  136. function TImageFormatReaderTPicture.LoadFromStream(ADest: TCustomBitmap32; AStream: TStream): boolean;
  137. {$ifdef LOADFROMSTREAM}
  138. var
  139. Picture: TPicture;
  140. {$endif LOADFROMSTREAM}
  141. begin
  142. {$ifdef LOADFROMSTREAM}
  143. // TPicture.LoadFromStream requires TGraphic.CanLoadFromStream.
  144. // Introduced in Delphi 10.2 and present in FPC as well
  145. // See issue #145
  146. Picture := TPicture.Create;
  147. try
  148. try
  149. Picture.LoadFromStream(AStream);
  150. except
  151. on E: EInvalidGraphic do
  152. Exit(False);
  153. end;
  154. ADest.Assign(Picture.Graphic);
  155. finally
  156. Picture.Free;
  157. end;
  158. Result := True;
  159. {$else LOADFROMSTREAM}
  160. Result := False;
  161. {$endif LOADFROMSTREAM}
  162. end;
  163. //------------------------------------------------------------------------------
  164. // IImageFormatFileReader
  165. //------------------------------------------------------------------------------
  166. function TImageFormatReaderTPicture.LoadFromFile(ADest: TCustomBitmap32; const AFilename: string): boolean;
  167. var
  168. Picture: TPicture;
  169. begin
  170. Picture := TPicture.Create;
  171. try
  172. try
  173. Picture.LoadFromFile(AFilename);
  174. except
  175. on E: EInvalidGraphic do
  176. Exit(False);
  177. end;
  178. ADest.Assign(Picture.Graphic);
  179. finally
  180. Picture.Free;
  181. end;
  182. Result := True;
  183. end;
  184. //------------------------------------------------------------------------------
  185. // IImageFormatClipboard
  186. //------------------------------------------------------------------------------
  187. function TImageFormatReaderTPicture.SupportsClipboardFormat(AFormat: TClipboardFormat): Boolean;
  188. begin
  189. Result := TPicture.SupportsClipboardFormat(AFormat);
  190. end;
  191. function TImageFormatReaderTPicture.PasteFromClipboard(ADest: TCustomBitmap32): boolean;
  192. var
  193. Picture: TPicture;
  194. begin
  195. Picture := TPicture.Create;
  196. try
  197. Picture.Assign(Clipboard);
  198. ADest.Assign(Picture.Graphic);
  199. finally
  200. Picture.Free;
  201. end;
  202. Result := True;
  203. end;
  204. function TImageFormatReaderTPicture.LoadFromClipboardFormat(ADest: TCustomBitmap32; AFormat: TClipboardFormat; AData: THandle; APalette: THandle): boolean;
  205. var
  206. Picture: TPicture;
  207. begin
  208. Picture := TPicture.Create;
  209. try
  210. {$ifdef FPC}
  211. Picture.LoadFromClipboardFormat(AFormat);
  212. {$else FPC}
  213. Picture.LoadFromClipboardFormat(AFormat, AData, APalette);
  214. {$endif FPC}
  215. ADest.Assign(Picture.Graphic);
  216. finally
  217. Picture.Free;
  218. end;
  219. Result := True;
  220. end;
  221. //------------------------------------------------------------------------------
  222. //------------------------------------------------------------------------------
  223. //------------------------------------------------------------------------------
  224. var
  225. ImageFormatAdapterHandle: integer = 0;
  226. ImageFormatReaderHandle: integer = 0;
  227. initialization
  228. ImageFormatAdapterHandle := ImageFormatManager.RegisterImageFormat(TImageFormatAdapterTPicture.Create, ImageFormatPriorityNormal);
  229. {$ifdef LOADFROMSTREAM}
  230. ImageFormatReaderHandle := ImageFormatManager.RegisterImageFormat(TImageFormatReaderTPicture.Create, ImageFormatPriorityWorst);
  231. {$endif LOADFROMSTREAM}
  232. finalization
  233. ImageFormatManager.UnregisterImageFormat(ImageFormatAdapterHandle);
  234. ImageFormatManager.UnregisterImageFormat(ImageFormatReaderHandle);
  235. end.