def get_decoder(self): decoder = MockPyDecoder(None) def closure(mode, *args): decoder.__init__(mode, *args) return decoder Image.register_decoder('MOCK', closure) return decoder
def get_decoder(self): decoder = MockPyDecoder(None) def closure(mode, *args): decoder.__init__(mode, *args) return decoder Image.register_decoder("MOCK", closure) return decoder
def setup_class(cls): cls.decoder = MockPyDecoder(None) cls.encoder = MockPyEncoder(None) def decoder_closure(mode, *args): cls.decoder.__init__(mode, *args) return cls.decoder def encoder_closure(mode, *args): cls.encoder.__init__(mode, *args) return cls.encoder Image.register_decoder("MOCK", decoder_closure) Image.register_encoder("MOCK", encoder_closure)
def test_eof(self): # Even though this decoder never says that it is finished # the image should still end when there is no new data class InfiniteMockPyDecoder(ImageFile.PyDecoder): def decode(self, buffer): return 0, 0 decoder = InfiniteMockPyDecoder(None) def closure(mode, *args): decoder.__init__(mode, *args) return decoder Image.register_decoder("INFINITE", closure) with Image.open(TEST_FILE) as im: im.tile = [ ("INFINITE", (0, 0, 128, 128), 0, ("RGB", 0, 1)), ] ImageFile.LOAD_TRUNCATED_IMAGES = True im.load() ImageFile.LOAD_TRUNCATED_IMAGES = False
return (i >> k) & head \ | (_compact(i >>1) & m) \ , (_compact(i ) & m) else: def get_xy(i): # YYYyxyxyx → xxx,YYYyyy return (_compact(i ) & m) \ , (_compact(i >>1) & m) \ | (i >> k) & head ret = [0] * width * height for i in range(len(data)): x, y = get_xy(i) ret[y * width + x] = data[i] return bytes(ret) Image.register_open("GXT", GxtImageFile) Image.register_decoder("gxt", GxtDecoder) Image.register_extension("GXT", ".gxt") if __name__ == "__main__": import argparse from PIL import Image parser = argparse.ArgumentParser("python3 gxt.py") parser.add_argument("filename") args = parser.parse_args() tmp = Image.open(args.filename) tmp.save(args.filename[:-4] + ".png")
if not (height == activeHeight and width == activeWidth): dstPixelBytes = self.dstChannels * self.dstChannelBytes dstRowBytes = dstPixelBytes * width activeRowBytes = activeWidth * dstPixelBytes newimg = bytearray(dstPixelBytes * activeWidth * activeHeight) if not newimg: return 0, 0 # Convert from total area to active area: for yy in range(activeHeight): for xx in range(activeWidth): for zz in range(dstPixelBytes): newimg[yy * activeRowBytes + xx * dstPixelBytes + zz] = self.dstImage[yy * dstRowBytes + xx * dstPixelBytes + zz] self.dstImage = newimg return bytes(self.dstImage) def decode(self, buffer): self.set_as_raw( self._ktxUnpackETC(buffer, self.args[0], self.state.xsize, self.state.ysize)) return -1, 0 Image.register_decoder('etc2', ETC2Decoder)
def decode(self, buffer): try: self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize)) except struct.error as e: raise OSError("Truncated DDS file") from e return 0, 0 class DXT5Decoder(ImageFile.PyDecoder): _pulls_fd = True def decode(self, buffer): try: self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize)) except struct.error as e: raise OSError("Truncated DDS file") from e return 0, 0 Image.register_decoder("DXT1", DXT1Decoder) Image.register_decoder("DXT5", DXT5Decoder) def _validate(prefix): return prefix[:4] == b"DDS " Image.register_open(DdsImageFile.format, DdsImageFile, _validate) Image.register_extension(DdsImageFile.format, ".dds")
_pulls_fd = True def decode(self, buffer): try: self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize)) except struct.error: raise IOError("Truncated DDS file") return 0, 0 class DXT5Decoder(ImageFile.PyDecoder): _pulls_fd = True def decode(self, buffer): try: self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize)) except struct.error: raise IOError("Truncated DDS file") return 0, 0 Image.register_decoder('DXT1', DXT1Decoder) Image.register_decoder('DXT5', DXT5Decoder) def _validate(prefix): return prefix[:4] == b"DDS " Image.register_open(DdsImageFile.format, DdsImageFile, _validate) Image.register_extension(DdsImageFile.format, ".dds")
for d in data: raw[x] = 0 if d & m else 0xff x += 1 self.set_as_raw(bytes(raw)) return -1, 0 @staticmethod def from_stream(f: BinaryIO, width: int = 16, height: int = 16) -> Image.Image: return Image.frombytes("L", (width * 8, height * 8), f.read(width * height * 8), "tile") Image.register_decoder("tile", TileDecoder) def bigQ_into_bytearray(tile: int, mask: int, im: Image.Image, start_x: int, start_y: int): cols = [((tile >> x) & 0xff, (mask >> x) & 0xff) for x in range(56, -1, -8)] for m, y in zip((1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80), range(start_y, start_y + 8)): for (c, a), x in zip(cols, range(start_x, start_x + 8)): im.putpixel((x, y), (0 if c & m else 0xff, 0 if a & m else 0xff)) class SpriteDecoder(PyDecoder): def decode(self, b: bytes):
type = self.fp.read(1)[0] #is a byte. not exactly much to process here... self._size = struct.unpack("<HH",self.fp.read(4)) #can just read width/height directly into tuple... if (type == 0): #we're a 24-bit image self.mode = "RGBA" self.tile = [ ("Siglus", (0,0) + self.size, self.fp.tell(), ("RGBA", 0, 1)) ] # decomp = decode24(self.fp) # img = Image.frombytes("G00_24",[width,height],bytes(decomp),"raw","BGRA") # img.show() elif (type == 1): #we're an 8-bit image self.mode = "L" self.tile = [ ("Siglus", (0,0) + self.size, self.fp.tell(), ("8", 0, 1)) ] elif (type == 2): #if not self.LOAD_COMPLEX: raise SyntaxError("Complex g00 image archives are not supported by PIL plugin mode. Use one of the included helpers instead.") #decodedir(self.fp, self._size) except Exception as e: print(e) traceback.print_exc(file=sys.stdout) Image.register_decoder("Siglus", SiglusImageDecode) Image.register_open("G00", SiglusImageFile) Image.register_extension("G00", ".g00")
self.fd.write(self.number_of_colors) self.fd.write(self.palette) self.fd.write(self.encoded_data) return 0, 0 def cleanup( self): # required to exist; not sure what it is supposed to do... pass def _save(im, fp, filename): if im.mode == "1": magic_number = b"R4" elif im.mode in ("L", "P", "RGB", "RGBA"): magic_number = b"R6" else: raise OSError(f"Cannot write mode {im.mode} as DJVURLE") fp.write(magic_number) fp.write(("\n%d %d\n" % im.size).encode("ascii")) ImageFile._save(im, fp, [("DJVURLE", (0, 0) + im.size, 0, (im.mode))]) # -------------------------------------------------------------------- Image.register_open(DjvuRleImageFile.format, DjvuRleImageFile, _accept) Image.register_extensions(DjvuRleImageFile.format, [".rle", ".djvurle"]) Image.register_mime(DjvuRleImageFile.format, "image/x-djvurle-anymap") Image.register_decoder(DjvuRleImageFile.format, DjvuRleDecoder) Image.register_encoder(DjvuRleImageFile.format, DjvuRleEncoder) Image.register_save(DjvuRleImageFile.format, _save)
def decode(self, buffer): try: self.set_as_raw(_dxt1(self.fd, self.state.xsize, self.state.ysize)) except struct.error: raise IOError("Truncated DDS file") return 0, 0 class DXT5Decoder(ImageFile.PyDecoder): _pulls_fd = True def decode(self, buffer): try: self.set_as_raw(_dxt5(self.fd, self.state.xsize, self.state.ysize)) except struct.error: raise IOError("Truncated DDS file") return 0, 0 Image.register_decoder('DXT1', DXT1Decoder) Image.register_decoder('DXT5', DXT5Decoder) def _validate(prefix): return prefix[:4] == b"DDS " Image.register_open(DdsImageFile.format, DdsImageFile, _validate) Image.register_extension(DdsImageFile.format, ".dds")
# Copyright (c) 2017-2020 Wenyi Tang. # Author: Wenyi Tang # Email: [email protected] # Update: 2020 - 2 - 7 from io import BytesIO, SEEK_CUR, SEEK_END, SEEK_SET from pathlib import Path import numpy as np from PIL import Image from . import NVDecoder, YVDecoder from .FloDecoder import open_flo, KITTI Image.register_decoder('NV12', NVDecoder.NV12Decoder) Image.register_decoder('NV21', NVDecoder.NV21Decoder) Image.register_decoder('YV12', YVDecoder.YV12Decoder) Image.register_decoder('YV21', YVDecoder.YV21Decoder) class File: """An abstract file object NOTE: If `path` is a file, `File` opens it and calculates its length. If `path` is a folder, `File` opens every file in the folder in abc order. Args: path: path to a **node**, where node can be a **file** or a **folder** contains multiple files. rewind: rewind the file automatically when reaches EOF. """
image_draw = ImageDraw.Draw( self.im, image_draw_mode) if image_draw == None else image_draw self.imagesize = (self.im.width, self.im.height) if image_size == None else image_size self.target = SvgPainter(image_draw, self.imagesize, background) self.parser = XMLParser(target=self.target) def decode(self, buffer): self.parser.feed(buffer) return (len(buffer) if not self.target.finished else -1, 0) def cleanup(self): self.parser.close() Image.register_decoder("SVGXML", lambda mode, *args: SvgDecoder(mode, *args)) def draw_svg_file(file: str, imagedraw: ImageDraw.ImageDraw, imagesize: Tuple[int, int], background: str): decoder = SvgDecoder("", None, None, imagedraw, imagesize, background) f = open(file, "r") xmlString = f.read() decoder.decode(xmlString) decoder.cleanup() def _accept(prefix): prefixStr = prefix.decode("utf-8") return "<?xml" in prefixStr or "<svg " in prefixStr or "<!DOC" in prefixStr
def _set_as_raw(self, data, mode, rawmode=None, stride=0): # override PIL set_as_raw() so we can set stride if not rawmode: rawmode = mode d = Image._getdecoder(mode, "raw", (rawmode, stride, 1)) d.setimage(self.im, self.state.extents()) s = d.decode(data) if s[0] >= 0: raise GalImageError("not enough image data") if s[1] != 0: raise GalImageError("cannot decode image data") def _set_as_jpeg(self, data, mode): from PIL.JpegImagePlugin import RAWMODE d = Image._getdecoder(mode, "jpeg", (RAWMODE[mode], "")) d.setimage(self.im, self.state.extents()) s = d.decode(data) if s[0] >= 0: raise GalImageError("not enough image data") if s[1] != 0: raise GalImageError("cannot decode image data") Image.register_decoder("GAL", GalImageDecoder) Image.register_open(GalImageFile.format, GalImageFile, _accept) Image.register_extensions(GalImageFile.format, [".gal"])
def ind_to_coord(self, index): return (index % self.block_dim[0], int(index / self.block_dim[0])) def write_blocks_to_image(self): data = bytearray() for v in range(0, self.block_dim[1]): for y in range(0, 4): if y + v * 4 >= self.im.size[1]: break for u in range(0, self.block_dim[0]): for x in range(0, 4): if x + u * 4 >= self.im.size[0]: break data.extend(self.blocks_rgb[u][v].colors[x][y]) if self.texture_type == TextureType.ETC2PACKAGE_RGBA1_NO_MIPMAPS: #punchthrough data.append(self.blocks_rgb[u][v].alphas[x][y]) elif self.texture_type == TextureType.ETC2PACKAGE_RGBA_NO_MIPMAPS: #alpha blocks data.append(self.blocks_alpha[u][v].alphas[x][y]) print(self.texture_type) print(len(data)) self.set_as_raw(bytes(data)) Image.register_open(ETCImageFile.format, ETCImageFile) Image.register_extension(ETCImageFile.format, ".pkm") Image.register_extension(ETCImageFile.format, ".ktx") Image.register_decoder("ETC", ETCDecoder)
def register_heif_opener(): Image.register_open(HeifImageFile.format, HeifImageFile, RawHeifImage.check_file_type) Image.register_decoder('heif', HeifDecoder) Image.register_extensions(HeifImageFile.format, ['.heic', '.heif']) Image.register_mime(HeifImageFile.format, 'image/heif')
mips[i] = moffset - offset self.mode = "RGBA" #yes, this is constant. for DXT images at least. self._size = ( f.width, f.height ) #abuse the mutability of python to alter the image dimensions on the fly self.tile = [("bntx", (0, 0) + (f.width, f.height), offset, (f, (1, ))) ] #this takes both swizzle and unswizzle if DEBUG: print(self.tile) if pil: #we're a PIL plugin; register with PIL. if DEBUG: print("Registering PIL handles...") Image.register_decoder("bntx", BntxSwizzler) Image.register_open("BNTX", BntxImageFile) Image.register_extension("BNTX", ".bntx") else: #we're a gimp plugin; define the required bits and register with gimp. if DEBUG: print("!FIXME! !NotImplemented! Registering with GIMP/Glimpse...") def load_bntx(filename, raw_filename): with open(filename, 'rb') as fd: width, height = (0, 0) bntx = BntxImageFile(fd) for frame in bntx.frames: #get the largest dimensions for the canvas if frame.width > width: width = frame.width if frame.height > height: