@ai-ecoverse/py-pillow 12.3.0-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/LICENSE +30 -0
  2. package/README.md +4 -0
  3. package/lib/python3.14/site-packages/PIL/AvifImagePlugin.py +295 -0
  4. package/lib/python3.14/site-packages/PIL/BdfFontFile.py +124 -0
  5. package/lib/python3.14/site-packages/PIL/BlpImagePlugin.py +498 -0
  6. package/lib/python3.14/site-packages/PIL/BmpImagePlugin.py +514 -0
  7. package/lib/python3.14/site-packages/PIL/BufrStubImagePlugin.py +72 -0
  8. package/lib/python3.14/site-packages/PIL/ContainerIO.py +173 -0
  9. package/lib/python3.14/site-packages/PIL/CurImagePlugin.py +103 -0
  10. package/lib/python3.14/site-packages/PIL/DcxImagePlugin.py +84 -0
  11. package/lib/python3.14/site-packages/PIL/DdsImagePlugin.py +632 -0
  12. package/lib/python3.14/site-packages/PIL/EpsImagePlugin.py +484 -0
  13. package/lib/python3.14/site-packages/PIL/ExifTags.py +384 -0
  14. package/lib/python3.14/site-packages/PIL/FitsImagePlugin.py +153 -0
  15. package/lib/python3.14/site-packages/PIL/FliImagePlugin.py +184 -0
  16. package/lib/python3.14/site-packages/PIL/FontFile.py +160 -0
  17. package/lib/python3.14/site-packages/PIL/FpxImagePlugin.py +262 -0
  18. package/lib/python3.14/site-packages/PIL/FtexImagePlugin.py +115 -0
  19. package/lib/python3.14/site-packages/PIL/GbrImagePlugin.py +103 -0
  20. package/lib/python3.14/site-packages/PIL/GdImageFile.py +104 -0
  21. package/lib/python3.14/site-packages/PIL/GifImagePlugin.py +1223 -0
  22. package/lib/python3.14/site-packages/PIL/GimpGradientFile.py +154 -0
  23. package/lib/python3.14/site-packages/PIL/GimpPaletteFile.py +75 -0
  24. package/lib/python3.14/site-packages/PIL/GribStubImagePlugin.py +72 -0
  25. package/lib/python3.14/site-packages/PIL/Hdf5StubImagePlugin.py +72 -0
  26. package/lib/python3.14/site-packages/PIL/IcnsImagePlugin.py +401 -0
  27. package/lib/python3.14/site-packages/PIL/IcoImagePlugin.py +396 -0
  28. package/lib/python3.14/site-packages/PIL/ImImagePlugin.py +390 -0
  29. package/lib/python3.14/site-packages/PIL/Image.py +4385 -0
  30. package/lib/python3.14/site-packages/PIL/ImageChops.py +311 -0
  31. package/lib/python3.14/site-packages/PIL/ImageCms.py +1078 -0
  32. package/lib/python3.14/site-packages/PIL/ImageColor.py +320 -0
  33. package/lib/python3.14/site-packages/PIL/ImageDraw.py +1002 -0
  34. package/lib/python3.14/site-packages/PIL/ImageDraw2.py +244 -0
  35. package/lib/python3.14/site-packages/PIL/ImageEnhance.py +113 -0
  36. package/lib/python3.14/site-packages/PIL/ImageFile.py +938 -0
  37. package/lib/python3.14/site-packages/PIL/ImageFilter.py +617 -0
  38. package/lib/python3.14/site-packages/PIL/ImageFont.py +1330 -0
  39. package/lib/python3.14/site-packages/PIL/ImageGrab.py +234 -0
  40. package/lib/python3.14/site-packages/PIL/ImageMath.py +314 -0
  41. package/lib/python3.14/site-packages/PIL/ImageMode.py +85 -0
  42. package/lib/python3.14/site-packages/PIL/ImageMorph.py +317 -0
  43. package/lib/python3.14/site-packages/PIL/ImageOps.py +749 -0
  44. package/lib/python3.14/site-packages/PIL/ImagePalette.py +290 -0
  45. package/lib/python3.14/site-packages/PIL/ImagePath.py +20 -0
  46. package/lib/python3.14/site-packages/PIL/ImageQt.py +219 -0
  47. package/lib/python3.14/site-packages/PIL/ImageSequence.py +88 -0
  48. package/lib/python3.14/site-packages/PIL/ImageShow.py +367 -0
  49. package/lib/python3.14/site-packages/PIL/ImageStat.py +167 -0
  50. package/lib/python3.14/site-packages/PIL/ImageText.py +509 -0
  51. package/lib/python3.14/site-packages/PIL/ImageTk.py +266 -0
  52. package/lib/python3.14/site-packages/PIL/ImageTransform.py +136 -0
  53. package/lib/python3.14/site-packages/PIL/ImageWin.py +247 -0
  54. package/lib/python3.14/site-packages/PIL/ImtImagePlugin.py +103 -0
  55. package/lib/python3.14/site-packages/PIL/IptcImagePlugin.py +226 -0
  56. package/lib/python3.14/site-packages/PIL/Jpeg2KImagePlugin.py +466 -0
  57. package/lib/python3.14/site-packages/PIL/JpegImagePlugin.py +889 -0
  58. package/lib/python3.14/site-packages/PIL/JpegPresets.py +242 -0
  59. package/lib/python3.14/site-packages/PIL/McIdasImagePlugin.py +78 -0
  60. package/lib/python3.14/site-packages/PIL/MicImagePlugin.py +103 -0
  61. package/lib/python3.14/site-packages/PIL/MpegImagePlugin.py +84 -0
  62. package/lib/python3.14/site-packages/PIL/MpoImagePlugin.py +203 -0
  63. package/lib/python3.14/site-packages/PIL/MspImagePlugin.py +200 -0
  64. package/lib/python3.14/site-packages/PIL/PSDraw.py +238 -0
  65. package/lib/python3.14/site-packages/PIL/PaletteFile.py +54 -0
  66. package/lib/python3.14/site-packages/PIL/PalmImagePlugin.py +217 -0
  67. package/lib/python3.14/site-packages/PIL/PcdImagePlugin.py +68 -0
  68. package/lib/python3.14/site-packages/PIL/PcfFontFile.py +256 -0
  69. package/lib/python3.14/site-packages/PIL/PcxImagePlugin.py +232 -0
  70. package/lib/python3.14/site-packages/PIL/PdfImagePlugin.py +315 -0
  71. package/lib/python3.14/site-packages/PIL/PdfParser.py +1092 -0
  72. package/lib/python3.14/site-packages/PIL/PixarImagePlugin.py +72 -0
  73. package/lib/python3.14/site-packages/PIL/PngImagePlugin.py +1578 -0
  74. package/lib/python3.14/site-packages/PIL/PpmImagePlugin.py +375 -0
  75. package/lib/python3.14/site-packages/PIL/PsdImagePlugin.py +339 -0
  76. package/lib/python3.14/site-packages/PIL/QoiImagePlugin.py +235 -0
  77. package/lib/python3.14/site-packages/PIL/SgiImagePlugin.py +231 -0
  78. package/lib/python3.14/site-packages/PIL/SpiderImagePlugin.py +332 -0
  79. package/lib/python3.14/site-packages/PIL/SunImagePlugin.py +145 -0
  80. package/lib/python3.14/site-packages/PIL/TarIO.py +61 -0
  81. package/lib/python3.14/site-packages/PIL/TgaImagePlugin.py +284 -0
  82. package/lib/python3.14/site-packages/PIL/TiffImagePlugin.py +2354 -0
  83. package/lib/python3.14/site-packages/PIL/TiffTags.py +566 -0
  84. package/lib/python3.14/site-packages/PIL/WalImageFile.py +129 -0
  85. package/lib/python3.14/site-packages/PIL/WebPImagePlugin.py +322 -0
  86. package/lib/python3.14/site-packages/PIL/WmfImagePlugin.py +183 -0
  87. package/lib/python3.14/site-packages/PIL/XVThumbImagePlugin.py +83 -0
  88. package/lib/python3.14/site-packages/PIL/XbmImagePlugin.py +98 -0
  89. package/lib/python3.14/site-packages/PIL/XpmImagePlugin.py +157 -0
  90. package/lib/python3.14/site-packages/PIL/__init__.py +87 -0
  91. package/lib/python3.14/site-packages/PIL/__main__.py +7 -0
  92. package/lib/python3.14/site-packages/PIL/__pycache__/AvifImagePlugin.cpython-314.pyc +0 -0
  93. package/lib/python3.14/site-packages/PIL/__pycache__/BdfFontFile.cpython-314.pyc +0 -0
  94. package/lib/python3.14/site-packages/PIL/__pycache__/BlpImagePlugin.cpython-314.pyc +0 -0
  95. package/lib/python3.14/site-packages/PIL/__pycache__/BmpImagePlugin.cpython-314.pyc +0 -0
  96. package/lib/python3.14/site-packages/PIL/__pycache__/BufrStubImagePlugin.cpython-314.pyc +0 -0
  97. package/lib/python3.14/site-packages/PIL/__pycache__/ContainerIO.cpython-314.pyc +0 -0
  98. package/lib/python3.14/site-packages/PIL/__pycache__/CurImagePlugin.cpython-314.pyc +0 -0
  99. package/lib/python3.14/site-packages/PIL/__pycache__/DcxImagePlugin.cpython-314.pyc +0 -0
  100. package/lib/python3.14/site-packages/PIL/__pycache__/DdsImagePlugin.cpython-314.pyc +0 -0
  101. package/lib/python3.14/site-packages/PIL/__pycache__/EpsImagePlugin.cpython-314.pyc +0 -0
  102. package/lib/python3.14/site-packages/PIL/__pycache__/ExifTags.cpython-314.pyc +0 -0
  103. package/lib/python3.14/site-packages/PIL/__pycache__/FitsImagePlugin.cpython-314.pyc +0 -0
  104. package/lib/python3.14/site-packages/PIL/__pycache__/FliImagePlugin.cpython-314.pyc +0 -0
  105. package/lib/python3.14/site-packages/PIL/__pycache__/FontFile.cpython-314.pyc +0 -0
  106. package/lib/python3.14/site-packages/PIL/__pycache__/FpxImagePlugin.cpython-314.pyc +0 -0
  107. package/lib/python3.14/site-packages/PIL/__pycache__/FtexImagePlugin.cpython-314.pyc +0 -0
  108. package/lib/python3.14/site-packages/PIL/__pycache__/GbrImagePlugin.cpython-314.pyc +0 -0
  109. package/lib/python3.14/site-packages/PIL/__pycache__/GdImageFile.cpython-314.pyc +0 -0
  110. package/lib/python3.14/site-packages/PIL/__pycache__/GifImagePlugin.cpython-314.pyc +0 -0
  111. package/lib/python3.14/site-packages/PIL/__pycache__/GimpGradientFile.cpython-314.pyc +0 -0
  112. package/lib/python3.14/site-packages/PIL/__pycache__/GimpPaletteFile.cpython-314.pyc +0 -0
  113. package/lib/python3.14/site-packages/PIL/__pycache__/GribStubImagePlugin.cpython-314.pyc +0 -0
  114. package/lib/python3.14/site-packages/PIL/__pycache__/Hdf5StubImagePlugin.cpython-314.pyc +0 -0
  115. package/lib/python3.14/site-packages/PIL/__pycache__/IcnsImagePlugin.cpython-314.pyc +0 -0
  116. package/lib/python3.14/site-packages/PIL/__pycache__/IcoImagePlugin.cpython-314.pyc +0 -0
  117. package/lib/python3.14/site-packages/PIL/__pycache__/ImImagePlugin.cpython-314.pyc +0 -0
  118. package/lib/python3.14/site-packages/PIL/__pycache__/Image.cpython-314.pyc +0 -0
  119. package/lib/python3.14/site-packages/PIL/__pycache__/ImageChops.cpython-314.pyc +0 -0
  120. package/lib/python3.14/site-packages/PIL/__pycache__/ImageCms.cpython-314.pyc +0 -0
  121. package/lib/python3.14/site-packages/PIL/__pycache__/ImageColor.cpython-314.pyc +0 -0
  122. package/lib/python3.14/site-packages/PIL/__pycache__/ImageDraw.cpython-314.pyc +0 -0
  123. package/lib/python3.14/site-packages/PIL/__pycache__/ImageDraw2.cpython-314.pyc +0 -0
  124. package/lib/python3.14/site-packages/PIL/__pycache__/ImageEnhance.cpython-314.pyc +0 -0
  125. package/lib/python3.14/site-packages/PIL/__pycache__/ImageFile.cpython-314.pyc +0 -0
  126. package/lib/python3.14/site-packages/PIL/__pycache__/ImageFilter.cpython-314.pyc +0 -0
  127. package/lib/python3.14/site-packages/PIL/__pycache__/ImageFont.cpython-314.pyc +0 -0
  128. package/lib/python3.14/site-packages/PIL/__pycache__/ImageGrab.cpython-314.pyc +0 -0
  129. package/lib/python3.14/site-packages/PIL/__pycache__/ImageMath.cpython-314.pyc +0 -0
  130. package/lib/python3.14/site-packages/PIL/__pycache__/ImageMode.cpython-314.pyc +0 -0
  131. package/lib/python3.14/site-packages/PIL/__pycache__/ImageMorph.cpython-314.pyc +0 -0
  132. package/lib/python3.14/site-packages/PIL/__pycache__/ImageOps.cpython-314.pyc +0 -0
  133. package/lib/python3.14/site-packages/PIL/__pycache__/ImagePalette.cpython-314.pyc +0 -0
  134. package/lib/python3.14/site-packages/PIL/__pycache__/ImagePath.cpython-314.pyc +0 -0
  135. package/lib/python3.14/site-packages/PIL/__pycache__/ImageQt.cpython-314.pyc +0 -0
  136. package/lib/python3.14/site-packages/PIL/__pycache__/ImageSequence.cpython-314.pyc +0 -0
  137. package/lib/python3.14/site-packages/PIL/__pycache__/ImageShow.cpython-314.pyc +0 -0
  138. package/lib/python3.14/site-packages/PIL/__pycache__/ImageStat.cpython-314.pyc +0 -0
  139. package/lib/python3.14/site-packages/PIL/__pycache__/ImageText.cpython-314.pyc +0 -0
  140. package/lib/python3.14/site-packages/PIL/__pycache__/ImageTk.cpython-314.pyc +0 -0
  141. package/lib/python3.14/site-packages/PIL/__pycache__/ImageTransform.cpython-314.pyc +0 -0
  142. package/lib/python3.14/site-packages/PIL/__pycache__/ImageWin.cpython-314.pyc +0 -0
  143. package/lib/python3.14/site-packages/PIL/__pycache__/ImtImagePlugin.cpython-314.pyc +0 -0
  144. package/lib/python3.14/site-packages/PIL/__pycache__/IptcImagePlugin.cpython-314.pyc +0 -0
  145. package/lib/python3.14/site-packages/PIL/__pycache__/Jpeg2KImagePlugin.cpython-314.pyc +0 -0
  146. package/lib/python3.14/site-packages/PIL/__pycache__/JpegImagePlugin.cpython-314.pyc +0 -0
  147. package/lib/python3.14/site-packages/PIL/__pycache__/JpegPresets.cpython-314.pyc +0 -0
  148. package/lib/python3.14/site-packages/PIL/__pycache__/McIdasImagePlugin.cpython-314.pyc +0 -0
  149. package/lib/python3.14/site-packages/PIL/__pycache__/MicImagePlugin.cpython-314.pyc +0 -0
  150. package/lib/python3.14/site-packages/PIL/__pycache__/MpegImagePlugin.cpython-314.pyc +0 -0
  151. package/lib/python3.14/site-packages/PIL/__pycache__/MpoImagePlugin.cpython-314.pyc +0 -0
  152. package/lib/python3.14/site-packages/PIL/__pycache__/MspImagePlugin.cpython-314.pyc +0 -0
  153. package/lib/python3.14/site-packages/PIL/__pycache__/PSDraw.cpython-314.pyc +0 -0
  154. package/lib/python3.14/site-packages/PIL/__pycache__/PaletteFile.cpython-314.pyc +0 -0
  155. package/lib/python3.14/site-packages/PIL/__pycache__/PalmImagePlugin.cpython-314.pyc +0 -0
  156. package/lib/python3.14/site-packages/PIL/__pycache__/PcdImagePlugin.cpython-314.pyc +0 -0
  157. package/lib/python3.14/site-packages/PIL/__pycache__/PcfFontFile.cpython-314.pyc +0 -0
  158. package/lib/python3.14/site-packages/PIL/__pycache__/PcxImagePlugin.cpython-314.pyc +0 -0
  159. package/lib/python3.14/site-packages/PIL/__pycache__/PdfImagePlugin.cpython-314.pyc +0 -0
  160. package/lib/python3.14/site-packages/PIL/__pycache__/PdfParser.cpython-314.pyc +0 -0
  161. package/lib/python3.14/site-packages/PIL/__pycache__/PixarImagePlugin.cpython-314.pyc +0 -0
  162. package/lib/python3.14/site-packages/PIL/__pycache__/PngImagePlugin.cpython-314.pyc +0 -0
  163. package/lib/python3.14/site-packages/PIL/__pycache__/PpmImagePlugin.cpython-314.pyc +0 -0
  164. package/lib/python3.14/site-packages/PIL/__pycache__/PsdImagePlugin.cpython-314.pyc +0 -0
  165. package/lib/python3.14/site-packages/PIL/__pycache__/QoiImagePlugin.cpython-314.pyc +0 -0
  166. package/lib/python3.14/site-packages/PIL/__pycache__/SgiImagePlugin.cpython-314.pyc +0 -0
  167. package/lib/python3.14/site-packages/PIL/__pycache__/SpiderImagePlugin.cpython-314.pyc +0 -0
  168. package/lib/python3.14/site-packages/PIL/__pycache__/SunImagePlugin.cpython-314.pyc +0 -0
  169. package/lib/python3.14/site-packages/PIL/__pycache__/TarIO.cpython-314.pyc +0 -0
  170. package/lib/python3.14/site-packages/PIL/__pycache__/TgaImagePlugin.cpython-314.pyc +0 -0
  171. package/lib/python3.14/site-packages/PIL/__pycache__/TiffImagePlugin.cpython-314.pyc +0 -0
  172. package/lib/python3.14/site-packages/PIL/__pycache__/TiffTags.cpython-314.pyc +0 -0
  173. package/lib/python3.14/site-packages/PIL/__pycache__/WalImageFile.cpython-314.pyc +0 -0
  174. package/lib/python3.14/site-packages/PIL/__pycache__/WebPImagePlugin.cpython-314.pyc +0 -0
  175. package/lib/python3.14/site-packages/PIL/__pycache__/WmfImagePlugin.cpython-314.pyc +0 -0
  176. package/lib/python3.14/site-packages/PIL/__pycache__/XVThumbImagePlugin.cpython-314.pyc +0 -0
  177. package/lib/python3.14/site-packages/PIL/__pycache__/XbmImagePlugin.cpython-314.pyc +0 -0
  178. package/lib/python3.14/site-packages/PIL/__pycache__/XpmImagePlugin.cpython-314.pyc +0 -0
  179. package/lib/python3.14/site-packages/PIL/__pycache__/__init__.cpython-314.pyc +0 -0
  180. package/lib/python3.14/site-packages/PIL/__pycache__/__main__.cpython-314.pyc +0 -0
  181. package/lib/python3.14/site-packages/PIL/__pycache__/_binary.cpython-314.pyc +0 -0
  182. package/lib/python3.14/site-packages/PIL/__pycache__/_deprecate.cpython-314.pyc +0 -0
  183. package/lib/python3.14/site-packages/PIL/__pycache__/_tkinter_finder.cpython-314.pyc +0 -0
  184. package/lib/python3.14/site-packages/PIL/__pycache__/_typing.cpython-314.pyc +0 -0
  185. package/lib/python3.14/site-packages/PIL/__pycache__/_util.cpython-314.pyc +0 -0
  186. package/lib/python3.14/site-packages/PIL/__pycache__/_version.cpython-314.pyc +0 -0
  187. package/lib/python3.14/site-packages/PIL/__pycache__/features.cpython-314.pyc +0 -0
  188. package/lib/python3.14/site-packages/PIL/__pycache__/report.cpython-314.pyc +0 -0
  189. package/lib/python3.14/site-packages/PIL/_avif.pyi +3 -0
  190. package/lib/python3.14/site-packages/PIL/_binary.py +113 -0
  191. package/lib/python3.14/site-packages/PIL/_deprecate.py +72 -0
  192. package/lib/python3.14/site-packages/PIL/_imaging.cpython-314-wasm32-wasix.so +0 -0
  193. package/lib/python3.14/site-packages/PIL/_imaging.pyi +31 -0
  194. package/lib/python3.14/site-packages/PIL/_imagingcms.pyi +143 -0
  195. package/lib/python3.14/site-packages/PIL/_imagingft.cpython-314-wasm32-wasix.so +0 -0
  196. package/lib/python3.14/site-packages/PIL/_imagingft.pyi +70 -0
  197. package/lib/python3.14/site-packages/PIL/_imagingmath.cpython-314-wasm32-wasix.so +0 -0
  198. package/lib/python3.14/site-packages/PIL/_imagingmath.pyi +3 -0
  199. package/lib/python3.14/site-packages/PIL/_imagingmorph.cpython-314-wasm32-wasix.so +0 -0
  200. package/lib/python3.14/site-packages/PIL/_imagingmorph.pyi +3 -0
  201. package/lib/python3.14/site-packages/PIL/_imagingtk.cpython-314-wasm32-wasix.so +0 -0
  202. package/lib/python3.14/site-packages/PIL/_imagingtk.pyi +3 -0
  203. package/lib/python3.14/site-packages/PIL/_tkinter_finder.py +20 -0
  204. package/lib/python3.14/site-packages/PIL/_typing.py +45 -0
  205. package/lib/python3.14/site-packages/PIL/_util.py +29 -0
  206. package/lib/python3.14/site-packages/PIL/_version.py +4 -0
  207. package/lib/python3.14/site-packages/PIL/_webp.pyi +3 -0
  208. package/lib/python3.14/site-packages/PIL/features.py +343 -0
  209. package/lib/python3.14/site-packages/PIL/py.typed +0 -0
  210. package/lib/python3.14/site-packages/PIL/report.py +5 -0
  211. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/METADATA +180 -0
  212. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/RECORD +117 -0
  213. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/WHEEL +5 -0
  214. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/licenses/LICENSE +30 -0
  215. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/top_level.txt +1 -0
  216. package/lib/python3.14/site-packages/pillow-12.3.0.dist-info/zip-safe +1 -0
  217. package/package.json +46 -0
