Exemple #1
0
    def test_use_zopfli(self):
        png = zopfli.ZopfliPNG()
        self.assertTrue(png.use_zopfli)

        png.use_zopfli = False
        self.assertFalse(png.use_zopfli)

        png = zopfli.ZopfliPNG(use_zopfli=False)
        self.assertFalse(png.use_zopfli)

        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().use_zopfli
Exemple #2
0
    def test_lossy_8bit(self):
        png = zopfli.ZopfliPNG()
        self.assertFalse(png.lossy_8bit)

        png.lossy_8bit = True
        self.assertTrue(png.lossy_8bit)

        png = zopfli.ZopfliPNG(lossy_8bit=True)
        self.assertTrue(png.lossy_8bit)

        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().lossy_8bit
Exemple #3
0
    def test_verbose(self):
        png = zopfli.ZopfliPNG()
        self.assertFalse(png.verbose)

        png.verbose = True
        self.assertTrue(png.verbose)

        png = zopfli.ZopfliPNG(verbose=True)
        self.assertTrue(png.verbose)

        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().verbose
Exemple #4
0
    def test_iterations_large(self):
        png = zopfli.ZopfliPNG()
        self.assertEqual(png.iterations_large, 5)

        png.iterations_large *= 2
        self.assertEqual(png.iterations_large, 10)

        png = zopfli.ZopfliPNG(iterations_large=10)
        self.assertEqual(png.iterations_large, 10)

        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG(iterations_large=None)
        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG().iterations_large = None
        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().iterations_large
Exemple #5
0
    def test_iterations(self):
        png = zopfli.ZopfliPNG()
        self.assertEqual(png.iterations, 15)

        png.iterations *= 2
        self.assertEqual(png.iterations, 30)

        png = zopfli.ZopfliPNG(iterations=30)
        self.assertEqual(png.iterations, 30)

        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG(iterations=None)
        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG().iterations = None
        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().iterations
Exemple #6
0
    def test_optimize(self):
        png = zopfli.ZopfliPNG()
        self.assertGreater(len(black_png), len(png.optimize(black_png)))

        with self.assertRaises(TypeError):
            png.optimize(None)
        with self.assertRaises(ValueError):
            png.optimize(b'')
Exemple #7
0
    def test_filter_strategies(self):
        png = zopfli.ZopfliPNG()
        self.assertEqual(png.filter_strategies, '')
        self.assertTrue(png.auto_filter_strategy)

        png.filter_strategies = '01234mepb'
        self.assertEqual(png.filter_strategies, '01234mepb')
        self.assertFalse(png.auto_filter_strategy)

        with self.assertRaises(ValueError):
            png.filter_strategies = '.'
        self.assertEqual(png.filter_strategies, '')
        self.assertTrue(png.auto_filter_strategy)

        png = zopfli.ZopfliPNG(filter_strategies='01234mepb')
        self.assertEqual(png.filter_strategies, '01234mepb')
        self.assertFalse(png.auto_filter_strategy)

        png.auto_filter_strategy = True
        self.assertEqual(png.filter_strategies, '')
        self.assertTrue(png.auto_filter_strategy)

        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG(filter_strategies=None)
        with self.assertRaises(ValueError):
            zopfli.ZopfliPNG(filter_strategies=u'\u00B7')
        with self.assertRaises(ValueError):
            zopfli.ZopfliPNG(filter_strategies='z')
        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().filter_strategies

        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().auto_filter_strategy
Exemple #8
0
def optimize(input_file, output_file, options={}, verbose=False, quiet=False):
    options = normalize_options(options)

    image = Image.open(input_file)

    if options["output_format"] == "orig" and image.format not in (
            "JPEG", "PNG"):  # noqa
        raise ValueError(
            "The input image must be a JPEG or a PNG when setting 'output_format' to 'orig'"
        )  # noqa

    # resize
    if options["resize"] != "orig":
        image.thumbnail(options["resize"], Image.LANCZOS)

    # output format
    output_format = None

    if options["output_format"] == "orig":
        output_format = image.format.lower()
    elif options["output_format"] in ("jpeg", "png"):
        output_format = options["output_format"]
    else:  # auto
        if image_have_alpha(image, options["opacity_threshold"]):
            output_format = "png"
        else:
            # XXX Maybe we should try to encode in both format
            # and choose the smaller output?
            output_format = "jpeg"

    # convert / optimize
    output_image_bytes = None
    if output_format == "jpeg":
        output_image_bytes = pyguetzli.process_pil_image(
            image, int(options["jpeg_quality"] * 100))
    else:
        pass
        image_io = io.BytesIO()
        image.save(image_io, format="PNG", optimize=False)
        image_io.seek(0)
        image_bytes = image_io.read()

        # Optimize using zopflipng
        zopflipng = zopfli.ZopfliPNG()
        zopflipng.lossy_8bit = True
        zopflipng.lossy_transparent = True
        zopflipng.filter_strategies = "01234mepb"
        zopflipng.iterations = 20
        zopflipng.iterations_large = 7
        output_image_bytes = zopflipng.optimize(image_bytes)

    # write to output_file
    if not hasattr(output_file, "write"):
        output_file = open(output_file, "wb")

    output_file.write(output_image_bytes)
