uloadimage.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit ULoadImage;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, LazPaintType, BGRABitmap, BGRALayers, BGRASVGOriginal;
  7. function LoadFlatImageUTF8(AFilename: string; AEntryToLoad: integer = -1): TImageEntry;
  8. procedure FreeMultiImage(var images: ArrayOfImageEntry);
  9. function AbleToLoadUTF8(AFilename: string): boolean;
  10. function LoadSVGImageUTF8(AFilename: string): TBGRALayeredBitmap;
  11. function LoadSVGOriginalUTF8(AFilename: string): TBGRALayerSVGOriginal;
  12. implementation
  13. uses FileUtil, BGRAAnimatedGif, Graphics, UMultiImage,
  14. BGRAReadLzp, LCLProc, BGRABitmapTypes, BGRAReadPng,
  15. UFileSystem, BGRAIconCursor, BGRAReadTiff,
  16. Dialogs, math, URaw;
  17. function LoadIcoEntryFromStream(AStream: TStream; AIndex: integer): TImageEntry;
  18. var ico: TBGRAIconCursor;
  19. begin
  20. if AIndex < 0 then raise exception.Create('Index out of bounds');
  21. result := TImageEntry.Empty;
  22. ico := TBGRAIconCursor.Create;
  23. try
  24. ico.LoadFromStream(AStream);
  25. result.bmp := ico.GetBitmap(AIndex) as TBGRABitmap;
  26. result.bmp.Caption := IntTostr(ico.Width[AIndex])+'x'+IntToStr(ico.Height[AIndex])+' '+IntToStr(ico.BitDepth[AIndex])+'bit';
  27. if Assigned(result.bmp.XorMask) then result.bmp.XorMask.Caption := result.bmp.Caption + ' (xor)';
  28. result.bpp := ico.BitDepth[AIndex];
  29. result.frameIndex:= AIndex;
  30. result.frameCount:= ico.Count;
  31. finally
  32. ico.Free;
  33. end;
  34. end;
  35. function LoadIcoMultiImageFromStream(AStream: TStream): ArrayOfImageEntry;
  36. var ico: TBGRAIconCursor; i: integer;
  37. begin
  38. ico := TBGRAIconCursor.Create;
  39. try
  40. ico.LoadFromStream(AStream);
  41. setlength(result,ico.Count);
  42. for i := 0 to ico.Count-1 do
  43. begin
  44. result[i].bmp := ico.GetBitmap(i) as TBGRABitmap;
  45. result[i].bmp.Caption := IntTostr(ico.Width[i])+'x'+IntToStr(ico.Height[i])+' '+IntToStr(ico.BitDepth[i])+'bit';
  46. if Assigned(result[i].bmp.XorMask) then result[i].bmp.XorMask.Caption := result[i].bmp.Caption + ' (xor)';
  47. result[i].bpp := ico.BitDepth[i];
  48. result[i].frameIndex:= i;
  49. result[i].frameCount:= ico.Count;
  50. end;
  51. finally
  52. ico.Free;
  53. end;
  54. end;
  55. function LoadGifEntryFromStream(AStream: TStream; AIndex: integer): TImageEntry;
  56. var gif: TBGRAAnimatedGif;
  57. begin
  58. if AIndex < 0 then raise exception.Create('Index out of bounds');
  59. result := TImageEntry.Empty;
  60. gif := TBGRAAnimatedGif.Create(AStream);
  61. try
  62. gif.CurrentImage:= AIndex;
  63. result.bmp := gif.MemBitmap.Duplicate as TBGRABitmap;
  64. result.bmp.Caption := 'Frame'+IntToStr(AIndex+1);
  65. result.frameIndex := AIndex;
  66. result.frameCount := gif.Count;
  67. finally
  68. gif.Free;
  69. end;
  70. end;
  71. function LoadGifMultiImageFromStream(AStream: TStream): ArrayOfImageEntry;
  72. var gif: TBGRAAnimatedGif; i: integer;
  73. begin
  74. gif := TBGRAAnimatedGif.Create(AStream);
  75. try
  76. setlength(result,gif.Count);
  77. for i := 0 to gif.Count-1 do
  78. begin
  79. gif.CurrentImage:= i;
  80. result[i].bmp := gif.MemBitmap.Duplicate as TBGRABitmap;
  81. result[i].bmp.Caption := 'Frame'+IntToStr(i+1);
  82. result[i].bpp := 0;
  83. result[i].frameIndex := i;
  84. result[i].frameCount := gif.Count;
  85. end;
  86. finally
  87. gif.Free;
  88. end;
  89. end;
  90. function LoadTiffEntryFromStream(AStream: TStream; AIndex: integer): TImageEntry;
  91. var tiff: TBGRAReaderTiff;
  92. begin
  93. if AIndex < 0 then raise exception.Create('Index out of bounds');
  94. result := TImageEntry.Empty;
  95. tiff := TBGRAReaderTiff.Create;
  96. try
  97. tiff.LoadFromStream(AStream);
  98. result.bmp := (tiff.Images[AIndex].Img as TBGRABitmap).Duplicate as TBGRABitmap;
  99. result.bmp.Caption := 'Image'+IntToStr(AIndex+1);
  100. result.frameIndex:= AIndex;
  101. result.frameCount:= tiff.ImageCount;
  102. finally
  103. tiff.Free;
  104. end;
  105. end;
  106. function LoadTiffMultiImageFromStream(AStream: TStream): ArrayOfImageEntry;
  107. var tiff: TBGRAReaderTiff;
  108. i: Integer;
  109. begin
  110. tiff := TBGRAReaderTiff.Create;
  111. try
  112. tiff.LoadFromStream(AStream);
  113. setlength(result,tiff.ImageCount);
  114. for i := 0 to tiff.ImageCount-1 do
  115. begin
  116. result[i].bmp := (tiff.Images[i].Img as TBGRABitmap).Duplicate as TBGRABitmap;
  117. result[i].bmp.Caption := 'Image'+IntToStr(i+1);
  118. result[i].bpp := 0;
  119. result[i].frameIndex:= i;
  120. result[i].frameCount:= tiff.ImageCount;
  121. end;
  122. finally
  123. tiff.Free;
  124. end;
  125. end;
  126. function LoadFlatLzpFromStream(AStream: TStream): TBGRABitmap;
  127. var
  128. reader: TBGRAReaderLazPaint;
  129. begin
  130. reader := TBGRAReaderLazPaint.Create;
  131. result := TBGRABitmap.Create;
  132. try
  133. result.LoadFromStream(AStream, reader);
  134. finally
  135. reader.Free;
  136. if (result.Width = 0) or (result.Height = 0) then FreeAndNil(result);
  137. end;
  138. end;
  139. function LoadPngFromStream(AStream: TStream): TBGRABitmap;
  140. var
  141. reader: TBGRAReaderPNG;
  142. begin
  143. reader := TBGRAReaderPNG.Create;
  144. result := TBGRABitmap.Create;
  145. try
  146. result.LoadFromStream(AStream, reader);
  147. except
  148. FreeAndNil(result);
  149. end;
  150. if result <> nil then
  151. begin
  152. if (result.Width = 0) or (result.Height = 0) then FreeAndNil(result);
  153. end;
  154. reader.Free;
  155. end;
  156. procedure FreeMultiImage(var images: ArrayOfImageEntry);
  157. var i: integer;
  158. begin
  159. for i := 0 to high(images) do
  160. images[i].bmp.Free;
  161. images := nil;
  162. end;
  163. function AbleToLoadUTF8(AFilename: string): boolean;
  164. var
  165. s: TStream;
  166. begin
  167. if IsRawFilename(AFilename) then exit(true);
  168. s := FileManager.CreateFileStream(AFilename, fmOpenRead or fmShareDenyWrite);
  169. try
  170. result := DefaultBGRAImageReader[DetectFileFormat(s, ExtractFileExt(AFilename))] <> nil;
  171. finally
  172. s.Free;
  173. end;
  174. end;
  175. function LoadSVGImageUTF8(AFilename: string): TBGRALayeredBitmap;
  176. var
  177. svg: TBGRALayerSVGOriginal;
  178. begin
  179. svg := LoadSVGOriginalUTF8(AFilename);
  180. result := TBGRALayeredBitmap.Create(ceil(svg.Width),ceil(svg.Height));
  181. result.AddLayerFromOwnedOriginal(svg);
  182. result.RenderLayerFromOriginal(0);
  183. end;
  184. function LoadSVGOriginalUTF8(AFilename: string): TBGRALayerSVGOriginal;
  185. var
  186. svg: TBGRALayerSVGOriginal;
  187. s: TStream;
  188. begin
  189. s := FileManager.CreateFileStream(AFilename, fmOpenRead or fmShareDenyWrite);
  190. result := nil;
  191. try
  192. svg := TBGRALayerSVGOriginal.Create;
  193. svg.LoadSVGFromStream(s);
  194. result:= svg;
  195. svg:= nil;
  196. finally
  197. s.Free;
  198. svg.Free;
  199. end;
  200. end;
  201. function LoadFlatImageUTF8(AFilename: string; AEntryToLoad: integer): TImageEntry;
  202. var
  203. formMultiImage: TFMultiImage;
  204. multi: ArrayOfImageEntry;
  205. format : TBGRAImageFormat;
  206. s: TStream;
  207. procedure ChooseMulti(AStretch: boolean);
  208. begin
  209. if length(multi)=1 then
  210. begin
  211. result := multi[0];
  212. multi := nil;
  213. end else
  214. begin
  215. formMultiImage := TFMultiImage.Create(nil);
  216. try
  217. result := formMultiImage.ShowAndChoose(multi,AStretch, format);
  218. finally
  219. formMultiImage.Free;
  220. end;
  221. FreeMultiImage(multi);
  222. end;
  223. end;
  224. begin
  225. result := TImageEntry.Empty;
  226. s := FileManager.CreateFileStream(AFilename, fmOpenRead or fmShareDenyWrite);
  227. try
  228. format := DetectFileFormat(s, ExtractFileExt(AFilename));
  229. if IsRawFilename(AFilename) then
  230. begin
  231. result.bmp := GetRawStreamImage(s);
  232. result.bpp:= 0;
  233. end else
  234. if format in[ifIco,ifCur] then
  235. begin
  236. if AEntryToLoad <> -1 then
  237. result := LoadIcoEntryFromStream(s, AEntryToLoad)
  238. else
  239. begin
  240. multi := LoadIcoMultiImageFromStream(s);
  241. ChooseMulti(False);
  242. end;
  243. end else
  244. if format = ifGif then
  245. begin
  246. if AEntryToLoad <> -1 then
  247. result := LoadGifEntryFromStream(s, AEntryToLoad)
  248. else
  249. begin
  250. multi := LoadGifMultiImageFromStream(s);
  251. ChooseMulti(True);
  252. end;
  253. end else
  254. if format = ifTiff then
  255. begin
  256. if AEntryToLoad <> -1 then
  257. result := LoadTiffEntryFromStream(s, AEntryToLoad)
  258. else
  259. begin
  260. multi := LoadTiffMultiImageFromStream(s);
  261. ChooseMulti(True);
  262. end;
  263. end else
  264. if format = ifLazPaint then
  265. begin
  266. result.bmp := LoadFlatLzpFromStream(s);
  267. result.bpp := 32; //always 32-bit
  268. end else
  269. if format = ifPng then
  270. begin
  271. result.bmp := LoadPngFromStream(s);
  272. result.bpp := 0;
  273. end else
  274. begin
  275. result.bmp := TBGRABitmap.Create(s);
  276. result.bpp := 0;
  277. end;
  278. finally
  279. s.Free;
  280. end;
  281. end;
  282. end.