Exemple #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")
        logger.debug("BBox: %s %s %s %s", *bbox)

        # format
        version = i8(s[1])
        bits = i8(s[3])
        planes = i8(s[65])
        stride = i16(s, 66)
        logger.debug("PCX version %s, bits %s, planes %s, stride %s",
                     version, bits, planes, stride)

        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 i8(s[0]) == 12:
                # check if the palette is linear greyscale
                for i in range(256):
                    if s[i*3+1:i*3+4] != o8(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
        logger.debug("size: %sx%s", *self.size)

        self.tile = [("pcx", bbox, self.fp.tell(), (rawmode, planes * stride))]
Exemple #2
0
def test_getcolor():

    palette = ImagePalette()

    map = {}
    for i in range(256):
        map[palette.getcolor((i, i, i))] = i

    assert_equal(len(map), 256)
    assert_exception(ValueError, lambda: palette.getcolor((1, 2, 3)))
Exemple #3
0
    def test_getdata(self):
        # Arrange
        data_in = list(range(256))*3
        palette = ImagePalette("RGB", data_in)

        # Act
        mode, data_out = palette.getdata()

        # Assert
        self.assertEqual(mode, "RGB;L")
Exemple #4
0
    def test_getcolor(self):

        palette = ImagePalette()

        test_map = {}
        for i in range(256):
            test_map[palette.getcolor((i, i, i))] = i

        self.assertEqual(len(test_map), 256)
        self.assertRaises(ValueError, lambda: palette.getcolor((1, 2, 3)))
    def _open(self):

        # Screen
        s = self.fp.read(13)
        if s[:6] not in [b"GIF87a", b"GIF89a"]:
            raise SyntaxError("not a GIF file")

        self.info["version"] = s[:6]
        self.size = i16(s[6:]), i16(s[8:])
        self.tile = []
        flags = i8(s[10])
        bits = (flags & 7) + 1

        if flags & 128:
            # get global palette
            self.info["background"] = i8(s[11])
            # check if palette contains colour indices
            p = self.fp.read(3 << bits)
            for i in range(0, len(p), 3):
                if not (i // 3 == i8(p[i]) == i8(p[i + 1]) == i8(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 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):

        # 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)
             )]
Exemple #8
0
    def _open(self):

        # check magic
        if self.fp.read(6) != _MAGIC:
            raise SyntaxError("not an XV thumbnail file")

        # Skip to beginning of next line
        self.fp.readline()

        # skip info comments
        while True:
            s = self.fp.readline()
            if not s:
                raise SyntaxError("Unexpected EOF reading XV thumbnail file")
            if s[0] != b'#':
                break

        # parse header line (already read)
        s = s.strip().split()

        self.mode = "P"
        self.size = int(s[0:1]), int(s[1:2])

        self.palette = ImagePalette.raw("RGB", PALETTE)

        self.tile = [
            ("raw", (0, 0)+self.size,
             self.fp.tell(), (self.mode, 0, 1)
             )]
Exemple #9
0
    def test_file(self):

        palette = ImagePalette.ImagePalette("RGB", list(range(256))*3)

        f = self.tempfile("temp.lut")

        palette.save(f)

        p = ImagePalette.load(f)

        # load returns raw palette information
        self.assertEqual(len(p[0]), 768)
        self.assertEqual(p[1], "RGB")

        p = ImagePalette.raw(p[1], p[0])
        self.assertIsInstance(p, ImagePalette.ImagePalette)
        self.assertEqual(p.palette, palette.tobytes())
    def test_file(self):

        palette = ImagePalette()

        file = self.tempfile("temp.lut")

        palette.save(file)

        from PIL.ImagePalette import load, raw

        p = load(file)

        # load returns raw palette information
        self.assertEqual(len(p[0]), 768)
        self.assertEqual(p[1], "RGB")

        p = raw(p[1], p[0])
        self.assertIsInstance(p, ImagePalette)
Exemple #11
0
def test_file():

    palette = ImagePalette()

    file = tempfile("temp.lut")

    palette.save(file)
    
    from PIL.ImagePalette import load, raw

    p = load(file)

    # load returns raw palette information
    assert_equal(len(p[0]), 768)
    assert_equal(p[1], "RGB")

    p = raw(p[1], p[0])
    assert_true(isinstance(p, ImagePalette))
Exemple #12
0
    def test_rawmode_valueerrors(self):
        # Arrange
        palette = ImagePalette.raw("RGB", list(range(256))*3)

        # Act / Assert
        self.assertRaises(ValueError, palette.tobytes)
        self.assertRaises(ValueError, palette.getcolor, (1, 2, 3))
        f = self.tempfile("temp.lut")
        self.assertRaises(ValueError, palette.save, f)
Exemple #13
0
    def test_rawmode_getdata(self):
        # Arrange
        data_in = list(range(256))*3
        palette = ImagePalette.raw("RGB", data_in)

        # Act
        rawmode, data_out = palette.getdata()

        # Assert
        self.assertEqual(rawmode, "RGB")
        self.assertEqual(data_in, data_out)
    def test_load_via_imagepalette(self):
        # Arrange
        from PIL import ImagePalette
        test_file = "Tests/images/gimp_gradient.ggr"

        # Act
        palette = ImagePalette.load(test_file)

        # Assert
        # load returns raw palette information
        self.assertEqual(len(palette[0]), 1024)
        self.assertEqual(palette[1], "RGBA")
    def test_load_1_3_via_imagepalette(self):
        # Arrange
        from PIL import ImagePalette
        # GIMP 1.3 gradient files contain a name field
        test_file = "Tests/images/gimp_gradient_with_name.ggr"

        # Act
        palette = ImagePalette.load(test_file)

        # Assert
        # load returns raw palette information
        self.assertEqual(len(palette[0]), 1024)
        self.assertEqual(palette[1], "RGBA")
Exemple #16
0
    def test_sanity(self):
        im = Image.open(TEST_FILE)
        im.load()
        self.assertEqual(im.mode, "RGBA")
        self.assertEqual(im.size, (128, 128))
        self.assertEqual(im.format, "MIC")

        # Adjust for the gamma of 2.2 encoded into the file
        lut = ImagePalette.make_gamma_lut(1/2.2)
        im = Image.merge('RGBA', [chan.point(lut) for chan in im.split()])

        im2 = hopper("RGBA")
        self.assert_image_similar(im, im2, 10)
Exemple #17
0
def test_make_linear_lut():
    # Arrange
    black = 0
    white = 255

    # Act
    lut = ImagePalette.make_linear_lut(black, white)

    # Assert
    assert isinstance(lut, list)
    assert len(lut) == 256
    # Check values
    for i in range(0, len(lut)):
        assert lut[i] == i
Exemple #18
0
    def test__new(self):
        im = hopper("RGB")
        im_p = hopper("P")

        blank_p = Image.new("P", (10, 10))
        blank_pa = Image.new("PA", (10, 10))
        blank_p.palette = None
        blank_pa.palette = None

        def _make_new(base_image, im, palette_result=None):
            new_im = base_image._new(im)
            assert new_im.mode == im.mode
            assert new_im.size == im.size
            assert new_im.info == base_image.info
            if palette_result is not None:
                assert new_im.palette.tobytes() == palette_result.tobytes()
            else:
                assert new_im.palette is None

        _make_new(im, im_p, im_p.palette)
        _make_new(im_p, im, None)
        _make_new(im, blank_p, ImagePalette.ImagePalette())
        _make_new(im, blank_pa, ImagePalette.ImagePalette())