Exemple #9
0
    def test_keep_chunks(self):
        png = zopfli.ZopfliPNG()
        self.assertEqual(png.keep_chunks, ())

        png.keep_chunks = ['tEXt', 'zTXt', 'iTXt']
        self.assertEqual(png.keep_chunks, ('tEXt', 'zTXt', 'iTXt'))

        png = zopfli.ZopfliPNG(keep_chunks=['tEXt', 'zTXt', 'iTXt'])
        self.assertEqual(png.keep_chunks, ('tEXt', 'zTXt', 'iTXt'))

        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG(keep_chunks=None)
        with self.assertRaises(TypeError):
            zopfli.ZopfliPNG(keep_chunks=[None])
        with self.assertRaises(ValueError):
            zopfli.ZopfliPNG(keep_chunks=[u'\u00B7'])
        with self.assertRaises(TypeError):
            del zopfli.ZopfliPNG().keep_chunks
Exemple #10
0
    def _image_to_asset(self, image: PIL.Image.Image,
                        mime_type: Union[MimeType, str]) -> Asset:
        """
        Converts an PIL image to a MADAM asset. The conversion can also include
        a change in file type.

        :param image: PIL image
        :type image: PIL.Image.Image
        :param mime_type: MIME type of the target asset
        :type mime_type: MimeType or str
        :return: MADAM asset with the specified MIME type
        :rtype: Asset
        """
        mime_type = MimeType(mime_type)

        pil_format = PillowProcessor.__mime_type_to_pillow_type[mime_type]
        pil_options = dict(PillowProcessor.__format_defaults.get(
            mime_type, {}))
        format_config = dict(self.config.get(mime_type.type, {}))
        format_config.update(self.config.get(str(mime_type), {}))

        image_buffer = io.BytesIO()

        if mime_type == MimeType('image/png') and image.mode != 'P':
            use_zopfli = format_config.get('zopfli', False)
            if use_zopfli:
                import zopfli
                zopfli_png = zopfli.ZopfliPNG()
                # Convert 16-bit per channel images to 8-bit per channel
                zopfli_png.lossy_8bit = False
                # Allow altering hidden colors of fully transparent pixels
                zopfli_png.lossy_transparent = True
                # Use all available optimization strategies
                zopfli_png.filter_strategies = format_config.get(
                    'zopfli_strategies', '0me')

                pil_options.pop('optimize', False)
                essence = io.BytesIO()
                image.save(essence, 'PNG', optimize=False, **pil_options)
                essence.seek(0)
                optimized_data = zopfli_png.optimize(essence.read())
                image_buffer.write(optimized_data)
            else:
                image.save(image_buffer, pil_format, **pil_options)
        elif mime_type == MimeType('image/jpeg'):
            pil_options['progressive'] = int(
                format_config.get('progressive', pil_options['progressive']))
            pil_options['quality'] = int(
                format_config.get('quality', pil_options['quality']))
            image.save(image_buffer, pil_format, **pil_options)
        elif mime_type == MimeType('image/tiff') and image.mode == 'P':
            pil_options.pop('compression', '')
            image.save(image_buffer, pil_format, **pil_options)
        elif mime_type == MimeType('image/webp'):
            pil_options['method'] = int(
                format_config.get('method', pil_options['method']))
            pil_options['quality'] = int(
                format_config.get('quality', pil_options['quality']))
            image.save(image_buffer, pil_format, **pil_options)
        else:
            image.save(image_buffer, pil_format, **pil_options)

        image_buffer.seek(0)

        asset = self.read(image_buffer)
        return asset