Mercurial > libervia-backend
annotate libervia/backend/tools/image.py @ 4348:35d41de5b2aa @
doc (component): document use of Gateway Relayed Encryption:
fix 455
| author | Goffi <goffi@goffi.org> |
|---|---|
| date | Mon, 13 Jan 2025 01:23:22 +0100 |
| parents | 0d7bb4df2343 |
| children |
| rev | line source |
|---|---|
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
| 3137 | 2 |
|
3480
7550ae9cfbac
Renamed the project from "Salut à Toi" to "Libervia":
Goffi <goffi@goffi.org>
parents:
3479
diff
changeset
|
3 # Libervia: an XMPP client |
| 3479 | 4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
5 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
6 # This program is free software: you can redistribute it and/or modify |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
7 # it under the terms of the GNU Affero General Public License as published by |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
8 # the Free Software Foundation, either version 3 of the License, or |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
9 # (at your option) any later version. |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
10 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
11 # This program is distributed in the hope that it will be useful, |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
14 # GNU Affero General Public License for more details. |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
15 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
16 # You should have received a copy of the GNU Affero General Public License |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
18 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
19 """Methods to manipulate images""" |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
20 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
21 import tempfile |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
22 import mimetypes |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
23 from PIL import Image, ImageOps |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
24 from pathlib import Path |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
25 from twisted.internet import threads |
|
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
26 from libervia.backend.core.i18n import _ |
|
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
27 from libervia.backend.core import exceptions |
|
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
4037
diff
changeset
|
28 from libervia.backend.core.log import getLogger |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
29 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
30 log = getLogger(__name__) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
31 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
32 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
33 import cairosvg |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
34 except Exception as e: |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
35 log.warning(_("SVG support not available, please install cairosvg: {e}").format(e=e)) |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
36 cairosvg = None |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
37 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
38 |
| 3220 | 39 def check(host, path, max_size=None): |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
40 """Analyze image and return a report |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
42 report will indicate if image is too large, and the recommended new size if this is |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
43 the case |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
44 @param host: SàT instance |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 @param path(str, pathlib.Path): image to open |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
46 @param max_size(tuple[int, int]): maximum accepted size of image |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
47 None to use value set in config |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
48 @return dict: report on image, with following keys: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 - too_large: true if image is oversized |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 - recommended_size: if too_large is True, recommended size to use |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 """ |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 report = {} |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 image = Image.open(path) |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
54 if max_size is None: |
|
4037
524856bd7b19
massive refactoring to switch from camelCase to snake_case:
Goffi <goffi@goffi.org>
parents:
3480
diff
changeset
|
55 max_size = tuple(host.memory.config_get(None, "image_max", (1200, 720))) |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
56 if image.size > max_size: |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
57 report["too_large"] = True |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
58 if image.size[0] > max_size[0]: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
59 factor = max_size[0] / image.size[0] |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
60 if image.size[1] * factor > max_size[1]: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
61 factor = max_size[1] / image.size[1] |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
62 else: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
63 factor = max_size[1] / image.size[1] |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
64 report["recommended_size"] = [ |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
65 int(image.width * factor), |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
66 int(image.height * factor), |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
67 ] |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
68 else: |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
69 report["too_large"] = False |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
70 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
71 return report |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
72 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
73 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
74 def _resize_blocking(image_path, new_size, dest, fix_orientation): |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 im_path = Path(image_path) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
76 im = Image.open(im_path) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
77 resized = im.resize(new_size, Image.LANCZOS) |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
78 if fix_orientation: |
|
3477
9498f32ba6f7
tools (image): fix bad method name used when `fix_orientation` is set in `resize`
Goffi <goffi@goffi.org>
parents:
3332
diff
changeset
|
79 resized = ImageOps.exif_transpose(resized) |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
80 |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
81 if dest is None: |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
82 dest = tempfile.NamedTemporaryFile(suffix=im_path.suffix, delete=False) |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
83 elif isinstance(dest, Path): |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
84 dest = dest.open("wb") |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
85 |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
86 with dest as f: |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
87 resized.save(f, format=im.format) |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
88 |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 return Path(f.name) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
90 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
91 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
92 def resize(image_path, new_size, dest=None, fix_orientation=True): |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
93 """Resize an image to a new file, and return its path |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
94 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
95 @param image_path(str, Path): path of the original image |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
96 @param new_size(tuple[int, int]): size to use for new image |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
97 @param dest(None, Path, file): where the resized image must be stored, can be: |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
98 - None: use a temporary file |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
99 file will be converted to PNG |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
100 - Path: path to the file to create/overwrite |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
101 - file: a file object which must be opened for writing in binary mode |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
102 @param fix_orientation: if True, use EXIF data to set orientation |
|
3200
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
103 @return (Path): path of the resized file. |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
104 The image at this path should be deleted after use |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
105 """ |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
106 return threads.deferToThread( |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
107 _resize_blocking, image_path, new_size, dest, fix_orientation |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
108 ) |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
109 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
110 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
111 def _convert_blocking(image_path, dest, extra): |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
112 media_type = mimetypes.guess_type(str(image_path), strict=False)[0] |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
113 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
114 if dest is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
115 dest = tempfile.NamedTemporaryFile(suffix=".png", delete=False) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
116 filepath = Path(dest.name) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
117 elif isinstance(dest, Path): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
118 filepath = dest |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
119 else: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
120 # we should have a file-like object |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
121 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
122 name = dest.name |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
123 except AttributeError: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
124 name = None |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
125 if name: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
126 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
127 filepath = Path(name) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
128 except TypeError: |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
129 filepath = Path("noname.png") |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
130 else: |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
131 filepath = Path("noname.png") |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
132 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
133 if media_type == "image/svg+xml": |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
134 if cairosvg is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
135 raise exceptions.MissingModule( |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
136 f"Can't convert SVG image at {image_path} due to missing CairoSVG module" |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
137 ) |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
138 width, height = extra.get("width"), extra.get("height") |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
139 cairosvg.svg2png( |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
140 url=str(image_path), write_to=dest, output_width=width, output_height=height |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
141 ) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
142 else: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
143 suffix = filepath.suffix |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
144 if not suffix: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
145 raise ValueError( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
146 "A suffix is missing for destination, it is needed to determine file " |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
147 "format" |
|
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
148 ) |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
149 if not suffix in Image.EXTENSION: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
150 Image.init() |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
151 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
152 im_format = Image.EXTENSION[suffix] |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
153 except KeyError: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
154 raise ValueError( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
155 "Dest image format can't be determined, {suffix!r} suffix is unknown" |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
156 ) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
157 im = Image.open(image_path) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
158 im.save(dest, format=im_format) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
159 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
160 log.debug(f"image {image_path} has been converted to {filepath}") |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
161 return filepath |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
162 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
163 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
164 def convert(image_path, dest=None, extra=None): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
165 """Convert an image to a new file, and return its path |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
166 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
167 @param image_path(str, Path): path of the image to convert |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
168 @param dest(None, Path, file): where the converted image must be stored, can be: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
169 - None: use a temporary file |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
170 - Path: path to the file to create/overwrite |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
171 - file: a file object which must be opened for writing in binary mode |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
172 @param extra(None, dict): conversion options |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
173 if image_path link to a SVG file, following options can be used: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
174 - width: destination width |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
175 - height: destination height |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
176 @return (Path): path of the converted file. |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
177 a generic name is used if dest is an unnamed file like object |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
178 """ |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
179 image_path = Path(image_path) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
180 if not image_path.is_file(): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
181 raise ValueError(f"There is no file at {image_path}!") |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
182 if extra is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
183 extra = {} |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
184 return threads.deferToThread(_convert_blocking, image_path, dest, extra) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
185 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
186 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
187 def __fix_orientation_blocking(image_path): |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
188 im = Image.open(image_path) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
189 im_format = im.format |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
190 exif = im.getexif() |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
191 orientation = exif.get(0x0112) |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
192 if orientation is None or orientation < 2: |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
193 # nothing to do |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
194 return False |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
195 im = ImageOps.exif_transpose(im) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
196 im.save(image_path, im_format) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
197 log.debug(f"image {image_path} orientation has been fixed") |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
198 return True |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
199 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
200 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
201 def fix_orientation(image_path: Path) -> bool: |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
202 """Apply orientation found in EXIF data if any |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
203 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
204 @param image_path: image location, image will be modified in place |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
205 @return True if image has been modified |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
206 """ |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
207 return threads.deferToThread(__fix_orientation_blocking, image_path) |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
208 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
209 |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
210 def guess_type(source): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
211 """Guess image media type |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
212 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
213 @param source(str, Path, file): image to guess type |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
214 @return (str, None): media type, or None if we can't guess |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
215 """ |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
216 if isinstance(source, str): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
217 source = Path(source) |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
218 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
219 if isinstance(source, Path): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
220 # we first try to guess from file name |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
221 media_type = mimetypes.guess_type(source, strict=False)[0] |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
222 if media_type is not None: |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
223 return media_type |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
224 |
|
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
225 # file name is not enough, we try to open it |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
226 img = Image.open(source) |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
227 try: |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
228 return Image.MIME[img.format] |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
229 except KeyError: |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
230 return None |