Exemple #19
0
    def _open(self):

        # HEAD
        s = self.fp.read(128)
        magic = i16(s[4:6])
        if not (magic in [0xAF11, 0xAF12] and
                i16(s[14:16]) in [0, 3] and  # flags
                s[20:22] == b"\x00\x00"):  # reserved
            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 = [(a, a, a) for a in 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 = [o8(r)+o8(g)+o8(b) for (r, g, b) in palette]
        self.palette = ImagePalette.raw("RGB", b"".join(palette))

        # set things up to decode first frame
        self.__frame = -1
        self.__fp = self.fp
        self.__rewind = self.fp.tell()
        self._n_frames = None
        self._is_animated = None
        self.seek(0)
Exemple #20
0
    def test_make_linear_lut(self):
        # Arrange
        black = 0
        white = 255

        # Act
        lut = ImagePalette.make_linear_lut(black, white)

        # Assert
        self.assertIsInstance(lut, list)
        self.assertEqual(len(lut), 256)
        # Check values
        for i in range(0, len(lut)):
            self.assertEqual(lut[i], i)
Exemple #21
0
    def test_make_linear_lut(self):
        # Arrange
        black = 0
        white = 255

        # Act
        lut = ImagePalette.make_linear_lut(black, white)

        # Assert
        self.assertIsInstance(lut, list)
        self.assertEqual(len(lut), 256)
        # Check values
        for i in range(0, len(lut)):
            self.assertEqual(lut[i], i)
    def test_load_1_3_via_imagepalette(self):
        # Arrange
        from PIL import ImagePalette

        # GIMP 1.3 gradient files contain a name field
        test_file = "Tests/images/gimp_gradient_with_name.ggr"

        # Act
        palette = ImagePalette.load(test_file)

        # Assert
        # load returns raw palette information
        self.assertEqual(len(palette[0]), 1024)
        self.assertEqual(palette[1], "RGBA")
Exemple #23
0
    def _open(self):

        # HEAD
        s = self.fp.read(128)
        magic = i16(s[4:6])
        if not (magic in [0xAF11, 0xAF12] and i16(s[14:16]) in [0, 3]
                and  # flags
                s[20:22] == b"\x00\x00"):  # reserved
            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 = [(a, a, a) for a in 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 = [o8(r) + o8(g) + o8(b) for (r, g, b) in palette]
        self.palette = ImagePalette.raw("RGB", b"".join(palette))

        # set things up to decode first frame
        self.__frame = -1
        self.__fp = self.fp
        self.__rewind = self.fp.tell()
        self._n_frames = None
        self._is_animated = None
        self.seek(0)
Exemple #24
0
def test_getcolor():

    palette = ImagePalette.ImagePalette()

    test_map = {}
    for i in range(256):
        test_map[palette.getcolor((i, i, i))] = i

    assert len(test_map) == 256
    with pytest.raises(ValueError):
        palette.getcolor((1, 2, 3))

    # Test unknown color specifier
    with pytest.raises(ValueError):
        palette.getcolor("unknown")
    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))]
Exemple #26
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))]
Exemple #27
0
def show(scan, place=None):
    rrrgggbbb = [40, 160, 50, 50, 20, 160, 150, 100, 0, 160, 250, 150]
    pal = ImagePalette.ImagePalette("RGB", rrrgggbbb, 12)
    if place is None:
        img = Image.fromarray(scan, mode="P")
    else:
        img = Image.fromarray(
            scan[max(0, place[0] - place[2]):min(scan.shape[0] - 1, place[0] +
                                                 place[2]),
                 max(0, place[1] - place[3]):min(scan.shape[1] - 1, place[1] +
                                                 place[3])],
            mode="P")
        img = img.resize((img.size[0] * 10, img.size[1] * 10))
    img.putpalette(pal)
    img.show()
Exemple #28
0
    def test_make_gamma_lut(self):
        # Arrange
        exp = 5

        # Act
        lut = ImagePalette.make_gamma_lut(exp)

        # Assert
        self.assertIsInstance(lut, list)
        self.assertEqual(len(lut), 256)
        # Check a few values
        self.assertEqual(lut[0], 0)
        self.assertEqual(lut[63], 0)
        self.assertEqual(lut[127], 8)
        self.assertEqual(lut[191], 60)
        self.assertEqual(lut[255], 255)
Exemple #29
0
def getPaletteOfImg(imgPath, contrast_val=1.0, color_val=1.0):
    img = Image.open(imgPath)
    pal = ImagePalette.ImagePalette()
    print(pal)
    contrast = contrast_img(img, contrast_val, color_val)
    print('contrast: {}'.format(contrast))
    pal = img.getpalette()
    print(pal)
    newPalette = []
    palette = Haishoku.getPalette(imgPath)

    for i in range(0, len(palette)):
        for j in palette[i][1]:
            newPalette.append(j)
    print('   Palette: {}'.format(newPalette))
    return newPalette
Exemple #30
0
def test_make_gamma_lut():
    # Arrange
    exp = 5

    # Act
    lut = ImagePalette.make_gamma_lut(exp)

    # Assert
    assert isinstance(lut, list)
    assert len(lut) == 256
    # Check a few values
    assert lut[0] == 0
    assert lut[63] == 0
    assert lut[127] == 8
    assert lut[191] == 60
    assert lut[255] == 255
    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)
Exemple #32
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 True:

            #
            # 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()
Exemple #33
0
 def _new(self, im):
     new = Image()
     new.im = im
     new.mode = im.mode
     new.size = im.size
     if self.palette:
         new.palette = self.palette.copy()
     if im.mode == "P" and not new.palette:
         new.palette = ImagePalette.ImagePalette()
     try:
         new.info = self.info.copy()
     except AttributeError:
         # fallback (pre-1.5.2)
         new.info = {}
         for k, v in self.info:
             new.info[k] = v
     return new
Exemple #34
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 True:

            #
            # get next chunk

            cid, pos, length = self.png.read()

            try:
                s = self.png.call(cid, pos, length)
            except EOFError:
                break
            except AttributeError:
                if Image.DEBUG:
                    print(cid, pos, length, "(unknown)")
                s = ImageFile._safe_read(self.fp, length)

            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 = length  # used by load_read()
