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()
|