ethumb: automagically orient thumbnails based on:

- metadata contained in files (EXIF only currently) - default active;
 - orientation given by the caller against pixel data orientation.
 Code is based on els_icon.

 Next is to add that through dbus.

 Open question: if orientation is specified, do we need to save the thumbnail in a different folder?


SVN revision: 52465
This commit is contained in:
Chidambar Zinnoury 2010-09-19 17:07:35 +00:00
parent f1f122bd72
commit 0f4ce94ecf
7 changed files with 304 additions and 6 deletions

View File

@ -121,6 +121,29 @@ if $USE_MODULE_ETHUMBD ; then
]
)
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)

View File

@ -69,6 +69,10 @@ void *alloca (size_t);
#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__)
@ -224,6 +228,7 @@ ethumb_new(void)
/* 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;
@ -345,6 +350,7 @@ ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s)
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);
@ -412,6 +418,31 @@ ethumb_thumb_aspect_get(const Ethumb *e)
return e->aspect;
}
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)
{
@ -1171,12 +1202,135 @@ ethumb_image_save(Ethumb *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;
@ -1200,6 +1354,54 @@ _ethumb_image_load(Ethumb *e)
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;

View File

@ -119,16 +119,32 @@ typedef enum _Ethumb_Thumb_Aspect
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);

View File

@ -9,6 +9,10 @@ AM_CPPFLAGS = \
@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@
@ -24,6 +28,9 @@ libethumb_la_LIBADD = \
@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

View File

@ -844,7 +844,7 @@ ethumb_client_ethumb_setup(Ethumb_Client *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;
@ -900,6 +900,11 @@ ethumb_client_ethumb_setup(Ethumb_Client *client)
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);
@ -1487,6 +1492,48 @@ ethumb_client_aspect_get(const Ethumb_Client *client)
return ethumb_thumb_aspect_get(client->ethumb);
}
/**
* 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.
*

View File

@ -122,7 +122,7 @@ EAPI void ethumb_client_on_server_die_callback_set(Ethumb_Client *client, Ethumb
/**
* @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.
*
* @{
@ -135,6 +135,8 @@ EAPI void ethumb_client_format_set(Ethumb_Client *client, Ethumb_Thumb_Format f)
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);

View File

@ -20,6 +20,7 @@ struct _Ethumb
int tw, th;
int format;
int aspect;
int orientation;
float crop_x, crop_y;
int quality;
int compress;