summaryrefslogtreecommitdiffstats
path: root/share/extensions/raster_output_png.py
blob: b70baa0e844576be8548ec8d81255f7eeb97c840 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/usr/bin/env python
"""
Optimise PNG file using optipng
"""

import os
import inkex
from inkex.extensions import TempDirMixin
from inkex.command import ProgramRunError, call


class PngOutput(TempDirMixin, inkex.RasterOutputExtension):
    def add_arguments(self, pars):
        pars.add_argument("--tab")
        # Lossless options
        pars.add_argument("--interlace", type=inkex.Boolean, default=False)
        pars.add_argument("--level", type=int, default=0)
        # Lossy options
        pars.add_argument("--bitdepth", type=inkex.Boolean, default=False)
        pars.add_argument("--color", type=inkex.Boolean, default=False)
        pars.add_argument("--palette", type=inkex.Boolean, default=False)

    def load(self, stream):
        """Load the PNG file (prepare it for optipng)"""
        self.png_file = os.path.join(self.tempdir, "input.png")
        with open(self.png_file, "wb") as fhl:
            fhl.write(stream.read())

    def save(self, stream):
        """Pass the PNG file to optipng with the options"""
        options = {
            "o": self.options.level,
            "i": int(self.options.interlace),
            "nb": not self.options.bitdepth,
            "nc": not self.options.color,
            "np": not self.options.palette,
        }
        try:
            call("optipng", self.png_file, oldie=True, clobber=True, **options)
        except ProgramRunError as err:
            if "IDAT recoding is necessary" in err.stderr.decode("utf-8"):
                raise inkex.AbortExtension(
                    _(
                        "The optipng command failed, possibly due to a mismatch of the"
                        "interlacing and compression level options. Please try to disable "
                        '"Interlaced" or set "Level" to 1 or higher.'
                    )
                )
            else:
                raise inkex.AbortExtension(
                    _("The optipng command failed with the following message:")
                    + "\n"
                    + err.stderr.decode("utf-8")
                )

        if os.path.isfile(self.png_file):
            with open(self.png_file, "rb") as fhl:
                stream.write(fhl.read())


if __name__ == "__main__":
    PngOutput().run()