Exemple #35
0
def _get_palette_bytes(im, palette, info):
    if im.mode == "P":
        if palette and isinstance(palette, bytes):
            source_palette = palette[:768]
        else:
            source_palette = im.im.getpalette("RGB")[:768]
    else:  # L-mode
        if palette and isinstance(palette, bytes):
            source_palette = palette[:768]
        else:
            source_palette = bytearray([i // 3 for i in range(768)])

    used_palette_colors = palette_bytes = None

    if _get_optimize(im, info):
        used_palette_colors = _get_used_palette_colors(im)

        # create the new palette if not every color is used
        if len(used_palette_colors) < 256:
            palette_bytes = b""
            new_positions = {}

            i = 0
            # pick only the used colors from the palette
            for oldPosition in used_palette_colors:
                palette_bytes += source_palette[oldPosition *
                                                3:oldPosition * 3 + 3]
                new_positions[oldPosition] = i
                i += 1

            # replace the palette color id of all pixel with the new id
            image_bytes = bytearray(im.tobytes())
            for i in range(len(image_bytes)):
                image_bytes[i] = new_positions[image_bytes[i]]
            im.frombytes(bytes(image_bytes))
            new_palette_bytes = (palette_bytes +
                                 (768 - len(palette_bytes)) * b'\x00')
            im.putpalette(new_palette_bytes)
            im.palette = ImagePalette.ImagePalette("RGB",
                                                   palette=palette_bytes,
                                                   size=len(palette_bytes))

    if not palette_bytes:
        palette_bytes = source_palette
    return palette_bytes, used_palette_colors
Exemple #36
0
def Colormap2Palette(colormap=colormapLinrad):
    r=[]
    g=[]
    b=[]
    for i in range(256):
        j=31*i +1
        t=colormap[j:j+10]
        rr=int(255.0*float(t))
        t=colormap[j+10:j+20]
        gg=int(255.0*float(t))
        t=colormap[j+20:j+30]
        bb=int(255.0*float(t))
        r.append(rr)
        g.append(gg)
        b.append(bb)
    palette=ImagePalette.ImagePalette("RGB",r+g+b)
    WsjtMod.g.palette=palette
    return palette
Exemple #37
0
def test_transparent_optimize(tmp_path):
    # From issue #2195, if the transparent color is incorrectly optimized out, GIF loses
    # transparency.
    # Need a palette that isn't using the 0 color, and one that's > 128 items where the
    # transparent color is actually the top palette entry to trigger the bug.

    data = bytes(range(1, 254))
    palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)

    im = Image.new("L", (253, 1))
    im.frombytes(data)
    im.putpalette(palette)

    out = str(tmp_path / "temp.gif")
    im.save(out, transparency=253)
    with Image.open(out) as reloaded:

        assert reloaded.info["transparency"] == 253
Exemple #38
0
def process_image(src_ps3_path: str, src_ryukishi_path: str, dst_path: str, SMALL_IMAGE_MODE: bool, FOUR_THREE_ASPECT: bool):
	containing_path = str(Path(src_ps3_path).parent)
	containing_path_lower = containing_path.lower()

	ps3_image = Image.open(src_ps3_path)

	ryukishi_image = Image.open(src_ryukishi_path)
	output_image_mode = 'RGB'
	if has_transparency(ryukishi_image):
		output_image_mode = 'RGBA'

	# Convert paletted images to RGB first
	if ryukishi_image.mode in ['P', '1']:
		print(f"WARNING: converting paletted or binary image [{src_ryukishi_path}] to RGB/RGBA")
		ryukishi_image = ryukishi_image.convert(output_image_mode)

	# Check for strange image modes
	if ryukishi_image.mode not in ['RGB', 'RGBA', 'L']:
		raise Exception(f"Unhandled image mode: [{ryukishi_image.mode}]")

	out_noeffect = resize_image(ps3_image, ryukishi_image, SMALL_IMAGE_MODE, FOUR_THREE_ASPECT)

	if 'flashback' in containing_path_lower:
		# TODO: handle transparency when applying flashback effect! Currently converting to greyscale ('L') loses alpha
		out = out_noeffect.convert('L')
		out.putpalette(ImagePalette.sepia())
		out = out.convert(output_image_mode)
		# Adjust the strength of the sepia effect by blending with the original image
		# 0 = no sepia, 1 = full sepia
		out = Image.blend(out_noeffect, out, .7)
	elif 'greyscale' in containing_path_lower:
		# TODO: handle transparency when applying greyscale effect! Currently converting to greyscale ('L') loses alpha
		out = out_noeffect.convert('L')
	elif 'negative' in containing_path_lower:
		out = ImageOps.invert(out_noeffect)
	elif 'blur' in containing_path_lower:
		# This folder uses a zoom motion blur effect which I'm not sure how to implement uisng PIL
		# This folder will have to be done manually
		print(f"WARNING: file {dst_path} should have zoom motion blur applied manually")
		out = out_noeffect
	else:
		out = out_noeffect

	out.save(dst_path)
Exemple #39
0
    def test_transparent_optimize(self):
        # from issue #2195, if the transparent color is incorrectly
        # optimized out, gif loses transparency
        # Need a palette that isn't using the 0 color, and one
        # that's > 128 items where the transparent color is actually
        # the top palette entry to trigger the bug.

        data = bytes(bytearray(range(1, 254)))
        palette = ImagePalette.ImagePalette("RGB", list(range(256)) * 3)

        im = Image.new('L', (253, 1))
        im.frombytes(data)
        im.putpalette(palette)

        out = self.tempfile('temp.gif')
        im.save(out, transparency=253)
        reloaded = Image.open(out)

        self.assertEqual(reloaded.info['transparency'], 253)
    def test_write_with_raw_palette(self):
        palette = ImagePalette.raw('RGB', b'\x01\x02\x03\x04\x05\x06')
        img = SubImage8Bit(Image.new('P', (2, 2), color=1))
        img.image.putpalette(palette)
        imgs = Images8Bit([img], palette=palette, width=9, height=8)
        buffer = BytesIO()

        save_8bit_sti(imgs, buffer)

        self.assertEqual(buffer.getvalue(),
                         # Header
                         b'STCI\x48\x00\x00\x00\x08\x00\x00\x00' +
                         b'\x00\x00\x00\x00' + b'\x28\x00\x00\x00' + b'\x08\x00\x09\x00' +
                         b'\x00\x01\x00\x00\x01\x00\x08\x08\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' +
                         b'\x08' + (3 * b'\x00') + b'\x00\x00\x00\x00' + (12 * b'\x00') +
                         # Palette
                         b'\x01\x02\x03' + b'\x04\x05\x06' + (254 * b'\x00\x00\x00') +
                         # Sub Image Header
                         b'\x00\x00\x00\x00' + b'\x08\x00\x00\x00' + b'\x00\x00' + b'\x00\x00' + b'\x02\x00' + b'\x02\x00' +
                         # Data
                         b'\x02\x01\x01\x00\x02\x01\x01\x00')
    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)]
