forked from enlightenment/efl
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:
parent
f1f122bd72
commit
0f4ce94ecf
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -20,6 +20,7 @@ struct _Ethumb
|
|||
int tw, th;
|
||||
int format;
|
||||
int aspect;
|
||||
int orientation;
|
||||
float crop_x, crop_y;
|
||||
int quality;
|
||||
int compress;
|
||||
|
|
Loading…
Reference in New Issue