Mercurial > libervia-backend
annotate sat/tools/image.py @ 4035:9c76678a39e2
cli (info/disco): Add external services in results:
rel 418
| author | Goffi <goffi@goffi.org> |
|---|---|
| date | Fri, 07 Apr 2023 15:18:05 +0200 |
| parents | 7550ae9cfbac |
| children | 524856bd7b19 |
| 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 |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
26 from sat.core.i18n import _ |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
27 from sat.core import exceptions |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
28 from sat.core.log import getLogger |
|
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: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
35 log.warning(_("SVG support not available, please install cairosvg: {e}").format( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
36 e=e)) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
37 cairosvg = None |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
38 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
39 |
| 3220 | 40 def check(host, path, max_size=None): |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 """Analyze image and return a report |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
42 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
43 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
|
44 the case |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 @param host: SàT instance |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
46 @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
|
47 @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
|
48 None to use value set in config |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 @return dict: report on image, with following keys: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 - too_large: true if image is oversized |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 - 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
|
52 """ |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 report = {} |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 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
|
55 if max_size 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
|
56 max_size = tuple(host.memory.getConfig(None, "image_max", (1200, 720))) |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
57 if image.size > max_size: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
58 report['too_large'] = True |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
59 if image.size[0] > max_size[0]: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
60 factor = max_size[0] / image.size[0] |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
61 if image.size[1] * factor > max_size[1]: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
62 factor = max_size[1] / image.size[1] |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
63 else: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
64 factor = max_size[1] / image.size[1] |
|
3157
8b4354b5c05f
tools (images): fixed type for recommended_size.
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
65 report['recommended_size'] = [int(image.width*factor), int(image.height*factor)] |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
66 else: |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
67 report['too_large'] = False |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
68 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
69 return report |
|
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 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
72 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
|
73 im_path = Path(image_path) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
74 im = Image.open(im_path) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 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
|
76 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
|
77 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
|
78 |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
79 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
|
80 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
|
81 elif isinstance(dest, Path): |
| 3220 | 82 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
|
83 |
|
5c3bf37f2202
tools (images): max_size can now be manually specified in checkImage and dest in resizeImage:
Goffi <goffi@goffi.org>
parents:
3157
diff
changeset
|
84 with dest as f: |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
85 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
|
86 |
|
3066
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
87 return Path(f.name) |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
88 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
90 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
|
91 """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
|
92 |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
93 @param image_path(str, Path): path of the original image |
|
2cc2f65379f7
core: added imageCheck and imageResize methods:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
94 @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
|
95 @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
|
96 - None: use a temporary file |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
97 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
|
98 - 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
|
99 - 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
|
100 @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
|
101 @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
|
102 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
|
103 """ |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
104 return threads.deferToThread( |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
105 _resize_blocking, image_path, new_size, dest, fix_orientation) |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
106 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
107 |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
108 def _convert_blocking(image_path, dest, extra): |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
109 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
|
110 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
111 if dest is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
112 dest = tempfile.NamedTemporaryFile(suffix=".png", delete=False) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
113 filepath = Path(dest.name) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
114 elif isinstance(dest, Path): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
115 filepath = dest |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
116 else: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
117 # we should have a file-like object |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
118 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
119 name = dest.name |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
120 except AttributeError: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
121 name = None |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
122 if name: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
123 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
124 filepath = Path(name) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
125 except TypeError: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
126 filepath = Path('noname.png') |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
127 else: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
128 filepath = Path('noname.png') |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
129 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
130 if media_type == "image/svg+xml": |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
131 if cairosvg is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
132 raise exceptions.MissingModule( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
133 f"Can't convert SVG image at {image_path} due to missing CairoSVG module") |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
134 width, height = extra.get('width'), extra.get('height') |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
135 cairosvg.svg2png( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
136 url=str(image_path), write_to=dest, |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
137 output_width=width, output_height=height |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
138 ) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
139 else: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
140 suffix = filepath.suffix |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
141 if not suffix: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
142 raise ValueError( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
143 "A suffix is missing for destination, it is needed to determine file " |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
144 "format") |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
145 if not suffix in Image.EXTENSION: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
146 Image.init() |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
147 try: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
148 im_format = Image.EXTENSION[suffix] |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
149 except KeyError: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
150 raise ValueError( |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
151 "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
|
152 ) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
153 im = Image.open(image_path) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
154 im.save(dest, format=im_format) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
155 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
156 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
|
157 return filepath |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
158 |
|
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 def convert(image_path, dest=None, extra=None): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
161 """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
|
162 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
163 @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
|
164 @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
|
165 - None: use a temporary file |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
166 - Path: path to the file to create/overwrite |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
167 - 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
|
168 @param extra(None, dict): conversion options |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
169 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
|
170 - width: destination width |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
171 - height: destination height |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
172 @return (Path): path of the converted file. |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
173 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
|
174 """ |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
175 image_path = Path(image_path) |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
176 if not image_path.is_file(): |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
177 raise ValueError(f"There is no file at {image_path}!") |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
178 if extra is None: |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
179 extra = {} |
|
3332
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
180 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
|
181 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
182 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
183 def __fix_orientation_blocking(image_path): |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
184 im = Image.open(image_path) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
185 im_format = im.format |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
186 exif = im.getexif() |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
187 orientation = exif.get(0x0112) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
188 if orientation is None or orientation<2: |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
189 # nothing to do |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
190 return False |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
191 im = ImageOps.exif_transpose(im) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
192 im.save(image_path, im_format) |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
193 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
|
194 return True |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
195 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
196 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
197 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
|
198 """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
|
199 |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
200 @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
|
201 @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
|
202 """ |
|
1512cbd6c4ac
tools (image): fix_orientation on resize + `fix_orientation` method:
Goffi <goffi@goffi.org>
parents:
3259
diff
changeset
|
203 return threads.deferToThread(__fix_orientation_blocking, image_path) |
|
3259
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
204 |
|
f300d78f08f3
core: image convertion + SVG support:
Goffi <goffi@goffi.org>
parents:
3252
diff
changeset
|
205 |
|
3252
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
206 def guess_type(source): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
207 """Guess image media type |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
208 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
209 @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
|
210 @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
|
211 """ |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
212 if isinstance(source, str): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
213 source = Path(source) |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
214 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
215 if isinstance(source, Path): |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
216 # 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
|
217 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
|
218 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
|
219 return media_type |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
220 |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
221 # file name is not enough, we try to open it |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
222 img = Image.open(source) |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
223 try: |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
224 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
|
225 except KeyError: |
|
54934ee3f69c
tools (image): added a guess_type method to guess media type:
Goffi <goffi@goffi.org>
parents:
3220
diff
changeset
|
226 return None |
