From 93d2c010025795923feff53317775910876bfd1d Mon Sep 17 00:00:00 2001 From: Dave Andreoli Date: Sun, 3 Jan 2016 16:48:13 +0100 Subject: [PATCH] Implemented efl.Ethumb.Ethumb class. With docs and an example EthumbClient will follow asap --- doc/ethumb/class-ethumb.rst | 6 + doc/ethumb/ethumb.rst | 50 ++- doc/ethumb/ethumb_client.rst | 7 - doc/ethumb/ethumb_module.rst | 5 - doc/ethumb/module-ethumb.rst | 11 + doc/ethumb/pyethumb.rst | 9 - doc/index.rst | 1 + efl/ethumb/__init__.py | 30 -- efl/ethumb/efl.ethumb.pyx | 605 ++++++++++++++++++++++++++++++++++- examples/ethumb/ethumb.py | 120 +++++++ include/efl.c_ethumb.pxd | 120 +++++++ include/efl.ethumb.pxd | 104 +----- 12 files changed, 900 insertions(+), 168 deletions(-) create mode 100644 doc/ethumb/class-ethumb.rst delete mode 100644 doc/ethumb/ethumb_client.rst delete mode 100644 doc/ethumb/ethumb_module.rst create mode 100644 doc/ethumb/module-ethumb.rst delete mode 100644 doc/ethumb/pyethumb.rst delete mode 100644 efl/ethumb/__init__.py create mode 100755 examples/ethumb/ethumb.py create mode 100644 include/efl.c_ethumb.pxd diff --git a/doc/ethumb/class-ethumb.rst b/doc/ethumb/class-ethumb.rst new file mode 100644 index 0000000..70b69b1 --- /dev/null +++ b/doc/ethumb/class-ethumb.rst @@ -0,0 +1,6 @@ +.. currentmodule:: efl.ethumb + +:class:`efl.ethumb.Ethumb` Class +================================ + +.. autoclass:: efl.ethumb.Ethumb diff --git a/doc/ethumb/ethumb.rst b/doc/ethumb/ethumb.rst index 88a5524..9f33fe0 100644 --- a/doc/ethumb/ethumb.rst +++ b/doc/ethumb/ethumb.rst @@ -1,28 +1,54 @@ +.. _ethumb_main_intro: + + What is Ethumb? ----------------- +=============== +Ethumb will use Evas to generate thumbnail images of given files. The API +allows great customization of the generated files and also helps compling to +FreeDesktop.Org Thumbnail Specification. -How to use the Ethumb object ------------------------------ +(http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html) + +However, thumbnailing can be an expensive process that will impact your +application experience, blocking animations and user interaction during the +generation. Another problem is that one should try to cache the thumbnails in +a place that other applications can benefit from the file. + +:class:`~efl.ethumb_client.EthumbClient` exists to solve this. It will +communicate with a server using standard D-Bus protocol. The server will use +:class:`~efl.ethumb.Ethumb` itself to generate the thumbnail images and cache +them using FreeDesktop.Org standard. It is recommended that most applications +use :class:`~efl.ethumb_client.EthumbClient` instead of +:class:`~efl.ethumb.Ethumb` directly. + +Another difference is that one :class:`~efl.ethumb.Ethumb` instance +can only generate a single thumbnail at a given time, so you must implement +some sort of queue mechanism if you need more than one. Instead +:class:`~efl.ethumb_client.EthumbClient` is a able to receive more than one +request at the same time. + +Recommended reading: + + :class:`~efl.ethumb.Ethumb` to generate thumbnails in the local process. + + :class:`~efl.ethumb_client.EthumbClient` to generate thumbnails using a + server (recommended). API Reference -------------- +============= .. toctree:: - :maxdepth: 4 + :titlesonly: - ethumb_module - pyethumb - ethumb_client + module-ethumb.rst Inheritance diagram -------------------- +=================== -.. inheritance-diagram:: - efl.ethumb - efl.ethumb_client +.. inheritance-diagram:: efl.ethumb :parts: 2 diff --git a/doc/ethumb/ethumb_client.rst b/doc/ethumb/ethumb_client.rst deleted file mode 100644 index ebe7b15..0000000 --- a/doc/ethumb/ethumb_client.rst +++ /dev/null @@ -1,7 +0,0 @@ -.. currentmodule:: efl.ethumb - - -:class:`efl.ethumb_client.Client` Class -======================================== - -.. autoclass:: efl.ethumb_client.Client diff --git a/doc/ethumb/ethumb_module.rst b/doc/ethumb/ethumb_module.rst deleted file mode 100644 index a7189f9..0000000 --- a/doc/ethumb/ethumb_module.rst +++ /dev/null @@ -1,5 +0,0 @@ -:mod:`efl.ethumb` Module -======================== - -.. automodule:: efl.ethumb - :exclude-members: PyEthumb diff --git a/doc/ethumb/module-ethumb.rst b/doc/ethumb/module-ethumb.rst new file mode 100644 index 0000000..2891d11 --- /dev/null +++ b/doc/ethumb/module-ethumb.rst @@ -0,0 +1,11 @@ +diff --git doc/ethumb/ethumb_module.rst doc/ethumb/ethumb_module.rst +deleted file mode 100644 +index a7189f9..0000000 +--- doc/ethumb/ethumb_module.rst ++++ /dev/null +@@ -1,5 +0,0 @@ +-:mod:`efl.ethumb` Module +-======================== +- +-.. automodule:: efl.ethumb +- :exclude-members: PyEthumb diff --git a/doc/ethumb/pyethumb.rst b/doc/ethumb/pyethumb.rst deleted file mode 100644 index 70e2bda..0000000 --- a/doc/ethumb/pyethumb.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. currentmodule:: efl.ethumb - -:class:`efl.ethumb.PyEthumb` Class -================================== - -.. autoclass:: efl.ethumb.PyEthumb - -.. currentmodule:: efl.ethumb - diff --git a/doc/index.rst b/doc/index.rst index ad626cb..206894f 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -62,6 +62,7 @@ Ethumb ====== .. toctree:: ethumb/ethumb.rst + :titlesonly: Edje diff --git a/efl/ethumb/__init__.py b/efl/ethumb/__init__.py deleted file mode 100644 index d8d3e48..0000000 --- a/efl/ethumb/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) 2009 by ProFUSION embedded systems -# -# This file is part of Python-Ethumb. -# -# Python-Ethumb is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# Python-Ethumb is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this Python-Ethumb. If not, see . - -from c_ethumb import init, shutdown, PyEthumb - -ETHUMB_THUMB_NORMAL = 0 -ETHUMB_THUMB_LARGE = 1 - -ETHUMB_THUMB_FDO = 0 -ETHUMB_THUMB_JPEG = 1 -ETHUMB_THUMB_EET = 2 - -ETHUMB_THUMB_KEEP_ASPECT = 0 -ETHUMB_THUMB_IGNORE_ASPECT = 1 -ETHUMB_THUMB_CROP = 2 - diff --git a/efl/ethumb/efl.ethumb.pyx b/efl/ethumb/efl.ethumb.pyx index 573f811..d9f3d5b 100644 --- a/efl/ethumb/efl.ethumb.pyx +++ b/efl/ethumb/efl.ethumb.pyx @@ -15,19 +15,616 @@ # You should have received a copy of the GNU Lesser General Public License # along with this Python-EFL. If not, see . +""" + +:mod:`efl.ethumb` Module +######################## + + +Classes +======= + +.. toctree:: + + class-ethumb.rst + + +Enumerations +============ + +.. _Ethumb_Thumb_FDO_Size: + +Ethumb_Thumb_FDO_Size +--------------------- + +.. data:: ETHUMB_THUMB_NORMAL + + 128x128 as defined by FreeDesktop.Org standard + +.. data:: ETHUMB_THUMB_LARGE + + 256x256 as defined by FreeDesktop.Org standard + + +.. _Ethumb_Thumb_Format: + +Ethumb_Thumb_Format +------------------- + +.. data:: ETHUMB_THUMB_FDO + + PNG as defined by FreeDesktop.Org standard. + +.. data:: ETHUMB_THUMB_JPEG + + JPEGs are often smaller and faster to read/write. + +.. data:: ETHUMB_THUMB_EET + + EFL's own storage system, supports key parameter. + + +.. _Ethumb_Thumb_Aspect: + +Ethumb_Thumb_Aspect +------------------- + +.. data:: ETHUMB_THUMB_KEEP_ASPECT + + Keep original proportion between width and height + +.. data:: ETHUMB_THUMB_IGNORE_ASPECT + + Ignore aspect and foce it to match thumbnail's width and height + +.. data:: ETHUMB_THUMB_CROP + + keep aspect but crop (cut) the largest dimension + + +.. _Ethumb_Thumb_Orientation: + +Ethumb_Thumb_Orientation +------------------------ + +.. data:: ETHUMB_THUMB_ORIENT_NONE + + Keep orientation as pixel data is + +.. data:: ETHUMB_THUMB_ROTATE_90_CW + + Rotate 90° clockwise + +.. data:: ETHUMB_THUMB_ROTATE_180 + + Rotate 180° + +.. data:: ETHUMB_THUMB_ROTATE_90_CCW + + Rotate 90° counter-clockwise + +.. data:: ETHUMB_THUMB_FLIP_HORIZONTAL + + Flip horizontally + +.. data:: ETHUMB_THUMB_FLIP_VERTICAL + + Flip vertically + +.. data:: ETHUMB_THUMB_FLIP_TRANSPOSE + + Transpose + +.. data:: ETHUMB_THUMB_FLIP_TRANSVERSE + + Transverse + +.. data:: ETHUMB_THUMB_ORIENT_ORIGINAL + + Use orientation from metadata (EXIF-only currently) + + +Module level functions +====================== + +""" + +from libc.stdint cimport uintptr_t +from cpython cimport Py_INCREF, Py_DECREF, PyUnicode_AsUTF8String + +from efl.eina cimport Eina_Bool +from efl.utils.conversions cimport _ctouni +from efl.c_ethumb cimport Ethumb as cEthumb, Ethumb_Thumb_FDO_Size, \ + Ethumb_Thumb_Format, Ethumb_Thumb_Aspect, Ethumb_Thumb_Orientation, \ + ethumb_init, ethumb_shutdown, \ + ethumb_new, ethumb_free, ethumb_file_set, ethumb_file_get, ethumb_file_free, \ + ethumb_thumb_path_set, ethumb_thumb_path_get, ethumb_exists, ethumb_generate, \ + ethumb_frame_set, ethumb_frame_get, ethumb_thumb_dir_path_set, \ + ethumb_thumb_dir_path_get, ethumb_thumb_category_set, \ + ethumb_thumb_category_get, ethumb_thumb_fdo_set, ethumb_thumb_size_set, \ + ethumb_thumb_size_get, ethumb_thumb_format_set, ethumb_thumb_format_get, \ + ethumb_thumb_aspect_set, ethumb_thumb_aspect_get, ethumb_thumb_orientation_set, \ + ethumb_thumb_orientation_get, ethumb_thumb_crop_align_set, \ + ethumb_thumb_crop_align_get, ethumb_thumb_quality_set, ethumb_thumb_quality_get, \ + ethumb_thumb_compress_set, ethumb_thumb_compress_get, \ + ethumb_video_start_set, ethumb_video_start_get, ethumb_video_time_set, \ + ethumb_video_time_get, ethumb_video_interval_set, ethumb_video_interval_get, \ + ethumb_video_ntimes_set, ethumb_video_ntimes_get, ethumb_video_fps_set, \ + ethumb_video_fps_get, ethumb_document_page_set, ethumb_document_page_get + import atexit +import traceback + + +cdef void _generate_cb(void *data, cEthumb *e, Eina_Bool success) with gil: + obj = data + (self, func, args, kargs) = obj + try: + func(self, bool(success), *args, **kargs) + except Exception: + traceback.print_exc() + +cdef void _generate_free_cb(void *data) with gil: + obj = data + Py_DECREF(obj) + def init(): + """ Initialize the ethumb library. + + .. note:: You never need to call this function, it is automatically called + on module import. + + """ return ethumb_init() def shutdown(): + """ Shutdown the ethumb library. + + .. note:: You never need to call this function, it is automatically called + at exit. + + """ ethumb_shutdown() -cdef class PyEthumb: - """Ethumb thumbnail generator""" - def __init__(self): - """Ethumb constructor.""" +cdef class Ethumb(object): + """ Ethumb thumbnail generator. + + Use this class to generate thumbnails in the local process. + + .. seealso:: :class:`~efl.ethumb_client.EthumbClient` to generate thumbnails + using a server (recommended). + + """ + def __cinit__(self): + self.obj = NULL + + def __init__(self): + """ Ethumb constructor. """ + assert self.obj == NULL, "Object must be clean" + self.obj = ethumb_new() + if self.obj == NULL: + raise SystemError("Error creating the ethumb object.") + + def __repr__(self): + return ("<%s object at %#x (file='%s', thumb='%s')>") % ( + type(self).__name__, self, + self.file[0], self.thumb_path[0]) + + def delete(self): + """ Delete the underlying C object. + + .. note:: You MUST call this function when you don't need the object + anymore, as it will free all internal used resources. + + """ + ethumb_free(self.obj) + + def file_free(self): + """ Reset the source file information. """ + ethumb_file_free(self.obj) + + def exists(self): + """ Test if the thumbnail already exists. + + :return: ``True`` if thumbnail exists, ``False`` otherwise + + """ + return bool(ethumb_exists(self.obj)) + + def generate(self, func, *args, **kargs): + """ Generate the thumbnail. + + Thumbnail generation is asynchronous and depend on ecore main + loop running. Given function will be called back with + generation status if True is returned by this call. If False + is returned, given function will not be called. + + Existing thumbnails will be overwritten with this call. Check + if they already exist with :func:`exists` before calling. + + :param func: function to call on generation completion, even + if failed or succeeded. Signature is:: + + func(Ethumb, success, *args, **kargs) + + with success being ``True`` for successful generation or + ``False`` on failure. + + :return: ``True`` on success and ``False`` on failure + + :raise TypeError: if **func** is not callable. + + """ + cdef: + tuple func_data + + if not callable(func): + raise TypeError("func must be callable") + + func_data = (self, func, args, kargs) + if ethumb_generate(self.obj, _generate_cb, func_data, + _generate_free_cb) != 0: + Py_INCREF(func_data) + return True + else: + return False + + ## source file properties + property file: + """ The file to thumbnail. + + This is a tuple of 2 strings: ``path`` and ``key``. + + ``path``: Is the file to use. + + ``key``: If path allows storing multiple resources in a single file + (EET or Edje for instance), this is the name used to locate the right + resource inside the file. + + For convenience you can also assign a single string value (``path``), + ignoring the key. + + :type: **str** or (**str**, **str**) + + :raise RuntimeError: on failure setting the property + + """ + def __set__(self, value): + if isinstance(value, tuple): + path, key = value + else: + path, key = value, None + if isinstance(path, unicode): path = PyUnicode_AsUTF8String(path) + if isinstance(key, unicode): key = PyUnicode_AsUTF8String(key) + if ethumb_file_set(self.obj, + path if path is not None else NULL, + key if key is not None else NULL) == 0: + raise RuntimeError("Cannot set file") + + def __get__(self): + cdef: + const char *path + const char *key + ethumb_file_get(self.obj, &path, &key) + return (_ctouni(path), _ctouni(key)) + + property frame: + """ The optional edje file used to generate a frame around the thumbnail + + This can be used to simulate frames (wood, polaroid, etc) in the + generated thumbnails. + + :type: (**str**, **str**, **str**): (theme_file, group_name, swallow_name) + + :raise RuntimeError: on failure setting the property + + """ + def __set__(self, tuple value): + theme, group, swallow = value + if isinstance(theme, unicode): theme = PyUnicode_AsUTF8String(theme) + if isinstance(group, unicode): group = PyUnicode_AsUTF8String(group) + if isinstance(swallow, unicode): swallow = PyUnicode_AsUTF8String(swallow) + if ethumb_frame_set(self.obj, + theme if theme is not None else NULL, + group if group is not None else NULL, + swallow if swallow is not None else NULL) == 0: + raise RuntimeError("Cannot set frame") + + def __get__(self): + cdef: + const char *theme + const char *group + const char *swallow + ethumb_frame_get(self.obj, &theme, &group, &swallow) + return tuple(_ctouni(theme), _ctouni(group), _ctouni(swallow)) + + # destination thumb properties + property thumb_path: + """ The complete path of the generated thumbnail. + + This is a tuple of 2 strings: ``path`` and ``key``. + + ``path``: Is the complete file path. + + ``key``: If path allows storing multiple resources in a single file + (EET or Edje for instance), this is the name used to locate the right + resource inside the file. + + For convenience you can also assign a single string value (``path``), + ignoring the key. + + :type: **str** or (**str**, **str**) + + """ + def __set__(self, value): + if isinstance(value, tuple): + path, key = value + else: + path, key = value, None + if isinstance(path, unicode): path = PyUnicode_AsUTF8String(path) + if isinstance(key, unicode): key = PyUnicode_AsUTF8String(key) + ethumb_thumb_path_set(self.obj, + path if path is not None else NULL, + key if key is not None else NULL) + + def __get__(self): + cdef: + const char *path + const char *key + ethumb_thumb_path_get(self.obj, &path, &key) + return (_ctouni(path), _ctouni(key)) + + property thumb_dir_path: + """ Destination folder for the thumbnails. + + This is the base folder, a category folder is added to this path + as a sub directory. Default is ``~/.thumbnails`` + + :type: **str** + + """ + def __set__(self, path): + if isinstance(path, unicode): path = PyUnicode_AsUTF8String(path) + ethumb_thumb_dir_path_set(self.obj, + path if path is not None else NULL) + + def __get__(self): + cdef const char *path + path = ethumb_thumb_dir_path_get(self.obj) + return _ctouni(path) + + property thumb_category: + """ The thumbnails category + + Category sub directory to store thumbnail. Default is either "normal" + or "large" for FDO compliant thumbnails or + ``WIDTHxHEIGHT-ASPECT[-FRAMED]-FORMAT``. It can be a string or None to + use auto generated names. + + :type: **str** + + """ + def __set__(self, cat): + if isinstance(cat, unicode): cat = PyUnicode_AsUTF8String(cat) + ethumb_thumb_category_set(self.obj, + cat if cat is not None else NULL) + + def __get__(self): + cdef const char *cat + cat = ethumb_thumb_category_get(self.obj) + return _ctouni(cat) + + property thumb_fdo: + """ Set a standard FDO thumbnail size + + This is a preset to provide freedesktop.org (fdo) standard + compliant thumbnails. That is, files are stored as JPEG under + ~/.thumbnails/SIZE, with size being either normal (128x128) or + large (256x256). + + :type: :ref:`Ethumb_Thumb_FDO_Size` **writeonly** + + """ + def __set__(self, Ethumb_Thumb_FDO_Size value): + ethumb_thumb_fdo_set(self.obj, value) + + property thumb_size: + """ The size of thumbnails. + + :type: (int **width**, int **height**) + + """ + def __set__(self, tuple value): + w, h = value + ethumb_thumb_size_set(self.obj, w, h) + + def __get__(self): + cdef: + int w + int h + ethumb_thumb_size_get(self.obj, &w, &h) + return tuple(w, h) + + property thumb_format: + """ The fileformat for the thumbnails. + + Thumbnails are compressed; possible formats are PNG, JPEG and EET. + + :type: :ref:`Ethumb_Thumb_Format` + + """ + def __set__(self, Ethumb_Thumb_Format value): + ethumb_thumb_format_set(self.obj, value) + + def __get__(self): + return ethumb_thumb_format_get(self.obj) + + property thumb_aspect: + """ The aspect ratio policy. + + When the source and thumbnail aspect ratios don't match, this policy + sets how to adapt from the former to the latter: resize keeping source + aspect ratio, resize ignoring it or crop. + + :type: :ref:`Ethumb_Thumb_Aspect` + + """ + def __set__(self, Ethumb_Thumb_Aspect value): + ethumb_thumb_aspect_set(self.obj, value) + + def __get__(self): + return ethumb_thumb_aspect_get(self.obj) + + property thumb_orientation: + """ The thumbnail rotation or flip. + + :type: :ref:`Ethumb_Thumb_Orientation` + + """ + def __set__(self, Ethumb_Thumb_Orientation value): + ethumb_thumb_orientation_set(self.obj, value) + + def __get__(self): + return ethumb_thumb_orientation_get(self.obj) + + property thumb_crop_align: + """ Crop alignment in use. + + :param x: horizontal alignment. 0.0 means left side will be + visible or right side is being lost. 1.0 means right side + will be visible or left side is being lost. 0.5 means just + center is visible, both sides will be lost. Default is 0.5. + :param y: vertical alignment. 0.0 is top visible, 1.0 is + bottom visible, 0.5 is center visible. Default is 0.5 + + :type: (float **x**, float **y**) + + """ + def __set__(self, tuple value): + x, y = value + ethumb_thumb_crop_align_set(self.obj, x, y) + + def __get__(self): + cdef: + float x + float y + ethumb_thumb_crop_align_get(self.obj, &x, &y) + return tuple(x, y) + + property thumb_quality: + """ The thumbnail compression quality. + + Value from 0 to 100, default is 80. The effect depends on the format + being used, PNG will not use it. + + :type: int + + """ + def __set__(self, int value): + ethumb_thumb_quality_set(self.obj, value) + + def __get__(self): + return ethumb_thumb_quality_get(self.obj) + + property thumb_compress: + """ The thumbnail compression rate. + + Value from 0 to 9, default is 9. The effect depends on the format being + used, JPEG will not use it. + + :type: int + + """ + def __set__(self, int value): + ethumb_thumb_compress_set(self.obj, value) + + def __get__(self): + return ethumb_thumb_compress_get(self.obj) + + ## video related + property video_start: + """ The start point for video thumbnails. + + :type: float (from 0.0 to 1.0) + + """ + def __set__(self, float value): + ethumb_video_start_set(self.obj, value) + + def __get__(self): + return ethumb_video_start_get(self.obj) + + property video_time: + """ The video time (duration) in seconds. + + :type: float + + """ + def __set__(self, float value): + ethumb_video_time_set(self.obj, value) + + def __get__(self): + return ethumb_video_time_get(self.obj) + + property video_interval: + """ The video frame interval, in seconds. + + This is useful for animated thumbnail and will define skip time before + going to the next frame. + + .. note:: that video backends might not be able to + precisely skip that amount as it will depend on various + factors, including video encoding. + + :type: float + + """ + def __set__(self, float value): + ethumb_video_interval_set(self.obj, value) + + def __get__(self): + return ethumb_video_interval_get(self.obj) + + property video_ntimes: + """ The number of times the video loops (if applicable). + + :type: int + + """ + def __set__(self, int value): + ethumb_video_ntimes_set(self.obj, value) + + def __get__(self): + return ethumb_video_ntimes_get(self.obj) + + property video_fps: + """ The thumbnail framerate. + + Default to 10. + + :type: int + + """ + def __set__(self, int value): + ethumb_video_fps_set(self.obj, value) + + def __get__(self): + return ethumb_video_fps_get(self.obj) + + ## document + property document_page: + """ The page number to thumbnail in paged documents. + + :type: int + + """ + def __set__(self, int value): + ethumb_document_page_set(self.obj, value) + + def __get__(self): + return ethumb_document_page_get(self.obj) init() atexit.register(shutdown) diff --git a/examples/ethumb/ethumb.py b/examples/ethumb/ethumb.py new file mode 100755 index 0000000..ff71431 --- /dev/null +++ b/examples/ethumb/ethumb.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import os +import sys +import time +import logging + +from efl import ecore +from efl import ethumb + + +script_path = os.path.dirname(os.path.abspath(__file__)) + +TESTS = [ + ("1. Generating a standard FDO thumbnail (default)...", {}), + ("2. Generating a large FDO thumbnail...", { + 'thumb_fdo': ethumb.ETHUMB_THUMB_LARGE, + }), + ("3. Generating a very large JPG thumbnail...", { + 'thumb_format': ethumb.ETHUMB_THUMB_JPEG, + 'thumb_size': (512, 512), + }), + ("4. Generating a cropped thumbnail...", { + 'thumb_aspect': ethumb.ETHUMB_THUMB_CROP, + }), + ("5. Generating a rotated thumbnail...", { + 'thumb_orientation': ethumb.ETHUMB_THUMB_ROTATE_180, + 'thumb_size': (256, 256), + 'thumb_aspect': ethumb.ETHUMB_THUMB_KEEP_ASPECT, + }), + ("6. Generating a poor quality thumbnail in this folder...", { + 'thumb_orientation': ethumb.ETHUMB_THUMB_ORIENT_NONE, + 'thumb_path': os.path.join(script_path, 'big_poor.jpg'), + 'thumb_format': ethumb.ETHUMB_THUMB_JPEG, + 'thumb_size': (512, 512), + 'thumb_quality': 10, + }), +] + + +# parse command line arguments +if len(sys.argv) != 2: + print("Python Ethumb test application.\n\n" \ + "usage: ethumb.py filename\n") + exit(1) +filename = sys.argv[1] +print("Original file: %s\n" % filename) + + +# setup efl logging (you also need to set EINA_LOG_LEVEL=X) +l = logging.getLogger("efl") +h = logging.StreamHandler() +h.setFormatter(logging.Formatter("EFL %(levelname)s %(message)s")) +l.addHandler(h) +l.setLevel(logging.DEBUG) + + +# create a single Ethumb instance +et = ethumb.Ethumb() +in_progress = False +start_time = 0.0 + + + +def generate_cb(et, success): + # thumbnail completed + if success is True: + # print out the result + print(" Completed in %.3f seconds." % (time.time() - start_time)) + print(" Thumb: '%s'\n" % et.thumb_path[0]) + else: + print(" ERROR! aborting.") + ecore.main_loop_quit() + in_progress = False + + +def start_thumb(label, params): + # setup ethumb params + et.file = filename + for name, val in params.items(): + setattr(et, name, val) + + # print test name and keep track of start time + print(label) + global start_time + start_time = time.time() + + # start the thumbnailing process + ret = et.generate(generate_cb) # TODO test args and kargs + if ret is False: + print("Error starting the thumbnailer!") + ecore.main_loop_quit() + else: + in_progress = True + + +def idler_cb(): + # Ethumb cannot generate more than one thumb at the same time + if in_progress: + return ecore.ECORE_CALLBACK_RENEW + + try: + # advance to the next test + label, params = TESTS.pop(0) + start_thumb(label, params) + except IndexError: + # all done, quit. + print("Test Completed!") + ecore.main_loop_quit() + + return ecore.ECORE_CALLBACK_RENEW + + +# start the idler and the main loop +idler = ecore.Idler(idler_cb) +ecore.main_loop_begin() + +# free used resource +et.delete() diff --git a/include/efl.c_ethumb.pxd b/include/efl.c_ethumb.pxd new file mode 100644 index 0000000..e6b853d --- /dev/null +++ b/include/efl.c_ethumb.pxd @@ -0,0 +1,120 @@ +# Copyright (C) 2007-2015 various contributors (see AUTHORS) +# +# This file is part of Python-EFL. +# +# Python-EFL is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 3 of the License, or (at your option) any later version. +# +# Python-EFL is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this Python-EFL. If not, see . + +from efl.eina cimport Eina_Bool, Eina_Free_Cb + + +cdef extern from "Ethumb.h": + + #################################################################### + # Enums + # + ctypedef enum Ethumb_Thumb_Orientation: + pass + + ctypedef enum Ethumb_Thumb_FDO_Size: + pass + + ctypedef enum Ethumb_Thumb_Format: + pass + + ctypedef enum Ethumb_Thumb_Aspect: + pass + + #################################################################### + # Structs + # + ctypedef struct Ethumb + + #################################################################### + # Other typedefs + # + ctypedef void (*Ethumb_Generate_Cb)(void *data, Ethumb *e, Eina_Bool success) + + #################################################################### + # Functions + # + int ethumb_init() + int ethumb_shutdown() + Ethumb * ethumb_new() + void ethumb_free(Ethumb *e) + + Eina_Bool ethumb_frame_set(Ethumb *e, const char *theme_file, const char *group, const char *swallow) + void ethumb_frame_get(Ethumb *e, const char **theme_file, const char **group, const char **swallow) + + void ethumb_thumb_dir_path_set(Ethumb *e, const char *path) + const char * ethumb_thumb_dir_path_get(Ethumb *e) + + void ethumb_thumb_category_set(Ethumb *e, const char *category) + const char * ethumb_thumb_category_get(Ethumb *e) + + void ethumb_thumb_path_set(Ethumb *e, const char *path, const char *key) + void ethumb_thumb_path_get(Ethumb *e, const char **path, const char **key) + void ethumb_thumb_hash(Ethumb *e) + void ethumb_thumb_hash_copy(Ethumb *dst, Ethumb *src) + + + void ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s) + + void ethumb_thumb_size_set(Ethumb *e, int tw, int th) + void ethumb_thumb_size_get(Ethumb *e, int *tw, int *th) + + void ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) + Ethumb_Thumb_Format ethumb_thumb_format_get(Ethumb *e) + + void ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) + Ethumb_Thumb_Aspect ethumb_thumb_aspect_get(Ethumb *e) + + void ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o) + Ethumb_Thumb_Orientation ethumb_thumb_orientation_get(Ethumb *e) + + void ethumb_thumb_crop_align_set(Ethumb *e, float x, float y) + void ethumb_thumb_crop_align_get(Ethumb *e, float *x, float *y) + + void ethumb_thumb_quality_set(Ethumb *e, int quality) + int ethumb_thumb_quality_get(Ethumb *e) + + void ethumb_thumb_compress_set(Ethumb *e, int compress) + int ethumb_thumb_compress_get(Ethumb *e) + + void ethumb_video_start_set(Ethumb *e, float start) + float ethumb_video_start_get(Ethumb *e) + void ethumb_video_time_set(Ethumb *e, float time) + float ethumb_video_time_get(Ethumb *e) + void ethumb_video_interval_set(Ethumb *e, float interval) + float ethumb_video_interval_get(Ethumb *e) + void ethumb_video_ntimes_set(Ethumb *e, unsigned int ntimes) + unsigned int ethumb_video_ntimes_get(Ethumb *e) + void ethumb_video_fps_set(Ethumb *e, unsigned int fps) + unsigned int ethumb_video_fps_get(Ethumb *e) + + void ethumb_document_page_set(Ethumb *e, unsigned int page) + unsigned int ethumb_document_page_get(Ethumb *e) + + Eina_Bool ethumb_file_set(Ethumb *e, const char *path, const char *key) + void ethumb_file_get(Ethumb *e, const char **path, const char **key) + void ethumb_file_free(Ethumb *e) + + Eina_Bool ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, const void *data, Eina_Free_Cb free_data) + Eina_Bool ethumb_exists(Ethumb *e) + + Ethumb * ethumb_dup(Ethumb *e) + Eina_Bool ethumb_cmp(Ethumb *e1, Ethumb *e2) + int ethumb_hash(void *key, int key_length) + int ethumb_key_cmp(void *key1, int key1_length, void *key2, int key2_length) + unsigned int ethumb_length(void *key) + diff --git a/include/efl.ethumb.pxd b/include/efl.ethumb.pxd index 29cf614..b4883d3 100644 --- a/include/efl.ethumb.pxd +++ b/include/efl.ethumb.pxd @@ -15,14 +15,11 @@ # You should have received a copy of the GNU Lesser General Public License # along with this Python-EFL. If not, see . -from efl.eina cimport Eina_Bool, Eina_Free_Cb +from efl.c_ethumb cimport Ethumb as cEthumb cdef extern from "Ethumb.h": - #################################################################### - # Enums - # cpdef enum Ethumb_Thumb_Orientation: ETHUMB_THUMB_ORIENT_NONE ETHUMB_THUMB_ROTATE_90_CW @@ -33,116 +30,21 @@ cdef extern from "Ethumb.h": ETHUMB_THUMB_FLIP_TRANSPOSE ETHUMB_THUMB_FLIP_TRANSVERSE ETHUMB_THUMB_ORIENT_ORIGINAL - ctypedef enum Ethumb_Thumb_Orientation: - pass cpdef enum Ethumb_Thumb_FDO_Size: ETHUMB_THUMB_NORMAL ETHUMB_THUMB_LARGE - ctypedef enum Ethumb_Thumb_FDO_Size: - pass cpdef enum Ethumb_Thumb_Format: ETHUMB_THUMB_FDO ETHUMB_THUMB_JPEG ETHUMB_THUMB_EET - ctypedef enum Ethumb_Thumb_Format: - pass cpdef enum Ethumb_Thumb_Aspect: ETHUMB_THUMB_KEEP_ASPECT ETHUMB_THUMB_IGNORE_ASPECT ETHUMB_THUMB_CROP - ctypedef enum Ethumb_Thumb_Aspect: - pass - - #################################################################### - # Structs - # - cdef struct Ethumb: - int tw - int th - int format - int aspect - - #################################################################### - # Other typedefs - # - ctypedef void (*Ethumb_Generate_Cb)(void *data, Ethumb *e, Eina_Bool success) - - #################################################################### - # Functions - # - int ethumb_init() - void ethumb_shutdown() - Ethumb * ethumb_new() - void ethumb_free(Ethumb *e) - - Eina_Bool ethumb_frame_set(Ethumb *e, const char *theme_file, const char *group, const char *swallow) - void ethumb_frame_get(Ethumb *e, const char **theme_file, const char **group, const char **swallow) - - void ethumb_thumb_dir_path_set(Ethumb *e, const char *path) - const char * ethumb_thumb_dir_path_get(Ethumb *e) - - void ethumb_thumb_category_set(Ethumb *e, const char *category) - const char * ethumb_thumb_category_get(Ethumb *e) - - void ethumb_thumb_path_set(Ethumb *e, const char *path, const char *key) - void ethumb_thumb_path_get(Ethumb *e, const char **path, const char **key) - void ethumb_thumb_hash(Ethumb *e) - void ethumb_thumb_hash_copy(Ethumb *dst, Ethumb *src) - void ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s) - - void ethumb_thumb_size_set(Ethumb *e, int tw, int th) - void ethumb_thumb_size_get(Ethumb *e, int *tw, int *th) - - void ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) - Ethumb_Thumb_Format ethumb_thumb_format_get(Ethumb *e) - - void ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) - Ethumb_Thumb_Aspect ethumb_thumb_aspect_get(Ethumb *e) - - void ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o) - Ethumb_Thumb_Orientation ethumb_thumb_orientation_get(Ethumb *e) - - void ethumb_thumb_crop_align_set(Ethumb *e, float x, float y) - void ethumb_thumb_crop_align_get(Ethumb *e, float *x, float *y) - - void ethumb_thumb_quality_set(Ethumb *e, int quality) - int ethumb_thumb_quality_get(Ethumb *e) - - void ethumb_thumb_compress_set(Ethumb *e, int compress) - int ethumb_thumb_compress_get(Ethumb *e) - - void ethumb_video_start_set(Ethumb *e, float start) - float ethumb_video_start_get(Ethumb *e) - void ethumb_video_time_set(Ethumb *e, float time) - float ethumb_video_time_get(Ethumb *e) - void ethumb_video_interval_set(Ethumb *e, float interval) - float ethumb_video_interval_get(Ethumb *e) - void ethumb_video_ntimes_set(Ethumb *e, unsigned int ntimes) - unsigned int ethumb_video_ntimes_get(Ethumb *e) - void ethumb_video_fps_set(Ethumb *e, unsigned int fps) - unsigned int ethumb_video_fps_get(Ethumb *e) - - void ethumb_document_page_set(Ethumb *e, unsigned int page) - unsigned int ethumb_document_page_get(Ethumb *e) - - Eina_Bool ethumb_file_set(Ethumb *e, const char *path, const char *key) - void ethumb_file_get(Ethumb *e, const char **path, const char **key) - void ethumb_file_free(Ethumb *e) - - Eina_Bool ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, void *data, Eina_Free_Cb free_data) - Eina_Bool ethumb_exists(Ethumb *e) - - Ethumb * ethumb_dup(Ethumb *e) - Eina_Bool ethumb_cmp(Ethumb *e1, Ethumb *e2) - int ethumb_hash(void *key, int key_length) - int ethumb_key_cmp(void *key1, int key1_length, void *key2, int key2_length) - unsigned int ethumb_length(void *key) - - -cdef class PyEthumb: - cdef Ethumb *obj +cdef class Ethumb: + cdef cEthumb *obj