예제 #1
0
    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))]
예제 #2
0
    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))]
예제 #3
0
    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
예제 #4
0
    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
예제 #5
0
    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))]
예제 #6
0
    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)
             )]
예제 #7
0
    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
예제 #8
0
    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))]
예제 #9
0
    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))]
예제 #10
0
    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()
예제 #11
0
    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)
예제 #12
0
    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)
예제 #13
0
    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()
예제 #14
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)]
예제 #15
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)]
예제 #16
0
    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))]
예제 #17
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
예제 #18
0
    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
예제 #19
0
    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
예제 #20
0
    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
예제 #21
0
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))]
예제 #22
0
    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
예제 #23
0
    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, ""))
예제 #24
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
예제 #25
0
    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"
예제 #26
0
    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))]