-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlektor_image_resize.py
154 lines (131 loc) · 5.72 KB
/
lektor_image_resize.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# -*- coding: utf-8 -*-
# This Lektor plugin is using ImageMagic (convert)
# to convert images to different pre-configured thumbnails
# as .jpg and .webp.
import shutil
from lektor.build_programs import AttachmentBuildProgram, buildprogram
from lektor.context import get_ctx
from lektor.db import Image
from lektor.imagetools import (compute_dimensions, find_imagemagick,
get_image_info, get_quality)
from lektor.pluginsystem import Plugin
from lektor.reporter import reporter
from lektor.utils import portable_popen
from werkzeug.utils import cached_property
# We override process_image here because Lektor does not support adding extra
# parameters yet, but maybe it will soon, and this can be removed when it does.
def process_image(
ctx,
source_image,
dst_imagename,
whqffdict=None,
extra_params=None,
resize_image=True,
):
"""Build image from source image, optionally compressing and resizing.
"source_image" is the absolute path of the source in the content directory,
"dst_imagename" is the absolute path of the target in the output directory.
"""
reporter.report_debug_info("processing image:", dst_imagename)
if whqffdict is not None:
width=int(whqffdict['width'])
height=int(whqffdict['height'])
quality=int(whqffdict['quality'])
file_format=str(whqffdict['file_format'])
if width is None and height is None:
raise ValueError("Must specify at least one of width or height.")
convert = find_imagemagick(ctx.build_state.config["IMAGEMAGICK_EXECUTABLE"])
cmdline = [convert, source_image, "-auto-orient"]
if quality is None:
quality = get_quality(source_image)
if resize_image:
resize_key = ""
if width is not None:
resize_key += str(width)
if height is not None:
resize_key += "x" + str(height)
cmdline += ["-resize", resize_key]
if file_format == 'webp':
cmdline += ['-define', 'webp:lossless=false']
if extra_params:
cmdline.extend(extra_params)
cmdline += ['-define', 'thread-level=1']
cmdline += ["-quality", str(quality), dst_imagename]
reporter.report_debug_info("imagemagick cmd line", cmdline)
portable_popen(cmdline).wait()
@buildprogram(Image)
class ResizedImageBuildProgram(AttachmentBuildProgram):
"""
Build all images in lektor content at initialisation...
"""
def build_artifact(self, artifact):
ctx = get_ctx()
plugin = ctx.env.plugins["image-resize"]
config = plugin.config
artifact.ensure_dir()
AttachmentBuildProgram.build_artifact(self, artifact)
if not config:
return
source_img = artifact.source_obj.attachment_filename
with open(source_img, "rb") as file:
_, _width, _height = get_image_info(file)
# For every section in the config, we need to generate one image.
for item, conf in config.items():
width = int(conf.get("width", 0))
height = int(conf.get("height", "0"))
filename = artifact.source_obj.url_path
ext_pos = filename.rfind(".")
f_prefix = f"{filename[:ext_pos]}-{item}"
f_suffixes = ['jpg', 'webp']
"""
makeing sure width and height are defined
"""
if width < 1:
if height < 1:
width = int(1280)
height = int(720)
print("WARNING: No size detected for " + str(f_prefix) +
", falling back to 1280x720." +
"Plese define at least width or height in 'configs/image-resize.ini'!")
else:
_, width = compute_dimensions(height, None, _height, _width)
if height < 1:
_, height = compute_dimensions(width, None, _width, _height)
for f_suffix in f_suffixes:
"""
run loop for each file we want to export
"""
whqffdict = {
'width': str(width),
'height': str(height),
'quality': str(89),
'file_format': str(f_prefix),
}
def closure(f_prefix, f_suffix, source_img, whqffdict, resize_image=True,):
# We need this closure, otherwise variables get updated and this
# doesn't work at all.
dst_filename = f"{f_prefix}.{f_suffix}"
@ctx.sub_artifact(artifact_name=dst_filename, sources=[source_img])
def build_thumbnail_artifact(artifact):
artifact.ensure_dir()
if not resize_image and f_suffix != 'webp':
shutil.copy2(source_img, artifact.dst_filename)
else:
process_image(
ctx,
source_img,
artifact.dst_filename,
whqffdict,
extra_params= ['-strip', '-interlace', 'Plane',],
resize_image=resize_image,
)
resize_image = _width > width or _height > height
closure(f_prefix, f_suffix, source_img, whqffdict, bool(resize_image))
class ImageResizePlugin(Plugin):
name = "thumbnail-generator"
description = "Generate JPG and WEBP Images and Thumbnails in predefined sizes."
image_exts = ["jpg", "webp"]
@cached_property
def config(self):
conf = self.get_config()
return {section: conf.section_as_dict(section) for section in conf.sections()}