Example #1
0
    def process(self, img):
        matte = False
        self.save_kwargs = {}
        if img.mode == 'RGBA':
            if self.format in RGBA_TRANSPARENCY_FORMATS:
                pass
            elif self.format in PALETTE_TRANSPARENCY_FORMATS:
                # If you're going from a format with alpha transparency to one
                # with palette transparency, transparency values will be
                # snapped: pixels that are more opaque than not will become
                # fully opaque; pixels that are more transparent than not will
                # become fully transparent. This will not produce a good-looking
                # result if your image contains varying levels of opacity; in
                # that case, you'll probably want to use a processor to matte
                # the image on a solid color. The reason we don't matte by
                # default is because not doing so allows processors to treat
                # RGBA-format images as a super-type of P-format images: if you
                # have an RGBA-format image with only a single transparent
                # color, and save it as a GIF, it will retain its transparency.
                # In other words, a P-format image converted to an
                # RGBA-formatted image by a processor and then saved as a
                # P-format image will give the expected results.
                alpha = img.split()[-1]
                mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
                img = img.convert('RGB').convert('P',
                                                 palette=Image.ADAPTIVE,
                                                 colors=255)
                img.paste(255, mask)
                self.save_kwargs['transparency'] = 255
            else:
                # Simply converting an RGBA-format image to an RGB one creates a
                # gross result, so we matte the image on a white background. If
                # that's not what you want, that's fine: use a processor to deal
                # with the transparency however you want. This is simply a
                # sensible default that will always produce something that looks
                # good. Or at least, it will look better than just a straight
                # conversion.
                matte = True
        elif img.mode == 'P':
            if self.format in PALETTE_TRANSPARENCY_FORMATS:
                try:
                    self.save_kwargs['transparency'] = img.info['transparency']
                except KeyError:
                    pass
            elif self.format in RGBA_TRANSPARENCY_FORMATS:
                # Currently PIL doesn't support any RGBA-mode formats that
                # aren't also P-mode formats, so this will never happen.
                img = img.convert('RGBA')
            else:
                matte = True
        else:
            img = img.convert('RGB')

            # GIFs are always going to be in palette mode, so we can do a little
            # optimization. Note that the RGBA sources also use adaptive
            # quantization (above). Images that are already in P mode don't need
            # any quantization because their colors are already limited.
            if self.format == 'GIF':
                img = img.convert('P', palette=Image.ADAPTIVE)

        if matte:
            img = img.convert('RGBA')
            bg = Image.new('RGBA', img.size, (255, 255, 255))
            bg.paste(img, img)
            img = bg.convert('RGB')

        if self.format == 'JPEG':
            self.save_kwargs['optimize'] = True

        return img
Example #2
0
    def process(self, img):
        matte = False
        self.save_kwargs = {}
        self.rgba_ = img.mode == 'RGBA'
        if self.rgba_:
            if self.format in RGBA_TRANSPARENCY_FORMATS:
                pass
            elif self.format in PALETTE_TRANSPARENCY_FORMATS:
                # If you're going from a format with alpha transparency to one
                # with palette transparency, transparency values will be
                # snapped: pixels that are more opaque than not will become
                # fully opaque; pixels that are more transparent than not will
                # become fully transparent. This will not produce a good-looking
                # result if your image contains varying levels of opacity; in
                # that case, you'll probably want to use a processor to matte
                # the image on a solid color. The reason we don't matte by
                # default is because not doing so allows processors to treat
                # RGBA-format images as a super-type of P-format images: if you
                # have an RGBA-format image with only a single transparent
                # color, and save it as a GIF, it will retain its transparency.
                # In other words, a P-format image converted to an
                # RGBA-formatted image by a processor and then saved as a
                # P-format image will give the expected results.
                alpha = img.split()[-1]
                mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
                img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE,
                        colors=255)
                img.paste(255, mask)
                self.save_kwargs['transparency'] = 255
            else:
                # Simply converting an RGBA-format image to an RGB one creates a
                # gross result, so we matte the image on a white background. If
                # that's not what you want, that's fine: use a processor to deal
                # with the transparency however you want. This is simply a
                # sensible default that will always produce something that looks
                # good. Or at least, it will look better than just a straight
                # conversion.
                matte = True
        elif img.mode == 'P':
            if self.format in PALETTE_TRANSPARENCY_FORMATS:
                try:
                    self.save_kwargs['transparency'] = img.info['transparency']
                except KeyError:
                    pass
            elif self.format in RGBA_TRANSPARENCY_FORMATS:
                # Currently PIL doesn't support any RGBA-mode formats that
                # aren't also P-mode formats, so this will never happen.
                img = img.convert('RGBA')
            else:
                matte = True
        else:
            img = img.convert('RGB')

            # GIFs are always going to be in palette mode, so we can do a little
            # optimization. Note that the RGBA sources also use adaptive
            # quantization (above). Images that are already in P mode don't need
            # any quantization because their colors are already limited.
            if self.format == 'GIF':
                img = img.convert('P', palette=Image.ADAPTIVE)

        if matte:
            img = img.convert('RGBA')
            bg = Image.new('RGBA', img.size, (255, 255, 255))
            bg.paste(img, img)
            img = bg.convert('RGB')

        if self.format == 'JPEG':
            self.save_kwargs['optimize'] = True

        return img