@@ -0,0 +1,401 @@
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # macOS icns file decoder, based on icns.py by Bob Ippolito.
6
+ #
7
+ # history:
8
+ # 2004-10-09 fl Turned into a PIL plugin; removed 2.3 dependencies.
9
+ # 2020-04-04 Allow saving on all operating systems.
10
+ #
11
+ # Copyright (c) 2004 by Bob Ippolito.
12
+ # Copyright (c) 2004 by Secret Labs.
13
+ # Copyright (c) 2004 by Fredrik Lundh.
14
+ # Copyright (c) 2014 by Alastair Houghton.
15
+ # Copyright (c) 2020 by Pan Jing.
16
+ #
17
+ # See the README file for information on usage and redistribution.
18
+ #
19
+ from __future__ import annotations
20
+
21
+ import io
22
+ import os
23
+ import struct
24
+ import sys
25
+ from typing import IO
26
+
27
+ from . import Image, ImageFile, PngImagePlugin, features
28
+
29
+ enable_jpeg2k = features.check_codec("jpg_2000")
30
+ if enable_jpeg2k:
31
+ from . import Jpeg2KImagePlugin
32
+
33
+ MAGIC = b"icns"
34
+ HEADERSIZE = 8
35
+
36
+
37
+ def nextheader(fobj: IO[bytes]) -> tuple[bytes, int]:
38
+ return struct.unpack(">4sI", fobj.read(HEADERSIZE))
39
+
40
+
41
+ def read_32t(
42
+ fobj: IO[bytes], start_length: tuple[int, int], size: tuple[int, int, int]
43
+ ) -> dict[str, Image.Image]:
44
+ # The 128x128 icon seems to have an extra header for some reason.
45
+ start, length = start_length
46
+ fobj.seek(start)
47
+ sig = fobj.read(4)
48
+ if sig != b"\x00\x00\x00\x00":
49
+ msg = "Unknown signature, expecting 0x00000000"
50
+ raise SyntaxError(msg)
51
+ return read_32(fobj, (start + 4, length - 4), size)
52
+
53
+
54
+ def read_32(
55
+ fobj: IO[bytes], start_length: tuple[int, int], size: tuple[int, int, int]
56
+ ) -> dict[str, Image.Image]:
57
+ """
58
+ Read a 32bit RGB icon resource. Seems to be either uncompressed or
59
+ an RLE packbits-like scheme.
60
+ """
61
+ start, length = start_length
62
+ fobj.seek(start)
63
+ pixel_size = (size[0] * size[2], size[1] * size[2])
64
+ sizesq = pixel_size[0] * pixel_size[1]
65
+ if length == sizesq * 3:
66
+ # uncompressed ("RGBRGBGB")
67
+ indata = fobj.read(length)
68
+ im = Image.frombuffer("RGB", pixel_size, indata, "raw", "RGB", 0, 1)
69
+ else:
70
+ # decode image
71
+ im = Image.new("RGB", pixel_size, None)
72
+ for band_ix in range(3):
73
+ data = []
74
+ bytesleft = sizesq
75
+ while bytesleft > 0:
76
+ byte = fobj.read(1)
77
+ if not byte:
78
+ break
79
+ byte_int = byte[0]
80
+ if byte_int & 0x80:
81
+ blocksize = byte_int - 125
82
+ byte = fobj.read(1)
83
+ data.extend([byte] * blocksize)
84
+ else:
85
+ blocksize = byte_int + 1
86
+ data.append(fobj.read(blocksize))
87
+ bytesleft -= blocksize
88
+ if bytesleft <= 0:
89
+ break
90
+ if bytesleft != 0:
91
+ msg = f"Error reading channel [{repr(bytesleft)} left]"
92
+ raise SyntaxError(msg)
93
+ band = Image.frombuffer("L", pixel_size, b"".join(data), "raw", "L", 0, 1)
94
+ im.im.putband(band.im, band_ix)
95
+ return {"RGB": im}
96
+
97
+
98
+ def read_mk(
99
+ fobj: IO[bytes], start_length: tuple[int, int], size: tuple[int, int, int]
100
+ ) -> dict[str, Image.Image]:
101
+ # Alpha masks seem to be uncompressed
102
+ start = start_length[0]
103
+ fobj.seek(start)
104
+ pixel_size = (size[0] * size[2], size[1] * size[2])
105
+ sizesq = pixel_size[0] * pixel_size[1]
106
+ band = Image.frombuffer("L", pixel_size, fobj.read(sizesq), "raw", "L", 0, 1)
107
+ return {"A": band}
108
+
109
+
110
+ def read_png_or_jpeg2000(
111
+ fobj: IO[bytes], start_length: tuple[int, int], size: tuple[int, int, int]
112
+ ) -> dict[str, Image.Image]:
113
+ start, length = start_length
114
+ fobj.seek(start)
115
+ sig = fobj.read(12)
116
+
117
+ im: Image.Image
118
+ if sig.startswith(b"\x89PNG\x0d\x0a\x1a\x0a"):
119
+ fobj.seek(start)
120
+ im = PngImagePlugin.PngImageFile(fobj)
121
+ Image._decompression_bomb_check(im.size)
122
+ return {"RGBA": im}
123
+ elif (
124
+ sig.startswith((b"\xff\x4f\xff\x51", b"\x0d\x0a\x87\x0a"))
125
+ or sig == b"\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a"
126
+ ):
127
+ if not enable_jpeg2k:
128
+ msg = (
129
+ "Unsupported icon subimage format (rebuild PIL "
130
+ "with JPEG 2000 support to fix this)"
131
+ )
132
+ raise ValueError(msg)
133
+ # j2k, jpc or j2c
134
+ fobj.seek(start)
135
+ jp2kstream = fobj.read(length)
136
+ f = io.BytesIO(jp2kstream)
137
+ im = Jpeg2KImagePlugin.Jpeg2KImageFile(f)
138
+ Image._decompression_bomb_check(im.size)
139
+ if im.mode != "RGBA":
140
+ im = im.convert("RGBA")
141
+ return {"RGBA": im}
142
+ else:
143
+ msg = "Unsupported icon subimage format"
144
+ raise ValueError(msg)
145
+
146
+
147
+ class IcnsFile:
148
+ SIZES = {
149
+ (512, 512, 2): [(b"ic10", read_png_or_jpeg2000)],
150
+ (512, 512, 1): [(b"ic09", read_png_or_jpeg2000)],
151
+ (256, 256, 2): [(b"ic14", read_png_or_jpeg2000)],
152
+ (256, 256, 1): [(b"ic08", read_png_or_jpeg2000)],
153
+ (128, 128, 2): [(b"ic13", read_png_or_jpeg2000)],
154
+ (128, 128, 1): [
155
+ (b"ic07", read_png_or_jpeg2000),
156
+ (b"it32", read_32t),
157
+ (b"t8mk", read_mk),
158
+ ],
159
+ (64, 64, 1): [(b"icp6", read_png_or_jpeg2000)],
160
+ (32, 32, 2): [(b"ic12", read_png_or_jpeg2000)],
161
+ (48, 48, 1): [(b"ih32", read_32), (b"h8mk", read_mk)],
162
+ (32, 32, 1): [
163
+ (b"icp5", read_png_or_jpeg2000),
164
+ (b"il32", read_32),
165
+ (b"l8mk", read_mk),
166
+ ],
167
+ (16, 16, 2): [(b"ic11", read_png_or_jpeg2000)],
168
+ (16, 16, 1): [
169
+ (b"icp4", read_png_or_jpeg2000),
170
+ (b"is32", read_32),
171
+ (b"s8mk", read_mk),
172
+ ],
173
+ }
174
+
175
+ def __init__(self, fobj: IO[bytes]) -> None:
176
+ """
177
+ fobj is a file-like object as an icns resource
178
+ """
179
+ # signature : (start, length)
180
+ self.dct = {}
181
+ self.fobj = fobj
182
+ sig, filesize = nextheader(fobj)
183
+ if not _accept(sig):
184
+ msg = "not an icns file"
185
+ raise SyntaxError(msg)
186
+ i = HEADERSIZE
187
+ while i < filesize:
188
+ sig, blocksize = nextheader(fobj)
189
+ if blocksize <= 0:
190
+ msg = "invalid block header"
191
+ raise SyntaxError(msg)
192
+ i += HEADERSIZE
193
+ blocksize -= HEADERSIZE
194
+ self.dct[sig] = (i, blocksize)
195
+ fobj.seek(blocksize, io.SEEK_CUR)
196
+ i += blocksize
197
+
198
+ def itersizes(self) -> list[tuple[int, int, int]]:
199
+ sizes = []
200
+ for size, fmts in self.SIZES.items():
201
+ for fmt, reader in fmts:
202
+ if fmt in self.dct:
203
+ sizes.append(size)
204
+ break
205
+ return sizes
206
+
207
+ def bestsize(self) -> tuple[int, int, int]:
208
+ sizes = self.itersizes()
209
+ if not sizes:
210
+ msg = "No 32bit icon resources found"
211
+ raise SyntaxError(msg)
212
+ return max(sizes)
213
+
214
+ def dataforsize(self, size: tuple[int, int, int]) -> dict[str, Image.Image]:
215
+ """
216
+ Get an icon resource as {channel: array}. Note that
217
+ the arrays are bottom-up like windows bitmaps and will likely
218
+ need to be flipped or transposed in some way.
219
+ """
220
+ dct = {}
221
+ for code, reader in self.SIZES[size]:
222
+ desc = self.dct.get(code)
223
+ if desc is not None:
224
+ dct.update(reader(self.fobj, desc, size))
225
+ return dct
226
+
227
+ def getimage(
228
+ self, size: tuple[int, int] | tuple[int, int, int] | None = None
229
+ ) -> Image.Image:
230
+ if size is None:
231
+ size = self.bestsize()
232
+ elif len(size) == 2:
233
+ size = (size[0], size[1], 1)
234
+ channels = self.dataforsize(size)
235
+
236
+ im = channels.get("RGBA")
237
+ if im:
238
+ return im
239
+
240
+ im = channels["RGB"].copy()
241
+ try:
242
+ im.putalpha(channels["A"])
243
+ except KeyError:
244
+ pass
245
+ return im
246
+
247
+
248
+ ##
249
+ # Image plugin for Mac OS icons.
250
+
251
+
252
+ class IcnsImageFile(ImageFile.ImageFile):
253
+ """
254
+ PIL image support for Mac OS .icns files.
255
+ Chooses the best resolution, but will possibly load
256
+ a different size image if you mutate the size attribute
257
+ before calling 'load'.
258
+
259
+ The info dictionary has a key 'sizes' that is a list
260
+ of sizes that the icns file has.
261
+ """
262
+
263
+ format = "ICNS"
264
+ format_description = "Mac OS icns resource"
265
+
266
+ def _open(self) -> None:
267
+ assert self.fp is not None
268
+ self.icns = IcnsFile(self.fp)
269
+ self._mode = "RGBA"
270
+ self.info["sizes"] = self.icns.itersizes()
271
+ self.best_size = self.icns.bestsize()
272
+ self.size = (
273
+ self.best_size[0] * self.best_size[2],
274
+ self.best_size[1] * self.best_size[2],
275
+ )
276
+
277
+ @property
278
+ def size(self) -> tuple[int, int]:
279
+ return self._size
280
+
281
+ @size.setter
282
+ def size(self, value: tuple[int, int]) -> None:
283
+ # Check that a matching size exists,
284
+ # or that there is a scale that would create a size that matches
285
+ for size in self.info["sizes"]:
286
+ simple_size = size[0] * size[2], size[1] * size[2]
287
+ scale = simple_size[0] // value[0]
288
+ if simple_size[1] / value[1] == scale:
289
+ self._size = value
290
+ return
291
+ msg = "This is not one of the allowed sizes of this image"
292
+ raise ValueError(msg)
293
+
294
+ def load(self, scale: int | None = None) -> Image.core.PixelAccess | None:
295
+ if scale is not None:
296
+ width, height = self.size[:2]
297
+ self.size = width * scale, height * scale
298
+ self.best_size = width, height, scale
299
+
300
+ px = Image.Image.load(self)
301
+ if self._im is not None and self.im.size == self.size:
302
+ # Already loaded
303
+ return px
304
+ self.load_prepare()
305
+ # This is likely NOT the best way to do it, but whatever.
306
+ im = self.icns.getimage(self.best_size)
307
+
308
+ # If this is a PNG or JPEG 2000, it won't be loaded yet
309
+ px = im.load()
310
+
311
+ self.im = im.im
312
+ self._mode = im.mode
313
+ self.size = im.size
314
+
315
+ return px
316
+
317
+
318
+ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
319
+ """
320
+ Saves the image as a series of PNG files,
321
+ that are then combined into a .icns file.
322
+ """
323
+ if hasattr(fp, "flush"):
324
+ fp.flush()
325
+
326
+ sizes = {
327
+ b"ic07": 128,
328
+ b"ic08": 256,
329
+ b"ic09": 512,
330
+ b"ic10": 1024,
331
+ b"ic11": 32,
332
+ b"ic12": 64,
333
+ b"ic13": 256,
334
+ b"ic14": 512,
335
+ }
336
+ provided_images = {im.width: im for im in im.encoderinfo.get("append_images", [])}
337
+ size_streams = {}
338
+ for size in set(sizes.values()):
339
+ image = (
340
+ provided_images[size]
341
+ if size in provided_images
342
+ else im.resize((size, size))
343
+ )
344
+
345
+ temp = io.BytesIO()
346
+ image.save(temp, "png")
347
+ size_streams[size] = temp.getvalue()
348
+
349
+ entries = []
350
+ for type, size in sizes.items():
351
+ stream = size_streams[size]
352
+ entries.append((type, HEADERSIZE + len(stream), stream))
353
+
354
+ # Header
355
+ fp.write(MAGIC)
356
+ file_length = HEADERSIZE # Header
357
+ file_length += HEADERSIZE + 8 * len(entries) # TOC
358
+ file_length += sum(entry[1] for entry in entries)
359
+ fp.write(struct.pack(">i", file_length))
360
+
361
+ # TOC
362
+ fp.write(b"TOC ")
363
+ fp.write(struct.pack(">i", HEADERSIZE + len(entries) * HEADERSIZE))
364
+ for entry in entries:
365
+ fp.write(entry[0])
366
+ fp.write(struct.pack(">i", entry[1]))
367
+
368
+ # Data
369
+ for entry in entries:
370
+ fp.write(entry[0])
371
+ fp.write(struct.pack(">i", entry[1]))
372
+ fp.write(entry[2])
373
+
374
+ if hasattr(fp, "flush"):
375
+ fp.flush()
376
+
377
+
378
+ def _accept(prefix: bytes) -> bool:
379
+ return prefix.startswith(MAGIC)
380
+
381
+
382
+ Image.register_open(IcnsImageFile.format, IcnsImageFile, _accept)
383
+ Image.register_extension(IcnsImageFile.format, ".icns")
384
+
385
+ Image.register_save(IcnsImageFile.format, _save)
386
+ Image.register_mime(IcnsImageFile.format, "image/icns")
387
+
388
+ if __name__ == "__main__":
389
+ if len(sys.argv) < 2:
390
+ print("Syntax: python3 IcnsImagePlugin.py [file]")
391
+ sys.exit()
392
+
393
+ with open(sys.argv[1], "rb") as fp:
394
+ imf = IcnsImageFile(fp)
395
+ for size in imf.info["sizes"]:
396
+ width, height, scale = imf.size = size
397
+ imf.save(f"out-{width}-{height}-{scale}.png")
398
+ with Image.open(sys.argv[1]) as im:
399
+ im.save("out.png")
400
+ if sys.platform == "windows":
401
+ os.startfile("out.png")