4 * Copyright (C) 2009 by ProFUSION embedded systems
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or (at your
9 * option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * @author Rafael Antognolli <antognolli@profusion.mobi>
29 #elif defined __GNUC__
30 # define alloca __builtin_alloca
32 # define alloca __alloca
33 #elif defined _MSC_VER
35 # define alloca _alloca
41 void *alloca (size_t);
50 #include <sys/types.h>
57 # define PATH_MAX 4096
61 #include <eina_safety_checks.h>
64 #include <Ecore_Evas.h>
65 #include <Ecore_File.h>
69 #include "ethumb_private.h"
70 #include "Ethumb_Plugin.h"
73 static int _log_dom = -1;
74 #define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)
75 #define INF(...) EINA_LOG_DOM_INFO(_log_dom, __VA_ARGS__)
76 #define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
77 #define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
79 static int initcount = 0;
80 static const char *_home_thumb_dir = NULL;
81 static const char *_thumb_category_normal = NULL;
82 static const char *_thumb_category_large = NULL;
84 static const int THUMB_SIZE_NORMAL = 128;
85 static const int THUMB_SIZE_LARGE = 256;
87 static Eina_Hash *_plugins_ext = NULL;
88 static Eina_Array *_plugins = NULL;
91 _ethumb_plugin_list_cb(Eina_Module *m, void *data __UNUSED__)
95 Ethumb_Plugin *plugin;
96 Ethumb_Plugin *(*plugin_get)(void);
98 file = eina_module_file_get(m);
99 if (!eina_module_load(m))
101 ERR("could not load module \"%s\": %s",
102 file, eina_error_msg_get(eina_error_get()));
106 plugin_get = eina_module_symbol_get(m, "ethumb_plugin_get");
109 ERR("could not find ethumb_plugin_get() in module \"%s\": %s",
110 file, eina_error_msg_get(eina_error_get()));
111 eina_module_unload(m);
115 plugin = plugin_get();
118 ERR("plugin \"%s\" failed to init.", file);
119 eina_module_unload(m);
123 DBG("loaded plugin \"%s\" (%p) with extensions:", file, plugin);
124 for (ext = plugin->extensions; *ext; ext++)
126 DBG(" extension \"%s\"", *ext);
127 eina_hash_add(_plugins_ext, *ext, plugin);
134 _ethumb_plugins_load(void)
136 _plugins_ext = eina_hash_string_small_new(NULL);
137 EINA_SAFETY_ON_NULL_RETURN(_plugins_ext);
139 _plugins = eina_module_list_get(_plugins, PLUGINSDIR, 1,
140 &_ethumb_plugin_list_cb, NULL);
144 _ethumb_plugins_unload(void)
146 eina_hash_free(_plugins_ext);
148 eina_module_list_unload(_plugins);
149 eina_module_list_free(_plugins);
150 eina_array_free(_plugins);
165 fprintf(stderr, "ERROR: Could not initialize eina.\n");
168 _log_dom = eina_log_domain_register("ethumb", EINA_COLOR_GREEN);
171 EINA_LOG_ERR("Could not register log domain: ethumb");
181 home = getenv("HOME");
182 snprintf(buf, sizeof(buf), "%s/.thumbnails", home);
184 _home_thumb_dir = eina_stringshare_add(buf);
185 _thumb_category_normal = eina_stringshare_add("normal");
186 _thumb_category_large = eina_stringshare_add("large");
188 _ethumb_plugins_load();
193 ethumb_shutdown(void)
198 _ethumb_plugins_unload();
199 eina_stringshare_del(_home_thumb_dir);
200 eina_stringshare_del(_thumb_category_normal);
201 eina_stringshare_del(_thumb_category_large);
204 ecore_evas_shutdown();
206 eina_log_domain_unregister(_log_dom);
218 Ecore_Evas *ee, *sub_ee;
220 Evas_Object *o, *img;
222 ethumb = calloc(1, sizeof(Ethumb));
223 EINA_SAFETY_ON_NULL_RETURN_VAL(ethumb, NULL);
225 /* IF CHANGED, UPDATE DOCS in (Ethumb.c, Ethumb_Client.c, python...)!!! */
226 ethumb->tw = THUMB_SIZE_NORMAL;
227 ethumb->th = THUMB_SIZE_NORMAL;
228 ethumb->crop_x = 0.5;
229 ethumb->crop_y = 0.5;
230 ethumb->quality = 80;
231 ethumb->compress = 9;
232 ethumb->video.start = 0.1;
233 ethumb->video.time = 3;
234 ethumb->video.interval = 0.05;
235 ethumb->video.ntimes = 3;
236 ethumb->video.fps = 10;
238 ee = ecore_evas_buffer_new(1, 1);
239 e = ecore_evas_get(ee);
242 ERR("could not create ecore evas buffer");
246 evas_image_cache_set(e, 0);
247 evas_font_cache_set(e, 0);
249 o = ecore_evas_object_image_new(ee);
252 ERR("could not create sub ecore evas buffer");
258 sub_ee = evas_object_data_get(o, "Ecore_Evas");
259 sub_e = ecore_evas_get(sub_ee);
261 evas_image_cache_set(sub_e, 0);
262 evas_font_cache_set(sub_e, 0);
264 img = evas_object_image_add(sub_e);
267 ERR("could not create source objects.");
275 ethumb->sub_ee = sub_ee;
276 ethumb->sub_e = sub_e;
280 DBG("ethumb=%p", ethumb);
286 _ethumb_frame_free(Ethumb_Frame *frame)
293 if (frame->swallow && frame->edje)
295 o = edje_object_part_swallow_get(frame->edje, frame->swallow);
297 edje_object_part_unswallow(frame->edje, o);
299 eina_stringshare_del(frame->file);
300 eina_stringshare_del(frame->group);
301 eina_stringshare_del(frame->swallow);
304 evas_object_del(frame->edje);
310 ethumb_free(Ethumb *ethumb)
312 EINA_SAFETY_ON_NULL_RETURN(ethumb);
314 DBG("ethumb=%p", ethumb);
317 _ethumb_frame_free(ethumb->frame);
318 ethumb_file_free(ethumb);
319 ecore_evas_free(ethumb->o);
320 ecore_evas_free(ethumb->ee);
321 ecore_evas_free(ethumb->sub_ee);
322 eina_stringshare_del(ethumb->thumb_dir);
323 eina_stringshare_del(ethumb->category);
324 if (ethumb->finished_idler)
325 ecore_idler_del(ethumb->finished_idler);
330 ethumb_thumb_fdo_set(Ethumb *e, Ethumb_Thumb_FDO_Size s)
332 EINA_SAFETY_ON_NULL_RETURN(e);
333 EINA_SAFETY_ON_FALSE_RETURN(s == ETHUMB_THUMB_NORMAL ||
334 s == ETHUMB_THUMB_LARGE);
335 DBG("ethumb=%p, size=%d", e, s);
337 if (s == ETHUMB_THUMB_NORMAL)
339 e->tw = THUMB_SIZE_NORMAL;
340 e->th = THUMB_SIZE_NORMAL;
344 e->tw = THUMB_SIZE_LARGE;
345 e->th = THUMB_SIZE_LARGE;
348 e->format = ETHUMB_THUMB_FDO;
349 e->aspect = ETHUMB_THUMB_KEEP_ASPECT;
350 _ethumb_frame_free(e->frame);
352 eina_stringshare_del(e->thumb_dir);
353 eina_stringshare_del(e->category);
359 ethumb_thumb_size_set(Ethumb *e, int tw, int th)
361 EINA_SAFETY_ON_NULL_RETURN(e);
362 EINA_SAFETY_ON_FALSE_RETURN(tw > 0);
363 EINA_SAFETY_ON_FALSE_RETURN(th > 0);
365 DBG("ethumb=%p, w=%d, h=%d", e, tw, th);
371 ethumb_thumb_size_get(const Ethumb *e, int *tw, int *th)
373 EINA_SAFETY_ON_NULL_RETURN(e);
380 ethumb_thumb_format_set(Ethumb *e, Ethumb_Thumb_Format f)
382 EINA_SAFETY_ON_NULL_RETURN(e);
383 EINA_SAFETY_ON_FALSE_RETURN(f == ETHUMB_THUMB_FDO ||
384 f == ETHUMB_THUMB_JPEG ||
385 f == ETHUMB_THUMB_EET);
387 DBG("ethumb=%p, format=%d", e, f);
391 EAPI Ethumb_Thumb_Format
392 ethumb_thumb_format_get(const Ethumb *e)
394 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
399 ethumb_thumb_aspect_set(Ethumb *e, Ethumb_Thumb_Aspect a)
401 EINA_SAFETY_ON_NULL_RETURN(e);
402 EINA_SAFETY_ON_FALSE_RETURN(a == ETHUMB_THUMB_KEEP_ASPECT ||
403 a == ETHUMB_THUMB_IGNORE_ASPECT ||
404 a == ETHUMB_THUMB_CROP);
406 DBG("ethumb=%p, aspect=%d", e, a);
410 EAPI Ethumb_Thumb_Aspect
411 ethumb_thumb_aspect_get(const Ethumb *e)
413 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
418 ethumb_thumb_crop_align_set(Ethumb *e, float x, float y)
420 EINA_SAFETY_ON_NULL_RETURN(e);
422 DBG("ethumb=%p, x=%f, y=%f", e, x, y);
428 ethumb_thumb_crop_align_get(const Ethumb *e, float *x, float *y)
430 EINA_SAFETY_ON_NULL_RETURN(e);
432 if (x) *x = e->crop_x;
433 if (y) *y = e->crop_y;
437 ethumb_thumb_quality_set(Ethumb *e, int quality)
439 EINA_SAFETY_ON_NULL_RETURN(e);
441 DBG("ethumb=%p, quality=%d", e, quality);
442 e->quality = quality;
446 ethumb_thumb_quality_get(const Ethumb *e)
448 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
453 ethumb_thumb_compress_set(Ethumb *e, int compress)
455 EINA_SAFETY_ON_NULL_RETURN(e);
457 DBG("ethumb=%p, compress=%d", e, compress);
458 e->compress = compress;
462 ethumb_thumb_compress_get(const Ethumb *e)
464 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
469 ethumb_frame_set(Ethumb *e, const char *theme_file, const char *group, const char *swallow)
471 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
476 DBG("ethumb=%p, theme_file=%s, group=%s, swallow=%s",
477 e, theme_file ? theme_file : "", group ? group : "",
478 swallow ? swallow : "");
482 edje_object_part_unswallow(frame->edje, e->img);
484 _ethumb_frame_free(frame);
495 frame = calloc(1, sizeof(Ethumb_Frame));
498 ERR("could not allocate Ethumb_Frame structure.");
502 frame->edje = edje_object_add(e->sub_e);
505 ERR("could not create edje frame object.");
506 _ethumb_frame_free(frame);
512 if (!edje_object_file_set(frame->edje, theme_file, group))
514 ERR("could not load frame theme.");
515 _ethumb_frame_free(frame);
520 edje_object_part_swallow(frame->edje, swallow, e->img);
521 if (!edje_object_part_swallow_get(frame->edje, swallow))
523 ERR("could not swallow image to edje frame.");
524 _ethumb_frame_free(frame);
529 eina_stringshare_replace(&frame->file, theme_file);
530 eina_stringshare_replace(&frame->group, group);
531 eina_stringshare_replace(&frame->swallow, swallow);
539 ethumb_frame_get(const Ethumb *e, const char **theme_file, const char **group, const char **swallow)
541 EINA_SAFETY_ON_NULL_RETURN(e);
545 if (theme_file) *theme_file = e->frame->file;
546 if (group) *group = e->frame->group;
547 if (swallow) *swallow = e->frame->swallow;
551 if (theme_file) *theme_file = NULL;
552 if (group) *group = NULL;
553 if (swallow) *swallow = NULL;
558 _ethumb_build_absolute_path(const char *path, char buf[PATH_MAX])
570 else if (path[0] == '~')
572 const char *home = getenv("HOME");
584 if (!getcwd(p, PATH_MAX))
597 ethumb_thumb_dir_path_set(Ethumb *e, const char *path)
600 EINA_SAFETY_ON_NULL_RETURN(e);
602 DBG("ethumb=%p, path=%s", e, path ? path : "");
603 path = _ethumb_build_absolute_path(path, buf);
604 eina_stringshare_replace(&e->thumb_dir, path);
608 ethumb_thumb_dir_path_get(const Ethumb *e)
610 EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
616 ethumb_thumb_category_set(Ethumb *e, const char *category)
618 EINA_SAFETY_ON_NULL_RETURN(e);
620 DBG("ethumb=%p, category=%s", e, category ? category : "");
621 eina_stringshare_replace(&e->category, category);
625 ethumb_thumb_category_get(const Ethumb *e)
627 EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
633 ethumb_video_start_set(Ethumb *e, float start)
635 EINA_SAFETY_ON_NULL_RETURN(e);
636 EINA_SAFETY_ON_FALSE_RETURN(start >= 0.0);
637 EINA_SAFETY_ON_FALSE_RETURN(start <= 1.0);
639 DBG("ethumb=%p, video_start=%f", e, start);
640 e->video.start = start;
644 ethumb_video_start_get(const Ethumb *e)
646 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
648 return e->video.start;
652 ethumb_video_time_set(Ethumb *e, float time)
654 EINA_SAFETY_ON_NULL_RETURN(e);
656 DBG("ethumb=%p, video_start=%f", e, time);
657 e->video.time = time;
661 ethumb_video_time_get(const Ethumb *e)
663 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
665 return e->video.time;
669 ethumb_video_interval_set(Ethumb *e, float interval)
671 EINA_SAFETY_ON_NULL_RETURN(e);
673 DBG("ethumb=%p, video_interval=%f", e, interval);
674 e->video.interval = interval;
678 ethumb_video_interval_get(const Ethumb *e)
680 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
682 return e->video.interval;
686 ethumb_video_ntimes_set(Ethumb *e, unsigned int ntimes)
688 EINA_SAFETY_ON_NULL_RETURN(e);
689 EINA_SAFETY_ON_FALSE_RETURN(ntimes > 0);
691 DBG("ethumb=%p, video_ntimes=%d", e, ntimes);
692 e->video.ntimes = ntimes;
696 ethumb_video_ntimes_get(const Ethumb *e)
698 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
700 return e->video.ntimes;
704 ethumb_video_fps_set(Ethumb *e, unsigned int fps)
706 EINA_SAFETY_ON_NULL_RETURN(e);
707 EINA_SAFETY_ON_FALSE_RETURN(fps > 0);
709 DBG("ethumb=%p, video_fps=%d", e, fps);
714 ethumb_video_fps_get(const Ethumb *e)
716 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
722 ethumb_document_page_set(Ethumb *e, unsigned int page)
724 EINA_SAFETY_ON_NULL_RETURN(e);
726 DBG("ethumb=%p, document_page=%d", e, page);
727 e->document.page = page;
731 ethumb_document_page_get(const Ethumb *e)
733 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
735 return e->document.page;
739 ethumb_file_set(Ethumb *e, const char *path, const char *key)
742 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
744 DBG("ethumb=%p, path=%s, key=%s", e, path ? path : "", key ? key : "");
745 if (path && access(path, R_OK))
747 ERR("couldn't access file \"%s\"", path);
751 path = _ethumb_build_absolute_path(path, buf);
752 eina_stringshare_replace(&e->src_path, path);
753 eina_stringshare_replace(&e->src_key, key);
754 eina_stringshare_replace(&e->thumb_path, NULL);
755 eina_stringshare_replace(&e->thumb_key, NULL);
761 ethumb_file_get(const Ethumb *e, const char **path, const char **key)
763 EINA_SAFETY_ON_NULL_RETURN(e);
765 if (path) *path = e->src_path;
766 if (key) *key = e->src_key;
769 static const char ACCEPTABLE_URI_CHARS[96] = {
770 /* ! " # $ % & ' ( ) * + , - . / */
771 0x00,0x3F,0x20,0x20,0x28,0x00,0x2C,0x3F,0x3F,0x3F,0x3F,0x2A,0x28,0x3F,0x3F,0x1C,
772 /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
773 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x38,0x20,0x20,0x2C,0x20,0x20,
774 /* @ A B C D E F G H I J K L M N O */
775 0x38,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
776 /* P Q R S T U V W X Y Z [ \ ] ^ _ */
777 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x20,0x3F,
778 /* ` a b c d e f g h i j k l m n o */
779 0x20,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
780 /* p q r s t u v w x y z { | } ~ DEL */
781 0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x3F,0x20
785 _ethumb_generate_hash(const char *file)
789 char md5out[(2 * MD5_HASHBYTES) + 1];
790 unsigned char hash[MD5_HASHBYTES];
791 static const char hex[] = "0123456789abcdef";
795 const unsigned char *c;
797 #define _check_uri_char(c) \
798 ((c) >= 32 && (c) < 128 && (ACCEPTABLE_URI_CHARS[(c) - 32] & 0x08))
800 EINA_SAFETY_ON_NULL_RETURN_VAL(file, NULL);
802 uri = alloca(3 * strlen(file) + 9);
803 memcpy(uri, "file://", sizeof("file://") - 1);
804 t = uri + sizeof("file://") - 1;
806 for (c = (const unsigned char *)file; *c != '\0'; c++)
808 if (!_check_uri_char(*c))
819 #undef _check_uri_char
822 MD5Update (&ctx, (unsigned char const*)uri, (unsigned)strlen (uri));
823 MD5Final (hash, &ctx);
825 for (n = 0; n < MD5_HASHBYTES; n++)
827 md5out[2 * n] = hex[hash[n] >> 4];
828 md5out[2 * n + 1] = hex[hash[n] & 0x0f];
830 md5out[2 * n] = '\0';
832 DBG("md5=%s, file=%s", md5out, file);
833 return eina_stringshare_add(md5out);
837 _ethumb_file_check_fdo(Ethumb *e)
839 if (!((e->tw == THUMB_SIZE_NORMAL && e->th == THUMB_SIZE_NORMAL) ||
840 (e->tw == THUMB_SIZE_LARGE && e->th == THUMB_SIZE_LARGE)))
843 if (e->format != ETHUMB_THUMB_FDO)
846 if (e->aspect != ETHUMB_THUMB_KEEP_ASPECT)
856 _ethumb_file_generate_custom_category(Ethumb *e)
859 const char *aspect, *format;
862 if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT)
863 aspect = "keep_aspect";
864 else if (e->aspect == ETHUMB_THUMB_IGNORE_ASPECT)
865 aspect = "ignore_aspect";
869 if (e->format == ETHUMB_THUMB_FDO)
871 else if (e->format == ETHUMB_THUMB_JPEG)
881 snprintf(buf, sizeof(buf), "%dx%d-%s%s-%s",
882 e->tw, e->th, aspect, frame, format);
884 return eina_stringshare_add(buf);
888 _ethumb_file_generate_path(Ethumb *e)
893 const char *thumb_dir, *category;
898 fdo_format = _ethumb_file_check_fdo(e);
901 thumb_dir = eina_stringshare_ref(e->thumb_dir);
903 thumb_dir = eina_stringshare_ref(_home_thumb_dir);
906 category = eina_stringshare_ref(e->category);
907 else if (!fdo_format)
908 category = _ethumb_file_generate_custom_category(e);
911 if (e->tw == THUMB_SIZE_NORMAL)
912 category = eina_stringshare_ref(_thumb_category_normal);
913 else if (e->tw == THUMB_SIZE_LARGE)
914 category = eina_stringshare_ref(_thumb_category_large);
917 ERR("fdo_format but size %d is not NORMAL (%d) or LARGE (%d)?",
918 e->tw, THUMB_SIZE_NORMAL, THUMB_SIZE_LARGE);
919 category = "unknown";
923 if (e->format == ETHUMB_THUMB_FDO)
925 else if (e->format == ETHUMB_THUMB_JPEG)
931 fullname = ecore_file_realpath(e->src_path);
932 hash = _ethumb_generate_hash(fullname);
933 snprintf(buf, sizeof(buf), "%s/%s/%s.%s", thumb_dir, category, hash, ext);
935 DBG("ethumb=%p, path=%s", e, buf);
936 eina_stringshare_replace(&e->thumb_path, buf);
937 if (e->format == ETHUMB_THUMB_EET)
938 eina_stringshare_replace(&e->thumb_key, "thumbnail");
941 eina_stringshare_del(e->thumb_key);
945 eina_stringshare_del(thumb_dir);
946 eina_stringshare_del(category);
947 eina_stringshare_del(hash);
951 ethumb_file_free(Ethumb *e)
953 EINA_SAFETY_ON_NULL_RETURN(e);
956 eina_stringshare_replace(&e->src_path, NULL);
957 eina_stringshare_replace(&e->src_key, NULL);
958 eina_stringshare_replace(&e->thumb_path, NULL);
959 eina_stringshare_replace(&e->thumb_key, NULL);
963 ethumb_thumb_path_set(Ethumb *e, const char *path, const char *key)
967 EINA_SAFETY_ON_NULL_RETURN(e);
968 DBG("ethumb=%p, path=%s, key=%s", e, path ? path : "", key ? key : "");
972 eina_stringshare_replace(&e->thumb_path, NULL);
973 eina_stringshare_replace(&e->thumb_key, NULL);
977 path = _ethumb_build_absolute_path(path, buf);
978 eina_stringshare_replace(&e->thumb_path, path);
979 eina_stringshare_replace(&e->thumb_key, key);
984 ethumb_thumb_path_get(Ethumb *e, const char **path, const char **key)
986 EINA_SAFETY_ON_NULL_RETURN(e);
988 _ethumb_file_generate_path(e);
990 if (path) *path = e->thumb_path;
991 if (key) *key = e->thumb_key;
995 ethumb_calculate_aspect_from_ratio(Ethumb *e, float ia, int *w, int *h)
1005 a = e->tw / (float)e->th;
1007 if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT)
1009 if ((ia > a && e->tw > 0) || e->th <= 0)
1017 ethumb_calculate_aspect(Ethumb *e, int iw, int ih, int *w, int *h)
1021 ia = iw / (float)ih;
1023 ethumb_calculate_aspect_from_ratio(e, ia, w, h);
1027 ethumb_calculate_fill_from_ratio(Ethumb *e, float ia, int *fx, int *fy, int *fw, int *fh)
1039 a = e->tw / (float)e->th;
1041 if (e->aspect == ETHUMB_THUMB_CROP)
1043 if ((ia > a && e->tw > 0) || e->th <= 0)
1048 *fx = - e->crop_x * (*fw - e->tw);
1049 *fy = - e->crop_y * (*fh - e->th);
1051 else if (e->aspect == ETHUMB_THUMB_KEEP_ASPECT)
1053 if ((ia > a && e->tw > 0) || e->th <= 0)
1061 ethumb_calculate_fill(Ethumb *e, int iw, int ih, int *fx, int *fy, int *fw, int *fh)
1064 ia = iw / (float)ih;
1066 ethumb_calculate_fill_from_ratio(e, ia, fx, fy, fw, fh);
1070 _ethumb_plugin_generate(Ethumb *e)
1074 Ethumb_Plugin *plugin;
1077 extp = strrchr(e->src_path, '.');
1080 ERR("could not get extension for file \"%s\"", e->src_path);
1084 for (i = 0; extp[i] != '\0'; i++)
1085 ext[i] = tolower(extp[i + 1]);
1087 plugin = eina_hash_find(_plugins_ext, ext);
1090 DBG("no plugin for extension: \"%s\"", ext);
1095 evas_object_hide(e->frame->edje);
1097 evas_object_hide(e->img);
1099 plugin->generate_thumb(e);
1105 ethumb_plugin_image_resize(Ethumb *e, int w, int h)
1113 edje_extern_object_min_size_set(img, w, h);
1114 edje_extern_object_max_size_set(img, w, h);
1115 edje_object_calc_force(e->frame->edje);
1116 evas_object_move(e->frame->edje, 0, 0);
1117 evas_object_resize(e->frame->edje, w, h);
1121 evas_object_move(img, 0, 0);
1122 evas_object_resize(img, w, h);
1125 evas_object_image_size_set(e->o, w, h);
1126 ecore_evas_resize(e->sub_ee, w, h);
1135 ethumb_image_save(Ethumb *e)
1141 evas_damage_rectangle_add(e->sub_e, 0, 0, e->rw, e->rh);
1142 evas_render(e->sub_e);
1145 _ethumb_file_generate_path(e);
1149 ERR("could not create file path...");
1153 dname = ecore_file_dir_get(e->thumb_path);
1154 r = ecore_file_mkpath(dname);
1158 ERR("could not create directory '%s'", dname);
1162 snprintf(flags, sizeof(flags), "quality=%d compress=%d",
1163 e->quality, e->compress);
1164 r = evas_object_image_save(e->o, e->thumb_path, e->thumb_key, flags);
1168 ERR("could not save image: path=%s, key=%s", e->thumb_path,
1177 _ethumb_image_load(Ethumb *e)
1180 Evas_Coord w, h, ww, hh, fx, fy, fw, fh;
1186 evas_object_hide(e->frame->edje);
1188 evas_object_hide(img);
1189 evas_object_image_file_set(img, NULL, NULL);
1190 evas_object_image_load_size_set(img, e->tw, e->th);
1191 evas_object_image_file_set(img, e->src_path, e->src_key);
1194 evas_object_show(e->frame->edje);
1196 evas_object_show(img);
1198 error = evas_object_image_load_error_get(img);
1199 if (error != EVAS_LOAD_ERROR_NONE)
1201 ERR("could not load image '%s': %d", e->src_path, error);
1205 evas_object_image_size_get(img, &w, &h);
1206 if ((w <= 0) || (h <= 0))
1209 ethumb_calculate_aspect(e, w, h, &ww, &hh);
1213 edje_extern_object_min_size_set(img, ww, hh);
1214 edje_extern_object_max_size_set(img, ww, hh);
1215 edje_object_calc_force(e->frame->edje);
1216 evas_object_move(e->frame->edje, 0, 0);
1217 evas_object_resize(e->frame->edje, ww, hh);
1221 evas_object_move(img, 0, 0);
1222 evas_object_resize(img, ww, hh);
1225 ethumb_calculate_fill(e, w, h, &fx, &fy, &fw, &fh);
1226 evas_object_image_fill_set(img, fx, fy, fw, fh);
1228 evas_object_image_size_set(e->o, ww, hh);
1229 ecore_evas_resize(e->sub_ee, ww, hh);
1238 _ethumb_finished_idler_cb(void *data)
1242 e->finished_cb(e->cb_data, e, e->cb_result);
1243 if (e->cb_data_free)
1244 e->cb_data_free(e->cb_data);
1245 e->finished_idler = NULL;
1246 e->finished_cb = NULL;
1248 e->cb_data_free = NULL;
1254 ethumb_finished_callback_call(Ethumb *e, int result)
1256 EINA_SAFETY_ON_NULL_RETURN(e);
1258 e->cb_result = result;
1259 if (e->finished_idler)
1260 ecore_idler_del(e->finished_idler);
1261 e->finished_idler = ecore_idler_add(_ethumb_finished_idler_cb, e);
1265 ethumb_generate(Ethumb *e, Ethumb_Generate_Cb finished_cb, const void *data, Eina_Free_Cb free_data)
1269 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
1270 EINA_SAFETY_ON_NULL_RETURN_VAL(finished_cb, 0);
1271 DBG("ethumb=%p, finished_cb=%p, data=%p, free_data=%p, path=%s, key=%s",
1272 e, finished_cb, data, free_data,
1273 e->src_path ? e->src_path : "", e->src_key ? e->src_key : "");
1275 if (e->finished_idler)
1277 ERR("thumbnail generation already in progress.");
1280 e->finished_cb = finished_cb;
1281 e->cb_data = (void *)data;
1282 e->cb_data_free = free_data;
1286 ERR("no file set.");
1287 ethumb_finished_callback_call(e, 0);
1291 r = _ethumb_plugin_generate(e);
1295 if (!_ethumb_image_load(e))
1297 ERR("could not load input image.");
1298 ethumb_finished_callback_call(e, 0);
1302 r = ethumb_image_save(e);
1304 ethumb_finished_callback_call(e, r);
1310 ethumb_exists(Ethumb *e)
1312 struct stat thumb, src;
1314 Eina_Bool r = EINA_FALSE;
1316 EINA_SAFETY_ON_NULL_RETURN_VAL(e, 0);
1317 EINA_SAFETY_ON_NULL_RETURN_VAL(e->src_path, 0);
1318 DBG("ethumb=%p, path=%s", e, e->src_path ? e->src_path : "");
1321 _ethumb_file_generate_path(e);
1323 EINA_SAFETY_ON_NULL_RETURN_VAL(e->thumb_path, 0);
1325 r_thumb = stat(e->thumb_path, &thumb);
1326 r_src = stat(e->src_path, &src);
1328 EINA_SAFETY_ON_TRUE_RETURN_VAL(r_src, 0);
1330 if (r_thumb && errno != ENOENT)
1331 ERR("could not access file \"%s\": %s", e->thumb_path, strerror(errno));
1332 else if (!r_thumb && thumb.st_mtime > src.st_mtime)
1339 ethumb_evas_get(const Ethumb *e)
1341 EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
1347 ethumb_ecore_evas_get(const Ethumb *e)
1349 EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);