core, bridge: new imageGeneratePreview helped method to generate a thumbnail

This commit is contained in:
Goffi 2020-03-01 18:48:06 +01:00
commit 3686d7e036
6 changed files with 90 additions and 0 deletions

View file

@ -972,3 +972,14 @@ doc_param_1=width: width of the new image
doc_param_2=height: height of the new image
doc_return=path of the new image with desired size
the image must be deleted once not needed anymore
[imageGeneratePreview]
async=
type=method
category=core
sig_in=ss
sig_out=s
doc=Generate a preview of an image in cache
doc_param_0=image_path: path of the original image
doc_param_1=%(doc_profile_key)s
doc_return=path to the preview in cache

View file

@ -396,6 +396,12 @@ class DbusObject(dbus.service.Object):
def imageCheck(self, arg_0):
return self._callback("imageCheck", str(arg_0))
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
in_signature='ss', out_signature='s',
async_callbacks=('callback', 'errback'))
def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None):
return self._callback("imageGeneratePreview", str(image_path), str(profile_key), callback=callback, errback=errback)
@dbus.service.method(const_INT_PREFIX+const_CORE_SUFFIX,
in_signature='sii', out_signature='s',
async_callbacks=('callback', 'errback'))

View file

@ -135,6 +135,7 @@ class Const(object):
MESS_KEY_ATTACHMENTS = "attachments"
MESS_KEY_ATTACHMENTS_MEDIA_TYPE = "media_type"
MESS_KEY_ATTACHMENTS_PREVIEW = "preview"
# File encryption algorithms
ENC_AES_GCM = "AES-GCM"

View file

@ -20,6 +20,8 @@ from glob import glob
import sys
import os.path
import uuid
import hashlib
from pathlib import Path
import sat
from sat.core.i18n import _, D_, languageSwitch
from sat.core import patches
@ -173,6 +175,7 @@ class SAT(service.Service):
self.bridge.register_method("namespacesGet", self.getNamespaces)
self.bridge.register_method("imageCheck", self._imageCheck)
self.bridge.register_method("imageResize", self._imageResize)
self.bridge.register_method("imageGeneratePreview", self._imageGeneratePreview)
self.memory.initialized.addCallback(lambda __: defer.ensureDeferred(self._postMemoryInit()))
@ -684,6 +687,45 @@ class SAT(service.Service):
d.addCallback(lambda new_image_path: str(new_image_path))
return d
def _imageGeneratePreview(self, path, profile_key):
client = self.getClient(profile_key)
d = defer.ensureDeferred(self.imageGeneratePreview(client, Path(path)))
d.addCallback(lambda preview_path: str(preview_path))
return d
async def imageGeneratePreview(self, client, path):
"""Helper method to generate in cache a preview of an image
@param path(Path): path to the image
@return (Path): path to the generated preview
"""
report = images.checkImage(self, path, max_size=(300, 300))
if not report['too_large']:
# in the unlikely case that image is already smaller than a preview
preview_path = path
else:
# we use hash as id, to re-use potentially existing preview
path_hash = hashlib.sha256(str(path).encode()).hexdigest()
uid = f"{path.stem}_{path_hash}_preview"
filename = f"{uid}{path.suffix.lower()}"
metadata = client.cache.getMetadata(uid=uid)
if metadata is not None:
preview_path = metadata['path']
else:
with client.cache.cacheData(
source='HOST_PREVIEW',
uid=uid,
filename=filename) as cache_f:
preview_path = await images.resizeImage(
path,
new_size=report['recommended_size'],
dest=cache_f
)
return preview_path
# local dirs
def getLocalPath(self, client, dir_name, *extra_path, **kwargs):

View file

@ -489,6 +489,15 @@ class Bridge:
kwargs['error_handler'] = error_handler
return str(self.db_core_iface.imageCheck(arg_0, **kwargs))
def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None):
if callback is None:
error_handler = None
else:
if errback is None:
errback = log.error
error_handler = lambda err:errback(dbus_to_bridge_exception(err))
return str(self.db_core_iface.imageGeneratePreview(image_path, profile_key, timeout=const_TIMEOUT, reply_handler=callback, error_handler=error_handler))
def imageResize(self, image_path, width, height, callback=None, errback=None):
if callback is None:
error_handler = None
@ -1149,6 +1158,14 @@ class AIOBridge(Bridge):
self.db_core_iface.imageCheck(arg_0, timeout=const_TIMEOUT, reply_handler=reply_handler, error_handler=error_handler)
return fut
def imageGeneratePreview(self, image_path, profile_key):
loop = asyncio.get_running_loop()
fut = loop.create_future()
reply_handler = lambda ret=None: loop.call_soon_threadsafe(fut.set_result, ret)
error_handler = lambda err: loop.call_soon_threadsafe(fut.set_exception, dbus_to_bridge_exception(err))
self.db_core_iface.imageGeneratePreview(image_path, profile_key, timeout=const_TIMEOUT, reply_handler=reply_handler, error_handler=error_handler)
return fut
def imageResize(self, image_path, width, height):
loop = asyncio.get_running_loop()
fut = loop.create_future()

View file

@ -383,6 +383,14 @@ class Bridge(object):
errback = self._generic_errback
d.addErrback(errback)
def imageGeneratePreview(self, image_path, profile_key, callback=None, errback=None):
d = self.root.callRemote("imageGeneratePreview", image_path, profile_key)
if callback is not None:
d.addCallback(callback)
if errback is None:
errback = self._generic_errback
d.addErrback(errback)
def imageResize(self, image_path, width, height, callback=None, errback=None):
d = self.root.callRemote("imageResize", image_path, width, height)
if callback is not None:
@ -818,6 +826,11 @@ class AIOBridge(Bridge):
d.addErrback(self._errback)
return d.asFuture(asyncio.get_event_loop())
def imageGeneratePreview(self, image_path, profile_key):
d = self.root.callRemote("imageGeneratePreview", image_path, profile_key)
d.addErrback(self._errback)
return d.asFuture(asyncio.get_event_loop())
def imageResize(self, image_path, width, height):
d = self.root.callRemote("imageResize", image_path, width, height)
d.addErrback(self._errback)