admin / Synapse-Cortex
publicSelf Hosted ITSM Tool with RBAC/Tenanting and MFA
Synapse-Cortex / synapse-cortex / .venv / Lib / site-packages / PIL / XpmImagePlugin.py
4539 B · main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | # # The Python Imaging Library. # $Id$ # # XPM File handling # # History: # 1996-12-29 fl Created # 2001-02-17 fl Use 're' instead of 'regex' (Python 2.1) (0.7) # # Copyright (c) Secret Labs AB 1997-2001. # Copyright (c) Fredrik Lundh 1996-2001. # # See the README file for information on usage and redistribution. # from __future__ import annotations import re from . import Image, ImageFile, ImagePalette from ._binary import o8 # XPM header xpm_head = re.compile(b'"([0-9]*) ([0-9]*) ([0-9]*) ([0-9]*)') def _accept(prefix: bytes) -> bool: return prefix.startswith(b"/* XPM */") ## # Image plugin for X11 pixel maps. class XpmImageFile(ImageFile.ImageFile): format = "XPM" format_description = "X11 Pixel Map" def _open(self) -> None: assert self.fp is not None if not _accept(self.fp.read(9)): msg = "not an XPM file" raise SyntaxError(msg) # skip forward to next string while True: line = self.fp.readline() if not line: msg = "broken XPM file" raise SyntaxError(msg) m = xpm_head.match(line) if m: break self._size = int(m.group(1)), int(m.group(2)) palette_length = int(m.group(3)) bpp = int(m.group(4)) # # load palette description palette = {} for _ in range(palette_length): line = self.fp.readline().rstrip() c = line[1 : bpp + 1] s = line[bpp + 1 : -2].split() for i in range(0, len(s), 2): if s[i] == b"c": # process colour key rgb = s[i + 1] if rgb == b"None": self.info["transparency"] = c elif rgb.startswith(b"#"): rgb_int = int(rgb[1:], 16) palette[c] = ( o8((rgb_int >> 16) & 255) + o8((rgb_int >> 8) & 255) + o8(rgb_int & 255) ) else: # unknown colour msg = "cannot read this XPM file" raise ValueError(msg) break else: # missing colour key msg = "cannot read this XPM file" raise ValueError(msg) args: tuple[int, dict[bytes, bytes] | tuple[bytes, ...]] if palette_length > 256: self._mode = "RGB" args = (bpp, palette) else: self._mode = "P" self.palette = ImagePalette.raw("RGB", b"".join(palette.values())) args = (bpp, tuple(palette.keys())) self.tile = [ImageFile._Tile("xpm", (0, 0) + self.size, self.fp.tell(), args)] def load_read(self, read_bytes: int) -> bytes: # # load all image data in one chunk xsize, ysize = self.size assert self.fp is not None s = [self.fp.readline()[1 : xsize + 1].ljust(xsize) for i in range(ysize)] return b"".join(s) class XpmDecoder(ImageFile.PyDecoder): _pulls_fd = True def decode(self, buffer: Image.DecoderInput) -> tuple[int, int]: assert self.fd is not None data = bytearray() bpp, palette = self.args dest_length = self.state.xsize * self.state.ysize if self.mode == "RGB": dest_length *= 3 pixel_header = False while len(data) < dest_length: line = self.fd.readline() if not line: break if line.rstrip() == b"/* pixels */" and not pixel_header: pixel_header = True continue line = b'"'.join(line.split(b'"')[1:-1]) for i in range(0, len(line), bpp): key = line[i : i + bpp] if self.mode == "RGB": data += palette[key] else: data += o8(palette.index(key)) self.set_as_raw(bytes(data)) return -1, 0 # # Registry Image.register_open(XpmImageFile.format, XpmImageFile, _accept) Image.register_decoder("xpm", XpmDecoder) Image.register_extension(XpmImageFile.format, ".xpm") Image.register_mime(XpmImageFile.format, "image/xpm") |