]
)
fi
+AC_ARG_ENABLE([libexif],
+ [AC_HELP_STRING([--disable-libexif], [disable libexif support. Default is enabled.])],
+ [
+ if test "x${enableval}" = "xyes" ; then
+ _iv_enable_libexif="yes"
+ else
+ _iv_enable_libexif="no"
+ fi
+ ],
+ [_iv_enable_libexif="yes"]
+)
+
+AC_MSG_CHECKING([whether libexif is built])
+AC_MSG_RESULT([${_iv_enable_libexif}])
+
+HAVE_LIBEXIF="no"
+
+if test "x${_iv_enable_libexif}" = "xyes" ; then
+ AC_ETH_CHECK_PKG(LIBEXIF, libexif)
+fi
+
+AM_CONDITIONAL(HAVE_LIBEXIF, test $HAVE_LIBEXIF = yes)
+AC_SUBST(HAVE_LIBEXIF)
AC_SUBST(requirement_ethumb)
AC_SUBST(requirement_ethumb_client)
#include "Ethumb_Plugin.h"
#include "md5.h"
+#ifdef HAVE_LIBEXIF
+ #include <libexif/exif-data.h>
+#endif
+
static int _log_dom = -1;
#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
/* IF CHANGED, UPDATE DOCS in (Ethumb.c, Ethumb_Client.c, python...)!!! */
ethumb->tw = THUMB_SIZE_NORMAL;
ethumb->th = THUMB_SIZE_NORMAL;
+ ethumb->orientation = ETHUMB_THUMB_ORIENT_ORIGINAL;
ethumb->crop_x = 0.5;
ethumb->crop_y = 0.5;
ethumb->quality = 80;
e->format = ETHUMB_THUMB_FDO;
e->aspect = ETHUMB_THUMB_KEEP_ASPECT;
+ e->orientation = ETHUMB_THUMB_ORIENT_ORIGINAL;
_ethumb_frame_free(e->frame);
e->frame = NULL;
eina_stringshare_del(e->thumb_dir);
}
EAPI void
+ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o)
+{
+ EINA_SAFETY_ON_NULL_RETURN(e);
+ EINA_SAFETY_ON_FALSE_RETURN(o == ETHUMB_THUMB_ORIENT_NONE ||
+ o == ETHUMB_THUMB_ROTATE_90_CW ||
+ o == ETHUMB_THUMB_ROTATE_180 ||
+ o == ETHUMB_THUMB_ROTATE_90_CCW ||
+ o == ETHUMB_THUMB_FLIP_HORIZONTAL ||
+ o == ETHUMB_THUMB_FLIP_VERTICAL ||
+ o == ETHUMB_THUMB_FLIP_TRANSPOSE ||
+ o == ETHUMB_THUMB_FLIP_TRANSVERSE ||
+ o == ETHUMB_THUMB_ORIENT_ORIGINAL);
+
+ DBG("ethumb=%p, orientation=%d", e, o);
+ e->orientation = o;
+}
+
+EAPI Ethumb_Thumb_Orientation
+ethumb_thumb_orientation_get(const Ethumb *e)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
+ return e->orientation;
+}
+
+EAPI void
ethumb_thumb_crop_align_set(Ethumb *e, float x, float y)
{
EINA_SAFETY_ON_NULL_RETURN(e);
return EINA_TRUE;
}
+static void
+_ethumb_image_orient(Ethumb *e, int orientation)
+{
+ Evas_Object *img = e->img, *tmp;
+ unsigned int *data, *data2, *to, *from, *p1, *p2, pt;
+ int x, y, w, hw, iw, ih, tw, th;
+ const char *file, *key;
+
+ evas_object_image_size_get(img, &iw, &ih);
+ data = evas_object_image_data_get(img, 1);
+
+ switch (orientation)
+ {
+ case ETHUMB_THUMB_FLIP_HORIZONTAL:
+ for (y = 0; y < ih; y++)
+ {
+ p1 = data + (y * iw);
+ p2 = data + ((y + 1) * iw) - 1;
+ for (x = 0; x < (iw >> 1); x++)
+ {
+ pt = *p1;
+ *p1 = *p2;
+ *p2 = pt;
+ p1++;
+ p2--;
+ }
+ }
+ evas_object_image_data_set(img, data);
+ evas_object_image_data_update_add(img, 0, 0, iw, ih);
+ return;
+ case ETHUMB_THUMB_FLIP_VERTICAL:
+ for (y = 0; y < (ih >> 1); y++)
+ {
+ p1 = data + (y * iw);
+ p2 = data + ((ih - 1 - y) * iw);
+ for (x = 0; x < iw; x++)
+ {
+ pt = *p1;
+ *p1 = *p2;
+ *p2 = pt;
+ p1++;
+ p2++;
+ }
+ }
+ evas_object_image_data_set(img, data);
+ evas_object_image_data_update_add(img, 0, 0, iw, ih);
+ return;
+ case ETHUMB_THUMB_ROTATE_180:
+ hw = iw * ih;
+ x = (hw / 2);
+ p1 = data;
+ p2 = data + hw - 1;
+ for (; --x > 0;)
+ {
+ pt = *p1;
+ *p1 = *p2;
+ *p2 = pt;
+ p1++;
+ p2--;
+ }
+ evas_object_image_data_set(img, data);
+ evas_object_image_data_update_add(img, 0, 0, iw, ih);
+ return;
+ }
+
+ evas_object_image_load_size_get(img, &tw, &th);
+ evas_object_image_file_get(img, &file, &key);
+ tmp = evas_object_image_add(evas_object_evas_get(img));
+ evas_object_image_load_size_set(tmp, tw, th);
+ evas_object_image_file_set(tmp, file, key);
+ data2 = evas_object_image_data_get(tmp, 0);
+
+ w = ih;
+ ih = iw;
+ iw = w;
+ hw = w * ih;
+
+ evas_object_image_size_set(img, iw, ih);
+ data = evas_object_image_data_get(img, 1);
+
+ switch (orientation)
+ {
+ case ETHUMB_THUMB_FLIP_TRANSPOSE:
+ to = data;
+ hw = -hw + 1;
+ break;
+ case ETHUMB_THUMB_FLIP_TRANSVERSE:
+ to = data + hw - 1;
+ w = -w;
+ hw = hw - 1;
+ break;
+ case ETHUMB_THUMB_ROTATE_90_CW:
+ to = data + w - 1;
+ hw = -hw - 1;
+ break;
+ case ETHUMB_THUMB_ROTATE_90_CCW:
+ to = data + hw - w;
+ w = -w;
+ hw = hw + 1;
+ break;
+ default:
+ ERR("unknown orient %d", orientation);
+ evas_object_del(tmp);
+ evas_object_image_data_set(img, data); // give it back
+ return;
+ }
+ from = data2;
+ for (x = iw; --x >= 0;)
+ {
+ for (y = ih; --y >= 0;)
+ {
+ *to = *from;
+ from++;
+ to += w;
+ }
+ to += hw;
+ }
+ evas_object_del(tmp);
+ evas_object_image_data_set(img, data);
+ evas_object_image_data_update_add(img, 0, 0, iw, ih);
+}
+
static int
_ethumb_image_load(Ethumb *e)
{
int error;
Evas_Coord w, h, ww, hh, fx, fy, fw, fh;
Evas_Object *img;
+ int orientation = ETHUMB_THUMB_ORIENT_NONE;
img = e->img;
return 0;
}
+ if (e->orientation == ETHUMB_THUMB_ORIENT_ORIGINAL)
+ {
+#ifdef HAVE_LIBEXIF
+ ExifData *exif = exif_data_new_from_file(e->src_path);
+ ExifEntry *entry = NULL;
+ ExifByteOrder bo;
+ int o;
+
+ if (exif)
+ {
+ entry = exif_data_get_entry(exif, EXIF_TAG_ORIENTATION);
+ if (entry)
+ {
+ bo = exif_data_get_byte_order(exif);
+ o = exif_get_short(entry->data, bo);
+ }
+ exif_data_free(exif);
+ switch (o)
+ {
+ case 2:
+ orientation = ETHUMB_THUMB_FLIP_HORIZONTAL;
+ break;
+ case 3:
+ orientation = ETHUMB_THUMB_ROTATE_180;
+ break;
+ case 4:
+ orientation = ETHUMB_THUMB_FLIP_VERTICAL;
+ break;
+ case 5:
+ orientation = ETHUMB_THUMB_FLIP_TRANSPOSE;
+ break;
+ case 6:
+ orientation = ETHUMB_THUMB_ROTATE_90_CW;
+ break;
+ case 7:
+ orientation = ETHUMB_THUMB_FLIP_TRANSVERSE;
+ break;
+ case 8:
+ orientation = ETHUMB_THUMB_ROTATE_90_CCW;
+ break;
+ }
+ }
+#endif
+ }
+
+ if (orientation != ETHUMB_THUMB_ORIENT_NONE)
+ _ethumb_image_orient(e, orientation);
+
evas_object_image_size_get(img, &w, &h);
if ((w <= 0) || (h <= 0))
return 0;
ETHUMB_THUMB_CROP /**< keep aspect but crop (cut) the largest dimension */
} Ethumb_Thumb_Aspect;
+typedef enum _Ethumb_Thumb_Orientation
+{
+ ETHUMB_THUMB_ORIENT_NONE, /**< keep orientation as pixel data is */
+ ETHUMB_THUMB_ROTATE_90_CW, /**< rotate 90° clockwise */
+ ETHUMB_THUMB_ROTATE_180, /**< rotate 180° */
+ ETHUMB_THUMB_ROTATE_90_CCW, /**< rotate 90° counter-clockwise */
+ ETHUMB_THUMB_FLIP_HORIZONTAL, /**< flip horizontally */
+ ETHUMB_THUMB_FLIP_VERTICAL, /**< flip vertically */
+ ETHUMB_THUMB_FLIP_TRANSPOSE, /**< transpose */
+ ETHUMB_THUMB_FLIP_TRANSVERSE, /**< transverse */
+ ETHUMB_THUMB_ORIENT_ORIGINAL /**< use orientation from metadata (EXIF-only currently) */
+} Ethumb_Thumb_Orientation;
+
EAPI void ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s) EINA_ARG_NONNULL(1);
EAPI void ethumb_thumb_size_set(Ethumb *e, int tw, int th) EINA_ARG_NONNULL(1);
EAPI void ethumb_thumb_size_get(const Ethumb *e, int *tw, int *th) EINA_ARG_NONNULL(1);
-EAPI void ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) EINA_ARG_NONNULL(1);
-EAPI Ethumb_Thumb_Format ethumb_thumb_format_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+EAPI void ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f) EINA_ARG_NONNULL(1);
+EAPI Ethumb_Thumb_Format ethumb_thumb_format_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+
+EAPI void ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) EINA_ARG_NONNULL(1);
+EAPI Ethumb_Thumb_Aspect ethumb_thumb_aspect_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
-EAPI void ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a) EINA_ARG_NONNULL(1);
-EAPI Ethumb_Thumb_Aspect ethumb_thumb_aspect_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
+EAPI void ethumb_thumb_orientation_set(Ethumb *e, Ethumb_Thumb_Orientation o) EINA_ARG_NONNULL(1);
+EAPI Ethumb_Thumb_Orientation ethumb_thumb_orientation_get(const Ethumb *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
EAPI void ethumb_thumb_crop_align_set(Ethumb *e, float x, float y) EINA_ARG_NONNULL(1);
EAPI void ethumb_thumb_crop_align_get(const Ethumb *e, float *x, float *y) EINA_ARG_NONNULL(1);
@EINA_CFLAGS@ @EVAS_CFLAGS@ @ECORE_EVAS_CFLAGS@ @ECORE_FILE_CFLAGS@ @EDJE_CFLAGS@ \
@EFL_ETHUMB_BUILD@
+if HAVE_LIBEXIF
+AM_CPPFLAGS += @LIBEXIF_CFLAGS@
+endif
+
includes_HEADERS = Ethumb.h Ethumb_Plugin.h
includesdir = $(includedir)/ethumb-@VMAJ@
@EDJE_LIBS@ @ECORE_FILE_LIBS@ @ECORE_EVAS_LIBS@ @EVAS_LIBS@
libethumb_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@
+if HAVE_LIBEXIF
+libethumb_la_LIBADD += @LIBEXIF_LIBS@
+endif
if USE_MODULE_ETHUMBD
SUBDIRS += client
DBusMessageIter iter, aiter, diter, viter, vaiter;
Ethumb *e = client->ethumb;
const char *entry;
- dbus_int32_t tw, th, format, aspect, quality, compress;
+ dbus_int32_t tw, th, format, aspect, orientation, quality, compress;
float cx, cy;
double t;
const char *theme_file, *group, *swallow;
dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &aspect);
_close_variant_iter(viter);
+ _open_variant_iter("orientation", "i", viter);
+ orientation = ethumb_thumb_orientation_get(e);
+ dbus_message_iter_append_basic(&viter, DBUS_TYPE_INT32, &orientation);
+ _close_variant_iter(viter);
+
_open_variant_iter("crop", "(dd)", viter);
dbus_message_iter_open_container(&viter, DBUS_TYPE_STRUCT, NULL, &vaiter);
ethumb_thumb_crop_align_get(e, &cx, &cy);
}
/**
+ * Configure orientation to use for future requests.
+ *
+ * Default value is #ETHUMB_THUMB_ORIENT_ORIGINAL: metadata from the file
+ * will be used to orient pixel data.
+ *
+ * @param client the client instance to use. Must @b not be @c
+ * NULL. May be pending connected (can be called before @c
+ * connected_cb)
+ * @param f format identifier to use, either #ETHUMB_THUMB_ORIENT_NONE (0),
+ * #ETHUMB_THUMB_ROTATE_90_CW (1), #ETHUMB_THUMB_ROTATE_180 (2),
+ * #ETHUMB_THUMB_ROTATE_90_CCW (3), #ETHUMB_THUMB_FLIP_HORIZONTAL (4),
+ * #ETHUMB_THUMB_FLIP_VERTICAL (5), #ETHUMB_THUMB_FLIP_TRANSPOSE (6),
+ * #ETHUMB_THUMB_FLIP_TRANSVERSE (7) or #ETHUMB_THUMB_ORIENT_ORIGINAL
+ * (8). Default is ORIGINAL.
+ */
+EAPI void
+ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o)
+{
+ EINA_SAFETY_ON_NULL_RETURN(client);
+
+ client->ethumb_dirty = 1;
+ ethumb_thumb_orientation_set(client->ethumb, o);
+}
+
+/**
+ * Get current orientation in use for requests.
+ *
+ * @param client the client instance to use. Must @b not be @c
+ * NULL. May be pending connected (can be called before @c
+ * connected_cb)
+ *
+ * @return orientation in use for future requests.
+ */
+EAPI Ethumb_Thumb_Orientation
+ethumb_client_orientation_get(const Ethumb_Client *client)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(client, 0);
+
+ return ethumb_thumb_orientation_get(client->ethumb);
+}
+
+/**
* Configure crop alignment in use for future requests.
*
* @param client the client instance to use. Must @b not be @c
/**
* @defgroup Ethumb_Client_Setup Ethumb Client Fine Tune Setup
*
- * How to fine tune thumbnail generation, setting size, aspect,
+ * How to fine tune thumbnail generation, setting size, aspect, orientation,
* frames, quality and so on.
*
* @{
EAPI Ethumb_Thumb_Format ethumb_client_format_get(const Ethumb_Client *client);
EAPI void ethumb_client_aspect_set(Ethumb_Client *client, Ethumb_Thumb_Aspect a);
EAPI Ethumb_Thumb_Aspect ethumb_client_aspect_get(const Ethumb_Client *client);
+EAPI void ethumb_client_orientation_set(Ethumb_Client *client, Ethumb_Thumb_Orientation o);
+EAPI Ethumb_Thumb_Orientation ethumb_client_orientation_get(const Ethumb_Client *client);
EAPI void ethumb_client_crop_align_set(Ethumb_Client *client, float x, float y);
EAPI void ethumb_client_crop_align_get(const Ethumb_Client *client, float *x, float *y);
EAPI void ethumb_client_quality_set(Ethumb_Client *client, int quality);
int tw, th;
int format;
int aspect;
+ int orientation;
float crop_x, crop_y;
int quality;
int compress;