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>
48 #define MEDIA_THUMB_ROUND_UP_8(num) (((num)+7)&~7)
50 int _media_thumb_rgb_to_argb(const unsigned char *src_data, const int src_size,
51 unsigned char **dst_data,
52 unsigned int *buf_size,
56 int err = MS_MEDIA_ERR_NONE;
59 if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, width, height, buf_size) < 0) {
60 thumb_err("mm_util_get_image_size failed");
61 return MS_MEDIA_ERR_INTERNAL;
64 thumb_dbg("mm_util_get_image_size : %d", *buf_size);
66 *dst_data = (unsigned char *)malloc(*buf_size);
67 if (*dst_data == NULL) {
68 thumb_err("Failed to allocate memory");
69 return MS_MEDIA_ERR_OUT_OF_MEMORY;
72 for (j = 0; ((j < src_size) && (i < *buf_size)); j += 3) {
73 (*dst_data)[i++] = (src_data[j + 2]);
74 (*dst_data)[i++] = (src_data[j + 1]);
75 (*dst_data)[i++] = (src_data[j]);
76 (*dst_data)[i++] = 0x0;
79 thumb_dbg("_media_thumb_rgb_to_argb success");
84 int _media_thumb_resize_with_evas(const void *image, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
86 Ecore_Evas *resize_img_ee;
89 thumb_err("Invalid parameter");
90 return MS_MEDIA_ERR_INVALID_PARAMETER;
92 resize_img_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
94 thumb_err("ecore_evas_buffer_new failed");
95 return MS_MEDIA_ERR_INTERNAL;
98 Evas *resize_img_e = ecore_evas_get(resize_img_ee);
100 thumb_err("ecore_evas_get failed");
101 ecore_evas_free(resize_img_ee);
102 return MS_MEDIA_ERR_INTERNAL;
105 Evas_Object *source_img = evas_object_image_add(resize_img_e);
107 thumb_err("evas_object_image_add failed");
108 ecore_evas_free(resize_img_ee);
109 return MS_MEDIA_ERR_INTERNAL;
112 evas_object_image_size_set(source_img, thumb_info->origin_width, thumb_info->origin_height);
113 evas_object_image_colorspace_set(source_img, EVAS_COLORSPACE_ARGB8888);
114 evas_object_image_fill_set(source_img, 0, 0, thumb_info->origin_width, thumb_info->origin_height);
115 evas_object_image_filled_set(source_img, EINA_TRUE);
117 evas_object_image_data_set(source_img, (int *)image);
118 evas_object_image_data_update_add(source_img, 0, 0, thumb_info->origin_width, thumb_info->origin_height);
120 if (thumb_info->origin_width * thumb_info->origin_height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB) {
121 thumb_warn("This is too large image. so this's scale is going to be down");
122 evas_object_image_load_scale_down_set(source_img, 10);
125 ecore_evas_resize(resize_img_ee, thumb_width, thumb_height);
127 evas_object_image_load_size_set(source_img, thumb_width, thumb_height);
128 evas_object_image_fill_set(source_img, 0, 0, thumb_width, thumb_height);
129 evas_object_image_filled_set(source_img, EINA_TRUE);
131 evas_object_resize(source_img, thumb_width, thumb_height);
132 evas_object_show(source_img);
134 /* Set alpha from original */
135 thumb_info->alpha = evas_object_image_alpha_get(source_img);
136 if (thumb_info->alpha)
137 ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
139 /* Create target buffer and copy origin resized img to it */
140 Ecore_Evas *target_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
142 thumb_err("ecore_evas_buffer_new failed");
143 ecore_evas_free(resize_img_ee);
144 return MS_MEDIA_ERR_INTERNAL;
147 Evas *target_evas = ecore_evas_get(target_ee);
149 thumb_err("ecore_evas_get failed");
150 ecore_evas_free(resize_img_ee);
151 ecore_evas_free(target_ee);
152 return MS_MEDIA_ERR_INTERNAL;
155 Evas_Object *ret_image = evas_object_image_add(target_evas);
156 evas_object_image_size_set(ret_image, thumb_width, thumb_height);
157 evas_object_image_fill_set(ret_image, 0, 0, thumb_width, thumb_height);
158 evas_object_image_filled_set(ret_image, EINA_TRUE);
160 evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
161 evas_object_image_data_update_add(ret_image, 0, 0, thumb_width, thumb_height);
163 unsigned int buf_size = 0;
164 if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
165 thumb_err("mm_util_get_image_size failed");
167 ecore_evas_free(resize_img_ee);
168 ecore_evas_free(target_ee);
170 return MS_MEDIA_ERR_INTERNAL;
173 thumb_info->size = buf_size;
174 thumb_info->width = thumb_width;
175 thumb_info->height = thumb_height;
176 thumb_info->data = malloc(buf_size);
177 if (thumb_info->data == NULL) {
178 thumb_err("Failed to allocate memory");
179 ecore_evas_free(resize_img_ee);
180 ecore_evas_free(target_ee);
182 return MS_MEDIA_ERR_OUT_OF_MEMORY;
185 void *image_data = evas_object_image_data_get(ret_image, EINA_TRUE);
186 if (image_data != NULL) {
187 memcpy(thumb_info->data, image_data, buf_size);
189 thumb_err("image_data is NULL. evas_object_image_data_get failed");
192 ecore_evas_free(target_ee);
193 ecore_evas_free(resize_img_ee);
195 thumb_dbg("_media_thumb_resize_with_evas success");
197 return MS_MEDIA_ERR_NONE;
200 int _media_thumb_rotate_argb(unsigned char *source, const unsigned int size, int format, int *ori_width, int *ori_height)
202 int dpp = 0; /* data per pixel */
205 int width = 0, height = 0;
206 unsigned char *temp_buf = NULL;
208 if (format == MM_UTIL_JPEG_FMT_BGRA8888) {
210 } else if (format == MM_UTIL_JPEG_FMT_RGB888) {
213 thumb_err("Invalid parameter");
214 return MS_MEDIA_ERR_INVALID_PARAMETER;
217 temp_buf = malloc(size);
218 if (temp_buf == NULL) {
219 thumb_err("Failed to allocate memory");
220 return MS_MEDIA_ERR_OUT_OF_MEMORY;
223 memset(temp_buf, 0x00, size);
225 height = *ori_height;
227 /* rotate image to 90 degree clockwise */
228 for (y = 0; y < height; y++) {
229 for (x = 0; x < width; x++) {
230 for (i = 0; i < dpp; i++) {
231 temp_buf[(x * height + (height - y - 1)) * dpp + i] = source[(y * width + x) * dpp + i];
236 /* copy image from temp buffer to original buffer */
237 memcpy(source, temp_buf, size);
240 /* swap width & height due to rotate 90 degree */
244 return MS_MEDIA_ERR_NONE;
247 int _media_thumb_rotate_thumb(unsigned char *data, int size, int *width, int *height, int orientation, int format)
249 int err = MS_MEDIA_ERR_NONE;
250 int i = 0, count = 0;
252 if (orientation == MM_UTIL_ROTATE_90) {
254 } else if (orientation == MM_UTIL_ROTATE_180) {
256 } else if (orientation == MM_UTIL_ROTATE_270) {
260 for (i = 0; i < count; i++) {
261 err = _media_thumb_rotate_argb(data, size, format, width, height);
262 if (err != MS_MEDIA_ERR_NONE) {
263 thumb_err("Failed to rotate video thumbnail %d", err);
266 // thumb_dbg("[%d rotate] width:%d, height:%d", (i + 1) * 90, thumb_info->width, thumb_info->height);
269 thumb_dbg("_media_thumb_rotate_thumb success");
270 return MS_MEDIA_ERR_NONE;
273 int _media_thumb_get_proper_thumb_size(int orig_w, int orig_h, int *thumb_w, int *thumb_h)
275 BOOL portrait = FALSE;
278 if (orig_w < orig_h) {
282 /* Set smaller length to default size */
284 if (orig_w < *thumb_w)
286 ratio = (double)orig_h / (double)orig_w;
287 *thumb_h = *thumb_w * ratio;
289 if (orig_h < *thumb_h)
291 ratio = (double)orig_w / (double)orig_h;
292 *thumb_w = *thumb_h * ratio;
295 /** CAUTION :: The width of RGB888 raw data has to be rounded by 8 **/
296 *thumb_w = MEDIA_THUMB_ROUND_UP_8(*thumb_w);
298 thumb_dbg("proper thumb w: %d h: %d", *thumb_w, *thumb_h);
300 return MS_MEDIA_ERR_NONE;
303 int _media_thumb_get_exif_info(ExifData *ed, int *value, int ifdtype, long tagtype)
310 return MS_MEDIA_ERR_INVALID_PARAMETER;
316 entry = exif_content_get_entry(ed->ifd[ifd], tag);
318 if (tag == EXIF_TAG_ORIENTATION ||
319 tag == EXIF_TAG_PIXEL_X_DIMENSION ||
320 tag == EXIF_TAG_PIXEL_Y_DIMENSION) {
323 thumb_err("value is NULL");
324 return MS_MEDIA_ERR_INVALID_PARAMETER;
327 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
328 short exif_value = exif_get_short(entry->data, mByteOrder);
329 *value = (int)exif_value;
333 return MS_MEDIA_ERR_NONE;
336 static int __media_thumb_safe_atoi(char *buffer, int *si)
340 thumb_retvm_if(buffer == NULL || si == NULL, MS_MEDIA_ERR_INTERNAL, "invalid parameter");
342 const long sl = strtol(buffer, &end, 10);
344 thumb_retvm_if(end == buffer, MS_MEDIA_ERR_INTERNAL, "not a decimal number");
345 thumb_retvm_if('\0' != *end, MS_MEDIA_ERR_INTERNAL, "extra characters at end of input: %s", end);
346 thumb_retvm_if((LONG_MIN == sl || LONG_MAX == sl) && (ERANGE == errno), MS_MEDIA_ERR_INTERNAL, "out of range of type long");
347 thumb_retvm_if(sl > INT_MAX, MS_MEDIA_ERR_INTERNAL, "greater than INT_MAX");
348 thumb_retvm_if(sl < INT_MIN, MS_MEDIA_ERR_INTERNAL, "less than INT_MIN");
352 return MS_MEDIA_ERR_NONE;
355 static int _media_thumb_get_data_from_exif(ExifData *ed,
367 ExifByteOrder byte_order = exif_data_get_byte_order(ed);
370 tag = EXIF_TAG_COMPRESSION;
372 entry = exif_content_get_entry(ed->ifd[ifd], tag);
375 /* Get the contents of the tag in human-readable form */
376 ExifShort value = exif_get_short(entry->data, byte_order);
377 //thumb_dbg("%s: %d", exif_tag_get_name_in_ifd(tag,ifd), value);
380 thumb_dbg("There's jpeg thumb in this image");
382 thumb_dbg("There's NO jpeg thumb in this image");
383 return MS_MEDIA_ERR_INVALID_PARAMETER;
386 thumb_dbg("entry is NULL");
387 return MS_MEDIA_ERR_INVALID_PARAMETER;
390 /* copy the real thumbnail data from exif data */
391 if (ed->data && ed->size) {
392 /* NOTICE : ExifData->size type is unsigned int, But Internal IPC, and CAPI use int */
393 if (ed->size > INT_MAX) {
394 thumb_err("EXIF thumbnail size is over INT_MAX");
395 return MS_MEDIA_ERR_THUMB_TOO_BIG;
398 *thumb_data = (char *)malloc(ed->size);
400 if (*thumb_data == NULL) {
401 thumb_dbg("malloc failed!");
402 return MS_MEDIA_ERR_INVALID_PARAMETER;
405 memcpy(*thumb_data, (void *)ed->data, ed->size);
406 *thumb_size = ed->size;
408 thumb_dbg("data is NULL");
409 return MS_MEDIA_ERR_INVALID_PARAMETER;
412 /* Get width and height of thumbnail */
413 tag = EXIF_TAG_IMAGE_WIDTH;
414 entry = exif_content_get_entry(ed->ifd[ifd], tag);
417 /* Get the contents of the tag in human-readable form */
418 char width[10] = {0,};
419 exif_entry_get_value(entry, width, 10);
420 __media_thumb_safe_atoi(width, thumb_width);
422 thumb_warn("EXIF_TAG_IMAGE_WIDTH does not exist");
426 tag = EXIF_TAG_IMAGE_LENGTH;
427 entry = exif_content_get_entry(ed->ifd[ifd], tag);
429 /* Get the contents of the tag in human-readable form */
430 char height[10] = {0, };
431 exif_entry_get_value(entry, height, 10);
432 __media_thumb_safe_atoi(height, thumb_height);
434 thumb_warn("EXIF_TAG_IMAGE_LENGTH does not exist");
438 thumb_dbg("thumb width : height [%d:%d]", *thumb_width, *thumb_height);
440 /* Get width and height of original image from exif */
442 tag = EXIF_TAG_PIXEL_X_DIMENSION;
443 entry = exif_content_get_entry(ed->ifd[ifd], tag);
446 char width[10] = {0,};
447 exif_entry_get_value(entry, width, 10);
448 __media_thumb_safe_atoi(width, origin_width);
450 thumb_warn("EXIF_TAG_PIXEL_X_DIMENSION does not exist");
454 tag = EXIF_TAG_PIXEL_Y_DIMENSION;
455 entry = exif_content_get_entry(ed->ifd[ifd], tag);
458 char height[10] = {0, };
459 exif_entry_get_value(entry, height, 10);
460 __media_thumb_safe_atoi(height, origin_height);
462 thumb_warn("EXIF_TAG_PIXEL_Y_DIMENSION does not exist");
466 return MS_MEDIA_ERR_NONE;
469 int _media_thumb_get_thumb_from_exif(ExifData *ed,
470 const char *file_full_path,
471 const char *thumb_path,
475 media_thumb_info *thumb_info)
477 int err = MS_MEDIA_ERR_NONE;
480 int thumb_height = 0;
481 int origin_width = 0;
482 int origin_height = 0;
484 bool is_rotated = (orientation == ROT_90 || orientation == ROT_180 || orientation == ROT_270) ? TRUE : FALSE;
485 mm_util_jpeg_yuv_data decoded = {0,};
488 return MS_MEDIA_ERR_INVALID_PARAMETER;
491 err = _media_thumb_get_data_from_exif(ed,
499 if (err != MS_MEDIA_ERR_NONE) {
500 thumb_err("There is no exif data");
504 thumb_dbg("thumb width : height [%d:%d]", thumb_width, thumb_height);
505 thumb_dbg("origin width : height [%d:%d]", origin_width, origin_height);
506 thumb_info->origin_height = origin_height;
507 thumb_info->origin_width = origin_width;
509 if (thumb_width < required_width) {
510 thumb_err("Thumb data in exif is too small");
512 return MS_MEDIA_ERR_INVALID_PARAMETER;
516 err = mm_util_decode_from_jpeg_memory(&decoded, thumb, (unsigned int)size, MM_UTIL_JPEG_FMT_RGB888);
518 if (err != MS_MEDIA_ERR_NONE) {
519 thumb_err("mm_util_decode_from_jpeg_turbo_memory failed : %d", err);
523 thumb_width = decoded.width;
524 thumb_height = decoded.height;
526 int rot_type = MM_UTIL_ROTATE_0;
527 if (orientation == ROT_90) {
528 rot_type = MM_UTIL_ROTATE_90;
529 } else if (orientation == ROT_180) {
530 rot_type = MM_UTIL_ROTATE_180;
531 } else if (orientation == ROT_270) {
532 rot_type = MM_UTIL_ROTATE_270;
534 err = _media_thumb_rotate_thumb(decoded.data, decoded.size, &(decoded.width), &(decoded.height), rot_type, MM_UTIL_JPEG_FMT_RGB888);
535 if (err != MS_MEDIA_ERR_NONE) {
536 thumb_err("_media_thumb_rotate_thumb falied: %d", err);
537 SAFE_FREE(thumb_info->data);
540 //thumb_dbg("Width : %d, Height : %d", decoded.width, decoded.height);
541 thumb_info->data = decoded.data;
542 thumb_info->size = decoded.size;
543 thumb_info->width = decoded.width;
544 thumb_info->height = decoded.height;
546 /*in this case, just write raw data in file */
547 thumb_dbg_slog("Thumb is :%s", thumb_path);
550 int fd = open(thumb_path, O_RDWR | O_CREAT | O_EXCL | O_SYNC, 0644);
552 if (errno == EEXIST) {
553 thumb_err("thumb alread exist!");
555 thumb_err("open failed");
557 return MS_MEDIA_ERR_INVALID_PARAMETER;
560 nwrite = write(fd, thumb, size);
562 thumb_err("write failed");
566 return MS_MEDIA_ERR_INVALID_PARAMETER;
572 thumb_info->data = NULL;
573 thumb_info->size = size;
574 thumb_info->width = thumb_width;
575 thumb_info->height = thumb_height;
576 thumb_info->is_saved = TRUE;
582 int _media_thumb_get_wh_with_evas(const char *origin_path, int *width, int *height)
584 /* using evas to get w/h */
585 Ecore_Evas *ee = ecore_evas_buffer_new(0, 0);
587 thumb_err("ecore_evas_buffer_new fails");
588 return MS_MEDIA_ERR_INTERNAL;
591 Evas *evas = ecore_evas_get(ee);
593 thumb_err("ecore_evas_get fails");
595 return MS_MEDIA_ERR_INTERNAL;
598 Evas_Object *image_object = evas_object_image_add(evas);
600 thumb_err("evas_object_image_add fails");
602 return MS_MEDIA_ERR_INTERNAL;
605 evas_object_image_file_set(image_object, origin_path, NULL);
606 evas_object_image_size_get(image_object, width, height);
608 thumb_dbg("Width:%d, Height:%d", *width, *height);
612 return MS_MEDIA_ERR_NONE;
615 int _media_thumb_decode_with_evas(const char *origin_path,
616 int thumb_width, int thumb_height,
617 media_thumb_info *thumb_info, int need_scale, int orientation)
619 Ecore_Evas *resize_img_ee;
621 resize_img_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
622 if (!resize_img_ee) {
623 thumb_err("ecore_evas_buffer_new failed");
624 return MS_MEDIA_ERR_INTERNAL;
627 Evas *resize_img_e = ecore_evas_get(resize_img_ee);
629 thumb_err("ecore_evas_get failed");
630 ecore_evas_free(resize_img_ee);
631 return MS_MEDIA_ERR_INTERNAL;
634 Evas_Object *source_img = evas_object_image_add(resize_img_e);
636 thumb_err("evas_object_image_add failed");
637 ecore_evas_free(resize_img_ee);
638 return MS_MEDIA_ERR_INTERNAL;
641 evas_object_image_file_set(source_img, origin_path, NULL);
643 /* Get w/h of original image */
647 evas_object_image_size_get(source_img, &width, &height);
648 thumb_info->origin_width = width;
649 thumb_info->origin_height = height;
650 //thumb_dbg("origin width:%d, origin height:%d", width, height);
652 /* This case for only JPEG format.. JPEG can be partially processed.. */
653 if ((need_scale == 1) && (width * height > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
654 thumb_warn("This is too large image. so this's scale is going to be down");
655 evas_object_image_load_scale_down_set(source_img, 10);
658 if (orientation != TRANSPOSE)
659 evas_object_image_load_orientation_set(source_img, 1);
661 int rotated_orig_w = 0;
662 int rotated_orig_h = 0;
664 if (orientation == ROT_90 || orientation == ROT_270) {
665 rotated_orig_w = height;
666 rotated_orig_h = width;
668 rotated_orig_w = width;
669 rotated_orig_h = height;
671 //thumb_dbg("rotated - origin width:%d, origin height:%d", rotated_orig_w, rotated_orig_h);
673 int err = MS_MEDIA_ERR_NONE;
675 err = _media_thumb_get_proper_thumb_size(rotated_orig_w, rotated_orig_h, &thumb_width, &thumb_height);
676 if (err != MS_MEDIA_ERR_NONE) {
677 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
678 ecore_evas_free(resize_img_ee);
682 ecore_evas_resize(resize_img_ee, thumb_width, thumb_height);
684 evas_object_image_load_size_set(source_img, thumb_width, thumb_height);
685 evas_object_image_fill_set(source_img, 0, 0, thumb_width, thumb_height);
686 evas_object_image_filled_set(source_img, 1);
688 evas_object_resize(source_img, thumb_width, thumb_height);
689 evas_object_show(source_img);
691 /* Set alpha from original */
692 thumb_info->alpha = evas_object_image_alpha_get(source_img);
693 if (thumb_info->alpha) ecore_evas_alpha_set(resize_img_ee, EINA_TRUE);
695 /* Create target buffer and copy origin resized img to it */
696 Ecore_Evas *target_ee = ecore_evas_buffer_new(thumb_width, thumb_height);
698 thumb_err("ecore_evas_buffer_new failed");
699 ecore_evas_free(resize_img_ee);
700 return MS_MEDIA_ERR_INTERNAL;
703 Evas *target_evas = ecore_evas_get(target_ee);
705 thumb_err("ecore_evas_get failed");
706 ecore_evas_free(resize_img_ee);
707 ecore_evas_free(target_ee);
708 return MS_MEDIA_ERR_INTERNAL;
711 Evas_Object *ret_image = evas_object_image_add(target_evas);
712 evas_object_image_size_set(ret_image, thumb_width, thumb_height);
713 evas_object_image_fill_set(ret_image, 0, 0, thumb_width, thumb_height);
714 evas_object_image_filled_set(ret_image, EINA_TRUE);
716 evas_object_image_data_set(ret_image, (int *)ecore_evas_buffer_pixels_get(resize_img_ee));
717 evas_object_image_data_update_add(ret_image, 0, 0, thumb_width, thumb_height);
719 unsigned int buf_size = 0;
720 if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
721 thumb_err("mm_util_get_image_size failed");
723 ecore_evas_free(resize_img_ee);
724 ecore_evas_free(target_ee);
726 return MS_MEDIA_ERR_INTERNAL;
728 //thumb_dbg("mm_util_get_image_size : %d", buf_size);
730 thumb_info->size = buf_size;
731 thumb_info->width = thumb_width;
732 thumb_info->height = thumb_height;
733 thumb_info->data = malloc(buf_size);
734 if (thumb_info->data == NULL) {
735 thumb_err("Failed to allocate memory");
736 ecore_evas_free(resize_img_ee);
737 ecore_evas_free(target_ee);
739 return MS_MEDIA_ERR_OUT_OF_MEMORY;
742 void *image_data = evas_object_image_data_get(ret_image, 1);
743 if (image_data != NULL) {
744 memcpy(thumb_info->data, image_data, buf_size);
746 thumb_err("image_data is NULL. evas_object_image_data_get failed");
749 ecore_evas_free(target_ee);
750 ecore_evas_free(resize_img_ee);
755 int _media_thumb_convert_data(media_thumb_info *thumb_info, int thumb_width, int thumb_height)
757 int err = MS_MEDIA_ERR_NONE;
758 unsigned int buf_size = 0;
759 unsigned char *src_data = thumb_info->data;
760 unsigned char *dst_data = NULL;
763 if (mm_util_get_image_size(MM_UTIL_IMG_FMT_BGRA8888, thumb_width, thumb_height, &buf_size) < 0) {
764 thumb_err("mm_util_get_image_size failed");
765 return MS_MEDIA_ERR_INTERNAL;
768 thumb_dbg("mm_util_get_image_size : %d", buf_size);
770 dst_data = (unsigned char *)malloc(buf_size);
771 if (dst_data == NULL) {
772 thumb_err("Failed to allocate memory");
773 return MS_MEDIA_ERR_OUT_OF_MEMORY;
776 for (j = 0; j < thumb_width * 3 * thumb_height; j += 3) {
777 dst_data[i++] = (src_data[j + 2]);
778 dst_data[i++] = (src_data[j + 1]);
779 dst_data[i++] = (src_data[j]);
783 SAFE_FREE(thumb_info->data);
784 thumb_info->data = dst_data;
785 thumb_info->size = buf_size;
787 thumb_dbg("_media_thumb_convert_data success");
792 int _media_thumb_agif(const char *origin_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
794 int err = MS_MEDIA_ERR_NONE;
795 unsigned int *thumb = NULL;
796 unsigned char *dst_image = NULL;
797 unsigned int dst_size = 0;
798 unsigned int thumb_size = 0;
800 thumb = ImgGetFirstFrameAGIFAtSize(origin_path, thumb_info->origin_width, thumb_info->origin_height);
802 thumb_err("Frame data is NULL!!");
803 return MS_MEDIA_ERR_INTERNAL;
806 err = mm_util_get_image_size(MM_UTIL_IMG_FMT_RGB888, thumb_info->origin_width, thumb_info->origin_height, &thumb_size);
807 if (err != MS_MEDIA_ERR_NONE) {
808 thumb_err("mm_util_get_image_size failed: %d", err);
813 err = _media_thumb_get_proper_thumb_size(thumb_info->origin_width, thumb_info->origin_height, &thumb_width, &thumb_height);
814 if (err != MS_MEDIA_ERR_NONE) {
815 thumb_err("_media_thumb_get_proper_thumb_size failed: %d", err);
820 err = _media_thumb_rgb_to_argb((unsigned char *) thumb, thumb_size, &dst_image, &dst_size, thumb_info->origin_width, thumb_info->origin_height);
821 if (err != MS_MEDIA_ERR_NONE) {
822 thumb_err("_media_thumb_convert_data falied: %d", err);
827 err = _media_thumb_resize_with_evas(dst_image, thumb_width, thumb_height, thumb_info);
828 if (err != MS_MEDIA_ERR_NONE) {
829 thumb_err("_media_thumb_resize_data failed: %d", err);
830 SAFE_FREE(thumb_info->data);
840 int _media_thumb_general(const char *origin_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
842 int err = MS_MEDIA_ERR_NONE;
844 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, NORMAL);
845 if (err != MS_MEDIA_ERR_NONE) {
846 thumb_err("decode_with_evas failed : %d", err);
853 int _media_thumb_jpeg(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
855 int err = MS_MEDIA_ERR_NONE;
857 int orientation = NORMAL;
860 if (!thumb_info->is_raw) {
861 /* Load an ExifData object from an EXIF file */
862 ed = exif_data_new_from_file(origin_path);
865 /* First, Get orientation from exif */
866 err = _media_thumb_get_exif_info(ed, &orientation, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
867 if (err != MS_MEDIA_ERR_NONE) {
868 thumb_warn("_media_thumb_get_exif_info failed");
871 /* Second, Get thumb from exif */
872 err = _media_thumb_get_thumb_from_exif(ed, origin_path, thumb_path, orientation, thumb_width, thumb_height, thumb_info);
873 if (err != MS_MEDIA_ERR_NONE) {
874 thumb_dbg("_media_thumb_get_thumb_from_exif failed");
877 thumb_dbg("_media_thumb_get_thumb_from_exif succeed");
879 /* The case that original image's size is not in exif header. Use evas to get w/h */
880 if (thumb_info->origin_width == 0 || thumb_info->origin_height == 0) {
881 thumb_warn("original image's size is not in exif header. Use evas to get w/h");
882 err = _media_thumb_get_wh_with_evas(origin_path, &(thumb_info->origin_width), &(thumb_info->origin_height));
883 if (err != MS_MEDIA_ERR_NONE) {
884 thumb_err("Couldn't get w/h using evas : %s", origin_path);
886 thumb_dbg("origin w : %d, origin h : %d", thumb_info->origin_width, thumb_info->origin_height);
890 if (thumb_info->is_saved == FALSE) {
891 err = _media_thumb_convert_data(thumb_info, thumb_info->width, thumb_info->height);
892 if (err != MS_MEDIA_ERR_NONE) {
893 thumb_err("_media_thumb_convert_data failed : %d", err);
903 ed = exif_data_new_from_file(origin_path);
905 err = _media_thumb_get_exif_info(ed, &orientation, EXIF_IFD_0, EXIF_TAG_ORIENTATION);
906 if (err != MS_MEDIA_ERR_NONE) {
907 thumb_warn("_media_thumb_get_exif_info failed");
914 err = _media_thumb_decode_with_evas(origin_path, thumb_width, thumb_height, thumb_info, 1, orientation);
915 if (err != MS_MEDIA_ERR_NONE) {
916 thumb_err("decode_with_evas failed : %d", err);
924 int _media_thumb_image(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
926 int err = MS_MEDIA_ERR_NONE;
927 ImgCodecType image_type = 0;
928 unsigned int origin_w = 0;
929 unsigned int origin_h = 0;
931 err = ImgGetImageInfoForThumb(origin_path, &image_type, &origin_w, &origin_h);
932 if (err != MS_MEDIA_ERR_NONE) {
933 thumb_warn("Getting image info is failed err: %d", err);
936 thumb_info->origin_width = origin_w;
937 thumb_info->origin_height = origin_h;
939 if ((image_type != IMG_CODEC_JPEG) && (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) {
940 thumb_warn("This original image is too big");
941 return MS_MEDIA_ERR_THUMB_TOO_BIG;
944 if (image_type == IMG_CODEC_AGIF) {
945 err = _media_thumb_agif(origin_path, thumb_width, thumb_height, thumb_info);
946 } else if (image_type == IMG_CODEC_JPEG) {
947 err = _media_thumb_jpeg(origin_path, thumb_path, thumb_width, thumb_height, thumb_info);
948 } else if (image_type == IMG_CODEC_PNG || image_type == IMG_CODEC_GIF || image_type == IMG_CODEC_BMP || image_type == IMG_CODEC_WBMP) {
949 err = _media_thumb_general(origin_path, thumb_width, thumb_height, thumb_info);
951 thumb_warn("Unsupported image type");
952 return MS_MEDIA_ERR_THUMB_UNSUPPORTED;
958 int _media_thumb_video(const char *origin_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info)
960 int err = MS_MEDIA_ERR_NONE;
962 MMHandleType content = (MMHandleType) NULL;
964 int video_track_num = 0;
965 char *err_msg = NULL;
970 bool drm_type = FALSE;
974 /* Get Content Tag attribute for orientatin */
975 MMHandleType tag = (MMHandleType) NULL;
978 err = mm_file_create_tag_attrs(&tag, origin_path);
979 mm_util_img_rotate_type rot_type = MM_UTIL_ROTATE_0;
981 if (err == FILEINFO_ERROR_NONE) {
982 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL);
983 if (err == FILEINFO_ERROR_NONE && size >= 0) {
985 rot_type = MM_UTIL_ROTATE_0;
987 if (strncmp(p, "90", size) == 0) {
988 rot_type = MM_UTIL_ROTATE_90;
989 } else if (strncmp(p, "180", size) == 0) {
990 rot_type = MM_UTIL_ROTATE_180;
991 } else if (strncmp(p, "270", size) == 0) {
992 rot_type = MM_UTIL_ROTATE_270;
994 rot_type = MM_UTIL_ROTATE_0;
997 thumb_dbg("There is tag rotate : %d", rot_type);
999 thumb_dbg("There is NOT tag rotate");
1000 rot_type = MM_UTIL_ROTATE_0;
1004 err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL);
1005 if (err != FILEINFO_ERROR_NONE) {
1011 rot_type = MM_UTIL_ROTATE_0;
1015 err = mm_file_destroy_tag_attrs(tag);
1016 if (err != FILEINFO_ERROR_NONE) {
1017 thumb_err("fail to free tag attr - err(%x)", err);
1020 if (cdis_value == 1) {
1021 thumb_warn("This is CDIS vlaue 1");
1022 err = mm_file_create_content_attrs_safe(&content, origin_path);
1024 err = mm_file_create_content_attrs(&content, origin_path);
1027 if (err != FILEINFO_ERROR_NONE) {
1028 thumb_err("mm_file_create_content_attrs fails : %d", err);
1029 return MS_MEDIA_ERR_INTERNAL;
1032 err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL);
1033 if (err != FILEINFO_ERROR_NONE) {
1034 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1036 mm_file_destroy_content_attrs(content);
1037 return MS_MEDIA_ERR_INTERNAL;
1040 /* MMF api handle both normal and DRM video */
1041 if (video_track_num > 0 || is_drm) {
1042 err = mm_file_get_attrs(content, &err_msg,
1043 MM_FILE_CONTENT_VIDEO_WIDTH,
1045 MM_FILE_CONTENT_VIDEO_HEIGHT,
1047 MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */
1050 if (err != FILEINFO_ERROR_NONE) {
1051 thumb_err("mm_file_get_attrs fails : %s", err_msg);
1053 mm_file_destroy_content_attrs(content);
1054 return MS_MEDIA_ERR_INTERNAL;
1057 thumb_dbg("video width: %d", width);
1058 thumb_dbg("video height: %d", height);
1059 thumb_dbg("thumbnail size: %d", size);
1060 thumb_dbg("frame: %p", frame);
1061 thumb_dbg("orientation: %d", rot_type);
1063 if (frame == NULL || width == 0 || height == 0) {
1064 thumb_err("Failed to get frame data");
1065 mm_file_destroy_content_attrs(content);
1066 return MS_MEDIA_ERR_INTERNAL;
1069 thumb_info->origin_width = width;
1070 thumb_info->origin_height = height;
1072 err = _media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height);
1074 unsigned int new_size = 0;
1075 unsigned char *new_frame = NULL;
1076 err = _media_thumb_rgb_to_argb(frame, size, &new_frame, &new_size, width, height);
1077 if ((err != MS_MEDIA_ERR_NONE) || (new_frame == NULL)) {
1078 thumb_err("_media_thumb_convert_video falied: %d", err);
1079 mm_file_destroy_content_attrs(content);
1080 SAFE_FREE(new_frame);
1083 mm_file_destroy_content_attrs(content);
1084 thumb_dbg("original size - width:%d, height:%d", width, height);
1085 thumb_dbg("proper thumb size - width:%d, height:%d", thumb_width, thumb_height);
1086 if (width > thumb_width || height > thumb_height) {
1087 err = _media_thumb_resize_with_evas(new_frame, thumb_width, thumb_height, thumb_info);
1088 if (err != MS_MEDIA_ERR_NONE) {
1089 thumb_err("_media_thumb_resize_video_with_evas falied: %d", err);
1090 SAFE_FREE(new_frame);
1094 thumb_info->size = new_size;
1095 thumb_info->width = width;
1096 thumb_info->height = height;
1097 thumb_info->data = malloc(new_size);
1098 if (thumb_info->data == NULL) {
1099 thumb_err("memory allcation failed");
1100 SAFE_FREE(new_frame);
1101 return MS_MEDIA_ERR_OUT_OF_MEMORY;
1103 memcpy(thumb_info->data, new_frame, new_size);
1105 SAFE_FREE(new_frame);
1107 if (rot_type == MM_UTIL_ROTATE_90 || rot_type == MM_UTIL_ROTATE_180 || rot_type == MM_UTIL_ROTATE_270) {
1108 err = _media_thumb_rotate_thumb(thumb_info->data, thumb_info->size, &(thumb_info->width), &(thumb_info->height), rot_type, MM_UTIL_JPEG_FMT_BGRA8888);
1109 if (err != MS_MEDIA_ERR_NONE) {
1110 thumb_err("_media_thumb_rotate_thumb falied: %d", err);
1111 SAFE_FREE(thumb_info->data);
1116 thumb_dbg("no contents information");
1118 mm_file_destroy_content_attrs(content);
1120 return MS_MEDIA_ERR_INTERNAL;
1126 int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid)
1128 char *hash_name = NULL;
1129 /*char *thumb_dir = NULL;*/
1130 char file_ext[255] = { 0 };
1131 char *get_path = NULL;
1133 ms_user_storage_type_t store_type = -1;
1134 int ret = MS_MEDIA_ERR_NONE;
1136 if (file_full_path == NULL || thumb_hash_path == NULL || max_thumb_path <= 0) {
1137 thumb_err("file_full_path==NULL || thumb_hash_path == NULL || max_thumb_path <= 0");
1138 return MS_MEDIA_ERR_INVALID_PARAMETER;
1141 _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext));
1143 ret = ms_user_get_storage_type(uid, file_full_path, &store_type);
1144 if((ret != MS_MEDIA_ERR_NONE) || ((store_type != MS_USER_STORAGE_INTERNAL) && (store_type != MS_USER_STORAGE_EXTERNAL))) {
1145 thumb_err_slog("origin path(%s) is invalid. err : [%d] store_type [%d]", file_full_path, ret, store_type);
1146 return MS_MEDIA_ERR_INVALID_PARAMETER;
1149 hash_name = _media_thumb_generate_hash_name(file_full_path);
1150 if (hash_name == NULL) {
1151 thumb_err("_media_thumb_generate_hash_name fail");
1152 return MS_MEDIA_ERR_INTERNAL;
1155 if (store_type == MS_USER_STORAGE_EXTERNAL) {
1156 ret = ms_user_get_mmc_thumb_store_path(uid, &get_path);
1157 if (get_path != NULL)
1158 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1160 ret = ms_user_get_default_thumb_store_path(uid, &get_path);
1161 if (get_path != NULL)
1162 ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name);
1165 SAFE_FREE(get_path);
1167 if ((ret_len < 0) || (ret_len > (int)max_thumb_path)) {
1168 thumb_err("invalid hash path ret_len[%d]", ret_len);
1169 return MS_MEDIA_ERR_INTERNAL;
1171 //thumb_dbg("thumb hash : %s", thumb_hash_path);
1173 return MS_MEDIA_ERR_NONE;
1177 int _media_thumb_save_to_file_with_evas(unsigned char *data, int w, int h, int alpha, char *thumb_path)
1179 Ecore_Evas *ee = ecore_evas_buffer_new(w, h);
1181 thumb_err("ecore_evas_buffer_new failed");
1182 return MS_MEDIA_ERR_INTERNAL;
1185 Evas *evas = ecore_evas_get(ee);
1187 thumb_err("ecore_evas_get failed");
1188 ecore_evas_free(ee);
1189 return MS_MEDIA_ERR_INTERNAL;
1192 Evas_Object *img = NULL;
1193 img = evas_object_image_add(evas);
1196 thumb_err("evas_object_image_add failed");
1197 ecore_evas_free(ee);
1198 return MS_MEDIA_ERR_INTERNAL;
1201 evas_object_image_colorspace_set(img, EVAS_COLORSPACE_ARGB8888);
1202 evas_object_image_size_set(img, w, h);
1203 evas_object_image_fill_set(img, 0, 0, w, h);
1205 if (alpha) evas_object_image_alpha_set(img, 1);
1207 evas_object_image_data_set(img, data);
1208 evas_object_image_data_update_add(img, 0, 0, w, h);
1210 if (evas_object_image_save(img, thumb_path, NULL, "quality=90 compress=1")) {
1211 thumb_dbg("evas_object_image_save success");
1212 ecore_evas_free(ee);
1214 return MS_MEDIA_ERR_NONE;
1216 thumb_err("evas_object_image_save failed");
1217 ecore_evas_free(ee);
1218 return MS_MEDIA_ERR_INTERNAL;