Mercurial > libervia-desktop-kivy
comparison cagou/core/image.py @ 460:b5e8e470f7f7
core (image): convert SVG images + better error handling:
- when an SVG image is found, new backend `imageConvert` method is used to convert it to PNG
- by default, 128x128 is used as dest size.
- removed code to handle image without extension in filename, as it is now working with
Kivy.
- if texture is not updated after `texture_update` is called, an error is logged, a
fallback image is used, and `on_error` event is dispatched
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 19 Apr 2020 17:06:57 +0200 |
parents | aa204c813f07 |
children | 3c9ba4a694ef |
comparison
equal
deleted
inserted
replaced
459:72290ebfaa8b | 460:b5e8e470f7f7 |
---|---|
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 17 # You should have received a copy of the GNU Affero General Public License |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | 19 |
20 | 20 |
21 import mimetypes | |
22 from functools import partial | |
23 from kivy.uix import image as kivy_img | |
21 from sat.core import log as logging | 24 from sat.core import log as logging |
25 from sat.tools.common import data_format | |
26 from cagou import G | |
27 | |
22 log = logging.getLogger(__name__) | 28 log = logging.getLogger(__name__) |
23 from kivy.uix import image as kivy_img | |
24 from kivy.core.image import Image as CoreImage | |
25 from kivy.resources import resource_find | |
26 import io | |
27 import PIL | |
28 | 29 |
29 | 30 |
30 class Image(kivy_img.Image): | 31 class Image(kivy_img.Image): |
31 """Image widget which accept source without extension""" | 32 """Image widget which accept source without extension""" |
33 SVG_CONVERT_EXTRA = {'width': 128, 'height': 128} | |
34 | |
35 def __init__(self, **kwargs): | |
36 self.register_event_type('on_error') | |
37 super().__init__(**kwargs) | |
38 | |
39 def _imageConvertCb(self, path): | |
40 self.source = path | |
32 | 41 |
33 def texture_update(self, *largs): | 42 def texture_update(self, *largs): |
34 if not self.source: | 43 if self.source: |
35 self.texture = None | 44 if mimetypes.guess_type(self.source, strict=False)[0] == 'image/svg+xml': |
36 else: | 45 log.debug(f"Converting SVG image at {self.source} to PNG") |
37 filename = resource_find(self.source) | 46 G.host.bridge.imageConvert( |
38 self._loops = 0 | 47 self.source, |
39 if filename is None: | 48 "", |
40 return log.error('Image: Error reading file {filename}'. | 49 data_format.serialise(self.SVG_CONVERT_EXTRA), |
41 format(filename=self.source)) | 50 "", |
42 mipmap = self.mipmap | 51 callback=self._imageConvertCb, |
43 if self._coreimage is not None: | 52 errback=partial( |
44 self._coreimage.unbind(on_texture=self._on_tex_change) | 53 G.host.errback, |
45 try: | 54 message=f"Can't load image at {self.source}: {{msg}}" |
46 self._coreimage = ci = CoreImage(filename, mipmap=mipmap, | 55 ) |
47 anim_delay=self.anim_delay, | 56 ) |
48 keep_data=self.keep_data, | 57 return |
49 nocache=self.nocache) | |
50 except Exception: | |
51 # loading failed probably because of unmanaged extention, | |
52 # we try our luck with with PIL | |
53 try: | |
54 im = PIL.Image.open(filename) | |
55 ext = im.format.lower() | |
56 del im | |
57 # we can't use im.tobytes as it would use the | |
58 # internal decompressed representation from pillow | |
59 # and im.save would need processing to handle format | |
60 data = io.BytesIO(open(filename, "rb").read()) | |
61 cache_filename = "{}.{}".format(filename,ext) # needed for kivy's Image to use cache | |
62 self._coreimage = ci = CoreImage(data, ext=ext, | |
63 filename=cache_filename, mipmap=mipmap, | |
64 anim_delay=self.anim_delay, | |
65 keep_data=self.keep_data, | |
66 nocache=self.nocache) | |
67 except Exception as e: | |
68 log.warning("Can't load image: {}".format(e)) | |
69 self._coreimage = ci = None | |
70 | 58 |
71 if ci: | 59 super().texture_update(*largs) |
72 ci.bind(on_texture=self._on_tex_change) | 60 if self.source and self.texture is None: |
73 self.texture = ci.texture | 61 log.warning( |
62 f"Image {self.source} has not been imported correctly, replacing by " | |
63 f"empty one") | |
64 # FIXME: temporary image, to be replaced by something showing that something | |
65 # went wrong | |
66 self.source = G.host.app.expand( | |
67 "{media}/misc/borders/border_hollow_black.png") | |
68 self.dispatch('on_error', Exception(f"Can't load source {self.source}")) | |
69 | |
70 def on_error(self, err): | |
71 pass | |
74 | 72 |
75 | 73 |
76 class AsyncImage(kivy_img.AsyncImage): | 74 class AsyncImage(kivy_img.AsyncImage): |
77 """AsyncImage which accept file:// schema""" | 75 """AsyncImage which accept file:// schema""" |
78 | 76 |