4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hyunjun Ko <zzoon.ko@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
22 #include "media-thumb-debug.h"
23 #include "media-thumb-util.h"
24 #include "media-thumb-internal.h"
25 #include "media-thumb-ipc.h"
27 #include "AGifFrameInfo.h"
28 #include "IfegDecodeAGIF.h"
29 #include "img-codec.h"
30 #include "img-codec-agif.h"
31 #include "img-codec-common.h"
32 #include "img-codec-osal.h"
33 #include "img-codec-parser.h"
35 #include <sys/types.h>
41 #include <mm_util_imgp.h>
42 #include <mm_util_jpeg.h>
44 #include <Ecore_Evas.h>
45 #include <libexif/exif-data.h>
50 #define MEDIA_THUMB_ROUND_UP_8(num) (((num)+7)&~7)
52 int _media_thumb_resize_data(unsigned char *src_data,
55 mm_util_img_format src_format,
56 media_thumb_info *thumb_info,
60 int _media_thumb_get_proper_thumb_size(int orig_w, int orig_h,
61 int *thumb_w, int *thumb_h)
63 BOOL portrait = FALSE;
66 if (orig_w < orig_h) {
70 /* Set smaller length to default size */
72 if (orig_w < *thumb_w)
74 ratio = (double)orig_h / (double)orig_w;
75 *thumb_h = *thumb_w * ratio;
77 if (orig_h < *thumb_h)
79 ratio = (double)orig_w / (double)orig_h;
80 *thumb_w = *thumb_h * ratio;
83 /** CAUTION :: The width of RGB888 raw data has to be rounded by 8 **/
84 *thumb_w = MEDIA_THUMB_ROUND_UP_8(*thumb_w);
86 thumb_dbg("proper thumb w: %d h: %d", *thumb_w, *thumb_h);
88 return MS_MEDIA_ERR_NONE;
91 int _media_thumb_get_exif_info(ExifData *ed, char *buf, int max_size, int *value, int ifdtype, long tagtype)
98 return MS_MEDIA_ERR_INVALID_PARAMETER;
104 entry = exif_content_get_entry(ed->ifd[ifd], tag);
106 if (tag == EXIF_TAG_ORIENTATION ||
107 tag == EXIF_TAG_PIXEL_X_DIMENSION ||
108 tag == EXIF_TAG_PIXEL_Y_DIMENSION) {
111 thumb_err("value is NULL");
112 return MS_MEDIA_ERR_INVALID_PARAMETER;
115 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
116 short exif_value = exif_get_short(entry->data, mByteOrder);
117 *value = (int)exif_value;
119 /* Get the contents of the tag in human-readable form */
121 thumb_err("buf is NULL");
122 return MS_MEDIA_ERR_INVALID_PARAMETER;
124 exif_entry_get_value(entry, buf, max_size);
125 buf[strlen(buf)] = '\0';
129 return MS_MEDIA_ERR_NONE;
132 static int _media_thumb_get_data_from_exif(ExifData *ed,
144 ExifByteOrder byte_order = exif_data_get_byte_order(ed);
147 tag = EXIF_TAG_COMPRESSION;
149 entry = exif_content_get_entry(ed->ifd[ifd], tag);
152 /* Get the contents of the tag in human-readable form */
153 ExifShort value = exif_get_short(entry->data, byte_order);
154 //thumb_dbg("%s: %d", exif_tag_get_name_in_ifd(tag,ifd), value);
157 thumb_dbg("There's jpeg thumb in this image");
159 thumb_dbg("There's NO jpeg thumb in this image");
160 return MS_MEDIA_ERR_INVALID_PARAMETER;
163 thumb_dbg("entry is NULL");
164 return MS_MEDIA_ERR_INVALID_PARAMETER;
167 /* copy the real thumbnail data from exif data */
168 if (ed->data && ed->size) {
169 //thumb_dbg("Size: %d, thumb: 0x%x", ed->size, ed->data);
170 *thumb_data = (char *)malloc(ed->size);
172 if (*thumb_data == NULL) {
173 thumb_dbg("malloc failed!");
174 return MS_MEDIA_ERR_INVALID_PARAMETER;
177 memcpy(*thumb_data, (void *)ed->data, ed->size);
178 *thumb_size = ed->size;
180 thumb_dbg("data is NULL");
181 return MS_MEDIA_ERR_INVALID_PARAMETER;
184 /* Get width and height of thumbnail */
185 tag = EXIF_TAG_IMAGE_WIDTH;
186 entry = exif_content_get_entry(ed->ifd[ifd], tag);
189 /* Get the contents of the tag in human-readable form */
190 char width[10] = {0,};
191 exif_entry_get_value(entry, width, 10);
193 *thumb_width = atoi(width);
195 thumb_warn("EXIF_TAG_IMAGE_WIDTH does not exist");
199 tag = EXIF_TAG_IMAGE_LENGTH;
200 entry = exif_content_get_entry(ed->ifd[ifd], tag);
202 /* Get the contents of the tag in human-readable form */
203 char height[10] = {0, };
204 exif_entry_get_value(entry, height, 10);
206 *thumb_height = atoi(height);
208 thumb_warn("EXIF_TAG_IMAGE_LENGTH does not exist");
212 thumb_dbg("thumb width : height [%d:%d]", *thumb_width, *thumb_height);
214 /* Get width and height of original image from exif */
216 tag = EXIF_TAG_PIXEL_X_DIMENSION;
217 entry = exif_content_get_entry(ed->ifd[ifd], tag);
220 char width[10] = {0,};
221 exif_entry_get_value(entry, width, 10);
223 *origin_width = atoi(width);
225 thumb_warn("EXIF_TAG_PIXEL_X_DIMENSION does not exist");
229 tag = EXIF_TAG_PIXEL_Y_DIMENSION;
230 entry = exif_content_get_entry(ed->ifd[ifd], tag);
233 char height[10] = {0, };
234 exif_entry_get_value(entry, height, 10);
236 *origin_height = atoi(height);
238 thumb_warn("EXIF_TAG_PIXEL_Y_DIMENSION does not exist");
242 return MS_MEDIA_ERR_NONE;
245 int _media_thumb_get_thumb_from_exif(ExifData *ed,
246 const char *file_full_path,
247 const char *thumb_path,
251 media_thumb_info *thumb_info)
253 int err = MS_MEDIA_ERR_NONE;
256 int thumb_height = 0;
257 int origin_width = 0;
258 int origin_height = 0;
260 bool is_rotated = (orientation == ROT_90 || orientation == ROT_180 || orientation == ROT_270) ? TRUE : FALSE;
261 mm_util_jpeg_yuv_data decoded = {0,};
264 return MS_MEDIA_ERR_INVALID_PARAMETER;
267 err = _media_thumb_get_data_from_exif(ed,
275 if (err != MS_MEDIA_ERR_NONE) {
276 thumb_err("There is no exif data");
280 thumb_dbg("thumb width : height [%d:%d]", thumb_width, thumb_height);
281 thumb_dbg("origin width : height [%d:%d]", origin_width, origin_height);
282 thumb_info->origin_height = origin_height;
283 thumb_info->origin_width = origin_width;
285 if (thumb_width < required_width) {
286 thumb_err("Thumb data in exif is too small");
288 return MS_MEDIA_ERR_INVALID_PARAMETER;
292 err = mm_util_decode_from_jpeg_memory(&decoded, thumb, size, MM_UTIL_JPEG_FMT_RGB888);
294 if (err != MS_MEDIA_ERR_NONE) {
295 thumb_err("mm_util_decode_from_jpeg_turbo_memory failed : %d", err);
299 thumb_width = decoded.width;
300 thumb_height = decoded.height;
303 /* Start to decode to rotate */
304 unsigned char *rotated = NULL;
305 unsigned int r_w = decoded.height;
306 unsigned int r_h = decoded.width;
307 unsigned int r_size = 0;
308 mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
310 int i, rotate_cnt = 0;
312 rot_type = MM_UTIL_ROTATE_90;
313 if (orientation == ROT_90) {
315 } else if (orientation == ROT_180) {
317 } else if (orientation == ROT_270) {
321 for (i = 0; i < rotate_cnt; i++) {
324 r_h = decoded.height;
327 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
328 if (err != MS_MEDIA_ERR_NONE) {
329 thumb_err("mm_util_get_image_size failed : %d", err);
330 SAFE_FREE(decoded.data);
334 rotated = (unsigned char *)malloc(r_size);
335 err = mm_util_rotate_image(decoded.data, decoded.width, decoded.height,
336 MM_UTIL_IMG_FMT_RGB888,
340 if (err != MS_MEDIA_ERR_NONE) {
341 thumb_err("mm_util_rotate_image failed : %d", err);
342 SAFE_FREE(decoded.data);
346 thumb_err("mm_util_rotate_image succeed");
349 SAFE_FREE(decoded.data);
350 decoded.data = rotated;
352 decoded.height = r_h;
355 //thumb_dbg("Width : %d, Height : %d", r_w, r_h);
356 thumb_info->data = rotated;
357 thumb_info->size = r_size;
358 thumb_info->width = r_w;
359 thumb_info->height = r_h;
361 thumb_warn("Unknown orientation");
362 SAFE_FREE(decoded.data);
363 return MS_MEDIA_ERR_INVALID_PARAMETER;
366 /*in this case, just write raw data in file */
367 thumb_dbg_slog("Thumb is :%s", thumb_path);
370 int fd = open(thumb_path, O_RDWR | O_CREAT | O_EXCL | O_SYNC, 0644);
372 if (errno == EEXIST) {
373 thumb_err("thumb alread exist!");
375 thumb_err("open failed");
377 return MS_MEDIA_ERR_INVALID_PARAMETER;
380 nwrite = write(fd, thumb, size);
382 thumb_err("write failed");
386 return MS_MEDIA_ERR_INVALID_PARAMETER;
392 thumb_info->data = NULL;
393 thumb_info->size = size;
394 thumb_info->width = thumb_width;
395 thumb_info->height = thumb_height;
396 thumb_info->is_saved = TRUE;
402 int _media_thumb_resize_data(unsigned char *src_data,
405 mm_util_img_format src_format,
406 media_thumb_info *thumb_info,
410 int thumb_width = dst_width;
411 int thumb_height = dst_height;
412 unsigned int buf_size = 0;
414 if (mm_util_get_image_size(src_format, thumb_width, thumb_height, &buf_size) < 0) {
415 thumb_err("Failed to get buffer size");
416 return MS_MEDIA_ERR_INTERNAL;
419 thumb_dbg("mm_util_get_image_size : %d", buf_size);
421 unsigned char *dst = (unsigned char *)malloc(buf_size);
424 thumb_err("malloc fails");
425 return MS_MEDIA_ERR_OUT_OF_MEMORY;
428 if (mm_util_resize_image((unsigned char *)src_data, src_width,
429 src_height, src_format,
430 dst, (unsigned int *)&thumb_width,
431 (unsigned int *)&thumb_height) < 0) {
432 thumb_err("Failed to resize the thumbnails");
436 return MS_MEDIA_ERR_INTERNAL;
439 thumb_info->size = buf_size;
440 thumb_info->width = thumb_width;
441 thumb_info->height = thumb_height;
442 thumb_info->data = malloc(buf_size);
443 if (thumb_info->data != NULL) {
444 memcpy(thumb_info->data, dst, buf_size);
446 thumb_err("malloc fails");
448 return MS_MEDIA_ERR_OUT_OF_MEMORY;
452 return MS_MEDIA_ERR_NONE;
455 int _media_thumb_get_wh_with_evas(const char *origin_path, int *width, int *height)
457 /* using evas to get w/h */
458 Ecore_Evas *ee = ecore_evas_buffer_new(0, 0);
460 thumb_err("ecore_evas_buffer_new fails");
461 return MS_MEDIA_ERR_INTERNAL;
464 Evas *evas = ecore_evas_get(ee);
466 thumb_err("ecore_evas_get fails");
468 return MS_MEDIA_ERR_INTERNAL;
471 Evas_Object *image_object = evas_object_image_add(evas);
473 thumb_err("evas_object_image_add fails");
475 return MS_MEDIA_ERR_INTERNAL;
478 evas_object_image_file_set(image_object, origin_path, NULL);
479 evas_object_image_size_get(image_object, width, height);
481 thumb_dbg("Width:%d, Height:%d", *width, *height);
485 return MS_MEDIA_ERR_NONE;
488 int _media_thumb_decode_with_evas(const char *origin_path,
489 int thumb_width, int thumb_height,
490 media_thumb_info *thumb_info, int need_scale, int orientation)
492 Ecore_Evas *resize_img_ee;
494 resize_img_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
495 if (!resize_img_ee) {
496 thumb_err("ecore_evas_buffer_new failed");
497 return MS_MEDIA_ERR_INTERNAL;
500 Evas *resize_img_e = ecore_evas_get(resize_img_ee);
502 thumb_err("ecore_evas_get failed");
503 ecore_evas_free(resize_img_ee);
504 return MS_MEDIA_ERR_INTERNAL;
507 Evas_Object *source_img = evas_object_image_add(resize_img_e);
509 thumb_err("evas_object_image_add failed");
510 ecore_evas_free(resize_img_ee);
511 return MS_MEDIA_ERR_INTERNAL;
514 evas_object_image_file_set(source_img, origin_path, NULL);
516 /* Get w/h of original image */
520 evas_object_image_size_get(source_img, &width, &height);
521 thumb_info->origin_width = width;
522 thumb_info->origin_height = height;
523 //thumb_dbg("origin width:%d, origin height:%d", width, height);
525 if ((need_scale == 1) && (width * height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
526 thumb_warn("This is too large image. so this's scale is going to be down");
527 evas_object_image_load_scale_down_set(source_img, 10);
530 if (orientation != TRANSPOSE)
531 evas_object_image_load_orientation_set(source_img, 1);
533 int rotated_orig_w = 0;
534 int rotated_orig_h = 0;
536 if (orientation == ROT_90 || orientation == ROT_270) {
537 rotated_orig_w = height;
538 rotated_orig_h = width;
540 rotated_orig_w = width;
541 rotated_orig_h = height;
543 //thumb_dbg("rotated - origin width:%d, origin height:%d", rotated_orig_w, rotated_orig_h);
545 int err = MS_MEDIA_ERR_NONE;
547 err = _media_thumb_get_proper_thumb_size(rotated_orig_w, rotated_orig_h, &thumb_width, &thumb_height);
548 if (err != MS_MEDIA_ERR_NONE) {
549 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
550 ecore_evas_free(resize_img_ee);
554 ecore_evas_resize(resize_img_ee, thumb_width, thumb_height);
556 evas_object_image_load_size_set(source_img, thumb_width, thumb_height);
557 evas_object_image_fill_set(source_img, 0, 0, thumb_width, thumb_height);
558 evas_object_image_filled_set(source_img, 1);
560 evas_object_resize(source_img, thumb_width, thumb_height);
561 evas_object_show(source_img);
563 /* Set alpha from original */
564 thumb_info->alpha = evas_object_image_alpha_get(source_img);
565 if (thumb_info->alpha) ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
567 /* Create target buffer and copy origin resized img to it */
568 Ecore_Evas *target_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
570 thumb_err("ecore_evas_buffer_new failed");
571 ecore_evas_free(resize_img_ee);
572 return MS_MEDIA_ERR_INTERNAL;
575 Evas *target_evas = ecore_evas_get(target_ee);
577 thumb_err("ecore_evas_get failed");
578 ecore_evas_free(resize_img_ee);
579 ecore_evas_free(target_ee);
580 return MS_MEDIA_ERR_INTERNAL;
583 Evas_Object *ret_image = evas_object_image_add(target_evas);
584 evas_object_image_size_set(ret_image, thumb_width, thumb_height);
585 evas_object_image_fill_set(ret_image, 0, 0, thumb_width, thumb_height);
586 evas_object_image_filled_set(ret_image, EINA_TRUE);
588 evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
589 evas_object_image_data_update_add(ret_image, 0, 0, thumb_width, thumb_height);
591 unsigned int buf_size = 0;
592 if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
593 thumb_err("mm_util_get_image_size failed");
595 ecore_evas_free(resize_img_ee);
596 ecore_evas_free(target_ee);
598 return MS_MEDIA_ERR_INTERNAL;
600 //thumb_dbg("mm_util_get_image_size : %d", buf_size);
602 thumb_info->size = buf_size;
603 thumb_info->width = thumb_width;
604 thumb_info->height = thumb_height;
605 thumb_info->data = malloc(buf_size);
606 if (thumb_info->data == NULL) {
607 thumb_err("Failed to allocate memory");
608 ecore_evas_free(resize_img_ee);
609 ecore_evas_free(target_ee);
611 return MS_MEDIA_ERR_OUT_OF_MEMORY;
614 void *image_data = evas_object_image_data_get(ret_image, 1);
615 if (image_data != NULL) {
616 memcpy(thumb_info->data, image_data, buf_size);
618 thumb_err("image_data is NULL. evas_object_image_data_get failed");
621 ecore_evas_free(target_ee);
622 ecore_evas_free(resize_img_ee);
627 mm_util_img_format _media_thumb_get_format(media_thumb_format src_format)
629 switch (src_format) {
630 case MEDIA_THUMB_BGRA:
631 return MM_UTIL_IMG_FMT_BGRA8888;
632 case MEDIA_THUMB_RGB888:
633 return MM_UTIL_IMG_FMT_RGB888;
635 return MS_MEDIA_ERR_INVALID_PARAMETER;
639 int _media_thumb_convert_data(media_thumb_info *thumb_info,
642 mm_util_img_format src_format,
643 mm_util_img_format dst_format)
645 int err = MS_MEDIA_ERR_NONE;
646 unsigned int buf_size = 0;
647 unsigned char *src_data = thumb_info->data;
648 unsigned char *dst_data = NULL;
650 thumb_dbg("src format:%d, dst format:%d", src_format, dst_format);
652 if (mm_util_get_image_size(dst_format, thumb_width, thumb_height, &buf_size) < 0) {
653 thumb_err("mm_util_get_image_size failed");
654 return MS_MEDIA_ERR_INTERNAL;
657 thumb_dbg("mm_util_get_image_size : %d", buf_size);
659 dst_data = (unsigned char *)malloc(buf_size);
661 if (dst_data == NULL) {
662 thumb_err("Failed to allocate memory");
663 return MS_MEDIA_ERR_OUT_OF_MEMORY;
666 if (src_format == MM_UTIL_IMG_FMT_RGB888 &&
667 dst_format == MM_UTIL_IMG_FMT_BGRA8888) {
670 for (j = 0; j < thumb_width * 3 * thumb_height;
672 dst_data[i++] = (src_data[j + 2]);
673 dst_data[i++] = (src_data[j + 1]);
674 dst_data[i++] = (src_data[j]);
679 err = mm_util_convert_colorspace(src_data,
687 thumb_err("Failed to change from rgb888 to argb8888 %d", err);
689 return MS_MEDIA_ERR_INTERNAL;
693 SAFE_FREE(thumb_info->data);
694 thumb_info->data = dst_data;
695 thumb_info->size = buf_size;
697 thumb_dbg("_media_thumb_convert_data success");
702 int _media_thumb_convert_format(media_thumb_info *thumb_info,
703 media_thumb_format src_format,
704 media_thumb_format dst_format)
706 int err = MS_MEDIA_ERR_NONE;
708 if (src_format == dst_format) {
709 //thumb_dbg("src_format == dst_format");
713 mm_util_img_format src_mm_format;
714 mm_util_img_format dst_mm_format;
716 src_mm_format = _media_thumb_get_format(src_format);
717 dst_mm_format = _media_thumb_get_format(dst_format);
719 if ((int)src_mm_format == -1 || (int)dst_mm_format == -1) {
720 thumb_err("Format is invalid");
721 return MS_MEDIA_ERR_INVALID_PARAMETER;
724 err = _media_thumb_convert_data(thumb_info,
730 if (err != MS_MEDIA_ERR_NONE) {
731 thumb_err("media_thumb_convert_format failed : %d", err);
738 int _media_thumb_agif(const char *origin_path,
743 media_thumb_format format,
744 media_thumb_info *thumb_info)
746 int err = MS_MEDIA_ERR_NONE;
747 unsigned int *thumb = NULL;
749 thumb = ImgGetFirstFrameAGIFAtSize(origin_path, image_width, image_height);
752 thumb_err("Frame data is NULL!!");
753 return MS_MEDIA_ERR_INTERNAL;
756 err = _media_thumb_get_proper_thumb_size(thumb_info->origin_width, thumb_info->origin_height, &thumb_width, &thumb_height);
757 if (err != MS_MEDIA_ERR_NONE) {
758 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
763 err = _media_thumb_resize_data((unsigned char *)thumb,
766 MM_UTIL_IMG_FMT_RGB888,
771 if (err != MS_MEDIA_ERR_NONE) {
772 thumb_err("_media_thumb_resize_data failed: %d", err);
779 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
780 if (err != MS_MEDIA_ERR_NONE) {
781 thumb_err("_media_thumb_convert_format falied: %d", err);
782 SAFE_FREE(thumb_info->data);
789 int _media_thumb_png(const char *origin_path,
792 media_thumb_format format,
793 media_thumb_info *thumb_info)
795 int err = MS_MEDIA_ERR_NONE;
796 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
798 if (err != MS_MEDIA_ERR_NONE) {
799 thumb_err("decode_with_evas failed : %d", err);
803 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
804 if (err != MS_MEDIA_ERR_NONE) {
805 thumb_err("_media_thumb_convert_format falied: %d", err);
806 SAFE_FREE(thumb_info->data);
813 int _media_thumb_bmp(const char *origin_path,
816 media_thumb_format format,
817 media_thumb_info *thumb_info)
819 int err = MS_MEDIA_ERR_NONE;
820 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
822 if (err != MS_MEDIA_ERR_NONE) {
823 thumb_err("decode_with_evas failed : %d", err);
827 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
828 if (err != MS_MEDIA_ERR_NONE) {
829 thumb_err("_media_thumb_convert_format falied: %d", err);
830 SAFE_FREE(thumb_info->data);
837 int _media_thumb_wbmp(const char *origin_path,
840 media_thumb_format format,
841 media_thumb_info *thumb_info)
843 int err = MS_MEDIA_ERR_NONE;
844 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
846 if (err != MS_MEDIA_ERR_NONE) {
847 thumb_err("decode_with_evas failed : %d", err);
851 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
852 if (err != MS_MEDIA_ERR_NONE) {
853 thumb_err("_media_thumb_convert_format falied: %d", err);
854 SAFE_FREE(thumb_info->data);
861 int _media_thumb_gif(const char *origin_path,
864 media_thumb_format format,
865 media_thumb_info *thumb_info)
867 int err = MS_MEDIA_ERR_NONE;
868 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
870 if (err != MS_MEDIA_ERR_NONE) {
871 thumb_err("decode_with_evas failed : %d", err);
875 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
876 if (err != MS_MEDIA_ERR_NONE) {
877 thumb_err("_media_thumb_convert_format falied: %d", err);
878 SAFE_FREE(thumb_info->data);
885 int _media_thumb_jpeg(const char *origin_path,
886 const char *thumb_path,
889 media_thumb_format format,
890 media_thumb_info *thumb_info)
892 int err = MS_MEDIA_ERR_NONE;
895 int orientation = NORMAL;
897 /* Load an ExifData object from an EXIF file */
898 ed = exif_data_new_from_file(origin_path);
901 /* First, Get orientation from exif */
902 err = _media_thumb_get_exif_info(ed, NULL, 0, &orientation, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
904 if (err != MS_MEDIA_ERR_NONE) {
905 thumb_warn("_media_thumb_get_exif_info failed");
908 /* Second, Get thumb from exif */
909 err = _media_thumb_get_thumb_from_exif(ed, origin_path, thumb_path, orientation, thumb_width, thumb_height, thumb_info);
911 if (err != MS_MEDIA_ERR_NONE) {
912 thumb_dbg("_media_thumb_get_thumb_from_exif failed");
915 thumb_dbg("_media_thumb_get_thumb_from_exif succeed");
917 /* The case that original image's size is not in exif header. Use evas to get w/h */
918 if (thumb_info->origin_width == 0 || thumb_info->origin_height == 0) {
919 thumb_warn("original image's size is not in exif header. Use evas to get w/h");
920 err = _media_thumb_get_wh_with_evas(origin_path, &(thumb_info->origin_width), &(thumb_info->origin_height));
921 if (err != MS_MEDIA_ERR_NONE) {
922 thumb_err("Couldn't get w/h using evas : %s", origin_path);
924 thumb_dbg("origin w : %d, origin h : %d", thumb_info->origin_width, thumb_info->origin_height);
928 if (thumb_info->is_saved == FALSE) {
929 mm_util_img_format dst_format = _media_thumb_get_format(format);
931 err = _media_thumb_convert_data(thumb_info,
934 MM_UTIL_IMG_FMT_RGB888,
937 if (err != MS_MEDIA_ERR_NONE) {
938 thumb_err("_media_thumb_convert_data failed : %d", err);
950 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, orientation);
952 if (err != MS_MEDIA_ERR_NONE) {
953 thumb_err("decode_with_evas failed : %d", err);
957 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
958 if (err != MS_MEDIA_ERR_NONE) {
959 thumb_err("_media_thumb_convert_format falied: %d", err);
960 SAFE_FREE(thumb_info->data);
968 int _media_thumb_jpeg_for_raw(const char *origin_path,
969 const char *thumb_path,
972 media_thumb_format format,
973 media_thumb_info *thumb_info)
975 int err = MS_MEDIA_ERR_NONE;
976 int orientation = NORMAL;
978 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, orientation);
980 if (err != MS_MEDIA_ERR_NONE) {
981 thumb_err("decode_with_evas failed : %d", err);
985 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_BGRA, format);
986 if (err != MS_MEDIA_ERR_NONE) {
987 thumb_err("_media_thumb_convert_format falied: %d", err);
988 SAFE_FREE(thumb_info->data);
994 int _media_thumb_image(const char *origin_path,
995 const char *thumb_path,
998 media_thumb_format format,
999 media_thumb_info *thumb_info,
1002 int err = MS_MEDIA_ERR_NONE;
1003 ImgCodecType image_type = 0;
1004 unsigned int origin_w = 0;
1005 unsigned int origin_h = 0;
1007 err = ImgGetImageInfoForThumb(origin_path, &image_type, &origin_w, &origin_h);
1009 if (err != MS_MEDIA_ERR_NONE) {
1010 thumb_warn("Getting image info is failed err: %d", err);
1013 thumb_info->origin_width = origin_w;
1014 thumb_info->origin_height = origin_h;
1016 //thumb_dbg("image type is %d, width:%d, height:%d", image_type, origin_w, origin_h);
1018 if ((image_type != IMG_CODEC_JPEG) &&
1019 (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
1020 thumb_warn("This original image is too big");
1021 return MS_MEDIA_ERR_THUMB_TOO_BIG;
1024 if (image_type == IMG_CODEC_AGIF) {
1025 err = _media_thumb_agif(origin_path, origin_w, origin_h, thumb_width, thumb_height, format, thumb_info);
1026 } else if (image_type == IMG_CODEC_JPEG) {
1027 if (is_req_raw == TRUE) {
1028 err = _media_thumb_jpeg_for_raw(origin_path, thumb_path, thumb_width, thumb_height, format, thumb_info);
1030 err = _media_thumb_jpeg(origin_path, thumb_path, thumb_width, thumb_height, format, thumb_info);
1032 } else if (image_type == IMG_CODEC_PNG) {
1033 err = _media_thumb_png(origin_path, thumb_width, thumb_height, format, thumb_info);
1034 } else if (image_type == IMG_CODEC_GIF) {
1035 err = _media_thumb_gif(origin_path, thumb_width, thumb_height, format, thumb_info);
1036 } else if (image_type == IMG_CODEC_BMP) {
1037 err = _media_thumb_bmp(origin_path, thumb_width, thumb_height, format, thumb_info);
1040 err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext));
1041 if (err != MS_MEDIA_ERR_NONE) {
1042 thumb_warn("_media_thumb_get_file_ext failed");
1044 if (strcasecmp(file_ext, "wbmp") == 0) {
1045 image_type = IMG_CODEC_WBMP;
1047 int wbmp_height = 0;
1049 err = _media_thumb_get_wh_with_evas(origin_path, &wbmp_width, &wbmp_height);
1050 if (err != MS_MEDIA_ERR_NONE) {
1051 thumb_err("_media_thumb_get_wh_with_evas in WBMP : %d", err);
1055 if (wbmp_width * wbmp_height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB) {
1056 thumb_warn("This original image is too big");
1057 return MS_MEDIA_ERR_THUMB_TOO_BIG;
1060 thumb_info->origin_width = wbmp_width;
1061 thumb_info->origin_height = wbmp_height;
1063 err = _media_thumb_wbmp(origin_path, thumb_width, thumb_height, format, thumb_info);
1069 thumb_warn("Unsupported image type");
1070 return MS_MEDIA_ERR_INVALID_PARAMETER;
1076 int _media_thumb_video(const char *origin_path,
1079 media_thumb_format format,
1080 media_thumb_info *thumb_info)
1082 int err = MS_MEDIA_ERR_NONE;
1084 MMHandleType content = (MMHandleType) NULL;
1086 int video_track_num = 0;
1087 char *err_msg = NULL;
1092 bool drm_type = FALSE;
1096 /* Get Content Tag attribute for orientatin */
1097 MMHandleType tag = (MMHandleType) NULL;
1100 err = mm_file_create_tag_attrs(&tag, origin_path);
1101 mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
1103 if (err == FILEINFO_ERROR_NONE) {
1104 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
1105 if (err == FILEINFO_ERROR_NONE && size >= 0) {
1107 rot_type = MM_UTIL_ROTATE_0;
1109 if (strncmp(p, "90", size) == 0) {
1110 rot_type = MM_UTIL_ROTATE_90;
1111 } else if (strncmp(p, "180", size) == 0) {
1112 rot_type = MM_UTIL_ROTATE_180;
1113 } else if (strncmp(p, "270", size) == 0) {
1114 rot_type = MM_UTIL_ROTATE_270;
1116 rot_type = MM_UTIL_ROTATE_0;
1119 thumb_dbg("There is tag rotate : %d", rot_type);
1121 thumb_dbg("There is NOT tag rotate");
1122 rot_type = MM_UTIL_ROTATE_0;
1126 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL);
1127 if (err != FILEINFO_ERROR_NONE) {
1133 rot_type = MM_UTIL_ROTATE_0;
1137 err = mm_file_destroy_tag_attrs(tag);
1138 if (err != FILEINFO_ERROR_NONE) {
1139 thumb_err("fail to free tag attr - err(%x)", err);
1142 if (cdis_value == 1) {
1143 thumb_warn("This is CDIS vlaue 1");
1144 err = mm_file_create_content_attrs_safe(&content, origin_path);
1146 err = mm_file_create_content_attrs(&content, origin_path);
1149 if (err != FILEINFO_ERROR_NONE) {
1150 thumb_err("mm_file_create_content_attrs fails : %d", err);
1151 return MS_MEDIA_ERR_INTERNAL;
1154 err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL);
1155 if (err != FILEINFO_ERROR_NONE) {
1156 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1158 mm_file_destroy_content_attrs(content);
1159 return MS_MEDIA_ERR_INTERNAL;
1162 /* MMF api handle both normal and DRM video */
1163 if (video_track_num > 0 || is_drm) {
1165 err = mm_file_get_attrs(content, &err_msg,
1166 MM_FILE_CONTENT_VIDEO_WIDTH,
1168 MM_FILE_CONTENT_VIDEO_HEIGHT,
1170 MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */
1173 if (err != FILEINFO_ERROR_NONE) {
1174 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1176 mm_file_destroy_content_attrs(content);
1177 return MS_MEDIA_ERR_INTERNAL;
1180 thumb_dbg("video width: %d", width);
1181 thumb_dbg("video height: %d", height);
1182 thumb_dbg("thumbnail size=%d", size);
1183 thumb_dbg("frame = 0x%x", frame);
1185 if (frame == NULL || width == 0 || height == 0) {
1186 thumb_err("Failed to get frame data");
1187 mm_file_destroy_content_attrs(content);
1188 return MS_MEDIA_ERR_INTERNAL;
1191 thumb_info->origin_width = width;
1192 thumb_info->origin_height = height;
1194 err = _media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height);
1196 if (width > thumb_width || height > thumb_height) {
1197 err = _media_thumb_resize_data(frame,
1200 MM_UTIL_IMG_FMT_RGB888,
1205 if (err != MS_MEDIA_ERR_NONE) {
1206 thumb_err("_media_thumb_resize_data failed - %d", err);
1207 SAFE_FREE(thumb_info->data);
1208 mm_file_destroy_content_attrs(content);
1212 thumb_info->size = size;
1213 thumb_info->width = width;
1214 thumb_info->height = height;
1215 thumb_info->data = malloc(size);
1216 if (thumb_info->data == NULL) {
1217 thumb_err("memory allcation failed");
1218 mm_file_destroy_content_attrs(content);
1219 return MS_MEDIA_ERR_OUT_OF_MEMORY;
1221 memcpy(thumb_info->data, frame, size);
1224 mm_file_destroy_content_attrs(content);
1225 if (rot_type == MM_UTIL_ROTATE_90 || rot_type == MM_UTIL_ROTATE_180 || rot_type == MM_UTIL_ROTATE_270) {
1226 /* Start to decode to rotate */
1227 unsigned char *rotated = NULL;
1228 unsigned int r_w = thumb_info->height;
1229 unsigned int r_h = thumb_info->width;
1230 unsigned int r_size = 0;
1232 if (rot_type == MM_UTIL_ROTATE_180) {
1233 r_w = thumb_info->width;
1234 r_h = thumb_info->height;
1237 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, r_w, r_h, &r_size);
1238 if (err != FILEINFO_ERROR_NONE) {
1239 thumb_err("mm_util_get_image_size failed : %d", err);
1240 SAFE_FREE(thumb_info->data);
1244 //thumb_dbg("Size of Rotated : %d", r_size);
1245 rotated = (unsigned char *)malloc(r_size);
1246 err = mm_util_rotate_image(thumb_info->data, thumb_info->width, thumb_info->height,
1247 MM_UTIL_IMG_FMT_RGB888,
1248 rotated, &r_w, &r_h,
1251 if (err != FILEINFO_ERROR_NONE) {
1252 thumb_err("mm_util_rotate_image failed : %d", err);
1253 SAFE_FREE(thumb_info->data);
1257 thumb_dbg("mm_util_rotate_image succeed");
1260 SAFE_FREE(thumb_info->data);
1261 thumb_info->data = rotated;
1262 thumb_info->size = r_size;
1263 thumb_info->width = r_w;
1264 thumb_info->height = r_h;
1267 err = _media_thumb_convert_format(thumb_info, MEDIA_THUMB_RGB888, format);
1268 if (err != MS_MEDIA_ERR_NONE) {
1269 thumb_err("_media_thumb_convert_format falied: %d", err);
1270 SAFE_FREE(thumb_info->data);
1274 thumb_dbg("no contents information");
1276 mm_file_destroy_content_attrs(content);
1278 return MS_MEDIA_ERR_INTERNAL;
1284 static char* _media_thumb_mmc_get_path(uid_t uid)
1286 char *result_psswd = NULL;
1287 struct group *grpinfo = NULL;
1288 if (uid == getuid()) {
1289 if (THUMB_MMC_PATH != NULL)
1290 result_psswd = strndup(THUMB_MMC_PATH, strlen(THUMB_MMC_PATH));
1291 grpinfo = getgrnam("users");
1292 if (grpinfo == NULL) {
1293 thumb_err("getgrnam(users) returns NULL !");
1299 struct passwd *userinfo = getpwuid(uid);
1300 if (userinfo == NULL) {
1301 thumb_err("getpwuid(%d) returns NULL !", uid);
1304 grpinfo = getgrnam("users");
1305 if (grpinfo == NULL) {
1306 thumb_err("getgrnam(users) returns NULL !");
1309 // Compare git_t type and not group name
1310 if (grpinfo->gr_gid != userinfo->pw_gid) {
1311 thumb_err("UID [%d] does not belong to 'users' group!", uid);
1314 asprintf(&result_psswd, "%s/share/media/.thumb/mmc", userinfo->pw_dir);
1317 return result_psswd;
1320 static char* _media_thumb_phone_get_path(uid_t uid)
1322 char *result_psswd = NULL;
1323 struct group *grpinfo = NULL;
1324 if (uid == getuid()) {
1325 if (THUMB_PHONE_PATH != NULL)
1326 result_psswd = strndup(THUMB_PHONE_PATH, strlen(THUMB_PHONE_PATH));
1327 grpinfo = getgrnam("users");
1328 if (grpinfo == NULL) {
1329 thumb_err("getgrnam(users) returns NULL !");
1335 struct passwd *userinfo = getpwuid(uid);
1336 if (userinfo == NULL) {
1337 thumb_err("getpwuid(%d) returns NULL !", uid);
1340 grpinfo = getgrnam("users");
1341 if (grpinfo == NULL) {
1342 thumb_err("getgrnam(users) returns NULL !");
1345 // Compare git_t type and not group name
1346 if (grpinfo->gr_gid != userinfo->pw_gid) {
1347 thumb_err("UID [%d] does not belong to 'users' group!", uid);
1350 asprintf(&result_psswd, "%s/share/media/.thumb/phone", userinfo->pw_dir);
1353 return result_psswd;
1356 int _media_thumb_get_hash_name(const char *file_full_path,
1357 char *thumb_hash_path, size_t max_thumb_path, uid_t uid)
1359 char *hash_name = NULL;
1360 /*char *thumb_dir = NULL;*/
1361 char file_ext[255] = { 0 };
1362 char *get_path = NULL;
1364 media_thumb_store_type store_type = -1;
1366 if (file_full_path == NULL || thumb_hash_path == NULL || max_thumb_path <= 0) {
1367 thumb_err("file_full_path==NULL || thumb_hash_path == NULL || max_thumb_path <= 0");
1368 return MS_MEDIA_ERR_INVALID_PARAMETER;
1371 _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext));
1373 store_type = _media_thumb_get_store_type_by_path(file_full_path);
1374 /*if (store_type == THUMB_PHONE) {
1375 thumb_dir = _media_thumb_phone_get_path(uid);
1376 } else if (store_type == THUMB_MMC) {
1377 thumb_dir = _media_thumb_mmc_get_path(uid);
1379 thumb_dir = _media_thumb_phone_get_path(uid);
1382 hash_name = _media_thumb_generate_hash_name(file_full_path);
1383 if (hash_name == NULL) {
1384 thumb_err("_media_thumb_generate_hash_name fail");
1385 return MS_MEDIA_ERR_INTERNAL;
1388 if (store_type == THUMB_PHONE) {
1389 get_path = _media_thumb_phone_get_path(uid);
1390 if (get_path != NULL)
1391 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1392 } else if (store_type == THUMB_MMC) {
1393 get_path = _media_thumb_mmc_get_path(uid);
1394 if (get_path != NULL)
1395 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1397 get_path = _media_thumb_phone_get_path(uid);
1398 if (get_path != NULL)
1399 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1402 SAFE_FREE(get_path);
1404 if ((ret_len < 0) || (ret_len > (int)max_thumb_path)) {
1405 thumb_err("invalid hash path ret_len[%d]", ret_len);
1406 return MS_MEDIA_ERR_INTERNAL;
1408 //thumb_dbg("thumb hash : %s", thumb_hash_path);
1410 return MS_MEDIA_ERR_NONE;
1414 int _media_thumb_save_to_file_with_evas(unsigned char *data,
1420 Ecore_Evas *ee = ecore_evas_buffer_new(w, h);
1422 thumb_err("ecore_evas_buffer_new failed");
1423 return MS_MEDIA_ERR_INTERNAL;
1426 Evas *evas = ecore_evas_get(ee);
1428 thumb_err("ecore_evas_get failed");
1429 ecore_evas_free(ee);
1430 return MS_MEDIA_ERR_INTERNAL;
1433 Evas_Object *img = NULL;
1434 img = evas_object_image_add(evas);
1437 thumb_err("evas_object_image_add failed");
1438 ecore_evas_free(ee);
1439 return MS_MEDIA_ERR_INTERNAL;
1442 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
1443 evas_object_image_size_set(img, w, h);
1444 evas_object_image_fill_set(img, 0, 0, w, h);
1446 if (alpha) evas_object_image_alpha_set(img, 1);
1448 evas_object_image_data_set(img, data);
1449 evas_object_image_data_update_add(img, 0, 0, w, h);
1451 if (evas_object_image_save(img, thumb_path, NULL, "quality=90 compress=1")) {
1452 thumb_dbg("evas_object_image_save success");
1453 ecore_evas_free(ee);
1455 return MS_MEDIA_ERR_NONE;
1457 thumb_err("evas_object_image_save failed");
1458 ecore_evas_free(ee);
1459 return MS_MEDIA_ERR_INTERNAL;