GR32.ImageFormats.PNG32.pas 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. unit GR32.ImageFormats.PNG32;
  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 PNG 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. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$include GR32.inc}
  35. // Define GR32_CLIPBOARD_PNG to enable the "PNG" clipboard format.
  36. //
  37. // When this clipboard format is enabled, copying a TBitmap32 to the clipboard
  38. // will also place a copy of the bitmap in PNG format onto the clipboard and
  39. // pasting from the clipboard will also support the PNG format.
  40. {$define GR32_CLIPBOARD_PNG}
  41. const
  42. ClipboardFormatNamePNG = 'PNG';
  43. var
  44. CF_PNG: Word = 0;
  45. //------------------------------------------------------------------------------
  46. implementation
  47. uses
  48. Classes,
  49. Graphics,
  50. {$if defined(GR32_CLIPBOARD_PNG)}
  51. Clipbrd,
  52. {$if defined(MSWINDOWS)}
  53. Windows,
  54. {$ifend}
  55. GR32_Clipboard,
  56. {$ifend}
  57. GR32,
  58. GR32_Png,
  59. GR32_PortableNetworkGraphic,
  60. GR32.ImageFormats;
  61. resourcestring
  62. sImageFormatPNGName = 'PNG images';
  63. //------------------------------------------------------------------------------
  64. //
  65. // TImageFormatAdapterPNG32
  66. //
  67. //------------------------------------------------------------------------------
  68. // Implements IImageFormatAdapter for the PNG image format using the GR32
  69. // TPortableNetworkGraphic32 class.
  70. //------------------------------------------------------------------------------
  71. type
  72. TImageFormatAdapterPNG32 = class(TCustomImageFormatAdapter,
  73. IImageFormatAdapter,
  74. IImageFormatFileInfo,
  75. IImageFormatReader,
  76. IImageFormatWriter,
  77. IImageFormatAux)
  78. strict protected
  79. // IImageFormatAdapter
  80. function CanAssignFrom(Source: TPersistent): boolean; override;
  81. function AssignFrom(Dest: TCustomBitmap32; Source: TPersistent): boolean; override;
  82. function CanAssignTo(Dest: TPersistent): boolean; override;
  83. function AssignTo(Source: TCustomBitmap32; Dest: TPersistent): boolean; override;
  84. private
  85. // IImageFormatFileInfo
  86. function ImageFormatDescription: string;
  87. function ImageFormatFileTypes: TFileTypes;
  88. private
  89. // IImageFormatReader
  90. function CanLoadFromStream(AStream: TStream): boolean;
  91. function LoadFromStream(ADest: TCustomBitmap32; AStream: TStream): boolean;
  92. private
  93. // IImageFormatWriter
  94. procedure SaveToStream(ASource: TCustomBitmap32; AStream: TStream);
  95. private
  96. // IImageFormatAux
  97. function IsAuxFormat(Source: TCustomBitmap32; Dest: TPersistent): boolean;
  98. end;
  99. TPortableNetworkGraphic32Cracker = class(TPortableNetworkGraphic32);
  100. //------------------------------------------------------------------------------
  101. // IImageFormatAdapter
  102. //------------------------------------------------------------------------------
  103. function TImageFormatAdapterPNG32.CanAssignFrom(Source: TPersistent): boolean;
  104. begin
  105. Result := (Source is TPortableNetworkGraphic);
  106. {$if defined(GR32_CLIPBOARD_PNG)}
  107. Result := Result or ((Source is TClipboard) and (TClipboard(Source).HasFormat(CF_PNG)));
  108. {$ifend}
  109. end;
  110. function TImageFormatAdapterPNG32.AssignFrom(Dest: TCustomBitmap32; Source: TPersistent): boolean;
  111. var
  112. PNG32: TPortableNetworkGraphic32;
  113. {$if defined(GR32_CLIPBOARD_PNG)}
  114. Stream: TStream;
  115. {$ifend}
  116. begin
  117. if (Source is TPortableNetworkGraphic32) then
  118. begin
  119. // AssignTo avoids recursion
  120. TPortableNetworkGraphic32Cracker(Source).AssignTo(Dest);
  121. Result := True;
  122. end else
  123. if (Source is TPortableNetworkGraphic) then
  124. begin
  125. PNG32 := TPortableNetworkGraphic32.Create;
  126. try
  127. PNG32.Assign(Source);
  128. TPortableNetworkGraphic32Cracker(PNG32).AssignTo(Dest);
  129. finally
  130. PNG32.Free;
  131. end;
  132. Result := True;
  133. end else
  134. {$if defined(GR32_CLIPBOARD_PNG)}
  135. if (Source is TClipboard) then
  136. begin
  137. if (not Clipboard.HasFormat(CF_PNG)) then
  138. Exit(False);
  139. Dest.BeginUpdate;
  140. try
  141. {$ifndef FPC}
  142. Clipboard.Open;
  143. {$endif FPC}
  144. try
  145. Stream := TClipboardMemoryStream.Create(CF_PNG);
  146. try
  147. PNG32 := TPortableNetworkGraphic32.Create;
  148. try
  149. PNG32.LoadFromStream(Stream);
  150. TPortableNetworkGraphic32Cracker(PNG32).AssignTo(Dest);
  151. finally
  152. PNG32.Free;
  153. end;
  154. finally
  155. Stream.Free;
  156. end;
  157. finally
  158. {$ifndef FPC}
  159. Clipboard.Close;
  160. {$endif FPC}
  161. end;
  162. finally
  163. Dest.EndUpdate;
  164. end;
  165. Result := True;
  166. end else
  167. {$ifend}
  168. Result := inherited;
  169. end;
  170. //------------------------------------------------------------------------------
  171. function TImageFormatAdapterPNG32.CanAssignTo(Dest: TPersistent): boolean;
  172. begin
  173. Result := (Dest is TPortableNetworkGraphic);
  174. {$if defined(GR32_CLIPBOARD_PNG)}
  175. Result := Result or (Dest is TClipboard);
  176. {$ifend}
  177. end;
  178. {$ifdef FPC}
  179. type
  180. TMemoryStreamCracker = class(TMemoryStream);
  181. {$endif FPC}
  182. function TImageFormatAdapterPNG32.AssignTo(Source: TCustomBitmap32; Dest: TPersistent): boolean;
  183. var
  184. PNG32: TPortableNetworkGraphic32;
  185. {$if defined(GR32_CLIPBOARD_PNG)}
  186. Stream: TStream;
  187. {$ifend}
  188. begin
  189. if (Dest is TPortableNetworkGraphic32) then
  190. begin
  191. Dest.Assign(Source);
  192. Result := True;
  193. end else
  194. if (Dest is TPortableNetworkGraphic) then
  195. begin
  196. PNG32 := TPortableNetworkGraphic32.Create;
  197. try
  198. PNG32.Assign(Source);
  199. Dest.Assign(PNG32);
  200. finally
  201. PNG32.Free;
  202. end;
  203. Result := True;
  204. end else
  205. {$if defined(GR32_CLIPBOARD_PNG)}
  206. if (Dest is TClipboard) then
  207. begin
  208. {$ifndef FPC}
  209. Stream := TOwnedGlobalMemoryStream.Create(1024);
  210. {$else FPC}
  211. Stream := TMemoryStream.Create;
  212. {$endif FPC}
  213. try
  214. {$ifdef FPC}
  215. TMemoryStreamCracker(Stream).Capacity := 1024;
  216. {$endif FPC}
  217. SaveToStream(Source, Stream);
  218. {$ifndef FPC}
  219. Clipboard.SetAsHandle(CF_PNG, TGlobalMemoryStream(Stream).ReleaseHandle);
  220. {$else FPC}
  221. Clipboard.AddFormat(CF_PNG, Stream);
  222. {$endif FPC}
  223. finally
  224. Stream.Free;
  225. end;
  226. Result := True;
  227. end else
  228. {$ifend}
  229. Result := inherited;
  230. end;
  231. //------------------------------------------------------------------------------
  232. // IImageFormatFileInfo
  233. //------------------------------------------------------------------------------
  234. function TImageFormatAdapterPNG32.ImageFormatFileTypes: TFileTypes;
  235. begin
  236. Result := ['png'];
  237. end;
  238. function TImageFormatAdapterPNG32.ImageFormatDescription: string;
  239. begin
  240. Result := sImageFormatPNGName;
  241. end;
  242. //------------------------------------------------------------------------------
  243. // IImageFormatReader
  244. //------------------------------------------------------------------------------
  245. function TImageFormatAdapterPNG32.CanLoadFromStream(AStream: TStream): boolean;
  246. begin
  247. Result := IsValidPNG(AStream);
  248. end;
  249. function TImageFormatAdapterPNG32.LoadFromStream(ADest: TCustomBitmap32; AStream: TStream): boolean;
  250. var
  251. PNG32: TPortableNetworkGraphic32;
  252. begin
  253. if (not IsValidPNG(AStream)) then
  254. Exit(False);
  255. PNG32 := TPortableNetworkGraphic32.Create;
  256. try
  257. PNG32.LoadFromStream(AStream);
  258. TPortableNetworkGraphic32Cracker(PNG32).AssignTo(ADest);
  259. finally
  260. PNG32.Free;
  261. end;
  262. Result := True;
  263. end;
  264. //------------------------------------------------------------------------------
  265. // IImageFormatWriter
  266. //------------------------------------------------------------------------------
  267. procedure TImageFormatAdapterPNG32.SaveToStream(ASource: TCustomBitmap32; AStream: TStream);
  268. var
  269. PNG32: TPortableNetworkGraphic32;
  270. begin
  271. PNG32 := TPortableNetworkGraphic32.Create;
  272. try
  273. PNG32.Assign(ASource);
  274. PNG32.SaveToStream(AStream);
  275. finally
  276. PNG32.Free;
  277. end;
  278. end;
  279. //------------------------------------------------------------------------------
  280. // IImageFormatAux
  281. //------------------------------------------------------------------------------
  282. function TImageFormatAdapterPNG32.IsAuxFormat(Source: TCustomBitmap32; Dest: TPersistent): boolean;
  283. begin
  284. {$if defined(GR32_CLIPBOARD_PNG)}
  285. Result := (Dest is TClipboard);
  286. {$else}
  287. Result := False;
  288. {$ifend}
  289. end;
  290. //------------------------------------------------------------------------------
  291. //------------------------------------------------------------------------------
  292. //------------------------------------------------------------------------------
  293. var
  294. ImageFormatHandle: integer = 0;
  295. initialization
  296. ImageFormatHandle := ImageFormatManager.RegisterImageFormat(TImageFormatAdapterPNG32.Create, ImageFormatPriorityBetter);
  297. {$if defined(GR32_CLIPBOARD_PNG)}
  298. CF_PNG := RegisterClipboardFormat(ClipboardFormatNamePNG);
  299. {$ifend}
  300. finalization
  301. ImageFormatManager.UnregisterImageFormat(ImageFormatHandle);
  302. end.