Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/PalmImagePlugin.py: 30%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#
2# The Python Imaging Library.
3# $Id$
4#
6##
7# Image plugin for Palm pixmap images (output only).
8##
9from __future__ import annotations
11__lazy_modules__ = {"PIL._binary"}
13from . import Image, ImageFile
14from ._binary import o8
15from ._binary import o16be as o16b
17TYPE_CHECKING = False
18if TYPE_CHECKING:
19 from typing import IO
21_Palm8BitColormapValues = (
22 (255, 255, 255), (255, 204, 255), (255, 153, 255), (255, 102, 255),
23 (255, 51, 255), (255, 0, 255), (255, 255, 204), (255, 204, 204),
24 (255, 153, 204), (255, 102, 204), (255, 51, 204), (255, 0, 204),
25 (255, 255, 153), (255, 204, 153), (255, 153, 153), (255, 102, 153),
26 (255, 51, 153), (255, 0, 153), (204, 255, 255), (204, 204, 255),
27 (204, 153, 255), (204, 102, 255), (204, 51, 255), (204, 0, 255),
28 (204, 255, 204), (204, 204, 204), (204, 153, 204), (204, 102, 204),
29 (204, 51, 204), (204, 0, 204), (204, 255, 153), (204, 204, 153),
30 (204, 153, 153), (204, 102, 153), (204, 51, 153), (204, 0, 153),
31 (153, 255, 255), (153, 204, 255), (153, 153, 255), (153, 102, 255),
32 (153, 51, 255), (153, 0, 255), (153, 255, 204), (153, 204, 204),
33 (153, 153, 204), (153, 102, 204), (153, 51, 204), (153, 0, 204),
34 (153, 255, 153), (153, 204, 153), (153, 153, 153), (153, 102, 153),
35 (153, 51, 153), (153, 0, 153), (102, 255, 255), (102, 204, 255),
36 (102, 153, 255), (102, 102, 255), (102, 51, 255), (102, 0, 255),
37 (102, 255, 204), (102, 204, 204), (102, 153, 204), (102, 102, 204),
38 (102, 51, 204), (102, 0, 204), (102, 255, 153), (102, 204, 153),
39 (102, 153, 153), (102, 102, 153), (102, 51, 153), (102, 0, 153),
40 (51, 255, 255), (51, 204, 255), (51, 153, 255), (51, 102, 255),
41 (51, 51, 255), (51, 0, 255), (51, 255, 204), (51, 204, 204),
42 (51, 153, 204), (51, 102, 204), (51, 51, 204), (51, 0, 204),
43 (51, 255, 153), (51, 204, 153), (51, 153, 153), (51, 102, 153),
44 (51, 51, 153), (51, 0, 153), (0, 255, 255), (0, 204, 255),
45 (0, 153, 255), (0, 102, 255), (0, 51, 255), (0, 0, 255),
46 (0, 255, 204), (0, 204, 204), (0, 153, 204), (0, 102, 204),
47 (0, 51, 204), (0, 0, 204), (0, 255, 153), (0, 204, 153),
48 (0, 153, 153), (0, 102, 153), (0, 51, 153), (0, 0, 153),
49 (255, 255, 102), (255, 204, 102), (255, 153, 102), (255, 102, 102),
50 (255, 51, 102), (255, 0, 102), (255, 255, 51), (255, 204, 51),
51 (255, 153, 51), (255, 102, 51), (255, 51, 51), (255, 0, 51),
52 (255, 255, 0), (255, 204, 0), (255, 153, 0), (255, 102, 0),
53 (255, 51, 0), (255, 0, 0), (204, 255, 102), (204, 204, 102),
54 (204, 153, 102), (204, 102, 102), (204, 51, 102), (204, 0, 102),
55 (204, 255, 51), (204, 204, 51), (204, 153, 51), (204, 102, 51),
56 (204, 51, 51), (204, 0, 51), (204, 255, 0), (204, 204, 0),
57 (204, 153, 0), (204, 102, 0), (204, 51, 0), (204, 0, 0),
58 (153, 255, 102), (153, 204, 102), (153, 153, 102), (153, 102, 102),
59 (153, 51, 102), (153, 0, 102), (153, 255, 51), (153, 204, 51),
60 (153, 153, 51), (153, 102, 51), (153, 51, 51), (153, 0, 51),
61 (153, 255, 0), (153, 204, 0), (153, 153, 0), (153, 102, 0),
62 (153, 51, 0), (153, 0, 0), (102, 255, 102), (102, 204, 102),
63 (102, 153, 102), (102, 102, 102), (102, 51, 102), (102, 0, 102),
64 (102, 255, 51), (102, 204, 51), (102, 153, 51), (102, 102, 51),
65 (102, 51, 51), (102, 0, 51), (102, 255, 0), (102, 204, 0),
66 (102, 153, 0), (102, 102, 0), (102, 51, 0), (102, 0, 0),
67 (51, 255, 102), (51, 204, 102), (51, 153, 102), (51, 102, 102),
68 (51, 51, 102), (51, 0, 102), (51, 255, 51), (51, 204, 51),
69 (51, 153, 51), (51, 102, 51), (51, 51, 51), (51, 0, 51),
70 (51, 255, 0), (51, 204, 0), (51, 153, 0), (51, 102, 0),
71 (51, 51, 0), (51, 0, 0), (0, 255, 102), (0, 204, 102),
72 (0, 153, 102), (0, 102, 102), (0, 51, 102), (0, 0, 102),
73 (0, 255, 51), (0, 204, 51), (0, 153, 51), (0, 102, 51),
74 (0, 51, 51), (0, 0, 51), (0, 255, 0), (0, 204, 0),
75 (0, 153, 0), (0, 102, 0), (0, 51, 0), (17, 17, 17),
76 (34, 34, 34), (68, 68, 68), (85, 85, 85), (119, 119, 119),
77 (136, 136, 136), (170, 170, 170), (187, 187, 187), (221, 221, 221),
78 (238, 238, 238), (192, 192, 192), (128, 0, 0), (128, 0, 128),
79 (0, 128, 0), (0, 128, 128), (0, 0, 0), (0, 0, 0),
80 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
81 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
82 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
83 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
84 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
85 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
86) # fmt: skip
89# so build a prototype image to be used for palette resampling
90def build_prototype_image() -> Image.Image:
91 image = Image.new("L", (1, len(_Palm8BitColormapValues)))
92 image.putdata(list(range(len(_Palm8BitColormapValues))))
93 palettedata: tuple[int, ...] = ()
94 for colormapValue in _Palm8BitColormapValues:
95 palettedata += colormapValue
96 palettedata += (0, 0, 0) * (256 - len(_Palm8BitColormapValues))
97 image.putpalette(palettedata)
98 return image
101Palm8BitColormapImage = build_prototype_image()
103# OK, we now have in Palm8BitColormapImage,
104# a "P"-mode image with the right palette
105#
106# --------------------------------------------------------------------
108_FLAGS = {"custom-colormap": 0x4000, "is-compressed": 0x8000, "has-transparent": 0x2000}
110_COMPRESSION_TYPES = {"none": 0xFF, "rle": 0x01, "scanline": 0x00}
113#
114# --------------------------------------------------------------------
116##
117# (Internal) Image save plugin for the Palm format.
120def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
121 if im.mode == "P":
122 rawmode = "P"
123 bpp = 8
124 version = 1
126 elif im.mode == "L":
127 if im.encoderinfo.get("bpp") in (1, 2, 4):
128 # this is 8-bit grayscale, so we shift it to get the high-order bits,
129 # and invert it because
130 # Palm does grayscale from white (0) to black (1)
131 bpp = im.encoderinfo["bpp"]
132 maxval = (1 << bpp) - 1
133 shift = 8 - bpp
134 im = im.point(lambda x: maxval - (x >> shift))
135 elif im.info.get("bpp") in (1, 2, 4):
136 # here we assume that even though the inherent mode is 8-bit grayscale,
137 # only the lower bpp bits are significant.
138 # We invert them to match the Palm.
139 bpp = im.info["bpp"]
140 maxval = (1 << bpp) - 1
141 im = im.point(lambda x: maxval - (x & maxval))
142 else:
143 msg = f"cannot write mode {im.mode} as Palm"
144 raise OSError(msg)
146 rawmode = f"L;{bpp}"
147 version = 1
149 elif im.mode == "1":
150 # monochrome -- write it inverted, as is the Palm standard
151 rawmode = "1;I"
152 bpp = 1
153 version = 0
155 else:
156 msg = f"cannot write mode {im.mode} as Palm"
157 raise OSError(msg)
159 #
160 # make sure image data is available
161 im.load()
163 # write header
165 cols = im.size[0]
166 rows = im.size[1]
168 rowbytes = int((cols + (16 // bpp - 1)) / (16 // bpp)) * 2
169 transparent_index = 0
170 compression_type = _COMPRESSION_TYPES["none"]
172 flags = 0
173 if im.mode == "P":
174 flags |= _FLAGS["custom-colormap"]
175 colormap = im.im.getpalette("RGB")
176 colors = len(colormap) // 3
177 colormapsize = 4 * colors + 2
178 else:
179 colormapsize = 0
181 if "offset" in im.info:
182 offset = (rowbytes * rows + 16 + 3 + colormapsize) // 4
183 else:
184 offset = 0
186 fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
187 fp.write(o8(bpp))
188 fp.write(o8(version))
189 fp.write(o16b(offset))
190 fp.write(o8(transparent_index))
191 fp.write(o8(compression_type))
192 fp.write(o16b(0)) # reserved by Palm
194 # now write colormap if necessary
196 if colormapsize:
197 fp.write(o16b(colors))
198 for i in range(colors):
199 fp.write(o8(i))
200 fp.write(colormap[3 * i : 3 * i + 3])
202 # now convert data to raw form
203 ImageFile._save(im, fp, [ImageFile._Tile("raw", args=(rawmode, rowbytes, 1))])
205 if hasattr(fp, "flush"):
206 fp.flush()
209#
210# --------------------------------------------------------------------
212Image.register_save("PALM", _save)
214Image.register_extension("PALM", ".palm")
216Image.register_mime("PALM", "image/palm")