comparison libervia/backend/tools/image.py @ 4270:0d7bb4df2343

Reformatted code base using black.
author Goffi <goffi@goffi.org>
date Wed, 19 Jun 2024 18:44:57 +0200
parents 4b842c1fb686
children
comparison
equal deleted inserted replaced
4269:64a85ce8be70 4270:0d7bb4df2343
30 log = getLogger(__name__) 30 log = getLogger(__name__)
31 31
32 try: 32 try:
33 import cairosvg 33 import cairosvg
34 except Exception as e: 34 except Exception as e:
35 log.warning(_("SVG support not available, please install cairosvg: {e}").format( 35 log.warning(_("SVG support not available, please install cairosvg: {e}").format(e=e))
36 e=e))
37 cairosvg = None 36 cairosvg = None
38 37
39 38
40 def check(host, path, max_size=None): 39 def check(host, path, max_size=None):
41 """Analyze image and return a report 40 """Analyze image and return a report
53 report = {} 52 report = {}
54 image = Image.open(path) 53 image = Image.open(path)
55 if max_size is None: 54 if max_size is None:
56 max_size = tuple(host.memory.config_get(None, "image_max", (1200, 720))) 55 max_size = tuple(host.memory.config_get(None, "image_max", (1200, 720)))
57 if image.size > max_size: 56 if image.size > max_size:
58 report['too_large'] = True 57 report["too_large"] = True
59 if image.size[0] > max_size[0]: 58 if image.size[0] > max_size[0]:
60 factor = max_size[0] / image.size[0] 59 factor = max_size[0] / image.size[0]
61 if image.size[1] * factor > max_size[1]: 60 if image.size[1] * factor > max_size[1]:
62 factor = max_size[1] / image.size[1] 61 factor = max_size[1] / image.size[1]
63 else: 62 else:
64 factor = max_size[1] / image.size[1] 63 factor = max_size[1] / image.size[1]
65 report['recommended_size'] = [int(image.width*factor), int(image.height*factor)] 64 report["recommended_size"] = [
65 int(image.width * factor),
66 int(image.height * factor),
67 ]
66 else: 68 else:
67 report['too_large'] = False 69 report["too_large"] = False
68 70
69 return report 71 return report
70 72
71 73
72 def _resize_blocking(image_path, new_size, dest, fix_orientation): 74 def _resize_blocking(image_path, new_size, dest, fix_orientation):
77 resized = ImageOps.exif_transpose(resized) 79 resized = ImageOps.exif_transpose(resized)
78 80
79 if dest is None: 81 if dest is None:
80 dest = tempfile.NamedTemporaryFile(suffix=im_path.suffix, delete=False) 82 dest = tempfile.NamedTemporaryFile(suffix=im_path.suffix, delete=False)
81 elif isinstance(dest, Path): 83 elif isinstance(dest, Path):
82 dest = dest.open('wb') 84 dest = dest.open("wb")
83 85
84 with dest as f: 86 with dest as f:
85 resized.save(f, format=im.format) 87 resized.save(f, format=im.format)
86 88
87 return Path(f.name) 89 return Path(f.name)
100 @param fix_orientation: if True, use EXIF data to set orientation 102 @param fix_orientation: if True, use EXIF data to set orientation
101 @return (Path): path of the resized file. 103 @return (Path): path of the resized file.
102 The image at this path should be deleted after use 104 The image at this path should be deleted after use
103 """ 105 """
104 return threads.deferToThread( 106 return threads.deferToThread(
105 _resize_blocking, image_path, new_size, dest, fix_orientation) 107 _resize_blocking, image_path, new_size, dest, fix_orientation
108 )
106 109
107 110
108 def _convert_blocking(image_path, dest, extra): 111 def _convert_blocking(image_path, dest, extra):
109 media_type = mimetypes.guess_type(str(image_path), strict=False)[0] 112 media_type = mimetypes.guess_type(str(image_path), strict=False)[0]
110 113
121 name = None 124 name = None
122 if name: 125 if name:
123 try: 126 try:
124 filepath = Path(name) 127 filepath = Path(name)
125 except TypeError: 128 except TypeError:
126 filepath = Path('noname.png') 129 filepath = Path("noname.png")
127 else: 130 else:
128 filepath = Path('noname.png') 131 filepath = Path("noname.png")
129 132
130 if media_type == "image/svg+xml": 133 if media_type == "image/svg+xml":
131 if cairosvg is None: 134 if cairosvg is None:
132 raise exceptions.MissingModule( 135 raise exceptions.MissingModule(
133 f"Can't convert SVG image at {image_path} due to missing CairoSVG module") 136 f"Can't convert SVG image at {image_path} due to missing CairoSVG module"
134 width, height = extra.get('width'), extra.get('height') 137 )
138 width, height = extra.get("width"), extra.get("height")
135 cairosvg.svg2png( 139 cairosvg.svg2png(
136 url=str(image_path), write_to=dest, 140 url=str(image_path), write_to=dest, output_width=width, output_height=height
137 output_width=width, output_height=height
138 ) 141 )
139 else: 142 else:
140 suffix = filepath.suffix 143 suffix = filepath.suffix
141 if not suffix: 144 if not suffix:
142 raise ValueError( 145 raise ValueError(
143 "A suffix is missing for destination, it is needed to determine file " 146 "A suffix is missing for destination, it is needed to determine file "
144 "format") 147 "format"
148 )
145 if not suffix in Image.EXTENSION: 149 if not suffix in Image.EXTENSION:
146 Image.init() 150 Image.init()
147 try: 151 try:
148 im_format = Image.EXTENSION[suffix] 152 im_format = Image.EXTENSION[suffix]
149 except KeyError: 153 except KeyError:
183 def __fix_orientation_blocking(image_path): 187 def __fix_orientation_blocking(image_path):
184 im = Image.open(image_path) 188 im = Image.open(image_path)
185 im_format = im.format 189 im_format = im.format
186 exif = im.getexif() 190 exif = im.getexif()
187 orientation = exif.get(0x0112) 191 orientation = exif.get(0x0112)
188 if orientation is None or orientation<2: 192 if orientation is None or orientation < 2:
189 # nothing to do 193 # nothing to do
190 return False 194 return False
191 im = ImageOps.exif_transpose(im) 195 im = ImageOps.exif_transpose(im)
192 im.save(image_path, im_format) 196 im.save(image_path, im_format)
193 log.debug(f"image {image_path} orientation has been fixed") 197 log.debug(f"image {image_path} orientation has been fixed")
216 # we first try to guess from file name 220 # we first try to guess from file name
217 media_type = mimetypes.guess_type(source, strict=False)[0] 221 media_type = mimetypes.guess_type(source, strict=False)[0]
218 if media_type is not None: 222 if media_type is not None:
219 return media_type 223 return media_type
220 224
221 # file name is not enough, we try to open it 225 # file name is not enough, we try to open it
222 img = Image.open(source) 226 img = Image.open(source)
223 try: 227 try:
224 return Image.MIME[img.format] 228 return Image.MIME[img.format]
225 except KeyError: 229 except KeyError:
226 return None 230 return None