Exemple #42
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)]
Exemple #43
0
def encode(coding: str,
           image,
           quality: int,
           speed: int,
           supports_transparency: bool,
           grayscale: bool = False,
           resize=None):
    log("pillow.encode%s", (coding, image, quality, speed,
                            supports_transparency, grayscale, resize))
    assert coding in ("jpeg", "webp", "png", "png/P",
                      "png/L"), "unsupported encoding: %s" % coding
    assert image, "no image to encode"
    pixel_format = bytestostr(image.get_pixel_format())
    palette = None
    w = image.get_width()
    h = image.get_height()
    rgb = {
        "RLE8": "P",
        "XRGB": "RGB",
        "BGRX": "RGB",
        "RGBX": "RGB",
        "RGBA": "RGBA",
        "BGRA": "RGBA",
        "BGR": "RGB",
    }.get(pixel_format, pixel_format)
    bpp = 32
    pixels = image.get_pixels()
    assert pixels, "failed to get pixels from %s" % image
    #remove transparency if it cannot be handled,
    #and deal with non 24-bit formats:
    if pixel_format == "r210":
        stride = image.get_rowstride()
        from xpra.codecs.argb.argb import r210_to_rgba, r210_to_rgb  #@UnresolvedImport
        if supports_transparency:
            pixels = r210_to_rgba(pixels, w, h, stride, w * 4)
            pixel_format = "RGBA"
            rgb = "RGBA"
        else:
            image.set_rowstride(image.get_rowstride() * 3 // 4)
            pixels = r210_to_rgb(pixels, w, h, stride, w * 3)
            pixel_format = "RGB"
            rgb = "RGB"
            bpp = 24
    elif pixel_format == "BGR565":
        from xpra.codecs.argb.argb import bgr565_to_rgbx, bgr565_to_rgb  #@UnresolvedImport
        if supports_transparency:
            image.set_rowstride(image.get_rowstride() * 2)
            pixels = bgr565_to_rgbx(pixels)
            pixel_format = "RGBA"
            rgb = "RGBA"
        else:
            image.set_rowstride(image.get_rowstride() * 3 // 2)
            pixels = bgr565_to_rgb(pixels)
            pixel_format = "RGB"
            rgb = "RGB"
            bpp = 24
    elif pixel_format == "RLE8":
        pixel_format = "P"
        palette = []
        #pillow requires 8 bit palette values,
        #but we get 16-bit values from the image wrapper (X11 palettes are 16-bit):
        for r, g, b in image.get_palette():
            palette.append((r >> 8) & 0xFF)
            palette.append((g >> 8) & 0xFF)
            palette.append((b >> 8) & 0xFF)
        bpp = 8
    else:
        assert pixel_format in ("RGBA", "RGBX", "BGRA", "BGRX", "BGR", "RGB"), \
            "invalid pixel format '%s'" % pixel_format
    try:
        #PIL cannot use the memoryview directly:
        if isinstance(pixels, memoryview):
            pixels = pixels.tobytes()
        #it is safe to use frombuffer() here since the convert()
        #calls below will not convert and modify the data in place
        #and we save the compressed data then discard the image
        im = Image.frombuffer(rgb, (w, h), pixels, "raw", pixel_format,
                              image.get_rowstride(), 1)
        if palette:
            im.putpalette(palette)
            im.palette = ImagePalette.ImagePalette("RGB",
                                                   palette=palette,
                                                   size=len(palette))
        if coding != "png/L" and grayscale:
            if rgb.find(
                    "A") >= 0 and supports_transparency and coding != "jpeg":
                im = im.convert("LA")
            else:
                im = im.convert("L")
            rgb = "L"
            bpp = 8
        elif coding.startswith(
                "png") and not supports_transparency and rgb == "RGBA":
            im = im.convert("RGB")
            rgb = "RGB"
            bpp = 24
    except Exception:
        log.error(
            "pillow.encode%s converting %s pixels from %s to %s failed",
            (coding, image, speed, supports_transparency, grayscale, resize),
            type(pixels),
            pixel_format,
            rgb,
            exc_info=True)
        raise
    client_options = {}
    if resize:
        if speed >= 95:
            resample = "NEAREST"
        elif speed > 80:
            resample = "BILINEAR"
        elif speed >= 30:
            resample = "BICUBIC"
        else:
            resample = "LANCZOS"
        resample_value = getattr(Image, resample, 0)
        im = im.resize(resize, resample=resample_value)
        client_options["resample"] = resample
    if coding in ("jpeg", "webp"):
        #newer versions of pillow require explicit conversion to non-alpha:
        if pixel_format.find("A") >= 0:
            im = im.convert("RGB")
        q = int(min(100, max(1, quality)))
        kwargs = im.info
        kwargs["quality"] = q
        client_options["quality"] = q
        if coding == "jpeg" and speed < 50:
            #(optimizing jpeg is pretty cheap and worth doing)
            kwargs["optimize"] = True
            client_options["optimize"] = True
        elif coding == "webp" and q >= 100:
            kwargs["lossless"] = 1
        pil_fmt = coding.upper()
    else:
        assert coding in ("png", "png/P",
                          "png/L"), "unsupported encoding: %s" % coding
        if coding in ("png/L",
                      "png/P") and supports_transparency and rgb == "RGBA":
            #grab alpha channel (the last one):
            #we use the last channel because we know it is RGBA,
            #otherwise we should do: alpha_index= image.getbands().index('A')
            alpha = im.split()[-1]

            #convert to simple on or off mask:
            #set all pixel values below 128 to 255, and the rest to 0
            def mask_value(a):
                if a <= 128:
                    return 255
                return 0

            mask = Image.eval(alpha, mask_value)
        else:
            #no transparency
            mask = None
        if coding == "png/L":
            im = im.convert("L", palette=Image.ADAPTIVE, colors=255)
            bpp = 8
        elif coding == "png/P":
            #convert to 255 indexed colour if:
            # * we're not in palette mode yet (source is >8bpp)
            # * we need space for the mask (256 -> 255)
            if palette is None or mask:
                #I wanted to use the "better" adaptive method,
                #but this does NOT work (produces a black image instead):
                #im.convert("P", palette=Image.ADAPTIVE)
                im = im.convert("P", palette=Image.WEB, colors=255)
            bpp = 8
        kwargs = im.info
        if mask:
            # paste the alpha mask to the color of index 255
            im.paste(255, mask)
            client_options["transparency"] = 255
            kwargs["transparency"] = 255
        if speed == 0:
            #optimizing png is very rarely worth doing
            kwargs["optimize"] = True
            client_options["optimize"] = True
        #level can range from 0 to 9, but anything above 5 is way too slow for small gains:
        #76-100   -> 1
        #51-76    -> 2
        #etc
        level = max(1, min(5, (125 - speed) // 25))
        kwargs["compress_level"] = level
        #no need to expose to the client:
        #client_options["compress_level"] = level
        #default is good enough, no need to override, other options:
        #DEFAULT_STRATEGY, FILTERED, HUFFMAN_ONLY, RLE, FIXED
        #kwargs["compress_type"] = Image.DEFAULT_STRATEGY
        pil_fmt = "PNG"
    buf = BytesIO()
    im.save(buf, pil_fmt, **kwargs)
    if SAVE_TO_FILE:  # pragma: no cover
        filename = "./%s.%s" % (time.time(), pil_fmt)
        im.save(filename, pil_fmt)
        log.info("saved %s to %s", coding, filename)
    log("sending %sx%s %s as %s, mode=%s, options=%s", w, h, pixel_format,
        coding, im.mode, kwargs)
    data = buf.getvalue()
    buf.close()
    return coding, Compressed(
        coding,
        data), client_options, image.get_width(), image.get_height(), 0, bpp
Exemple #44
0
 def test_imagepalette(self):
     im = hopper("P")
     im.putpalette(ImagePalette.negative())
     im.putpalette(ImagePalette.random())
     im.putpalette(ImagePalette.sepia())
     im.putpalette(ImagePalette.wedge())
Exemple #45
0
    def _open(self):

        # process header
        s = self.fp.read(18)

        idlen = i8(s[0])

        colormaptype = i8(s[1])
        imagetype = i8(s[2])

        depth = i8(s[16])

        flags = i8(s[17])

        self.size = i16(s[12:]), i16(s[14:])

        # validate header fields
        if 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 idlen:
            self.info["id_section"] = self.fp.read(idlen)

        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", b"\0"*2*start + self.fp.read(2*size))
            elif mapdepth == 24:
                self.palette = ImagePalette.raw(
                    "BGR", b"\0"*3*start + self.fp.read(3*size))
            elif mapdepth == 32:
                self.palette = ImagePalette.raw(
                    "BGRA", b"\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
Exemple #46
0
import os
#os.environ['CUDA_HOME'] = '/opt/anaconda3/lib/python3.6/site-packages/torch/cuda'

from torch.nn import functional as F
from torchvision.transforms import ToTensor, Normalize, Compose
import torch
print(torch.cuda.is_available())

import cv2
import random
from pathlib import Path

# In[3]:

random.seed(42)
NUCLEI_PALETTE = ImagePalette.random()
random.seed()

# In[4]:

rcParams['figure.figsize'] = 15, 15

# In[5]:

from models.ternausnet2 import TernausNetV2
# print('...')

# In[6]:


def get_model(model_path):
    def test_sanity(self):

        ImagePalette("RGB", list(range(256)) * 3)
        self.assertRaises(ValueError,
                          lambda: ImagePalette("RGB",
                                               list(range(256)) * 2))
Exemple #48
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 = (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

        # BEGIN PATCH
        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:  # Inches
                self.info["dpi"] = xres, yres
            elif resunit == 3:  # Centimeters
                self.info["dpi"] = xres * 2.54, yres * 2.54
            else:  # No absolute unit of measurement.
                self.info["resolution"] = xres, yres
        # END PATCH

        # 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(324):
            # tiled image
            w = getscalar(322)
            h = getscalar(323)
            a = None
            for o in self.tag[324]:
                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, ""))
Exemple #49
0
    def _open(self):

        if not _accept(self.fp.read(9)):
            raise SyntaxError("not an XPM file")

        # skip forward to next string
        while True:
            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 = [b"\0\0\0"] * 256

        for i in range(pal):

            s = self.fp.readline()
            if s[-2:] == b'\r\n':
                s = s[:-2]
            elif s[-1:] in b'\r\n':
                s = s[:-1]

            c = i8(s[1])
            s = s[2:-2].split()

            for i in range(0, len(s), 2):

                if s[i] == b"c":

                    # process colour key
                    rgb = s[i+1]
                    if rgb == b"None":
                        self.info["transparency"] = c
                    elif rgb[0:1] == b"#":
                        # FIXME: handle colour names (see ImagePalette.py)
                        rgb = int(rgb[1:], 16)
                        palette[c] = o8((rgb >> 16) & 255) +\
                                     o8((rgb >> 8) & 255) +\
                                     o8(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", b"".join(palette))

        self.tile = [("raw", (0, 0)+self.size, self.fp.tell(), ("P", 0, 1))]
Exemple #50
0
def getheader(im, palette=None, info=None):
    """Return a list of strings representing a GIF header"""

    # Header Block
    # http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp

    version = b"87a"
    for extensionKey in ["transparency", "duration", "loop", "comment"]:
        if info and extensionKey in info:
            if ((extensionKey == "duration" and info[extensionKey] == 0) or
                (extensionKey == "comment" and not (1 <= len(info[extensionKey]) <= 255))):
                continue
            version = b"89a"
            break
    else:
        if im.info.get("version") == "89a":
            version = b"89a"

    header = [
        b"GIF"+version +        # signature + version
        o16(im.size[0]) +       # canvas width
        o16(im.size[1])         # canvas height
    ]

    if im.mode == "P":
        if palette and isinstance(palette, bytes):
            source_palette = palette[:768]
        else:
            source_palette = im.im.getpalette("RGB")[:768]
    else:  # L-mode
        if palette and isinstance(palette, bytes):
            source_palette = palette[:768]
        else:
            source_palette = bytearray([i//3 for i in range(768)])

    used_palette_colors = palette_bytes = None

    if _get_optimize(im, info):
        used_palette_colors = _get_used_palette_colors(im)

        # create the new palette if not every color is used
        if len(used_palette_colors) < 256:
            palette_bytes = b""
            new_positions = {}

            i = 0
            # pick only the used colors from the palette
            for oldPosition in used_palette_colors:
                palette_bytes += source_palette[oldPosition*3:oldPosition*3+3]
                new_positions[oldPosition] = i
                i += 1

            # replace the palette color id of all pixel with the new id
            image_bytes = bytearray(im.tobytes())
            for i in range(len(image_bytes)):
                image_bytes[i] = new_positions[image_bytes[i]]
            im.frombytes(bytes(image_bytes))
            new_palette_bytes = (palette_bytes +
                                 (768 - len(palette_bytes)) * b'\x00')
            im.putpalette(new_palette_bytes)
            im.palette = ImagePalette.ImagePalette("RGB",
                                                   palette=palette_bytes,
                                                   size=len(palette_bytes))

    if not palette_bytes:
        palette_bytes = source_palette

    # Logical Screen Descriptor
    # calculate the palette size for the header
    import math
    color_table_size = int(math.ceil(math.log(len(palette_bytes)//3, 2)))-1
    if color_table_size < 0:
        color_table_size = 0
    # size of global color table + global color table flag
    header.append(o8(color_table_size + 128))
    # background + reserved/aspect
    if info and "background" in info:
        background = info["background"]
    elif "background" in im.info:
        # This elif is redundant within GifImagePlugin
        # since im.info parameters are bundled into the info dictionary
        # However, external scripts may call getheader directly
        # So this maintains earlier behaviour
        background = im.info["background"]
    else:
        background = 0
    header.append(o8(background) + o8(0))
    # end of Logical Screen Descriptor

    # add the missing amount of bytes
    # the palette has to be 2<<n in size
    actual_target_size_diff = (2 << color_table_size) - len(palette_bytes)//3
    if actual_target_size_diff > 0:
        palette_bytes += o8(0) * 3 * actual_target_size_diff

    # Header + Logical Screen Descriptor + Global Color Table
    header.append(palette_bytes)
    return header, used_palette_colors
Exemple #51
0
    def _seek(self, frame):

        if frame == 0:
            # rewind
            self.__offset = 0
            self.dispose = None
            self.dispose_extent = [0, 0, 0, 0]  # x0, y0, x1, y1
            self.__frame = -1
            self.__fp.seek(self.__rewind)
            self._prev_im = None
            self.disposal_method = 0
        else:
            # ensure that the previous frame was loaded
            if not self.im:
                self.load()

        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.paste(self.dispose, self.dispose_extent)

        from copy import copy
        self.palette = copy(self.global_palette)

        while True:

            s = self.fp.read(1)
            if not s or s == b";":
                break

            elif s == b"!":
                #
                # extensions
                #
                s = self.fp.read(1)
                block = self.data()
                if i8(s) == 249:
                    #
                    # graphic control extension
                    #
                    flags = i8(block[0])
                    if flags & 1:
                        self.info["transparency"] = i8(block[3])
                    self.info["duration"] = i16(block[1:3]) * 10

                    # disposal method - find the value of bits 4 - 6
                    dispose_bits = 0b00011100 & flags
                    dispose_bits = dispose_bits >> 2
                    if dispose_bits:
                        # only set the dispose if it is not
                        # unspecified. I'm not sure if this is
                        # correct, but it seems to prevent the last
                        # frame from looking odd for some animations
                        self.disposal_method = dispose_bits
                elif i8(s) == 254:
                    #
                    # comment extension
                    #
                    self.info["comment"] = block
                elif i8(s) == 255:
                    #
                    # application extension
                    #
                    self.info["extension"] = block, self.fp.tell()
                    if block[:11] == b"NETSCAPE2.0":
                        block = self.data()
                        if len(block) >= 3 and i8(block[0]) == 1:
                            self.info["loop"] = i16(block[1:3])
                while self.data():
                    pass

            elif s == b",":
                #
                # 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:])
                self.dispose_extent = x0, y0, x1, y1
                flags = i8(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 = i8(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`" % i8(s)

        try:
            if self.disposal_method < 2:
                # do not dispose or none specified
                self.dispose = None
            elif self.disposal_method == 2:
                # replace with background colour
                self.dispose = Image.core.fill("P", self.size,
                                               self.info["background"])
            else:
                # replace with previous contents
                if self.im:
                    self.dispose = self.im.copy()

            # only dispose the extent in this frame
            if self.dispose:
                self.dispose = self.dispose.crop(self.dispose_extent)
        except (AttributeError, KeyError):
            pass

        if not self.tile:
            # self.__fp = None
            raise EOFError

        self.mode = "L"
        if self.palette:
            self.mode = "P"
    def _open(self):

        read = self.fp.read

        #
        # header

        s = read(26)
        if s[:4] != b"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(i8(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 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

        from copy import copy

        self.palette = copy(self.global_palette)

        while True:

            s = self.fp.read(1)
            if not s or s == b";":
                break

            elif s == b"!":
                #
                # extensions
                #
                s = self.fp.read(1)
                block = self.data()
                if i8(s) == 249:
                    #
                    # graphic control extension
                    #
                    flags = i8(block[0])
                    if flags & 1:
                        self.info["transparency"] = i8(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 i8(s) == 255:
                    #
                    # application extension
                    #
                    self.info["extension"] = block, self.fp.tell()
                    if block[:11] == b"NETSCAPE2.0":
                        block = self.data()
                        if len(block) >= 3 and i8(block[0]) == 1:
                            self.info["loop"] = i16(block[1:3])
                while self.data():
                    pass

            elif s == b",":
                #
                # 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 = i8(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 = i8(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`" % i8(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"
Exemple #54
0
    def _bitmap(self, header=0, offset=0):
        """ Read relevant info about the BMP """
        read, seek = self.fp.read, self.fp.seek
        if header:
            seek(header)
        file_info = dict()
        file_info["header_size"] = i32(read(4))  # read bmp header size @offset 14 (this is part of the header size)
        file_info["direction"] = -1
        # --------------------- If requested, read header at a specific position
        header_data = ImageFile._safe_read(
            self.fp, file_info["header_size"] - 4
        )  # read the rest of the bmp header, without its size
        # --------------------------------------------------- IBM OS/2 Bitmap v1
        # ------ This format has different offsets because of width/height types
        if file_info["header_size"] == 12:
            file_info["width"] = i16(header_data[0:2])
            file_info["height"] = i16(header_data[2:4])
            file_info["planes"] = i16(header_data[4:6])
            file_info["bits"] = i16(header_data[6:8])
            file_info["compression"] = self.RAW
            file_info["palette_padding"] = 3
        # ---------------------------------------------- Windows Bitmap v2 to v5
        elif file_info["header_size"] in (40, 64, 108, 124):  # v3, OS/2 v2, v4, v5
            if file_info["header_size"] >= 40:  # v3 and OS/2
                file_info["y_flip"] = i8(header_data[7]) == 0xFF
                file_info["direction"] = 1 if file_info["y_flip"] else -1
                file_info["width"] = i32(header_data[0:4])
                file_info["height"] = (
                    i32(header_data[4:8]) if not file_info["y_flip"] else 2 ** 32 - i32(header_data[4:8])
                )
                file_info["planes"] = i16(header_data[8:10])
                file_info["bits"] = i16(header_data[10:12])
                file_info["compression"] = i32(header_data[12:16])
                file_info["data_size"] = i32(header_data[16:20])  # byte size of pixel data
                file_info["pixels_per_meter"] = (i32(header_data[20:24]), i32(header_data[24:28]))
                file_info["colors"] = i32(header_data[28:32])
                file_info["palette_padding"] = 4
                self.info["dpi"] = tuple(map(lambda x: math.ceil(x / 39.3701), file_info["pixels_per_meter"]))
                if file_info["compression"] == self.BITFIELDS:
                    if len(header_data) >= 52:
                        for idx, mask in enumerate(["r_mask", "g_mask", "b_mask", "a_mask"]):
                            file_info[mask] = i32(header_data[36 + idx * 4 : 40 + idx * 4])
                    else:
                        for mask in ["r_mask", "g_mask", "b_mask", "a_mask"]:
                            file_info[mask] = i32(read(4))
                    file_info["rgb_mask"] = (file_info["r_mask"], file_info["g_mask"], file_info["b_mask"])
                    file_info["rgba_mask"] = (
                        file_info["r_mask"],
                        file_info["g_mask"],
                        file_info["b_mask"],
                        file_info["a_mask"],
                    )
        else:
            raise IOError("Unsupported BMP header type (%d)" % file_info["header_size"])
        # ------------------ Special case : header is reported 40, which
        # ---------------------- is shorter than real size for bpp >= 16
        self.size = file_info["width"], file_info["height"]
        # -------- If color count was not found in the header, compute from bits
        file_info["colors"] = file_info["colors"] if file_info.get("colors", 0) else (1 << file_info["bits"])
        # -------------------------------- Check abnormal values for DOS attacks
        if file_info["width"] * file_info["height"] > 2 ** 31:
            raise IOError("Unsupported BMP Size: (%dx%d)" % self.size)
        # ----------------------- Check bit depth for unusual unsupported values
        self.mode, raw_mode = BIT2MODE.get(file_info["bits"], (None, None))
        if self.mode is None:
            raise IOError("Unsupported BMP pixel depth (%d)" % file_info["bits"])
        # ----------------- Process BMP with Bitfields compression (not palette)
        if file_info["compression"] == self.BITFIELDS:
            SUPPORTED = {
                32: [(0xFF0000, 0xFF00, 0xFF, 0x0), (0xFF0000, 0xFF00, 0xFF, 0xFF000000), (0x0, 0x0, 0x0, 0x0)],
                24: [(0xFF0000, 0xFF00, 0xFF)],
                16: [(0xF800, 0x7E0, 0x1F), (0x7C00, 0x3E0, 0x1F)],
            }
            MASK_MODES = {
                (32, (0xFF0000, 0xFF00, 0xFF, 0x0)): "BGRX",
                (32, (0xFF0000, 0xFF00, 0xFF, 0xFF000000)): "BGRA",
                (32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
                (24, (0xFF0000, 0xFF00, 0xFF)): "BGR",
                (16, (0xF800, 0x7E0, 0x1F)): "BGR;16",
                (16, (0x7C00, 0x3E0, 0x1F)): "BGR;15",
            }
            if file_info["bits"] in SUPPORTED:
                if file_info["bits"] == 32 and file_info["rgba_mask"] in SUPPORTED[file_info["bits"]]:
                    raw_mode = MASK_MODES[(file_info["bits"], file_info["rgba_mask"])]
                    self.mode = "RGBA" if raw_mode in ("BGRA",) else self.mode
                elif file_info["bits"] in (24, 16) and file_info["rgb_mask"] in SUPPORTED[file_info["bits"]]:
                    raw_mode = MASK_MODES[(file_info["bits"], file_info["rgb_mask"])]
                else:
                    raise IOError("Unsupported BMP bitfields layout")
            else:
                raise IOError("Unsupported BMP bitfields layout")
        elif file_info["compression"] == self.RAW:
            if file_info["bits"] == 32 and header == 22:  # 32-bit .cur offset
                raw_mode, self.mode = "BGRA", "RGBA"
        else:
            raise IOError("Unsupported BMP compression (%d)" % file_info["compression"])
        # ---------------- Once the header is processed, process the palette/LUT
        if self.mode == "P":  # Paletted for 1, 4 and 8 bit images
            # ----------------------------------------------------- 1-bit images
            if not (0 < file_info["colors"] <= 65536):
                raise IOError("Unsupported BMP Palette size (%d)" % file_info["colors"])
            else:
                padding = file_info["palette_padding"]
                palette = read(padding * file_info["colors"])
                greyscale = True
                indices = (0, 255) if file_info["colors"] == 2 else list(range(file_info["colors"]))
                # ------------------ Check if greyscale and ignore palette if so
                for ind, val in enumerate(indices):
                    rgb = palette[ind * padding : ind * padding + 3]
                    if rgb != o8(val) * 3:
                        greyscale = False
                # -------- If all colors are grey, white or black, ditch palette
                if greyscale:
                    self.mode = "1" if file_info["colors"] == 2 else "L"
                    raw_mode = self.mode
                else:
                    self.mode = "P"
                    self.palette = ImagePalette.raw("BGRX" if padding == 4 else "BGR", palette)

        # ----------------------------- Finally set the tile data for the plugin
        self.info["compression"] = file_info["compression"]
        self.tile = [
            (
                "raw",
                (0, 0, file_info["width"], file_info["height"]),
                offset or self.fp.tell(),
                (raw_mode, ((file_info["width"] * file_info["bits"] + 31) >> 3) & (~3), file_info["direction"]),
            )
        ]
Exemple #55
0
    def _setup(self):
        "Setup this image object based on current tags"

        if 0xBC01 in self.tag_v2:
            raise IOError("Windows Media Photo files not yet supported")

        # extract relevant tags
        self._compression = COMPRESSION_INFO[self.tag_v2.get(COMPRESSION, 1)]
        self._planar_configuration = self.tag_v2.get(PLANAR_CONFIGURATION, 1)

        # photometric is a required tag, but not everyone is reading
        # the specification
        photo = self.tag_v2.get(PHOTOMETRIC_INTERPRETATION, 0)

        fillorder = self.tag_v2.get(FILLORDER, 1)

        if DEBUG:
            print("*** Summary ***")
            print("- compression:", self._compression)
            print("- photometric_interpretation:", photo)
            print("- planar_configuration:", self._planar_configuration)
            print("- fill_order:", fillorder)

        # size
        xsize = self.tag_v2.get(IMAGEWIDTH)
        ysize = self.tag_v2.get(IMAGELENGTH)
        self.size = xsize, ysize

        if DEBUG:
            print("- size:", self.size)

        format = self.tag_v2.get(SAMPLEFORMAT, (1,))
        if len(format) > 1 and max(format) == min(format) == 1:
            # SAMPLEFORMAT is properly per band, so an RGB image will
            # be (1,1,1).  But, we don't support per band pixel types,
            # and anything more than one band is a uint8. So, just
            # take the first element. Revisit this if adding support
            # for more exotic images.
            format = (1,)

        # mode: check photometric interpretation and bits per pixel
        key = (
            self.tag_v2.prefix, photo, format, fillorder,
            self.tag_v2.get(BITSPERSAMPLE, (1,)),
            self.tag_v2.get(EXTRASAMPLES, ())
            )
        if DEBUG:
            print("format key:", key)
        try:
            self.mode, rawmode = OPEN_INFO[key]
        except KeyError:
            if DEBUG:
                print("- unsupported format")
            raise SyntaxError("unknown pixel mode")

        if DEBUG:
            print("- raw mode:", rawmode)
            print("- pil mode:", self.mode)

        self.info["compression"] = self._compression

        xres = self.tag_v2.get(X_RESOLUTION, (1, 1))
        yres = self.tag_v2.get(Y_RESOLUTION, (1, 1))

        if xres and not isinstance(xres, tuple):
            xres = (xres, 1.)
        if yres and not isinstance(yres, tuple):
            yres = (yres, 1.)
        if xres and yres:
            xres = xres[0] / (xres[1] or 1)
            yres = yres[0] / (yres[1] or 1)
            resunit = self.tag_v2.get(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 STRIPOFFSETS in self.tag_v2:
            # striped image
            offsets = self.tag_v2[STRIPOFFSETS]
            h = self.tag_v2.get(ROWSPERSTRIP, ysize)
            w = self.size[0]
            if READ_LIBTIFF or self._compression in ["tiff_ccitt", "group3",
                                                     "group4", "tiff_jpeg",
                                                     "tiff_adobe_deflate",
                                                     "tiff_thunderscan",
                                                     "tiff_deflate",
                                                     "tiff_sgilog",
                                                     "tiff_sgilog24",
                                                     "tiff_raw_16"]:
                # if DEBUG:
                #     print "Activating g4 compression for whole file"

                # Decoder expects entire file as one tile.
                # There's a buffer size limit in load (64k)
                # so large g4 images will fail if we use that
                # function.
                #
                # Setup the one tile for the whole image, then
                # replace the existing load function with our
                # _load_libtiff function.

                self.load = self._load_libtiff

                # To be nice on memory footprint, if there's a
                # file descriptor, use that instead of reading
                # into a string in python.

                # libtiff closes the file descriptor, so pass in a dup.
                try:
                    fp = hasattr(self.fp, "fileno") and \
                        os.dup(self.fp.fileno())
                    # flush the file descriptor, prevents error on pypy 2.4+
                    # should also eliminate the need for fp.tell for py3
                    # in _seek
                    if hasattr(self.fp, "flush"):
                        self.fp.flush()
                except IOError:
                    # io.BytesIO have a fileno, but returns an IOError if
                    # it doesn't use a file descriptor.
                    fp = False

                # libtiff handles the fillmode for us, so 1;IR should
                # actually be 1;I. Including the R double reverses the
                # bits, so stripes of the image are reversed.  See
                # https://github.com/python-pillow/Pillow/issues/279
                if fillorder == 2:
                    key = (
                        self.tag_v2.prefix, photo, format, 1,
                        self.tag_v2.get(BITSPERSAMPLE, (1,)),
                        self.tag_v2.get(EXTRASAMPLES, ())
                        )
                    if DEBUG:
                        print("format key:", key)
                    # this should always work, since all the
                    # fillorder==2 modes have a corresponding
                    # fillorder=1 mode
                    self.mode, rawmode = OPEN_INFO[key]
                # libtiff always returns the bytes in native order.
                # we're expecting image byte order. So, if the rawmode
                # contains I;16, we need to convert from native to image
                # byte order.
                if self.mode in ('I;16B', 'I;16') and 'I;16' in rawmode:
                    rawmode = 'I;16N'

                # Offset in the tile tuple is 0, we go from 0,0 to
                # w,h, and we only do this once -- eds
                a = (rawmode, self._compression, fp)
                self.tile.append(
                    (self._compression,
                     (0, 0, w, ysize),
                     0, a))
                a = None

            else:
                for i in range(len(offsets)):
                    a = self._decoder(rawmode, l, i)
                    self.tile.append(
                        (self._compression,
                            (0, min(y, ysize), w, min(y+h, ysize)),
                            offsets[i], a))
                    if DEBUG:
                        print("tiles: ", self.tile)
                    y = y + h
                    if y >= self.size[1]:
                        x = y = 0
                        l += 1
                    a = None
        elif TILEOFFSETS in self.tag_v2:
            # tiled image
            w = self.tag_v2.get(322)
            h = self.tag_v2.get(323)
            a = None
            for o in self.tag_v2[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 += 1
                        a = None
        else:
            if DEBUG:
                print("- unsupported data organization")
            raise SyntaxError("unknown data organization")

        # fixup palette descriptor

        if self.mode == "P":
            palette = [o8(b // 256) for b in self.tag_v2[COLORMAP]]
            self.palette = ImagePalette.raw("RGB;L", b"".join(palette))
Exemple #56
0
def CSPalette():
    palette = ImagePalette.ImagePalette()
    for label in labels:
        palette.getcolor(label.color)
    return palette
Exemple #57
0
    def _open(self):

        # The Sun Raster file header is 32 bytes in length and has the following format:

        #     typedef struct _SunRaster
        #     {
        #         DWORD MagicNumber;      /* Magic (identification) number */
        #         DWORD Width;            /* Width of image in pixels */
        #         DWORD Height;           /* Height of image in pixels */
        #         DWORD Depth;            /* Number of bits per pixel */
        #         DWORD Length;           /* Size of image data in bytes */
        #         DWORD Type;             /* Type of raster file */
        #         DWORD ColorMapType;     /* Type of color map */
        #         DWORD ColorMapLength;   /* Size of the color map in bytes */
        #     } SUNRASTER;

        # HEAD
        s = self.fp.read(32)
        if i32(s) != 0x59a66a95:
            raise InvalidFileType("not a SUN raster file")

        offset = 32

        self.size = i32(s[4:8]), i32(s[8:12])

        depth = i32(s[12:16])
        data_length = i32(s[16:20])  # unreliable, ignore.
        file_type = i32(s[20:24])
        palette_type = i32(s[24:28])  # 0: None, 1: RGB, 2: Raw/arbitrary
        palette_length = i32(s[28:32])

        if depth == 1:
            self.mode, rawmode = "1", "1;I"
        elif depth == 4:
            self.mode, rawmode = "L", "L;4"
        elif depth == 8:
            self.mode = rawmode = "L"
        elif depth == 24:
            if file_type == 3:
                self.mode, rawmode = "RGB", "RGB"
            else:
                self.mode, rawmode = "RGB", "BGR"
        elif depth == 32:
            if file_type == 3:
                self.mode, rawmode = 'RGB', 'RGBX'
            else:
                self.mode, rawmode = 'RGB', 'BGRX'
        else:
            raise NotImplementedError("Unsupported Mode/Bit Depth")

        if palette_length:
            if palette_length > 1024:
                raise NotImplementedError("Unsupported Color Palette Length")

            if palette_type != 1:
                raise NotImplementedError("Unsupported Palette Type")

            offset = offset + palette_length
            self.palette = ImagePalette.raw("RGB;L",
                                            self.fp.read(palette_length))
            if self.mode == "L":
                self.mode = "P"
                rawmode = rawmode.replace('L', 'P')

        # 16 bit boundaries on stride
        stride = ((self.size[0] * depth + 15) // 16) * 2

        # file type: Type is the version (or flavor) of the bitmap
        # file. The following values are typically found in the Type
        # field:
        # 0000h	Old
        # 0001h	Standard
        # 0002h	Byte-encoded
        # 0003h	RGB format
        # 0004h	TIFF format
        # 0005h	IFF format
        # FFFFh	Experimental

        # Old and standard are the same, except for the length tag.
        # byte-encoded is run-length-encoded
        # RGB looks similar to standard, but RGB byte order
        # TIFF and IFF mean that they were converted from T/IFF
        # Experimental means that it's something else.
        # (http://www.fileformat.info/format/sunraster/egff.htm)

        if file_type in (0, 1, 3, 4, 5):
            self.tile = [("raw", (0, 0) + self.size, offset, (rawmode, stride))
                         ]
        elif file_type == 2:
            self.tile = [("sun_rle", (0, 0) + self.size, offset, rawmode)]
        else:
            raise NotImplementedError('Unsupported Sun Raster file type')
Exemple #58
0
    def _open(self):

        if not _accept(self.fp.read(9)):
            raise SyntaxError("not an XPM file")

        # skip forward to next string
        while True:
            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 = [b"\0\0\0"] * 256

        for i in range(pal):

            s = self.fp.readline()
            if s[-2:] == b'\r\n':
                s = s[:-2]
            elif s[-1:] in b'\r\n':
                s = s[:-1]

            c = i8(s[1])
            s = s[2:-2].split()

            for i in range(0, len(s), 2):

                if s[i] == b"c":

                    # process colour key
                    rgb = s[i + 1]
                    if rgb == b"None":
                        self.info["transparency"] = c
                    elif rgb[0:1] == b"#":
                        # FIXME: handle colour names (see ImagePalette.py)
                        rgb = int(rgb[1:], 16)
                        palette[c] = (o8((rgb >> 16) & 255) +
                                      o8((rgb >> 8) & 255) + o8(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", b"".join(palette))

        self.tile = [("raw", (0, 0) + self.size, self.fp.tell(), ("P", 0, 1))]
Exemple #59
0
    def _bitmap(self, header=0, offset=0):
        """ Read relevant info about the BMP """
        read, seek = self.fp.read, self.fp.seek
        if header:
            seek(header)
        file_info = dict()
        file_info['header_size'] = i32(
            read(4)
        )  # read bmp header size @offset 14 (this is part of the header size)
        file_info['direction'] = -1
        # --------------------- If requested, read header at a specific position
        header_data = ImageFile._safe_read(
            self.fp, file_info['header_size'] -
            4)  # read the rest of the bmp header, without its size
        # --------------------------------------------------- IBM OS/2 Bitmap v1
        # ------ This format has different offsets because of width/height types
        if file_info['header_size'] == 12:
            file_info['width'] = i16(header_data[0:2])
            file_info['height'] = i16(header_data[2:4])
            file_info['planes'] = i16(header_data[4:6])
            file_info['bits'] = i16(header_data[6:8])
            file_info['compression'] = self.RAW
            file_info['palette_padding'] = 3
        # ---------------------------------------------- Windows Bitmap v2 to v5
        elif file_info['header_size'] in (40, 64, 108,
                                          124):  # v3, OS/2 v2, v4, v5
            if file_info['header_size'] >= 40:  # v3 and OS/2
                file_info['y_flip'] = i8(header_data[7]) == 0xff
                file_info['direction'] = 1 if file_info['y_flip'] else -1
                file_info['width'] = i32(header_data[0:4])
                file_info['height'] = i32(
                    header_data[4:8]
                ) if not file_info['y_flip'] else 2**32 - i32(header_data[4:8])
                file_info['planes'] = i16(header_data[8:10])
                file_info['bits'] = i16(header_data[10:12])
                file_info['compression'] = i32(header_data[12:16])
                file_info['data_size'] = i32(
                    header_data[16:20])  # byte size of pixel data
                file_info['pixels_per_meter'] = (i32(header_data[20:24]),
                                                 i32(header_data[24:28]))
                file_info['colors'] = i32(header_data[28:32])
                file_info['palette_padding'] = 4
                self.info["dpi"] = tuple(
                    map(lambda x: int(math.ceil(x / 39.3701)),
                        file_info['pixels_per_meter']))
                if file_info['compression'] == self.BITFIELDS:
                    if len(header_data) >= 52:
                        for idx, mask in enumerate(
                            ['r_mask', 'g_mask', 'b_mask', 'a_mask']):
                            file_info[mask] = i32(header_data[36 + idx * 4:40 +
                                                              idx * 4])
                    else:
                        for mask in ['r_mask', 'g_mask', 'b_mask', 'a_mask']:
                            file_info[mask] = i32(read(4))
                    file_info['rgb_mask'] = (file_info['r_mask'],
                                             file_info['g_mask'],
                                             file_info['b_mask'])
                    file_info['rgba_mask'] = (file_info['r_mask'],
                                              file_info['g_mask'],
                                              file_info['b_mask'],
                                              file_info['a_mask'])
        else:
            raise IOError("Unsupported BMP header type (%d)" %
                          file_info['header_size'])
        # ------------------ Special case : header is reported 40, which
        # ---------------------- is shorter than real size for bpp >= 16
        self.size = file_info['width'], file_info['height']
        # -------- If color count was not found in the header, compute from bits
        file_info['colors'] = file_info['colors'] if file_info.get(
            'colors', 0) else (1 << file_info['bits'])
        # -------------------------------- Check abnormal values for DOS attacks
        if file_info['width'] * file_info['height'] > 2**31:
            raise IOError("Unsupported BMP Size: (%dx%d)" % self.size)
        # ----------------------- Check bit depth for unusual unsupported values
        self.mode, raw_mode = BIT2MODE.get(file_info['bits'], (None, None))
        if self.mode is None:
            raise IOError("Unsupported BMP pixel depth (%d)" %
                          file_info['bits'])
        # ----------------- Process BMP with Bitfields compression (not palette)
        if file_info['compression'] == self.BITFIELDS:
            SUPPORTED = {
                32: [(0xff0000, 0xff00, 0xff, 0x0),
                     (0xff0000, 0xff00, 0xff, 0xff000000),
                     (0x0, 0x0, 0x0, 0x0)],
                24: [(0xff0000, 0xff00, 0xff)],
                16: [(0xf800, 0x7e0, 0x1f), (0x7c00, 0x3e0, 0x1f)]
            }
            MASK_MODES = {
                (32, (0xff0000, 0xff00, 0xff, 0x0)): "BGRX",
                (32, (0xff0000, 0xff00, 0xff, 0xff000000)): "BGRA",
                (32, (0x0, 0x0, 0x0, 0x0)): "BGRA",
                (24, (0xff0000, 0xff00, 0xff)): "BGR",
                (16, (0xf800, 0x7e0, 0x1f)): "BGR;16",
                (16, (0x7c00, 0x3e0, 0x1f)): "BGR;15"
            }
            if file_info['bits'] in SUPPORTED:
                if file_info['bits'] == 32 and file_info[
                        'rgba_mask'] in SUPPORTED[file_info['bits']]:
                    raw_mode = MASK_MODES[(file_info['bits'],
                                           file_info['rgba_mask'])]
                    self.mode = "RGBA" if raw_mode in ("BGRA", ) else self.mode
                elif file_info['bits'] in (
                        24, 16
                ) and file_info['rgb_mask'] in SUPPORTED[file_info['bits']]:
                    raw_mode = MASK_MODES[(file_info['bits'],
                                           file_info['rgb_mask'])]
                else:
                    raise IOError("Unsupported BMP bitfields layout")
            else:
                raise IOError("Unsupported BMP bitfields layout")
        elif file_info['compression'] == self.RAW:
            if file_info['bits'] == 32 and header == 22:  # 32-bit .cur offset
                raw_mode, self.mode = "BGRA", "RGBA"
        else:
            raise IOError("Unsupported BMP compression (%d)" %
                          file_info['compression'])
        # ---------------- Once the header is processed, process the palette/LUT
        if self.mode == "P":  # Paletted for 1, 4 and 8 bit images
            # ----------------------------------------------------- 1-bit images
            if not (0 < file_info['colors'] <= 65536):
                raise IOError("Unsupported BMP Palette size (%d)" %
                              file_info['colors'])
            else:
                padding = file_info['palette_padding']
                palette = read(padding * file_info['colors'])
                greyscale = True
                indices = (0, 255) if file_info['colors'] == 2 else list(
                    range(file_info['colors']))
                # ------------------ Check if greyscale and ignore palette if so
                for ind, val in enumerate(indices):
                    rgb = palette[ind * padding:ind * padding + 3]
                    if rgb != o8(val) * 3:
                        greyscale = False
                # -------- If all colors are grey, white or black, ditch palette
                if greyscale:
                    self.mode = "1" if file_info['colors'] == 2 else "L"
                    raw_mode = self.mode
                else:
                    self.mode = "P"
                    self.palette = ImagePalette.raw(
                        "BGRX" if padding == 4 else "BGR", palette)

        # ----------------------------- Finally set the tile data for the plugin
        self.info['compression'] = file_info['compression']
        self.tile = [
            ('raw', (0, 0, file_info['width'], file_info['height']), offset
             or self.fp.tell(),
             (raw_mode,
              ((file_info['width'] * file_info['bits'] + 31) >> 3) & (~3),
              file_info['direction']))
        ]