@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,514 @@
1
+ #
2
+ # The Python Imaging Library.
3
+ # $Id$
4
+ #
5
+ # BMP file handler
6
+ #
7
+ # Windows (and OS/2) native bitmap storage format.
8
+ #
9
+ # history:
10
+ # 1995-09-01 fl Created
11
+ # 1996-04-30 fl Added save
12
+ # 1997-08-27 fl Fixed save of 1-bit images
13
+ # 1998-03-06 fl Load P images as L where possible
14
+ # 1998-07-03 fl Load P images as 1 where possible
15
+ # 1998-12-29 fl Handle small palettes
16
+ # 2002-12-30 fl Fixed load of 1-bit palette images
17
+ # 2003-04-21 fl Fixed load of 1-bit monochrome images
18
+ # 2003-04-23 fl Added limited support for BI_BITFIELDS compression
19
+ #
20
+ # Copyright (c) 1997-2003 by Secret Labs AB
21
+ # Copyright (c) 1995-2003 by Fredrik Lundh
22
+ #
23
+ # See the README file for information on usage and redistribution.
24
+ #
25
+ from __future__ import annotations
26
+
27
+ import os
28
+ from typing import IO, Any
29
+
30
+ from . import Image, ImageFile, ImagePalette
31
+ from ._binary import i16le as i16
32
+ from ._binary import i32le as i32
33
+ from ._binary import o8
34
+ from ._binary import o16le as o16
35
+ from ._binary import o32le as o32
36
+
37
+ #
38
+ # --------------------------------------------------------------------
39
+ # Read BMP file
40
+
41
+ BIT2MODE = {
42
+ # bits => mode, rawmode
43
+ 1: ("P", "P;1"),
44
+ 4: ("P", "P;4"),
45
+ 8: ("P", "P"),
46
+ 16: ("RGB", "BGR;15"),
47
+ 24: ("RGB", "BGR"),
48
+ 32: ("RGB", "BGRX"),
49
+ }
50
+
51
+ USE_RAW_ALPHA = False
52
+
53
+
54
+ def _accept(prefix: bytes) -> bool:
55
+ return prefix.startswith(b"BM")
56
+
57
+
58
+ def _dib_accept(prefix: bytes) -> bool:
59
+ return i32(prefix) in [12, 40, 52, 56, 64, 108, 124]
60
+
61
+
62
+ # =============================================================================
63
+ # Image plugin for the Windows BMP format.
64
+ # =============================================================================
65
+ class BmpImageFile(ImageFile.ImageFile):
66
+ """Image plugin for the Windows Bitmap format (BMP)"""
67
+
68
+ # ------------------------------------------------------------- Description
69
+ format_description = "Windows Bitmap"
70
+ format = "BMP"
71
+
72
+ # -------------------------------------------------- BMP Compression values
73
+ COMPRESSIONS = {"RAW": 0, "RLE8": 1, "RLE4": 2, "BITFIELDS": 3, "JPEG": 4, "PNG": 5}
74
+ for k, v in COMPRESSIONS.items():
75
+ vars()[k] = v
76
+
77
+ def _bitmap(self, header: int = 0, offset: int = 0) -> None:
78
+ """Read relevant info about the BMP"""
79
+ assert self.fp is not None
80
+ read, seek = self.fp.read, self.fp.seek
81
+ if header:
82
+ seek(header)
83
+ # read bmp header size @offset 14 (this is part of the header size)
84
+ file_info: dict[str, bool | int | tuple[int, ...]] = {
85
+ "header_size": i32(read(4)),
86
+ "direction": -1,
87
+ }
88
+
89
+ # -------------------- If requested, read header at a specific position
90
+ # read the rest of the bmp header, without its size
91
+ assert isinstance(file_info["header_size"], int)
92
+ header_data = ImageFile._safe_read(self.fp, file_info["header_size"] - 4)
93
+
94
+ # ------------------------------- Windows Bitmap v2, IBM OS/2 Bitmap v1
95
+ # ----- This format has different offsets because of width/height types
96
+ # 12: BITMAPCOREHEADER/OS21XBITMAPHEADER
97
+ if file_info["header_size"] == 12:
98
+ file_info["width"] = i16(header_data, 0)
99
+ file_info["height"] = i16(header_data, 2)
100
+ file_info["planes"] = i16(header_data, 4)
101
+ file_info["bits"] = i16(header_data, 6)
102
+ file_info["compression"] = self.COMPRESSIONS["RAW"]
103
+ file_info["palette_padding"] = 3
104
+
105
+ # --------------------------------------------- Windows Bitmap v3 to v5
106
+ # 40: BITMAPINFOHEADER
107
+ # 52: BITMAPV2HEADER
108
+ # 56: BITMAPV3HEADER
109
+ # 64: BITMAPCOREHEADER2/OS22XBITMAPHEADER
110
+ # 108: BITMAPV4HEADER
111
+ # 124: BITMAPV5HEADER
112
+ elif file_info["header_size"] in (40, 52, 56, 64, 108, 124):
113
+ file_info["y_flip"] = header_data[7] == 0xFF
114
+ file_info["direction"] = 1 if file_info["y_flip"] else -1
115
+ file_info["width"] = i32(header_data, 0)
116
+ file_info["height"] = (
117
+ i32(header_data, 4)
118
+ if not file_info["y_flip"]
119
+ else 2**32 - i32(header_data, 4)
120
+ )
121
+ file_info["planes"] = i16(header_data, 8)
122
+ file_info["bits"] = i16(header_data, 10)
123
+ file_info["compression"] = i32(header_data, 12)
124
+ # byte size of pixel data
125
+ file_info["data_size"] = i32(header_data, 16)
126
+ file_info["pixels_per_meter"] = (
127
+ i32(header_data, 20),
128
+ i32(header_data, 24),
129
+ )
130
+ file_info["colors"] = i32(header_data, 28)
131
+ file_info["palette_padding"] = 4
132
+ assert isinstance(file_info["pixels_per_meter"], tuple)
133
+ self.info["dpi"] = tuple(x / 39.3701 for x in file_info["pixels_per_meter"])
134
+ if file_info["compression"] == self.COMPRESSIONS["BITFIELDS"]:
135
+ masks = ["r_mask", "g_mask", "b_mask"]
136
+ if len(header_data) >= 48:
137
+ if len(header_data) >= 52:
138
+ masks.append("a_mask")
139
+ else:
140
+ file_info["a_mask"] = 0x0
141
+ for idx, mask in enumerate(masks):
142
+ file_info[mask] = i32(header_data, 36 + idx * 4)
143
+ else:
144
+ # 40 byte headers only have the three components in the
145
+ # bitfields masks, ref:
146
+ # https://msdn.microsoft.com/en-us/library/windows/desktop/dd183376(v=vs.85).aspx
147
+ # See also
148
+ # https://github.com/python-pillow/Pillow/issues/1293
149
+ # There is a 4th component in the RGBQuad, in the alpha
150
+ # location, but it is listed as a reserved component,
151
+ # and it is not generally an alpha channel
152
+ file_info["a_mask"] = 0x0
153
+ for mask in masks:
154
+ file_info[mask] = i32(read(4))
155
+ assert isinstance(file_info["r_mask"], int)
156
+ assert isinstance(file_info["g_mask"], int)
157
+ assert isinstance(file_info["b_mask"], int)
158
+ assert isinstance(file_info["a_mask"], int)
159
+ file_info["rgb_mask"] = (
160
+ file_info["r_mask"],
161
+ file_info["g_mask"],
162
+ file_info["b_mask"],
163
+ )
164
+ file_info["rgba_mask"] = (
165
+ file_info["r_mask"],
166
+ file_info["g_mask"],
167
+ file_info["b_mask"],
168
+ file_info["a_mask"],
169
+ )
170
+ else:
171
+ msg = f"Unsupported BMP header type ({file_info['header_size']})"
172
+ raise OSError(msg)
173
+
174
+ # ------------------ Special case : header is reported 40, which
175
+ # ---------------------- is shorter than real size for bpp >= 16
176
+ assert isinstance(file_info["width"], int)
177
+ assert isinstance(file_info["height"], int)
178
+ self._size = file_info["width"], file_info["height"]
179
+
180
+ # ------- If color count was not found in the header, compute from bits
181
+ assert isinstance(file_info["bits"], int)
182
+ if not file_info.get("colors", 0):
183
+ file_info["colors"] = 1 << file_info["bits"]
184
+ assert isinstance(file_info["palette_padding"], int)
185
+ assert isinstance(file_info["colors"], int)
186
+ if offset == 14 + file_info["header_size"] and file_info["bits"] <= 8:
187
+ offset += file_info["palette_padding"] * file_info["colors"]
188
+
189
+ # ---------------------- Check bit depth for unusual unsupported values
190
+ self._mode, raw_mode = BIT2MODE.get(file_info["bits"], ("", ""))
191
+ if not self.mode:
192
+ msg = f"Unsupported BMP pixel depth ({file_info['bits']})"
193
+ raise OSError(msg)
194
+
195
+ # ---------------- Process BMP with Bitfields compression (not palette)
196
+ decoder_name = "raw"
197
+ if file_info["compression"] == self.COMPRESSIONS["BITFIELDS"]:
198
+ SUPPORTED: dict[int, list[tuple[int, ...]]] = {
199
+ 32: [
200
+ (0xFF0000, 0xFF00, 0xFF, 0x0),
201
+ (0xFF000000, 0xFF0000, 0xFF00, 0x0),
202
+ (0xFF000000, 0xFF00, 0xFF, 0x0),
203
+ (0xFF000000, 0xFF0000, 0xFF00, 0xFF),
204
+ (0xFF, 0xFF00, 0xFF0000, 0xFF000000),
205
+ (0xFF0000, 0xFF00, 0xFF, 0xFF000000),
206
+ (0xFF000000, 0xFF00, 0xFF, 0xFF0000),
207
+ (0x0, 0x0, 0x0, 0x0),
208
+ ],
209
+ 24: [(0xFF0000, 0xFF00, 0xFF)],
210
+ 16: [(0xF800, 0x7E0, 0x1F), (0x7C00, 0x3E0, 0x1F)],
211
+ }
212
+ MASK_MODES = {
213
+ (32, (0xFF0000, 0xFF00, 0xFF, 0x0)): "BGRX",
214
+ (32, (0xFF000000, 0xFF0000, 0xFF00, 0x0)): "XBGR",
215
+ (32, (0xFF000000, 0xFF00, 0xFF, 0x0)): "BGXR",
216
+ (32, (0xFF000000, 0xFF0000, 0xFF00, 0xFF)): "ABGR",
217
+ (32, (0xFF, 0xFF00, 0xFF0000, 0xFF000000)): "RGBA",
218
+ (32, (0xFF0000, 0xFF00, 0xFF, 0xFF000000)): "BGRA",
219
+ (32, (0xFF000000, 0xFF00, 0xFF, 0xFF0000)): "BGAR",
220
+ (32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
221
+ (24, (0xFF0000, 0xFF00, 0xFF)): "BGR",
222
+ (16, (0xF800, 0x7E0, 0x1F)): "BGR;16",
223
+ (16, (0x7C00, 0x3E0, 0x1F)): "BGR;15",
224
+ }
225
+ if file_info["bits"] in SUPPORTED:
226
+ if (
227
+ file_info["bits"] == 32
228
+ and file_info["rgba_mask"] in SUPPORTED[file_info["bits"]]
229
+ ):
230
+ assert isinstance(file_info["rgba_mask"], tuple)
231
+ raw_mode = MASK_MODES[(file_info["bits"], file_info["rgba_mask"])]
232
+ self._mode = "RGBA" if "A" in raw_mode else self.mode
233
+ elif (
234
+ file_info["bits"] in (24, 16)
235
+ and file_info["rgb_mask"] in SUPPORTED[file_info["bits"]]
236
+ ):
237
+ assert isinstance(file_info["rgb_mask"], tuple)
238
+ raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
239
+ else:
240
+ msg = "Unsupported BMP bitfields layout"
241
+ raise OSError(msg)
242
+ else:
243
+ msg = "Unsupported BMP bitfields layout"
244
+ raise OSError(msg)
245
+ elif file_info["compression"] == self.COMPRESSIONS["RAW"]:
246
+ if file_info["bits"] == 32 and (
247
+ header == 22 or USE_RAW_ALPHA # 32-bit .cur offset
248
+ ):
249
+ raw_mode, self._mode = "BGRA", "RGBA"
250
+ elif file_info["compression"] in (
251
+ self.COMPRESSIONS["RLE8"],
252
+ self.COMPRESSIONS["RLE4"],
253
+ ):
254
+ decoder_name = "bmp_rle"
255
+ else:
256
+ msg = f"Unsupported BMP compression ({file_info['compression']})"
257
+ raise OSError(msg)
258
+
259
+ # --------------- Once the header is processed, process the palette/LUT
260
+ if self.mode == "P": # Paletted for 1, 4 and 8 bit images
261
+ # ---------------------------------------------------- 1-bit images
262
+ if not (0 < file_info["colors"] <= 65536):
263
+ msg = f"Unsupported BMP Palette size ({file_info['colors']})"
264
+ raise OSError(msg)
265
+ else:
266
+ padding = file_info["palette_padding"]
267
+ palette = read(padding * file_info["colors"])
268
+ grayscale = True
269
+ indices = (
270
+ (0, 255)
271
+ if file_info["colors"] == 2
272
+ else list(range(file_info["colors"]))
273
+ )
274
+
275
+ # ----------------- Check if grayscale and ignore palette if so
276
+ for ind, val in enumerate(indices):
277
+ rgb = palette[ind * padding : ind * padding + 3]
278
+ if rgb != o8(val) * 3:
279
+ grayscale = False
280
+
281
+ # ------- If all colors are gray, white or black, ditch palette
282
+ if grayscale:
283
+ self._mode = "1" if file_info["colors"] == 2 else "L"
284
+ raw_mode = self.mode
285
+ else:
286
+ self._mode = "P"
287
+ self.palette = ImagePalette.raw(
288
+ "BGRX" if padding == 4 else "BGR", palette
289
+ )
290
+
291
+ # ---------------------------- Finally set the tile data for the plugin
292
+ self.info["compression"] = file_info["compression"]
293
+ args: list[Any] = [raw_mode]
294
+ if decoder_name == "bmp_rle":
295
+ args.append(file_info["compression"] == self.COMPRESSIONS["RLE4"])
296
+ else:
297
+ assert isinstance(file_info["width"], int)
298
+ args.append(((file_info["width"] * file_info["bits"] + 31) >> 3) & (~3))
299
+ args.append(file_info["direction"])
300
+ self.tile = [
301
+ ImageFile._Tile(
302
+ decoder_name,
303
+ (0, 0, file_info["width"], file_info["height"]),
304
+ offset or self.fp.tell(),
305
+ tuple(args),
306
+ )
307
+ ]
308
+
309
+ def _open(self) -> None:
310
+ """Open file, check magic number and read header"""
311
+ # read 14 bytes: magic number, filesize, reserved, header final offset
312
+ assert self.fp is not None
313
+ head_data = self.fp.read(14)
314
+ # choke if the file does not have the required magic bytes
315
+ if not _accept(head_data):
316
+ msg = "Not a BMP file"
317
+ raise SyntaxError(msg)
318
+ # read the start position of the BMP image data (u32)
319
+ offset = i32(head_data, 10)
320
+ # load bitmap information (offset=raster info)
321
+ self._bitmap(offset=offset)
322
+
323
+
324
+ class BmpRleDecoder(ImageFile.PyDecoder):
325
+ _pulls_fd = True
326
+
327
+ def decode(self, buffer: Image.DecoderInput) -> tuple[int, int]:
328
+ assert self.fd is not None
329
+ rle4 = self.args[1]
330
+ data = bytearray()
331
+ x = 0
332
+ dest_length = self.state.xsize * self.state.ysize
333
+ while len(data) < dest_length:
334
+ pixels = self.fd.read(1)
335
+ byte = self.fd.read(1)
336
+ if not pixels or not byte:
337
+ break
338
+ num_pixels = pixels[0]
339
+ if num_pixels:
340
+ # encoded mode
341
+ if x + num_pixels > self.state.xsize:
342
+ # Too much data for row
343
+ num_pixels = max(0, self.state.xsize - x)
344
+ if rle4:
345
+ first_pixel = o8(byte[0] >> 4)
346
+ second_pixel = o8(byte[0] & 0x0F)
347
+ for index in range(num_pixels):
348
+ if index % 2 == 0:
349
+ data += first_pixel
350
+ else:
351
+ data += second_pixel
352
+ else:
353
+ data += byte * num_pixels
354
+ x += num_pixels
355
+ else:
356
+ if byte[0] == 0:
357
+ # end of line
358
+ while len(data) % self.state.xsize != 0:
359
+ data += b"\x00"
360
+ x = 0
361
+ elif byte[0] == 1:
362
+ # end of bitmap
363
+ break
364
+ elif byte[0] == 2:
365
+ # delta
366
+ bytes_read = self.fd.read(2)
367
+ if len(bytes_read) < 2:
368
+ break
369
+ right, up = bytes_read
370
+ data += b"\x00" * (right + up * self.state.xsize)
371
+ x = len(data) % self.state.xsize
372
+ else:
373
+ # absolute mode
374
+ if rle4:
375
+ # 2 pixels per byte
376
+ byte_count = byte[0] // 2
377
+ bytes_read = self.fd.read(byte_count)
378
+ for byte_read in bytes_read:
379
+ data += o8(byte_read >> 4)
380
+ data += o8(byte_read & 0x0F)
381
+ else:
382
+ byte_count = byte[0]
383
+ bytes_read = self.fd.read(byte_count)
384
+ data += bytes_read
385
+ if len(bytes_read) < byte_count:
386
+ break
387
+ x += byte[0]
388
+
389
+ # align to 16-bit word boundary
390
+ if self.fd.tell() % 2 != 0:
391
+ self.fd.seek(1, os.SEEK_CUR)
392
+ rawmode = "L" if self.mode == "L" else "P"
393
+ self.set_as_raw(bytes(data), rawmode, (0, self.args[-1]))
394
+ return -1, 0
395
+
396
+
397
+ # =============================================================================
398
+ # Image plugin for the DIB format (BMP alias)
399
+ # =============================================================================
400
+ class DibImageFile(BmpImageFile):
401
+ format = "DIB"
402
+ format_description = "Windows Bitmap"
403
+
404
+ def _open(self) -> None:
405
+ self._bitmap()
406
+
407
+
408
+ #
409
+ # --------------------------------------------------------------------
410
+ # Write BMP file
411
+
412
+
413
+ SAVE = {
414
+ "1": ("1", 1, 2),
415
+ "L": ("L", 8, 256),
416
+ "P": ("P", 8, 256),
417
+ "RGB": ("BGR", 24, 0),
418
+ "RGBA": ("BGRA", 32, 0),
419
+ }
420
+
421
+
422
+ def _dib_save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
423
+ _save(im, fp, filename, False)
424
+
425
+
426
+ def _save(
427
+ im: Image.Image, fp: IO[bytes], filename: str | bytes, bitmap_header: bool = True
428
+ ) -> None:
429
+ try:
430
+ rawmode, bits, colors = SAVE[im.mode]
431
+ except KeyError as e:
432
+ msg = f"cannot write mode {im.mode} as BMP"
433
+ raise OSError(msg) from e
434
+
435
+ info = im.encoderinfo
436
+
437
+ dpi = info.get("dpi", (96, 96))
438
+
439
+ # 1 meter == 39.3701 inches
440
+ ppm = tuple(int(x * 39.3701 + 0.5) for x in dpi)
441
+
442
+ stride = ((im.size[0] * bits + 7) // 8 + 3) & (~3)
443
+ header = 40 # or 64 for OS/2 version 2
444
+ image = stride * im.size[1]
445
+
446
+ if im.mode == "1":
447
+ palette = b"".join(o8(i) * 3 + b"\x00" for i in (0, 255))
448
+ elif im.mode == "L":
449
+ palette = b"".join(o8(i) * 3 + b"\x00" for i in range(256))
450
+ elif im.mode == "P":
451
+ palette = im.im.getpalette("RGB", "BGRX")
452
+ colors = len(palette) // 4
453
+ else:
454
+ palette = None
455
+
456
+ # bitmap header
457
+ if bitmap_header:
458
+ offset = 14 + header + colors * 4
459
+ file_size = offset + image
460
+ if file_size > 2**32 - 1:
461
+ msg = "File size is too large for the BMP format"
462
+ raise ValueError(msg)
463
+ fp.write(
464
+ b"BM" # file type (magic)
465
+ + o32(file_size) # file size
466
+ + o32(0) # reserved
467
+ + o32(offset) # image data offset
468
+ )
469
+
470
+ # bitmap info header
471
+ fp.write(
472
+ o32(header) # info header size
473
+ + o32(im.size[0]) # width
474
+ + o32(im.size[1]) # height
475
+ + o16(1) # planes
476
+ + o16(bits) # depth
477
+ + o32(0) # compression (0=uncompressed)
478
+ + o32(image) # size of bitmap
479
+ + o32(ppm[0]) # resolution
480
+ + o32(ppm[1]) # resolution
481
+ + o32(colors) # colors used
482
+ + o32(colors) # colors important
483
+ )
484
+
485
+ fp.write(b"\0" * (header - 40)) # padding (for OS/2 format)
486
+
487
+ if palette:
488
+ fp.write(palette)
489
+
490
+ ImageFile._save(
491
+ im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, (rawmode, stride, -1))]
492
+ )
493
+
494
+
495
+ #
496
+ # --------------------------------------------------------------------
497
+ # Registry
498
+
499
+
500
+ Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
501
+ Image.register_save(BmpImageFile.format, _save)
502
+
503
+ Image.register_extension(BmpImageFile.format, ".bmp")
504
+
505
+ Image.register_mime(BmpImageFile.format, "image/bmp")
506
+
507
+ Image.register_decoder("bmp_rle", BmpRleDecoder)
508
+
509
+ Image.register_open(DibImageFile.format, DibImageFile, _dib_accept)
510
+ Image.register_save(DibImageFile.format, _dib_save)
511
+
512
+ Image.register_extension(DibImageFile.format, ".dib")
513
+
514
+ Image.register_mime(DibImageFile.format, "image/bmp")
@@ -0,0 +1,72 @@
1
+ #
2
+ # The Python Imaging Library
3
+ # $Id$
4
+ #
5
+ # BUFR stub adapter
6
+ #
7
+ # Copyright (c) 1996-2003 by Fredrik Lundh
8
+ #
9
+ # See the README file for information on usage and redistribution.
10
+ #
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ from typing import IO
15
+
16
+ from . import Image, ImageFile
17
+
18
+ _handler = None
19
+
20
+
21
+ def register_handler(handler: ImageFile.StubHandler | None) -> None:
22
+ """
23
+ Install application-specific BUFR image handler.
24
+
25
+ :param handler: Handler object.
26
+ """
27
+ global _handler
28
+ _handler = handler
29
+
30
+
31
+ # --------------------------------------------------------------------
32
+ # Image adapter
33
+
34
+
35
+ def _accept(prefix: bytes) -> bool:
36
+ return prefix.startswith((b"BUFR", b"ZCZC"))
37
+
38
+
39
+ class BufrStubImageFile(ImageFile.StubImageFile):
40
+ format = "BUFR"
41
+ format_description = "BUFR"
42
+
43
+ def _open(self) -> None:
44
+ assert self.fp is not None
45
+ if not _accept(self.fp.read(4)):
46
+ msg = "Not a BUFR file"
47
+ raise SyntaxError(msg)
48
+
49
+ self.fp.seek(-4, os.SEEK_CUR)
50
+
51
+ # make something up
52
+ self._mode = "F"
53
+ self._size = 1, 1
54
+
55
+ def _load(self) -> ImageFile.StubHandler | None:
56
+ return _handler
57
+
58
+
59
+ def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
60
+ if _handler is None or not hasattr(_handler, "save"):
61
+ msg = "BUFR save handler not installed"
62
+ raise OSError(msg)
63
+ _handler.save(im, fp, filename)
64
+
65
+
66
+ # --------------------------------------------------------------------
67
+ # Registry
68
+
69
+ Image.register_open(BufrStubImageFile.format, BufrStubImageFile, _accept)
70
+ Image.register_save(BufrStubImageFile.format, _save)
71
+
72
+ Image.register_extension(BufrStubImageFile.format, ".bufr")