@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,322 @@
1
+ from __future__ import annotations
2
+
3
+ from io import BytesIO
4
+
5
+ from . import Image, ImageFile
6
+
7
+ try:
8
+ from . import _webp
9
+
10
+ SUPPORTED = True
11
+ except ImportError:
12
+ SUPPORTED = False
13
+
14
+ TYPE_CHECKING = False
15
+ if TYPE_CHECKING:
16
+ from typing import IO, Any
17
+
18
+ _VP8_MODES_BY_IDENTIFIER = {
19
+ b"VP8 ": "RGB",
20
+ b"VP8X": "RGBA",
21
+ b"VP8L": "RGBA", # lossless
22
+ }
23
+
24
+
25
+ def _accept(prefix: bytes) -> bool | str:
26
+ is_riff_file_format = prefix.startswith(b"RIFF")
27
+ is_webp_file = prefix[8:12] == b"WEBP"
28
+ is_valid_vp8_mode = prefix[12:16] in _VP8_MODES_BY_IDENTIFIER
29
+
30
+ if is_riff_file_format and is_webp_file and is_valid_vp8_mode:
31
+ if not SUPPORTED:
32
+ return (
33
+ "image file could not be identified because WEBP support not installed"
34
+ )
35
+ return True
36
+ return False
37
+
38
+
39
+ class WebPImageFile(ImageFile.ImageFile):
40
+ format = "WEBP"
41
+ format_description = "WebP image"
42
+ __loaded = 0
43
+ __logical_frame = 0
44
+
45
+ def _open(self) -> None:
46
+ assert self.fp is not None
47
+ s = self.fp.read()
48
+ if not _accept(s):
49
+ msg = "not a WEBP file"
50
+ raise SyntaxError(msg)
51
+
52
+ # Use the newer AnimDecoder API to parse the (possibly) animated file,
53
+ # and access muxed chunks like ICC/EXIF/XMP.
54
+ self._decoder = _webp.WebPAnimDecoder(s)
55
+
56
+ # Get info from decoder
57
+ self._size, self.info["loop"], bgcolor, self.n_frames, self.rawmode = (
58
+ self._decoder.get_info()
59
+ )
60
+ self.info["background"] = (
61
+ (bgcolor >> 16) & 0xFF, # R
62
+ (bgcolor >> 8) & 0xFF, # G
63
+ bgcolor & 0xFF, # B
64
+ (bgcolor >> 24) & 0xFF, # A
65
+ )
66
+ self.is_animated = self.n_frames > 1
67
+ self._mode = "RGB" if self.rawmode == "RGBX" else self.rawmode
68
+
69
+ # Attempt to read ICC / EXIF / XMP chunks from file
70
+ for key, chunk_name in {
71
+ "icc_profile": "ICCP",
72
+ "exif": "EXIF",
73
+ "xmp": "XMP ",
74
+ }.items():
75
+ if value := self._decoder.get_chunk(chunk_name):
76
+ self.info[key] = value
77
+
78
+ # Initialize seek state
79
+ self._reset(reset=False)
80
+
81
+ def _getexif(self) -> dict[int, Any] | None:
82
+ if "exif" not in self.info:
83
+ return None
84
+ return self.getexif()._get_merged_dict()
85
+
86
+ def seek(self, frame: int) -> None:
87
+ if not self._seek_check(frame):
88
+ return
89
+
90
+ # Set logical frame to requested position
91
+ self.__logical_frame = frame
92
+
93
+ def _reset(self, reset: bool = True) -> None:
94
+ if reset:
95
+ self._decoder.reset()
96
+ self.__physical_frame = 0
97
+ self.__loaded = -1
98
+ self.__timestamp = 0
99
+
100
+ def _get_next(self) -> tuple[bytes, int, int]:
101
+ # Get next frame
102
+ ret = self._decoder.get_next()
103
+ self.__physical_frame += 1
104
+
105
+ # Check if an error occurred
106
+ if ret is None:
107
+ self._reset() # Reset just to be safe
108
+ self.seek(0)
109
+ msg = "failed to decode next frame in WebP file"
110
+ raise EOFError(msg)
111
+
112
+ # Compute duration
113
+ data, timestamp = ret
114
+ duration = timestamp - self.__timestamp
115
+ self.__timestamp = timestamp
116
+
117
+ # libwebp gives frame end, adjust to start of frame
118
+ timestamp -= duration
119
+ return data, timestamp, duration
120
+
121
+ def _seek(self, frame: int) -> None:
122
+ if self.__physical_frame == frame:
123
+ return # Nothing to do
124
+ if frame < self.__physical_frame:
125
+ self._reset() # Rewind to beginning
126
+ while self.__physical_frame < frame:
127
+ self._get_next() # Advance to the requested frame
128
+
129
+ def load(self) -> Image.core.PixelAccess | None:
130
+ if self.__loaded != self.__logical_frame:
131
+ self._seek(self.__logical_frame)
132
+
133
+ # We need to load the image data for this frame
134
+ data, self.info["timestamp"], self.info["duration"] = self._get_next()
135
+ self.__loaded = self.__logical_frame
136
+
137
+ # Set tile
138
+ if self.fp and self._exclusive_fp:
139
+ self.fp.close()
140
+ self.fp = BytesIO(data)
141
+ self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 0, self.rawmode)]
142
+
143
+ return super().load()
144
+
145
+ def load_seek(self, pos: int) -> None:
146
+ pass
147
+
148
+ def tell(self) -> int:
149
+ return self.__logical_frame
150
+
151
+
152
+ def _convert_frame(im: Image.Image) -> Image.Image:
153
+ # Make sure image mode is supported
154
+ if im.mode not in ("RGBX", "RGBA", "RGB"):
155
+ im = im.convert("RGBA" if im.has_transparency_data else "RGB")
156
+ return im
157
+
158
+
159
+ def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
160
+ encoderinfo = im.encoderinfo.copy()
161
+ append_images = list(encoderinfo.get("append_images", []))
162
+
163
+ # If total frame count is 1, then save using the legacy API, which
164
+ # will preserve non-alpha modes
165
+ total = 0
166
+ for ims in [im] + append_images:
167
+ total += getattr(ims, "n_frames", 1)
168
+ if total == 1:
169
+ _save(im, fp, filename)
170
+ return
171
+
172
+ background: int | tuple[int, ...] = (0, 0, 0, 0)
173
+ if "background" in encoderinfo:
174
+ background = encoderinfo["background"]
175
+ elif "background" in im.info:
176
+ background = im.info["background"]
177
+ if isinstance(background, int):
178
+ # GifImagePlugin stores a global color table index in
179
+ # info["background"]. So it must be converted to an RGBA value
180
+ palette = im.getpalette()
181
+ if palette:
182
+ r, g, b = palette[background * 3 : (background + 1) * 3]
183
+ background = (r, g, b, 255)
184
+ else:
185
+ background = (background, background, background, 255)
186
+
187
+ duration = im.encoderinfo.get("duration", im.info.get("duration", 0))
188
+ loop = im.encoderinfo.get("loop", 0)
189
+ minimize_size = im.encoderinfo.get("minimize_size", False)
190
+ kmin = im.encoderinfo.get("kmin", None)
191
+ kmax = im.encoderinfo.get("kmax", None)
192
+ allow_mixed = im.encoderinfo.get("allow_mixed", False)
193
+ verbose = False
194
+ lossless = im.encoderinfo.get("lossless", False)
195
+ quality = im.encoderinfo.get("quality", 80)
196
+ alpha_quality = im.encoderinfo.get("alpha_quality", 100)
197
+ method = im.encoderinfo.get("method", 0)
198
+ icc_profile = im.encoderinfo.get("icc_profile") or ""
199
+ exif = im.encoderinfo.get("exif", "")
200
+ if isinstance(exif, Image.Exif):
201
+ exif = exif.tobytes()
202
+ xmp = im.encoderinfo.get("xmp", "")
203
+ if allow_mixed:
204
+ lossless = False
205
+
206
+ # Sensible keyframe defaults are from gif2webp.c script
207
+ if kmin is None:
208
+ kmin = 9 if lossless else 3
209
+ if kmax is None:
210
+ kmax = 17 if lossless else 5
211
+
212
+ # Validate background color
213
+ if (
214
+ not isinstance(background, (list, tuple))
215
+ or len(background) != 4
216
+ or not all(0 <= v < 256 for v in background)
217
+ ):
218
+ msg = f"Background color is not an RGBA tuple clamped to (0-255): {background}"
219
+ raise OSError(msg)
220
+
221
+ # Convert to packed uint
222
+ bg_r, bg_g, bg_b, bg_a = background
223
+ background = (bg_a << 24) | (bg_r << 16) | (bg_g << 8) | (bg_b << 0)
224
+
225
+ # Setup the WebP animation encoder
226
+ enc = _webp.WebPAnimEncoder(
227
+ im.size,
228
+ background,
229
+ loop,
230
+ minimize_size,
231
+ kmin,
232
+ kmax,
233
+ allow_mixed,
234
+ verbose,
235
+ )
236
+
237
+ # Add each frame
238
+ frame_idx = 0
239
+ timestamp = 0
240
+ cur_idx = im.tell()
241
+ try:
242
+ for ims in [im] + append_images:
243
+ # Get number of frames in this image
244
+ nfr = getattr(ims, "n_frames", 1)
245
+
246
+ for idx in range(nfr):
247
+ ims.seek(idx)
248
+
249
+ frame = _convert_frame(ims)
250
+
251
+ # Append the frame to the animation encoder
252
+ enc.add(
253
+ frame.getim(),
254
+ round(timestamp),
255
+ lossless,
256
+ quality,
257
+ alpha_quality,
258
+ method,
259
+ )
260
+
261
+ # Update timestamp and frame index
262
+ if isinstance(duration, (list, tuple)):
263
+ timestamp += duration[frame_idx]
264
+ else:
265
+ timestamp += duration
266
+ frame_idx += 1
267
+
268
+ finally:
269
+ im.seek(cur_idx)
270
+
271
+ # Force encoder to flush frames
272
+ enc.add(None, round(timestamp), lossless, quality, alpha_quality, 0)
273
+
274
+ # Get the final output from the encoder
275
+ data = enc.assemble(icc_profile, exif, xmp)
276
+ if data is None:
277
+ msg = "cannot write file as WebP (encoder returned None)"
278
+ raise OSError(msg)
279
+
280
+ fp.write(data)
281
+
282
+
283
+ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
284
+ lossless = im.encoderinfo.get("lossless", False)
285
+ quality = im.encoderinfo.get("quality", 80)
286
+ alpha_quality = im.encoderinfo.get("alpha_quality", 100)
287
+ icc_profile = im.encoderinfo.get("icc_profile") or ""
288
+ exif = im.encoderinfo.get("exif", b"")
289
+ if isinstance(exif, Image.Exif):
290
+ exif = exif.tobytes()
291
+ if exif.startswith(b"Exif\x00\x00"):
292
+ exif = exif[6:]
293
+ xmp = im.encoderinfo.get("xmp", "")
294
+ method = im.encoderinfo.get("method", 4)
295
+ exact = 1 if im.encoderinfo.get("exact") else 0
296
+
297
+ im = _convert_frame(im)
298
+
299
+ data = _webp.WebPEncode(
300
+ im.getim(),
301
+ lossless,
302
+ float(quality),
303
+ float(alpha_quality),
304
+ icc_profile,
305
+ method,
306
+ exact,
307
+ exif,
308
+ xmp,
309
+ )
310
+ if data is None:
311
+ msg = "cannot write file as WebP (encoder returned None)"
312
+ raise OSError(msg)
313
+
314
+ fp.write(data)
315
+
316
+
317
+ Image.register_open(WebPImageFile.format, WebPImageFile, _accept)
318
+ if SUPPORTED:
319
+ Image.register_save(WebPImageFile.format, _save)
320
+ Image.register_save_all(WebPImageFile.format, _save_all)
321
+ Image.register_extension(WebPImageFile.format, ".webp")
322
+ Image.register_mime(WebPImageFile.format, "image/webp")
@@ -0,0 +1,183 @@
1
+ #
2
+ # The Python Imaging Library
3
+ # $Id$
4
+ #
5
+ # WMF stub codec
6
+ #
7
+ # history:
8
+ # 1996-12-14 fl Created
9
+ # 2004-02-22 fl Turned into a stub driver
10
+ # 2004-02-23 fl Added EMF support
11
+ #
12
+ # Copyright (c) Secret Labs AB 1997-2004. All rights reserved.
13
+ # Copyright (c) Fredrik Lundh 1996.
14
+ #
15
+ # See the README file for information on usage and redistribution.
16
+ #
17
+ # WMF/EMF reference documentation:
18
+ # https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf
19
+ # http://wvware.sourceforge.net/caolan/index.html
20
+ # http://wvware.sourceforge.net/caolan/ora-wmf.html
21
+ from __future__ import annotations
22
+
23
+ from typing import IO
24
+
25
+ from . import Image, ImageFile
26
+ from ._binary import i16le as word
27
+ from ._binary import si16le as short
28
+ from ._binary import si32le as _long
29
+
30
+ _handler = None
31
+
32
+
33
+ def register_handler(handler: ImageFile.StubHandler | None) -> None:
34
+ """
35
+ Install application-specific WMF image handler.
36
+
37
+ :param handler: Handler object.
38
+ """
39
+ global _handler
40
+ _handler = handler
41
+
42
+
43
+ if hasattr(Image.core, "drawwmf"):
44
+ # install default handler (windows only)
45
+
46
+ class WmfHandler(ImageFile.StubHandler):
47
+ def open(self, im: ImageFile.StubImageFile) -> None:
48
+ self.bbox = im.info["wmf_bbox"]
49
+
50
+ def load(self, im: ImageFile.StubImageFile) -> Image.Image:
51
+ assert im.fp is not None
52
+ im.fp.seek(0) # rewind
53
+ return Image.frombytes(
54
+ "RGB",
55
+ im.size,
56
+ Image.core.drawwmf(im.fp.read(), im.size, self.bbox),
57
+ "raw",
58
+ "BGR",
59
+ (im.size[0] * 3 + 3) & -4,
60
+ -1,
61
+ )
62
+
63
+ register_handler(WmfHandler())
64
+
65
+ #
66
+ # --------------------------------------------------------------------
67
+ # Read WMF file
68
+
69
+
70
+ def _accept(prefix: bytes) -> bool:
71
+ return prefix.startswith((b"\xd7\xcd\xc6\x9a\x00\x00", b"\x01\x00\x00\x00"))
72
+
73
+
74
+ ##
75
+ # Image plugin for Windows metafiles.
76
+
77
+
78
+ class WmfStubImageFile(ImageFile.StubImageFile):
79
+ format = "WMF"
80
+ format_description = "Windows Metafile"
81
+
82
+ def _open(self) -> None:
83
+ # check placeable header
84
+ assert self.fp is not None
85
+ s = self.fp.read(44)
86
+
87
+ if s.startswith(b"\xd7\xcd\xc6\x9a\x00\x00"):
88
+ # placeable windows metafile
89
+
90
+ # get units per inch
91
+ inch = word(s, 14)
92
+ if inch == 0:
93
+ msg = "Invalid inch"
94
+ raise ValueError(msg)
95
+ self._inch: tuple[float, float] = inch, inch
96
+
97
+ # get bounding box
98
+ x0 = short(s, 6)
99
+ y0 = short(s, 8)
100
+ x1 = short(s, 10)
101
+ y1 = short(s, 12)
102
+
103
+ # normalize size to 72 dots per inch
104
+ self.info["dpi"] = 72
105
+ size = (
106
+ (x1 - x0) * self.info["dpi"] // inch,
107
+ (y1 - y0) * self.info["dpi"] // inch,
108
+ )
109
+
110
+ self.info["wmf_bbox"] = x0, y0, x1, y1
111
+
112
+ # sanity check (standard metafile header)
113
+ if s[22:26] != b"\x01\x00\t\x00":
114
+ msg = "Unsupported WMF file format"
115
+ raise SyntaxError(msg)
116
+
117
+ elif s.startswith(b"\x01\x00\x00\x00") and s[40:44] == b" EMF":
118
+ # enhanced metafile
119
+
120
+ # get bounding box
121
+ x0 = _long(s, 8)
122
+ y0 = _long(s, 12)
123
+ x1 = _long(s, 16)
124
+ y1 = _long(s, 20)
125
+
126
+ # get frame (in 0.01 millimeter units)
127
+ frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36)
128
+
129
+ size = x1 - x0, y1 - y0
130
+
131
+ # calculate dots per inch from bbox and frame
132
+ xdpi = 2540.0 * (x1 - x0) / (frame[2] - frame[0])
133
+ ydpi = 2540.0 * (y1 - y0) / (frame[3] - frame[1])
134
+
135
+ self.info["wmf_bbox"] = x0, y0, x1, y1
136
+
137
+ if xdpi == ydpi:
138
+ self.info["dpi"] = xdpi
139
+ else:
140
+ self.info["dpi"] = xdpi, ydpi
141
+ self._inch = xdpi, ydpi
142
+
143
+ else:
144
+ msg = "Unsupported file format"
145
+ raise SyntaxError(msg)
146
+
147
+ self._mode = "RGB"
148
+ self._size = size
149
+
150
+ def _load(self) -> ImageFile.StubHandler | None:
151
+ return _handler
152
+
153
+ def load(
154
+ self, dpi: float | tuple[float, float] | None = None
155
+ ) -> Image.core.PixelAccess | None:
156
+ if dpi is not None:
157
+ self.info["dpi"] = dpi
158
+ x0, y0, x1, y1 = self.info["wmf_bbox"]
159
+ if not isinstance(dpi, tuple):
160
+ dpi = dpi, dpi
161
+ self._size = (
162
+ int((x1 - x0) * dpi[0] / self._inch[0]),
163
+ int((y1 - y0) * dpi[1] / self._inch[1]),
164
+ )
165
+ return super().load()
166
+
167
+
168
+ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
169
+ if _handler is None or not hasattr(_handler, "save"):
170
+ msg = "WMF save handler not installed"
171
+ raise OSError(msg)
172
+ _handler.save(im, fp, filename)
173
+
174
+
175
+ #
176
+ # --------------------------------------------------------------------
177
+ # Registry stuff
178
+
179
+
180
+ Image.register_open(WmfStubImageFile.format, WmfStubImageFile, _accept)
181
+ Image.register_save(WmfStubImageFile.format, _save)
182
+
183
+ Image.register_extensions(WmfStubImageFile.format, [".wmf", ".emf"])
@@ -0,0 +1,83 @@
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # XV Thumbnail file handler by Charles E. "Gene" Cash
6
+ # (gcash@magicnet.net)
7
+ #
8
+ # see xvcolor.c and xvbrowse.c in the sources to John Bradley's XV,
9
+ # available from ftp://ftp.cis.upenn.edu/pub/xv/
10
+ #
11
+ # history:
12
+ # 98-08-15 cec created (b/w only)
13
+ # 98-12-09 cec added color palette
14
+ # 98-12-28 fl added to PIL (with only a few very minor modifications)
15
+ #
16
+ # To do:
17
+ # FIXME: make save work (this requires quantization support)
18
+ #
19
+ from __future__ import annotations
20
+
21
+ from . import Image, ImageFile, ImagePalette
22
+ from ._binary import o8
23
+
24
+ _MAGIC = b"P7 332"
25
+
26
+ # standard color palette for thumbnails (RGB332)
27
+ PALETTE = b""
28
+ for r in range(8):
29
+ for g in range(8):
30
+ for b in range(4):
31
+ PALETTE = PALETTE + (
32
+ o8((r * 255) // 7) + o8((g * 255) // 7) + o8((b * 255) // 3)
33
+ )
34
+
35
+
36
+ def _accept(prefix: bytes) -> bool:
37
+ return prefix.startswith(_MAGIC)
38
+
39
+
40
+ ##
41
+ # Image plugin for XV thumbnail images.
42
+
43
+
44
+ class XVThumbImageFile(ImageFile.ImageFile):
45
+ format = "XVThumb"
46
+ format_description = "XV thumbnail image"
47
+
48
+ def _open(self) -> None:
49
+ # check magic
50
+ assert self.fp is not None
51
+
52
+ if not _accept(self.fp.read(6)):
53
+ msg = "not an XV thumbnail file"
54
+ raise SyntaxError(msg)
55
+
56
+ # Skip to beginning of next line
57
+ self.fp.readline()
58
+
59
+ # skip info comments
60
+ while True:
61
+ s = self.fp.readline()
62
+ if not s:
63
+ msg = "Unexpected EOF reading XV thumbnail file"
64
+ raise SyntaxError(msg)
65
+ if s[0] != 35: # ie. when not a comment: '#'
66
+ break
67
+
68
+ # parse header line (already read)
69
+ w, h = s.strip().split(maxsplit=2)[:2]
70
+
71
+ self._mode = "P"
72
+ self._size = int(w), int(h)
73
+
74
+ self.palette = ImagePalette.raw("RGB", PALETTE)
75
+
76
+ self.tile = [
77
+ ImageFile._Tile("raw", (0, 0) + self.size, self.fp.tell(), self.mode)
78
+ ]
79
+
80
+
81
+ # --------------------------------------------------------------------
82
+
83
+ Image.register_open(XVThumbImageFile.format, XVThumbImageFile, _accept)
@@ -0,0 +1,98 @@
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # XBM File handling
6
+ #
7
+ # History:
8
+ # 1995-09-08 fl Created
9
+ # 1996-11-01 fl Added save support
10
+ # 1997-07-07 fl Made header parser more tolerant
11
+ # 1997-07-22 fl Fixed yet another parser bug
12
+ # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.4)
13
+ # 2001-05-13 fl Added hotspot handling (based on code from Bernhard Herzog)
14
+ # 2004-02-24 fl Allow some whitespace before first #define
15
+ #
16
+ # Copyright (c) 1997-2004 by Secret Labs AB
17
+ # Copyright (c) 1996-1997 by Fredrik Lundh
18
+ #
19
+ # See the README file for information on usage and redistribution.
20
+ #
21
+ from __future__ import annotations
22
+
23
+ import re
24
+ from typing import IO
25
+
26
+ from . import Image, ImageFile
27
+
28
+ # XBM header
29
+ xbm_head = re.compile(
30
+ rb"\s*#define[ \t]+.*_width[ \t]+(?P<width>[0-9]+)[\r\n]+"
31
+ b"#define[ \t]+.*_height[ \t]+(?P<height>[0-9]+)[\r\n]+"
32
+ b"(?P<hotspot>"
33
+ b"#define[ \t]+[^_]*_x_hot[ \t]+(?P<xhot>[0-9]+)[\r\n]+"
34
+ b"#define[ \t]+[^_]*_y_hot[ \t]+(?P<yhot>[0-9]+)[\r\n]+"
35
+ b")?"
36
+ rb"[\000-\377]*_bits\[]"
37
+ )
38
+
39
+
40
+ def _accept(prefix: bytes) -> bool:
41
+ return prefix.lstrip().startswith(b"#define")
42
+
43
+
44
+ ##
45
+ # Image plugin for X11 bitmaps.
46
+
47
+
48
+ class XbmImageFile(ImageFile.ImageFile):
49
+ format = "XBM"
50
+ format_description = "X11 Bitmap"
51
+
52
+ def _open(self) -> None:
53
+ assert self.fp is not None
54
+
55
+ m = xbm_head.match(self.fp.read(512))
56
+
57
+ if not m:
58
+ msg = "not a XBM file"
59
+ raise SyntaxError(msg)
60
+
61
+ xsize = int(m.group("width"))
62
+ ysize = int(m.group("height"))
63
+
64
+ if m.group("hotspot"):
65
+ self.info["hotspot"] = (int(m.group("xhot")), int(m.group("yhot")))
66
+
67
+ self._mode = "1"
68
+ self._size = xsize, ysize
69
+
70
+ self.tile = [ImageFile._Tile("xbm", (0, 0) + self.size, m.end())]
71
+
72
+
73
+ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
74
+ if im.mode != "1":
75
+ msg = f"cannot write mode {im.mode} as XBM"
76
+ raise OSError(msg)
77
+
78
+ fp.write(f"#define im_width {im.size[0]}\n".encode("ascii"))
79
+ fp.write(f"#define im_height {im.size[1]}\n".encode("ascii"))
80
+
81
+ hotspot = im.encoderinfo.get("hotspot")
82
+ if hotspot:
83
+ fp.write(f"#define im_x_hot {hotspot[0]}\n".encode("ascii"))
84
+ fp.write(f"#define im_y_hot {hotspot[1]}\n".encode("ascii"))
85
+
86
+ fp.write(b"static char im_bits[] = {\n")
87
+
88
+ ImageFile._save(im, fp, [ImageFile._Tile("xbm", (0, 0) + im.size)])
89
+
90
+ fp.write(b"};\n")
91
+
92
+
93
+ Image.register_open(XbmImageFile.format, XbmImageFile, _accept)
94
+ Image.register_save(XbmImageFile.format, _save)
95
+
96
+ Image.register_extension(XbmImageFile.format, ".xbm")
97
+
98
+ Image.register_mime(XbmImageFile.format, "image/xbm")