def test_little_endian(self): self.assertEqual(_binary.i16le(b'\xff\xff\x00\x00'), 65535) self.assertEqual(_binary.i32le(b'\xff\xff\x00\x00'), 65535) self.assertEqual(_binary.o16le(65535), b'\xff\xff') self.assertEqual(_binary.o32le(65535), b'\xff\xff\x00\x00')
def _gal_frames(self, info): read = self.fp.read seek = self.fp.seek frames = [] offsets = [] seek(info["offset"]) info["frames"] = [] for i in range(info["frame_count"]): frame_info = {} name_len = i32le(read(4)) frame_info["name"] = read(name_len).decode("cp932") mask = i32le(read(4)) seek(9, 1) layer_count = i32le(read(4)) if layer_count < 1: raise GalImageError("Invalid GAL frame") frame_info["width"] = si32le(read(4)) frame_info["height"] = si32le(read(4)) bpp = i32le(read(4)) if bpp not in _GAL_MODE or bpp > 32: print(layer_count) print(frame_info, mask) print(bpp) raise GalImageError("Unsupported GAL pixel format") frame_info["bpp"] = bpp if bpp <= 8: palette_size = 1 << bpp frame_info["palette"] = ImagePalette.raw( "BGRX", read(palette_size * 4)) else: frame_info["palette"] = None mode, rawmode = _GAL_MODE[bpp] layermode = mode stride = (frame_info["width"] * bpp + 7) // 8 if bpp >= 8: # align to 4 byte boundary stride = (stride + 3) & ~3 frame_info["stride"] = stride frame_info["alpha_stride"] = (frame_info["width"] + 3) & ~3 frame_info["layers"] = [] for j in range(layer_count): layer_info = {} left = si32le(read(4)) top = si32le(read(4)) layer_info["origin"] = (left, top) layer_info["visible"] = read(1)[0] layer_info["trans_color"] = si32le(read(4)) layer_info["alpha"] = si32le(read(4)) layer_info["alpha_on"] = read(1)[0] name_len = i32le(read(4)) seek(name_len, 1) if int(info["version"]) >= 107: layer_info["lock"] = read(1)[0] if j == 0: offsets.append(self.fp.tell()) else: print( "Warning: multilayer Gale images not fully supported") layer_size = si32le(read(4)) seek(layer_size, 1) alpha_size = si32le(read(4)) if layer_info["alpha_on"] and alpha_size > 0: if mode == "RGB": mode = "RGBA" elif mode == "P": mode = "PA" else: raise GalImageError("unsupported GAL alpha mode") seek(alpha_size, 1) frame_info["layers"].append(layer_info) info["frames"].append(frame_info) box = (0, 0, frame_info["width"], frame_info["height"]) frames.append((frame_info["name"], layer_count, mode, layermode, rawmode, box, frame_info["palette"])) # TODO: handle multi-frame images break return frames, offsets
def _galx_info(self, header): """LiveMaker GAL/X multiframe (multi-layer) image.""" read = self.fp.read header += read(3) info = {} info["version"] = header[4:] if info["version"] == b"X200": header_size = i32le(read(4)) xml = zlib.decompress(read(header_size)) try: # Note: LiveMaker's code for generating GAL/X images sometimes # creates invalid XML, but setting recover=False should let # lxml deal with most of these cases. root = etree.fromstring( xml, parser=etree.XMLParser(encoding="shift-jis", recover=True)) except etree.LxmlError as e: raise GalImageError( "Could not parse GAL/X image XML metadata: {}".format(e)) info["width"] = int(root.get("Width", 0)) info["height"] = int(root.get("Height", 0)) info["bpp"] = int(root.get("Bpp", 0)) info["frame_count"] = int(root.get("Count", 0)) info["compression"] = int(root.get("CompType", 0)) info["compression_level"] = int(root.get("CompLevel", 0)) info["randomized"] = root.get("Randomized") != "0" info["bg_color"] = int(root.get("BGColor", 0)) info["block_width"] = int(root.get("BlockWidth", 0)) info["block_height"] = int(root.get("BlockHeight", 0)) info["offset"] = header_size + 12 info["root"] = root else: raise GalImageError("Unsupported GAL/X version {}".format(header)) if info["frame_count"] != len(root): print("Warning: frame count mismatch") info["frames"] = [] for frame in root: frame_info = {} if len(frame) > 1: print("Warning: Frame contained multiple Layers tags") frame_info["name"] = frame.get("Name", "") # TODO: figure out what this bounding box is actually for # left = int(frame.get('L0', 0)) # top = int(frame.get('T0', 0)) # right = int(frame.get('R0', info['width'])) # bottom = int(frame.get('B0', info['height'])) # frame_info['box'] = (left, top, right, bottom) frame_info["box"] = (0, 0, info["width"], info["height"]) for layers in frame: frame_info["width"] = int(layers.get("Width", info["width"])) frame_info["height"] = int(layers.get("Height", info["height"])) frame_info["bpp"] = int(layers.get("bpp", info["bpp"])) stride = (frame_info["width"] * frame_info["bpp"] + 7) // 8 if frame_info["bpp"] >= 8: # align to 4 byte boundary stride = (stride + 3) & ~3 if frame_info["bpp"] <= 8: for rgb in layers.iter("RGB"): palette = unhexlify(rgb.text) frame_info["palette"] = ImagePalette.raw( "BGR", palette) else: frame_info["palette"] = None frame_info["stride"] = stride frame_info["alpha_stride"] = (frame_info["width"] + 3) & ~3 frame_info["layers"] = [] for layer in layers.iter("Layer"): layer_info = {} left = int(layer.get("Left", 0)) top = int(layer.get("Top", 0)) layer_info["origin"] = (left, top) layer_info["trans_color"] = int(layer.get( "TransColor", -1)) layer_info["visible"] = int(layer.get("Visible", 1)) layer_info["alpha"] = int(layer.get("Alpha", 255)) layer_info["alpha_on"] = int(layer.get("AlphaOn", 0)) frame_info["layers"].append(layer_info) info["frames"].append(frame_info) return info
def test_little_endian(): assert _binary.i16le(b"\xff\xff\x00\x00") == 65535 assert _binary.i32le(b"\xff\xff\x00\x00") == 65535 assert _binary.o16le(65535) == b"\xff\xff" assert _binary.o32le(65535) == b"\xff\xff\x00\x00"