Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/PIL/PalmImagePlugin.py: 28%
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
11from typing import IO
13from . import Image, ImageFile
14from ._binary import o8
15from ._binary import o16be as o16b
17_Palm8BitColormapValues = (
18 (255, 255, 255), (255, 204, 255), (255, 153, 255), (255, 102, 255),
19 (255, 51, 255), (255, 0, 255), (255, 255, 204), (255, 204, 204),
20 (255, 153, 204), (255, 102, 204), (255, 51, 204), (255, 0, 204),
21 (255, 255, 153), (255, 204, 153), (255, 153, 153), (255, 102, 153),
22 (255, 51, 153), (255, 0, 153), (204, 255, 255), (204, 204, 255),
23 (204, 153, 255), (204, 102, 255), (204, 51, 255), (204, 0, 255),
24 (204, 255, 204), (204, 204, 204), (204, 153, 204), (204, 102, 204),
25 (204, 51, 204), (204, 0, 204), (204, 255, 153), (204, 204, 153),
26 (204, 153, 153), (204, 102, 153), (204, 51, 153), (204, 0, 153),
27 (153, 255, 255), (153, 204, 255), (153, 153, 255), (153, 102, 255),
28 (153, 51, 255), (153, 0, 255), (153, 255, 204), (153, 204, 204),
29 (153, 153, 204), (153, 102, 204), (153, 51, 204), (153, 0, 204),
30 (153, 255, 153), (153, 204, 153), (153, 153, 153), (153, 102, 153),
31 (153, 51, 153), (153, 0, 153), (102, 255, 255), (102, 204, 255),
32 (102, 153, 255), (102, 102, 255), (102, 51, 255), (102, 0, 255),
33 (102, 255, 204), (102, 204, 204), (102, 153, 204), (102, 102, 204),
34 (102, 51, 204), (102, 0, 204), (102, 255, 153), (102, 204, 153),
35 (102, 153, 153), (102, 102, 153), (102, 51, 153), (102, 0, 153),
36 (51, 255, 255), (51, 204, 255), (51, 153, 255), (51, 102, 255),
37 (51, 51, 255), (51, 0, 255), (51, 255, 204), (51, 204, 204),
38 (51, 153, 204), (51, 102, 204), (51, 51, 204), (51, 0, 204),
39 (51, 255, 153), (51, 204, 153), (51, 153, 153), (51, 102, 153),
40 (51, 51, 153), (51, 0, 153), (0, 255, 255), (0, 204, 255),
41 (0, 153, 255), (0, 102, 255), (0, 51, 255), (0, 0, 255),
42 (0, 255, 204), (0, 204, 204), (0, 153, 204), (0, 102, 204),
43 (0, 51, 204), (0, 0, 204), (0, 255, 153), (0, 204, 153),
44 (0, 153, 153), (0, 102, 153), (0, 51, 153), (0, 0, 153),
45 (255, 255, 102), (255, 204, 102), (255, 153, 102), (255, 102, 102),
46 (255, 51, 102), (255, 0, 102), (255, 255, 51), (255, 204, 51),
47 (255, 153, 51), (255, 102, 51), (255, 51, 51), (255, 0, 51),
48 (255, 255, 0), (255, 204, 0), (255, 153, 0), (255, 102, 0),
49 (255, 51, 0), (255, 0, 0), (204, 255, 102), (204, 204, 102),
50 (204, 153, 102), (204, 102, 102), (204, 51, 102), (204, 0, 102),
51 (204, 255, 51), (204, 204, 51), (204, 153, 51), (204, 102, 51),
52 (204, 51, 51), (204, 0, 51), (204, 255, 0), (204, 204, 0),
53 (204, 153, 0), (204, 102, 0), (204, 51, 0), (204, 0, 0),
54 (153, 255, 102), (153, 204, 102), (153, 153, 102), (153, 102, 102),
55 (153, 51, 102), (153, 0, 102), (153, 255, 51), (153, 204, 51),
56 (153, 153, 51), (153, 102, 51), (153, 51, 51), (153, 0, 51),
57 (153, 255, 0), (153, 204, 0), (153, 153, 0), (153, 102, 0),
58 (153, 51, 0), (153, 0, 0), (102, 255, 102), (102, 204, 102),
59 (102, 153, 102), (102, 102, 102), (102, 51, 102), (102, 0, 102),
60 (102, 255, 51), (102, 204, 51), (102, 153, 51), (102, 102, 51),
61 (102, 51, 51), (102, 0, 51), (102, 255, 0), (102, 204, 0),
62 (102, 153, 0), (102, 102, 0), (102, 51, 0), (102, 0, 0),
63 (51, 255, 102), (51, 204, 102), (51, 153, 102), (51, 102, 102),
64 (51, 51, 102), (51, 0, 102), (51, 255, 51), (51, 204, 51),
65 (51, 153, 51), (51, 102, 51), (51, 51, 51), (51, 0, 51),
66 (51, 255, 0), (51, 204, 0), (51, 153, 0), (51, 102, 0),
67 (51, 51, 0), (51, 0, 0), (0, 255, 102), (0, 204, 102),
68 (0, 153, 102), (0, 102, 102), (0, 51, 102), (0, 0, 102),
69 (0, 255, 51), (0, 204, 51), (0, 153, 51), (0, 102, 51),
70 (0, 51, 51), (0, 0, 51), (0, 255, 0), (0, 204, 0),
71 (0, 153, 0), (0, 102, 0), (0, 51, 0), (17, 17, 17),
72 (34, 34, 34), (68, 68, 68), (85, 85, 85), (119, 119, 119),
73 (136, 136, 136), (170, 170, 170), (187, 187, 187), (221, 221, 221),
74 (238, 238, 238), (192, 192, 192), (128, 0, 0), (128, 0, 128),
75 (0, 128, 0), (0, 128, 128), (0, 0, 0), (0, 0, 0),
76 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
77 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
78 (0, 0, 0), (0, 0, 0), (0, 0, 0), (0, 0, 0),
79 (0, 0, 0), (0, 0, 0), (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) # fmt: skip
85# so build a prototype image to be used for palette resampling
86def build_prototype_image() -> Image.Image:
87 image = Image.new("L", (1, len(_Palm8BitColormapValues)))
88 image.putdata(list(range(len(_Palm8BitColormapValues))))
89 palettedata: tuple[int, ...] = ()
90 for colormapValue in _Palm8BitColormapValues:
91 palettedata += colormapValue
92 palettedata += (0, 0, 0) * (256 - len(_Palm8BitColormapValues))
93 image.putpalette(palettedata)
94 return image
97Palm8BitColormapImage = build_prototype_image()
99# OK, we now have in Palm8BitColormapImage,
100# a "P"-mode image with the right palette
101#
102# --------------------------------------------------------------------
104_FLAGS = {"custom-colormap": 0x4000, "is-compressed": 0x8000, "has-transparent": 0x2000}
106_COMPRESSION_TYPES = {"none": 0xFF, "rle": 0x01, "scanline": 0x00}
109#
110# --------------------------------------------------------------------
112##
113# (Internal) Image save plugin for the Palm format.
116def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
117 if im.mode == "P":
118 rawmode = "P"
119 bpp = 8
120 version = 1
122 elif im.mode == "L":
123 if im.encoderinfo.get("bpp") in (1, 2, 4):
124 # this is 8-bit grayscale, so we shift it to get the high-order bits,
125 # and invert it because
126 # Palm does grayscale from white (0) to black (1)
127 bpp = im.encoderinfo["bpp"]
128 maxval = (1 << bpp) - 1
129 shift = 8 - bpp
130 im = im.point(lambda x: maxval - (x >> shift))
131 elif im.info.get("bpp") in (1, 2, 4):
132 # here we assume that even though the inherent mode is 8-bit grayscale,
133 # only the lower bpp bits are significant.
134 # We invert them to match the Palm.
135 bpp = im.info["bpp"]
136 maxval = (1 << bpp) - 1
137 im = im.point(lambda x: maxval - (x & maxval))
138 else:
139 msg = f"cannot write mode {im.mode} as Palm"
140 raise OSError(msg)
142 # we ignore the palette here
143 im._mode = "P"
144 rawmode = f"P;{bpp}"
145 version = 1
147 elif im.mode == "1":
148 # monochrome -- write it inverted, as is the Palm standard
149 rawmode = "1;I"
150 bpp = 1
151 version = 0
153 else:
154 msg = f"cannot write mode {im.mode} as Palm"
155 raise OSError(msg)
157 #
158 # make sure image data is available
159 im.load()
161 # write header
163 cols = im.size[0]
164 rows = im.size[1]
166 rowbytes = int((cols + (16 // bpp - 1)) / (16 // bpp)) * 2
167 transparent_index = 0
168 compression_type = _COMPRESSION_TYPES["none"]
170 flags = 0
171 if im.mode == "P":
172 flags |= _FLAGS["custom-colormap"]
173 colormap = im.im.getpalette()
174 colors = len(colormap) // 3
175 colormapsize = 4 * colors + 2
176 else:
177 colormapsize = 0
179 if "offset" in im.info:
180 offset = (rowbytes * rows + 16 + 3 + colormapsize) // 4
181 else:
182 offset = 0
184 fp.write(o16b(cols) + o16b(rows) + o16b(rowbytes) + o16b(flags))
185 fp.write(o8(bpp))
186 fp.write(o8(version))
187 fp.write(o16b(offset))
188 fp.write(o8(transparent_index))
189 fp.write(o8(compression_type))
190 fp.write(o16b(0)) # reserved by Palm
192 # now write colormap if necessary
194 if colormapsize:
195 fp.write(o16b(colors))
196 for i in range(colors):
197 fp.write(o8(i))
198 fp.write(colormap[3 * i : 3 * i + 3])
200 # now convert data to raw form
201 ImageFile._save(
202 im, fp, [ImageFile._Tile("raw", (0, 0) + im.size, 0, (rawmode, rowbytes, 1))]
203 )
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")