Buckets:
| # | |
| # 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: bytes | Image.SupportsArrayInterface) -> 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") | |
Xet Storage Details
- Size:
- 4.4 kB
- Xet hash:
- 0624823c1c8fbc3b6515371e86070a0b2f9e052522f0ef2574f800c7b2d63d71
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.