/
__init__.py
65 lines (52 loc) · 2.03 KB
/
__init__.py
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
63
64
65
import io
from PIL import Image
import pyguetzli
import zopfli
from .options import normalize_options
from .helpers import image_have_alpha
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
if not hasattr(output_file, "write"):
output_file = open(output_file, "ab")
# 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
output_file.seek(0)
output_file.truncate()
output_file.write(output_image_bytes)