def _open(self): # header s = self.fp.read(128) if not _accept(s): raise SyntaxError, "not a PCX file" # image bbox = i16(s, 4), i16(s, 6), i16(s, 8) + 1, i16(s, 10) + 1 if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]: raise SyntaxError, "bad PCX image size" # format version = ord(s[1]) bits = ord(s[3]) planes = ord(s[65]) stride = i16(s, 66) self.info["dpi"] = i16(s, 12), i16(s, 14) if bits == 1 and planes == 1: mode = rawmode = "1" elif bits == 1 and planes in (2, 4): mode = "P" rawmode = "P;%dL" % planes self.palette = ImagePalette.raw("RGB", s[16:64]) elif version == 5 and bits == 8 and planes == 1: mode = rawmode = "L" # FIXME: hey, this doesn't work with the incremental loader !!! self.fp.seek(-769, 2) s = self.fp.read(769) if len(s) == 769 and ord(s[0]) == 12: # check if the palette is linear greyscale for i in range(256): if s[i * 3 + 1:i * 3 + 4] != chr(i) * 3: mode = rawmode = "P" break if mode == "P": self.palette = ImagePalette.raw("RGB", s[1:]) self.fp.seek(128) elif version == 5 and bits == 8 and planes == 3: mode = "RGB" rawmode = "RGB;L" else: raise IOError, "unknown PCX mode" self.mode = mode self.size = bbox[2] - bbox[0], bbox[3] - bbox[1] bbox = (0, 0) + self.size self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
def _open(self): # header s = self.fp.read(128) if not _accept(s): raise SyntaxError, "not a PCX file" # image bbox = i16(s,4), i16(s,6), i16(s,8)+1, i16(s,10)+1 if bbox[2] <= bbox[0] or bbox[3] <= bbox[1]: raise SyntaxError, "bad PCX image size" # format version = ord(s[1]) bits = ord(s[3]) planes = ord(s[65]) stride = i16(s,66) self.info["dpi"] = i16(s,12), i16(s,14) if bits == 1 and planes == 1: mode = rawmode = "1" elif bits == 1 and planes in (2, 4): mode = "P" rawmode = "P;%dL" % planes self.palette = ImagePalette.raw("RGB", s[16:64]) elif version == 5 and bits == 8 and planes == 1: mode = rawmode = "L" # FIXME: hey, this doesn't work with the incremental loader !!! self.fp.seek(-769, 2) s = self.fp.read(769) if len(s) == 769 and ord(s[0]) == 12: # check if the palette is linear greyscale for i in range(256): if s[i*3+1:i*3+4] != chr(i)*3: mode = rawmode = "P" break if mode == "P": self.palette = ImagePalette.raw("RGB", s[1:]) self.fp.seek(128) elif version == 5 and bits == 8 and planes == 3: mode = "RGB" rawmode = "RGB;L" else: raise IOError, "unknown PCX mode" self.mode = mode self.size = bbox[2]-bbox[0], bbox[3]-bbox[1] bbox = (0, 0) + self.size self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
def _open(self): # check magic s = self.fp.read(6) if s != "P7 332": raise SyntaxError, "not an XV thumbnail file" # Skip to beginning of next line self.fp.readline() # skip info comments while 1: s = self.fp.readline() if not s: raise SyntaxError, "Unexpected EOF reading XV thumbnail file" if s[0] != '#': break # parse header line (already read) s = string.split(s.strip()) self.mode = "P" self.size = int(s[0]), int(s[1]) self.palette = ImagePalette.raw("RGB", PALETTE) self.tile = [ ("raw", (0, 0)+self.size, self.fp.tell(), (self.mode, 0, 1) )]
def _open(self): # Screen s = self.fp.read(13) if s[:6] not in ["GIF87a", "GIF89a"]: raise SyntaxError, "not a GIF file" self.info["version"] = s[:6] self.size = i16(s[6:]), i16(s[8:]) self.tile = [] flags = ord(s[10]) bits = (flags & 7) + 1 if flags & 128: # get global palette self.info["background"] = ord(s[11]) # check if palette contains colour indices p = self.fp.read(3<<bits) for i in range(0, len(p), 3): if not (chr(i/3) == p[i] == p[i+1] == p[i+2]): p = ImagePalette.raw("RGB", p) self.global_palette = self.palette = p break self.__fp = self.fp # FIXME: hack self.__rewind = self.fp.tell() self.seek(0) # get ready to read first frame
def _open(self): # check magic s = self.fp.read(6) if s != "P7 332": raise SyntaxError, "not an XV thumbnail file" # Skip to beginning of next line self.fp.readline() # skip info comments while 1: s = self.fp.readline() if not s: raise SyntaxError, "Unexpected EOF reading XV thumbnail file" if s[0] != '#': break # parse header line (already read) s = string.split(s.strip()) self.mode = "P" self.size = int(s[0]), int(s[1]) self.palette = ImagePalette.raw("RGB", PALETTE) self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), (self.mode, 0, 1))]
def chunk_PLTE(self, offset, bytes): "PLTE -- palette data" s = self.fp.read(bytes) if self.mode == "P": self.palette = ImagePalette.raw("RGB", s) return s
def _open(self): # Header s = self.fp.read(775) self.mode = "L" # FIXME: "P" self.size = i16(s[0:2]), i16(s[2:4]) # transparency index tindex = i16(s[5:7]) if tindex < 256: self.info["transparent"] = tindex self.palette = ImagePalette.raw("RGB", s[7:]) self.tile = [("raw", (0, 0) + self.size, 775, ("L", 0, -1))]
def _open(self): # Header s = self.fp.read(775) self.mode = "L" # FIXME: "P" self.size = i16(s[0:2]), i16(s[2:4]) # transparency index tindex = i16(s[5:7]) if tindex < 256: self.info["transparent"] = tindex self.palette = ImagePalette.raw("RGB", s[7:]) self.tile = [("raw", (0,0)+self.size, 775, ("L", 0, -1))]
def _open(self): if self.fp.read(8) != _MAGIC: raise SyntaxError, "not a PNG file" # # Parse headers up to the first IDAT chunk self.png = PngStream(self.fp) while 1: # # get next chunk cid, pos, len = self.png.read() try: s = self.png.call(cid, pos, len) except EOFError: break except AttributeError: if Image.DEBUG: print cid, pos, len, "(unknown)" s = ImageFile._safe_read(self.fp, len) self.png.crc(cid, s) # # Copy relevant attributes from the PngStream. An alternative # would be to let the PngStream class modify these attributes # directly, but that introduces circular references which are # difficult to break if things go wrong in the decoder... # (believe me, I've tried ;-) self.mode = self.png.im_mode self.size = self.png.im_size self.info = self.png.im_info self.text = self.png.im_text # experimental self.tile = self.png.im_tile if self.png.im_palette: rawmode, data = self.png.im_palette self.palette = ImagePalette.raw(rawmode, data) self.__idat = len # used by load_read()
def _open(self): # HEAD s = self.fp.read(128) magic = i16(s[4:6]) if magic not in [0xAF11, 0xAF12]: raise SyntaxError, "not an FLI/FLC file" # image characteristics self.mode = "P" self.size = i16(s[8:10]), i16(s[10:12]) # animation speed duration = i32(s[16:20]) if magic == 0xAF11: duration = (duration * 1000) / 70 self.info["duration"] = duration # look for palette palette = map(lambda a: (a,a,a), range(256)) s = self.fp.read(16) self.__offset = 128 if i16(s[4:6]) == 0xF100: # prefix chunk; ignore it self.__offset = self.__offset + i32(s) s = self.fp.read(16) if i16(s[4:6]) == 0xF1FA: # look for palette chunk s = self.fp.read(6) if i16(s[4:6]) == 11: self._palette(palette, 2) elif i16(s[4:6]) == 4: self._palette(palette, 0) palette = map(lambda (r,g,b): chr(r)+chr(g)+chr(b), palette) self.palette = ImagePalette.raw("RGB", string.join(palette, "")) # set things up to decode first frame self.frame = -1 self.__fp = self.fp self.seek(0)
def _open(self): # HEAD s = self.fp.read(32) if i32(s) != 0x59a66a95: raise SyntaxError, "not an SUN raster file" offset = 32 self.size = i32(s[4:8]), i32(s[8:12]) depth = i32(s[12:16]) if depth == 1: self.mode, rawmode = "1", "1;I" elif depth == 8: self.mode = rawmode = "L" elif depth == 24: self.mode, rawmode = "RGB", "BGR" else: raise SyntaxError, "unsupported mode" compression = i32(s[20:24]) if i32(s[24:28]) != 0: length = i32(s[28:32]) offset = offset + length self.palette = ImagePalette.raw("RGB;L", self.fp.read(length)) if self.mode == "L": self.mode = rawmode = "P" stride = (((self.size[0] * depth + 7) / 8) + 3) & (~3) if compression == 1: self.tile = [("raw", (0,0)+self.size, offset, (rawmode, stride))] elif compression == 2: self.tile = [("sun_rle", (0,0)+self.size, offset, rawmode)]
def _bitmap(self, header = 0, offset = 0): if header: self.fp.seek(header) read = self.fp.read # CORE/INFO s = read(4) s = s + ImageFile._safe_read(self.fp, i32(s)-4) if len(s) == 12: # OS/2 1.0 CORE bits = i16(s[10:]) self.size = i16(s[4:]), i16(s[6:]) compression = 0 lutsize = 3 colors = 0 direction = -1 elif len(s) in [40, 64]: # WIN 3.1 or OS/2 2.0 INFO bits = i16(s[14:]) self.size = i32(s[4:]), i32(s[8:]) compression = i32(s[16:]) lutsize = 4 colors = i32(s[32:]) direction = -1 if s[11] == '\xff': # upside-down storage self.size = self.size[0], 2**32 - self.size[1] direction = 0 else: raise IOError("Unsupported BMP header type (%d)" % len(s)) if not colors: colors = 1 << bits # MODE try: self.mode, rawmode = BIT2MODE[bits] except KeyError: raise IOError("Unsupported BMP pixel depth (%d)" % bits) if compression == 3: # BI_BITFIELDS compression mask = i32(read(4)), i32(read(4)), i32(read(4)) if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff): rawmode = "BGRX" elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f): rawmode = "BGR;16" elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f): rawmode = "BGR;15" else: # print bits, map(hex, mask) raise IOError("Unsupported BMP bitfields layout") elif compression != 0: raise IOError("Unsupported BMP compression (%d)" % compression) # LUT if self.mode == "P": palette = [] greyscale = 1 if colors == 2: indices = (0, 255) else: indices = range(colors) for i in indices: rgb = read(lutsize)[:3] if rgb != chr(i)*3: greyscale = 0 palette.append(rgb) if greyscale: if colors == 2: self.mode = rawmode = "1" else: self.mode = rawmode = "L" else: self.mode = "P" self.palette = ImagePalette.raw( "BGR", string.join(palette, "") ) if not offset: offset = self.fp.tell() self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, ((self.size[0]*bits+31)>>3)&(~3), direction))] self.info["compression"] = compression
def _open(self): if not _accept(self.fp.read(9)): raise SyntaxError, "not an XPM file" # skip forward to next string while 1: s = self.fp.readline() if not s: raise SyntaxError, "broken XPM file" m = xpm_head.match(s) if m: break self.size = int(m.group(1)), int(m.group(2)) pal = int(m.group(3)) bpp = int(m.group(4)) if pal > 256 or bpp != 1: raise ValueError, "cannot read this XPM file" # # load palette description palette = ["\0\0\0"] * 256 for i in range(pal): s = self.fp.readline() if s[-2:] == '\r\n': s = s[:-2] elif s[-1:] in '\r\n': s = s[:-1] c = ord(s[1]) s = string.split(s[2:-2]) for i in range(0, len(s), 2): if s[i] == "c": # process colour key rgb = s[i + 1] if rgb == "None": self.info["transparency"] = c elif rgb[0] == "#": # FIXME: handle colour names (see ImagePalette.py) rgb = string.atoi(rgb[1:], 16) palette[c] = chr((rgb >> 16) & 255) +\ chr((rgb >> 8) & 255) +\ chr(rgb & 255) else: # unknown colour raise ValueError, "cannot read this XPM file" break else: # missing colour key raise ValueError, "cannot read this XPM file" self.mode = "P" self.palette = ImagePalette.raw("RGB", string.join(palette, "")) self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))]
def _bitmap(self, header=0, offset=0): if header: self.fp.seek(header) read = self.fp.read # CORE/INFO s = read(4) s = s + ImageFile._safe_read(self.fp, i32(s) - 4) if len(s) == 12: # OS/2 1.0 CORE bits = i16(s[10:]) self.size = i16(s[4:]), i16(s[6:]) compression = 0 lutsize = 3 colors = 0 direction = -1 elif len(s) in [40, 64]: # WIN 3.1 or OS/2 2.0 INFO bits = i16(s[14:]) self.size = i32(s[4:]), i32(s[8:]) compression = i32(s[16:]) lutsize = 4 colors = i32(s[32:]) direction = -1 if s[11] == '\xff': # upside-down storage self.size = self.size[0], 2**32 - self.size[1] direction = 0 else: raise IOError("Unsupported BMP header type (%d)" % len(s)) if not colors: colors = 1 << bits # MODE try: self.mode, rawmode = BIT2MODE[bits] except KeyError: raise IOError("Unsupported BMP pixel depth (%d)" % bits) if compression == 3: # BI_BITFIELDS compression mask = i32(read(4)), i32(read(4)), i32(read(4)) if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff): rawmode = "BGRX" elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f): rawmode = "BGR;16" elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f): rawmode = "BGR;15" else: # print bits, map(hex, mask) raise IOError("Unsupported BMP bitfields layout") elif compression != 0: raise IOError("Unsupported BMP compression (%d)" % compression) # LUT if self.mode == "P": palette = [] greyscale = 1 if colors == 2: indices = (0, 255) else: indices = range(colors) for i in indices: rgb = read(lutsize)[:3] if rgb != chr(i) * 3: greyscale = 0 palette.append(rgb) if greyscale: if colors == 2: self.mode = rawmode = "1" else: self.mode = rawmode = "L" else: self.mode = "P" self.palette = ImagePalette.raw("BGR", string.join(palette, "")) if not offset: offset = self.fp.tell() self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, ((self.size[0] * bits + 31) >> 3) & (~3), direction))] self.info["compression"] = compression
def seek(self, frame): if frame == 0: # rewind self.__offset = 0 self.dispose = None self.__frame = -1 self.__fp.seek(self.__rewind) if frame != self.__frame + 1: raise ValueError, "cannot seek to frame %d" % frame self.__frame = frame self.tile = [] self.fp = self.__fp if self.__offset: # backup to last frame self.fp.seek(self.__offset) while self.data(): pass self.__offset = 0 if self.dispose: self.im = self.dispose self.dispose = None self.palette = self.global_palette while 1: s = self.fp.read(1) if not s or s == ";": break elif s == "!": # # extensions # s = self.fp.read(1) block = self.data() if ord(s) == 249: # # graphic control extension # flags = ord(block[0]) if flags & 1: self.info["transparency"] = ord(block[3]) self.info["duration"] = i16(block[1:3]) * 10 try: # disposal methods if flags & 8: # replace with background colour self.dispose = Image.core.fill("P", self.size, self.info["background"]) elif flags & 16: # replace with previous contents self.dispose = self.im.copy() except (AttributeError, KeyError): pass elif ord(s) == 255: # # application extension # self.info["extension"] = block, self.fp.tell() if block[:11] == "NETSCAPE2.0": block = self.data() if len(block) >= 3 and ord(block[0]) == 1: self.info["loop"] = i16(block[1:3]) while self.data(): pass elif s == ",": # # local image # s = self.fp.read(9) # extent x0, y0 = i16(s[0:]), i16(s[2:]) x1, y1 = x0 + i16(s[4:]), y0 + i16(s[6:]) flags = ord(s[8]) interlace = (flags & 64) != 0 if flags & 128: bits = (flags & 7) + 1 self.palette =\ ImagePalette.raw("RGB", self.fp.read(3<<bits)) # image data bits = ord(self.fp.read(1)) self.__offset = self.fp.tell() self.tile = [("gif", (x0, y0, x1, y1), self.__offset, (bits, interlace))] break else: pass # raise IOError, "illegal GIF tag `%x`" % ord(s) if not self.tile: # self.__fp = None raise EOFError, "no more images in GIF file" self.mode = "L" if self.palette: self.mode = "P"
def _open(self): # process header s = self.fp.read(18) id = ord(s[0]) colormaptype = ord(s[1]) imagetype = ord(s[2]) depth = ord(s[16]) flags = ord(s[17]) self.size = i16(s[12:]), i16(s[14:]) # validate header fields if id != 0 or colormaptype not in (0, 1) or\ self.size[0] <= 0 or self.size[1] <= 0 or\ depth not in (1, 8, 16, 24, 32): raise SyntaxError, "not a TGA file" # image mode if imagetype in (3, 11): self.mode = "L" if depth == 1: self.mode = "1" # ??? elif imagetype in (1, 9): self.mode = "P" elif imagetype in (2, 10): self.mode = "RGB" if depth == 32: self.mode = "RGBA" else: raise SyntaxError, "unknown TGA mode" # orientation orientation = flags & 0x30 if orientation == 0x20: orientation = 1 elif not orientation: orientation = -1 else: raise SyntaxError, "unknown TGA orientation" self.info["orientation"] = orientation if imagetype & 8: self.info["compression"] = "tga_rle" if colormaptype: # read palette start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:]) if mapdepth == 16: self.palette = ImagePalette.raw("BGR;16", "\0"*2*start + self.fp.read(2*size)) elif mapdepth == 24: self.palette = ImagePalette.raw("BGR", "\0"*3*start + self.fp.read(3*size)) elif mapdepth == 32: self.palette = ImagePalette.raw("BGRA", "\0"*4*start + self.fp.read(4*size)) # setup tile descriptor try: rawmode = MODES[(imagetype&7, depth)] if imagetype & 8: # compressed self.tile = [("tga_rle", (0, 0)+self.size, self.fp.tell(), (rawmode, orientation, depth))] else: self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), (rawmode, 0, orientation))] except KeyError: pass # cannot decode
def _setup(self): "Setup this image object based on current tags" if self.tag.has_key(0xBC01): raise IOError, "Windows Media Photo files not yet supported" getscalar = self.tag.getscalar # extract relevant tags self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)] self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1) # photometric is a required tag, but not everyone is reading # the specification photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0) fillorder = getscalar(FILLORDER, 1) if Image.DEBUG: print "*** Summary ***" print "- compression:", self._compression print "- photometric_interpretation:", photo print "- planar_configuration:", self._planar_configuration print "- fill_order:", fillorder # size xsize = getscalar(IMAGEWIDTH) ysize = getscalar(IMAGELENGTH) self.size = xsize, ysize if Image.DEBUG: print "- size:", self.size format = getscalar(SAMPLEFORMAT, 1) # mode: check photometric interpretation and bits per pixel key = ( self.tag.prefix, photo, format, fillorder, self.tag.get(BITSPERSAMPLE, (1,)), self.tag.get(EXTRASAMPLES, ()) ) if Image.DEBUG: print "format key:", key try: self.mode, rawmode = OPEN_INFO[key] except KeyError: if Image.DEBUG: print "- unsupported format" raise SyntaxError, "unknown pixel mode" if Image.DEBUG: print "- raw mode:", rawmode print "- pil mode:", self.mode self.info["compression"] = self._compression xres = getscalar(X_RESOLUTION, (1, 1)) yres = getscalar(Y_RESOLUTION, (1, 1)) if xres and yres: xres = xres[0] / (xres[1] or 1) yres = yres[0] / (yres[1] or 1) resunit = getscalar(RESOLUTION_UNIT, 1) if resunit == 2: # dots per inch self.info["dpi"] = xres, yres elif resunit == 3: # dots per centimeter. convert to dpi self.info["dpi"] = xres * 2.54, yres * 2.54 else: # No absolute unit of measurement self.info["resolution"] = xres, yres # build tile descriptors x = y = l = 0 self.tile = [] if self.tag.has_key(STRIPOFFSETS): # striped image h = getscalar(ROWSPERSTRIP, ysize) w = self.size[0] a = None for o in self.tag[STRIPOFFSETS]: if not a: a = self._decoder(rawmode, l) self.tile.append( (self._compression, (0, min(y, ysize), w, min(y+h, ysize)), o, a)) y = y + h if y >= self.size[1]: x = y = 0 l = l + 1 a = None elif self.tag.has_key(TILEOFFSETS): # tiled image w = getscalar(322) h = getscalar(323) a = None for o in self.tag[TILEOFFSETS]: if not a: a = self._decoder(rawmode, l) # FIXME: this doesn't work if the image size # is not a multiple of the tile size... self.tile.append( (self._compression, (x, y, x+w, y+h), o, a)) x = x + w if x >= self.size[0]: x, y = 0, y + h if y >= self.size[1]: x = y = 0 l = l + 1 a = None else: if Image.DEBUG: print "- unsupported data organization" raise SyntaxError("unknown data organization") # fixup palette descriptor if self.mode == "P": palette = map(lambda a: chr(a / 256), self.tag[COLORMAP]) self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))
def _open(self): read = self.fp.read # # header s = read(26) if s[:4] != "8BPS" or i16(s[4:]) != 1: raise SyntaxError, "not a PSD file" psd_bits = i16(s[22:]) psd_channels = i16(s[12:]) psd_mode = i16(s[24:]) mode, channels = MODES[(psd_mode, psd_bits)] if channels > psd_channels: raise IOError, "not enough channels" self.mode = mode self.size = i32(s[18:]), i32(s[14:]) # # color mode data size = i32(read(4)) if size: data = read(size) if mode == "P" and size == 768: self.palette = ImagePalette.raw("RGB;L", data) # # image resources self.resources = [] size = i32(read(4)) if size: # load resources end = self.fp.tell() + size while self.fp.tell() < end: signature = read(4) id = i16(read(2)) name = read(ord(read(1))) if not (len(name) & 1): read(1) # padding data = read(i32(read(4))) if (len(data) & 1): read(1) # padding self.resources.append((id, name, data)) if id == 1039: # ICC profile self.info["icc_profile"] = data # # layer and mask information self.layers = [] size = i32(read(4)) if size: end = self.fp.tell() + size size = i32(read(4)) if size: self.layers = _layerinfo(self.fp) self.fp.seek(end) # # image descriptor self.tile = _maketile(self.fp, mode, (0, 0) + self.size, channels) # keep the file open self._fp = self.fp self.frame = 0
def _open(self): # process header s = self.fp.read(18) id = ord(s[0]) colormaptype = ord(s[1]) imagetype = ord(s[2]) depth = ord(s[16]) flags = ord(s[17]) self.size = i16(s[12:]), i16(s[14:]) # validate header fields if id != 0 or colormaptype not in (0, 1) or\ self.size[0] <= 0 or self.size[1] <= 0 or\ depth not in (1, 8, 16, 24, 32): raise SyntaxError, "not a TGA file" # image mode if imagetype in (3, 11): self.mode = "L" if depth == 1: self.mode = "1" # ??? elif imagetype in (1, 9): self.mode = "P" elif imagetype in (2, 10): self.mode = "RGB" if depth == 32: self.mode = "RGBA" else: raise SyntaxError, "unknown TGA mode" # orientation orientation = flags & 0x30 if orientation == 0x20: orientation = 1 elif not orientation: orientation = -1 else: raise SyntaxError, "unknown TGA orientation" self.info["orientation"] = orientation if imagetype & 8: self.info["compression"] = "tga_rle" if colormaptype: # read palette start, size, mapdepth = i16(s[3:]), i16(s[5:]), i16(s[7:]) if mapdepth == 16: self.palette = ImagePalette.raw( "BGR;16", "\0" * 2 * start + self.fp.read(2 * size)) elif mapdepth == 24: self.palette = ImagePalette.raw( "BGR", "\0" * 3 * start + self.fp.read(3 * size)) elif mapdepth == 32: self.palette = ImagePalette.raw( "BGRA", "\0" * 4 * start + self.fp.read(4 * size)) # setup tile descriptor try: rawmode = MODES[(imagetype & 7, depth)] if imagetype & 8: # compressed self.tile = [("tga_rle", (0, 0) + self.size, self.fp.tell(), (rawmode, orientation, depth))] else: self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), (rawmode, 0, orientation))] except KeyError: pass # cannot decode
class ImImageFile(ImageFile.ImageFile): format = "IM" format_description = "IFUNC Image Memory" def _open(self): # Quick rejection: if there's not an LF among the first # 100 bytes, this is (probably) not a text header. if not "\n" in self.fp.read(100): raise SyntaxError, "not an IM file" self.fp.seek(0) n = 0 # Default values self.info[MODE] = "L" self.info[SIZE] = (512, 512) self.info[FRAMES] = 1 self.rawmode = "L" while 1: s = self.fp.read(1) # Some versions of IFUNC uses \n\r instead of \r\n... if s == "\r": continue if not s or s[0] == chr(0) or s[0] == chr(26): break # FIXME: this may read whole file if not a text file s = s + self.fp.readline() if len(s) > 100: raise SyntaxError, "not an IM file" if s[-2:] == '\r\n': s = s[:-2] elif s[-1:] == '\n': s = s[:-1] try: m = split.match(s) except re.error, v: raise SyntaxError, "not an IM file" if m: k, v = m.group(1, 2) # Convert value as appropriate if k in [FRAMES, SCALE, SIZE]: v = string.replace(v, "*", ",") v = tuple(map(number, string.split(v, ","))) if len(v) == 1: v = v[0] elif k == MODE and OPEN.has_key(v): v, self.rawmode = OPEN[v] # Add to dictionary. Note that COMMENT tags are # combined into a list of strings. if k == COMMENT: if self.info.has_key(k): self.info[k].append(v) else: self.info[k] = [v] else: self.info[k] = v if TAGS.has_key(k): n = n + 1 else: raise SyntaxError, "Syntax error in IM header: " + s if not n: raise SyntaxError, "Not an IM file" # Basic attributes self.size = self.info[SIZE] self.mode = self.info[MODE] # Skip forward to start of image data while s and s[0] != chr(26): s = self.fp.read(1) if not s: raise SyntaxError, "File truncated" if self.info.has_key(LUT): # convert lookup table to palette or lut attribute palette = self.fp.read(768) greyscale = 1 # greyscale palette linear = 1 # linear greyscale palette for i in range(256): if palette[i] == palette[i + 256] == palette[i + 512]: if palette[i] != chr(i): linear = 0 else: greyscale = 0 if self.mode == "L" or self.mode == "LA": if greyscale: if not linear: self.lut = map(ord, palette[:256]) else: if self.mode == "L": self.mode = self.rawmode = "P" elif self.mode == "LA": self.mode = self.rawmode = "PA" self.palette = ImagePalette.raw("RGB;L", palette) elif self.mode == "RGB": if not greyscale or not linear: self.lut = map(ord, palette) self.frame = 0 self.__offset = offs = self.fp.tell() self.__fp = self.fp # FIXME: hack if self.rawmode[:2] == "F;": # ifunc95 formats try: # use bit decoder (if necessary) bits = int(self.rawmode[2:]) if bits not in [8, 16, 32]: self.tile = [("bit", (0, 0) + self.size, offs, (bits, 8, 3, 0, -1))] return except ValueError: pass if self.rawmode in ["RGB;T", "RYB;T"]: # Old LabEye/3PC files. Would be very surprised if anyone # ever stumbled upon such a file ;-) size = self.size[0] * self.size[1] self.tile = [ ("raw", (0, 0) + self.size, offs, ("G", 0, -1)), ("raw", (0, 0) + self.size, offs + size, ("R", 0, -1)), ("raw", (0, 0) + self.size, offs + 2 * size, ("B", 0, -1)) ] else: # LabEye/IFUNC files self.tile = [("raw", (0, 0) + self.size, offs, (self.rawmode, 0, -1))]
def _open(self): if not _accept(self.fp.read(9)): raise SyntaxError, "not an XPM file" # skip forward to next string while 1: s = self.fp.readline() if not s: raise SyntaxError, "broken XPM file" m = xpm_head.match(s) if m: break self.size = int(m.group(1)), int(m.group(2)) pal = int(m.group(3)) bpp = int(m.group(4)) if pal > 256 or bpp != 1: raise ValueError, "cannot read this XPM file" # # load palette description palette = ["\0\0\0"] * 256 for i in range(pal): s = self.fp.readline() if s[-2:] == '\r\n': s = s[:-2] elif s[-1:] in '\r\n': s = s[:-1] c = ord(s[1]) s = string.split(s[2:-2]) for i in range(0, len(s), 2): if s[i] == "c": # process colour key rgb = s[i+1] if rgb == "None": self.info["transparency"] = c elif rgb[0] == "#": # FIXME: handle colour names (see ImagePalette.py) rgb = string.atoi(rgb[1:], 16) palette[c] = chr((rgb >> 16) & 255) +\ chr((rgb >> 8) & 255) +\ chr(rgb & 255) else: # unknown colour raise ValueError, "cannot read this XPM file" break else: # missing colour key raise ValueError, "cannot read this XPM file" self.mode = "P" self.palette = ImagePalette.raw("RGB", string.join(palette, "")) self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), ("P", 0, 1))]
def _setup(self): "Setup this image object based on current tags" if self.tag.has_key(0xBC01): raise IOError, "Windows Media Photo files not yet supported" getscalar = self.tag.getscalar # extract relevant tags self._compression = COMPRESSION_INFO[getscalar(COMPRESSION, 1)] self._planar_configuration = getscalar(PLANAR_CONFIGURATION, 1) # photometric is a required tag, but not everyone is reading # the specification photo = getscalar(PHOTOMETRIC_INTERPRETATION, 0) fillorder = getscalar(FILLORDER, 1) if Image.DEBUG: print "*** Summary ***" print "- compression:", self._compression print "- photometric_interpretation:", photo print "- planar_configuration:", self._planar_configuration print "- fill_order:", fillorder # size xsize = getscalar(IMAGEWIDTH) ysize = getscalar(IMAGELENGTH) self.size = xsize, ysize if Image.DEBUG: print "- size:", self.size format = getscalar(SAMPLEFORMAT, 1) # mode: check photometric interpretation and bits per pixel key = (self.tag.prefix, photo, format, fillorder, self.tag.get(BITSPERSAMPLE, (1, )), self.tag.get(EXTRASAMPLES, ())) if Image.DEBUG: print "format key:", key try: self.mode, rawmode = OPEN_INFO[key] except KeyError: if Image.DEBUG: print "- unsupported format" raise SyntaxError, "unknown pixel mode" if Image.DEBUG: print "- raw mode:", rawmode print "- pil mode:", self.mode self.info["compression"] = self._compression xres = getscalar(X_RESOLUTION, (1, 1)) yres = getscalar(Y_RESOLUTION, (1, 1)) if xres and yres: xres = xres[0] / (xres[1] or 1) yres = yres[0] / (yres[1] or 1) resunit = getscalar(RESOLUTION_UNIT, 1) if resunit == 2: # dots per inch self.info["dpi"] = xres, yres elif resunit == 3: # dots per centimeter. convert to dpi self.info["dpi"] = xres * 2.54, yres * 2.54 else: # No absolute unit of measurement self.info["resolution"] = xres, yres # build tile descriptors x = y = l = 0 self.tile = [] if self.tag.has_key(STRIPOFFSETS): # striped image h = getscalar(ROWSPERSTRIP, ysize) w = self.size[0] a = None for o in self.tag[STRIPOFFSETS]: if not a: a = self._decoder(rawmode, l) self.tile.append( (self._compression, (0, min(y, ysize), w, min(y + h, ysize)), o, a)) y = y + h if y >= self.size[1]: x = y = 0 l = l + 1 a = None elif self.tag.has_key(TILEOFFSETS): # tiled image w = getscalar(322) h = getscalar(323) a = None for o in self.tag[TILEOFFSETS]: if not a: a = self._decoder(rawmode, l) # FIXME: this doesn't work if the image size # is not a multiple of the tile size... self.tile.append( (self._compression, (x, y, x + w, y + h), o, a)) x = x + w if x >= self.size[0]: x, y = 0, y + h if y >= self.size[1]: x = y = 0 l = l + 1 a = None else: if Image.DEBUG: print "- unsupported data organization" raise SyntaxError("unknown data organization") # fixup palette descriptor if self.mode == "P": palette = map(lambda a: chr(a / 256), self.tag[COLORMAP]) self.palette = ImagePalette.raw("RGB;L", string.join(palette, ""))