/* * libmedia-thumbnail * * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: Hyunjun Ko * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include "media-thumb-debug.h" #include "media-thumb-util.h" #include "media-thumb-internal.h" #include "media-thumb-ipc.h" #include "media-thumb-db.h" #include #include #include #include #include int _media_thumb_get_proper_thumb_size(int orig_w, int orig_h, int *thumb_w, int *thumb_h) { bool portrait = false; double ratio; if (orig_w < orig_h) portrait = true; /* Set smaller length to default size */ if (portrait) { if (orig_w < *thumb_w) *thumb_w = orig_w; ratio = (double)orig_h / (double)orig_w; *thumb_h = *thumb_w * ratio; } else { if (orig_h < *thumb_h) *thumb_h = orig_h; ratio = (double)orig_w / (double)orig_h; *thumb_w = *thumb_h * ratio; } thumb_dbg("proper thumb w: %d h: %d", *thumb_w, *thumb_h); return MS_MEDIA_ERR_NONE; } int _media_thumb_general(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info) { int err = MS_MEDIA_ERR_NONE; mm_util_image_h img = NULL; unsigned char *buf = NULL; unsigned int width = 0; unsigned int height = 0; size_t size = 0; mm_util_color_format_e format = MM_UTIL_COLOR_NUM; if (thumb_path != NULL) { err = mm_util_resize_P_P(origin_path, thumb_width, thumb_height, thumb_path); } else { err = mm_util_resize_P_B(origin_path, thumb_width, thumb_height, MM_UTIL_COLOR_BGRA, &img); if (err != MM_UTIL_ERROR_NONE) { thumb_err("mm_util_resize_P_B failed : %d", err); return MS_MEDIA_ERR_INTERNAL; } mm_util_get_image(img, &buf, &width, &height, &size, &format); thumb_info->data = calloc(1, size); memcpy(thumb_info->data, buf, size); thumb_info->size = size; thumb_info->width = width; thumb_info->height = height; SAFE_FREE(buf); mm_util_destroy_handle(img); } return err; } int _media_thumb_image(const char *origin_path, char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info) { int err = MS_MEDIA_ERR_NONE; mm_util_img_codec_type image_type = 0; unsigned int origin_w = 0; unsigned int origin_h = 0; err = mm_util_extract_image_info(origin_path, &image_type, &origin_w, &origin_h); if (err != MS_MEDIA_ERR_NONE) { thumb_warn("Getting image info is failed err: %d", err); return MS_MEDIA_ERR_INTERNAL; } if ((image_type != IMG_CODEC_JPEG) && (origin_w * origin_h > THUMB_MAX_ALLOWED_MEM_FOR_THUMB)) { thumb_warn("This original image is too big"); return MS_MEDIA_ERR_THUMB_TOO_BIG; } _media_thumb_get_proper_thumb_size(origin_w, origin_h, &thumb_width, &thumb_height); if (image_type == IMG_CODEC_PNG) { if (thumb_path != NULL) { char file_ext[10]; err = _media_thumb_get_file_ext(origin_path, file_ext, sizeof(file_ext)); if (strncasecmp(file_ext, "png", 3) == 0) { int len = strlen(thumb_path); thumb_path[len - 3] = 'p'; thumb_path[len - 2] = 'n'; thumb_path[len - 1] = 'g'; } } err = _media_thumb_general(origin_path, thumb_path, thumb_width, thumb_height, thumb_info); } else if (image_type == IMG_CODEC_JPEG || image_type == IMG_CODEC_GIF || image_type == IMG_CODEC_BMP || image_type == IMG_CODEC_WBMP) { err = _media_thumb_general(origin_path, thumb_path, thumb_width, thumb_height, thumb_info); } else { thumb_warn("Unsupported image type"); return MS_MEDIA_ERR_THUMB_UNSUPPORTED; } return err; } int _media_thumb_video(const char *origin_path, const char *thumb_path, int thumb_width, int thumb_height, media_thumb_info *thumb_info) { int err = MS_MEDIA_ERR_NONE; MMHandleType content = (MMHandleType) NULL; MMHandleType tag = (MMHandleType) NULL; char *p = NULL; int cdis_value = 0; void *frame = NULL; int video_track_num = 0; char *err_msg = NULL; int size = 0; int width = 0; int height = 0; mm_util_image_h img = NULL; mm_util_image_h resize_img = NULL; mm_util_image_h dst_img = NULL; unsigned char *res_buf = NULL; size_t res_size = 0; unsigned int res_width = 0; unsigned int res_height = 0; mm_util_color_format_e res_format; /* Get Content Tag attribute for orientation */ err = mm_file_create_tag_attrs(&tag, origin_path); mm_util_magick_rotate_type rot_type = MM_UTIL_ROTATE_NUM; if (err == FILEINFO_ERROR_NONE) { err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_ROTATE, &p, &size, NULL); if (err == FILEINFO_ERROR_NONE && size >= 0) { if (p == NULL) { rot_type = MM_UTIL_ROTATE_0; } else { if (strncmp(p, "90", size) == 0) rot_type = MM_UTIL_ROTATE_90; else if (strncmp(p, "180", size) == 0) rot_type = MM_UTIL_ROTATE_180; else if (strncmp(p, "270", size) == 0) rot_type = MM_UTIL_ROTATE_270; else rot_type = MM_UTIL_ROTATE_0; } thumb_dbg("There is tag rotate : %d", rot_type); } else { thumb_dbg("There is NOT tag rotate"); rot_type = MM_UTIL_ROTATE_0; SAFE_FREE(err_msg); } err = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL); if (err != FILEINFO_ERROR_NONE) { cdis_value = 0; SAFE_FREE(err_msg); } } else { rot_type = MM_UTIL_ROTATE_0; cdis_value = 0; } err = mm_file_destroy_tag_attrs(tag); if (err != FILEINFO_ERROR_NONE) { thumb_err("fail to free tag attr - err(%x)", err); } if (cdis_value == 1) { thumb_warn("This is CDIS vlaue 1"); err = mm_file_create_content_attrs_safe(&content, origin_path); } else { err = mm_file_create_content_attrs(&content, origin_path); } if (err != FILEINFO_ERROR_NONE) { thumb_err("mm_file_create_content_attrs fails : %d", err); return MS_MEDIA_ERR_INTERNAL; } err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL); if (err != FILEINFO_ERROR_NONE) { thumb_err("mm_file_get_attrs fails : %s", err_msg); SAFE_FREE(err_msg); goto ERROR; } if (video_track_num > 0) { err = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_WIDTH, &width, MM_FILE_CONTENT_VIDEO_HEIGHT, &height, MM_FILE_CONTENT_VIDEO_THUMBNAIL, &frame, /* raw image is RGB888 format */ &size, NULL); if (err != FILEINFO_ERROR_NONE) { thumb_err("mm_file_get_attrs fails : %s", err_msg); SAFE_FREE(err_msg); goto ERROR; } thumb_dbg("W[%d] H[%d] Size[%d] Frame[%p] Rotate[%d]", width, height, size, frame, rot_type); if (frame == NULL || width == 0 || height == 0) { thumb_err("Failed to get frame data"); goto ERROR; } err = _media_thumb_get_proper_thumb_size(width, height, &thumb_width, &thumb_height); if (thumb_width <= 0 || thumb_height <= 0) { thumb_err("Failed to get thumb size"); goto ERROR; } thumb_dbg("Origin:W[%d] H[%d] Proper:W[%d] H[%d]", width, height, thumb_width, thumb_height); err = mm_util_create_handle(&img, (unsigned char *)frame, width, height, size, MM_UTIL_COLOR_RGB24); if (width > thumb_width || height > thumb_height) { if (rot_type != MM_UTIL_ROTATE_0) { if (STRING_VALID(thumb_path)) { err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img); if (err != MM_UTIL_ERROR_NONE) goto ERROR; err = mm_util_rotate_B_P(resize_img, rot_type, thumb_path); } else { err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img); if (err != MM_UTIL_ERROR_NONE) goto ERROR; err = mm_util_rotate_B_B(resize_img, rot_type, &dst_img); if (err != MM_UTIL_ERROR_NONE) goto ERROR; mm_util_get_image(dst_img, &res_buf, &res_width, &res_height, &res_size, &res_format); thumb_info->data = calloc(1, res_size); memcpy(thumb_info->data, res_buf, res_size); thumb_info->size = res_size; thumb_info->width = res_width; thumb_info->height = res_height; SAFE_FREE(res_buf); } } else { if (STRING_VALID(thumb_path)) { err = mm_util_resize_B_P(img, thumb_width, thumb_height, thumb_path); } else { err = mm_util_resize_B_B(img, thumb_width, thumb_height, &resize_img); if (err != MM_UTIL_ERROR_NONE) goto ERROR; mm_util_get_image(resize_img, &res_buf, &res_width, &res_height, &res_size, &res_format); thumb_info->data = calloc(1, res_size); memcpy(thumb_info->data, res_buf, res_size); thumb_info->size = res_size; thumb_info->width = res_width; thumb_info->height = res_height; SAFE_FREE(res_buf); } } } else { if (rot_type != MM_UTIL_ROTATE_0) { if (STRING_VALID(thumb_path)) { err = mm_util_rotate_B_P(img, rot_type, thumb_path); } else { err = mm_util_rotate_B_B(img, rot_type, &dst_img); if (err != MM_UTIL_ERROR_NONE) goto ERROR; mm_util_get_image(dst_img, &res_buf, &res_width, &res_height, &res_size, &res_format); thumb_info->data = calloc(1, res_size); memcpy(thumb_info->data, res_buf, res_size); thumb_info->size = res_size; thumb_info->width = res_width; thumb_info->height = res_height; SAFE_FREE(res_buf); } } else { if (STRING_VALID(thumb_path)) { err = mm_util_resize_B_P(img, width, height, thumb_path); } else { thumb_info->data = calloc(1, size); memcpy(thumb_info->data, frame, size); thumb_info->size = size; thumb_info->width = width; thumb_info->height = height; } } } } ERROR: mm_util_destroy_handle(img); mm_util_destroy_handle(resize_img); mm_util_destroy_handle(dst_img); mm_file_destroy_content_attrs(content); if (err != MS_MEDIA_ERR_NONE) return MS_MEDIA_ERR_INTERNAL; return MS_MEDIA_ERR_NONE; } int _media_thumb_get_hash_name(const char *file_full_path, char *thumb_hash_path, size_t max_thumb_path, uid_t uid) { char *hash_name = NULL; char file_ext[255] = { 0 }; char *get_path = NULL; char *storage_id = NULL; int ret_len = 0; ms_user_storage_type_e storage_type = -1; int ret = MS_MEDIA_ERR_NONE; if (file_full_path == NULL || thumb_hash_path == NULL || max_thumb_path <= 0) { thumb_err("file_full_path==NULL || thumb_hash_path == NULL || max_thumb_path <= 0"); return MS_MEDIA_ERR_INVALID_PARAMETER; } _media_thumb_get_file_ext(file_full_path, file_ext, sizeof(file_ext)); ret = ms_user_get_storage_type(uid, file_full_path, &storage_type); if ((ret != MS_MEDIA_ERR_NONE) || ((storage_type != MS_USER_STORAGE_INTERNAL) && (storage_type != MS_USER_STORAGE_EXTERNAL))) { thumb_err_slog("origin path(%s) is invalid. err : [%d] storage_type [%d]", file_full_path, ret, storage_type); return MS_MEDIA_ERR_INVALID_PARAMETER; } hash_name = _media_thumb_generate_hash_name(file_full_path); if (hash_name == NULL) { thumb_err("_media_thumb_generate_hash_name fail"); return MS_MEDIA_ERR_INTERNAL; } ret = _media_thumb_get_storage_id_from_db(file_full_path, &storage_id, uid); if (ret != MS_MEDIA_ERR_NONE) { thumb_err("_media_thumb_get_storage_id_from_db fail"); return MS_MEDIA_ERR_INTERNAL; } ret = ms_user_get_root_thumb_store_path(uid, &get_path); SAFE_FREE(storage_id); if (get_path != NULL) ret_len = snprintf(thumb_hash_path, max_thumb_path - 1, "%s/.%s-%s.jpg", get_path, file_ext, hash_name); SAFE_FREE(get_path); if ((ret_len < 0) || (ret_len > (int)max_thumb_path)) { thumb_err("invalid hash path ret_len[%d]", ret_len); return MS_MEDIA_ERR_INTERNAL; } return MS_MEDIA_ERR_NONE; }