From: Minje Ahn Date: Wed, 17 Jan 2018 07:12:43 +0000 (+0900) Subject: [ACR-1157] Add synchronous API to create thumbnails X-Git-Tag: submit/tizen/20180205.005408~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=208c8e71c2ad576fcb30fb2582f43239711944fb;p=platform%2Fcore%2Fapi%2Fthumbnail-util.git [ACR-1157] Add synchronous API to create thumbnails Change-Id: I4f817d2c97a3f3badcd4356f4aa24888deec7032 Signed-off-by: Minje Ahn --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 20e0513..4f07ce6 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ SET(service "media") SET(submodule "thumbnail-util") # for package file -SET(dependents "dlog glib-2.0 capi-base-common media-thumbnail libmedia-utils storage") +SET(dependents "dlog glib-2.0 capi-base-common media-thumbnail libmedia-utils storage aul mm-fileinfo mmutil-magick") SET(fw_name "${project_prefix}-${service}-${submodule}") PROJECT(${fw_name}) diff --git a/doc/thumbnail_util_doc.h b/doc/thumbnail_util_doc.h index 77daafa..2290c9d 100755 --- a/doc/thumbnail_util_doc.h +++ b/doc/thumbnail_util_doc.h @@ -31,7 +31,7 @@ /** * @addtogroup CAPI_MEDIA_THUMBNAIL_UTIL_MODULE - * @brief The @ref CAPI_MEDIA_THUMBNAIL_UTIL_MODULE API provides functions for creating the thumbnail from an input media file. + * @brief The @ref CAPI_MEDIA_THUMBNAIL_UTIL_MODULE API provides functions for creating the thumbnail from a given media file. * @ingroup CAPI_MEDIA_FRAMEWORK * @section CAPI_MEDIA_THUMBNAIL_UTIL_MODULE_HEADER Required Header * \#include diff --git a/include/thumbnail_util.h b/include/thumbnail_util.h index 670982e..e5b5947 100755 --- a/include/thumbnail_util.h +++ b/include/thumbnail_util.h @@ -188,6 +188,73 @@ int thumbnail_util_cancel_all(thumbnail_h thumb) TIZEN_DEPRECATED_API; */ int thumbnail_util_destroy(thumbnail_h thumb); +/** + * @brief Extracts the thumbnail for the given media into a file, synchronously. + * @details This function creates thumbnail from a given media file. \n + * The generated thumbnail is saved in the given thumbnail path. \n + * The format of the thumbnail file is determined by the extension of the thumbnail path + * (e.g. path is input.jpg and thumbnail_path is thumbnail.png then thumbnail.png is encoded in the PNG format). \n + * If the extension is missing or the format is not supported, the thumbnail is encoded in the same format as the given media + * (e.g. path is input.jpg and thumbnail_path is thumbnail.out then thumbnail.out is encoded in the JPEG format). \n + * Supported image formats are as follows: \n + * - GIF, JPEG, PNG, BMP, WBMP \n + * Video files only support JPEG format thumbnail. + * + * @since_tizen 5.0 + * + * @remarks http://tizen.org/privilege/mediastorage is needed if input or output path points to media storage. \n + * http://tizen.org/privilege/externalstorage is needed if input or output path points to external storage. \n + * The width and height of the thumbnail to be generated cannot exceed 2000. \n + * + * @param[in] path The path of the original media file + * @param[in] width The width of the thumbnail + * @param[in] height The height of the thumbnail + * @param[in] thumbnail_path The path to save the generated thumbnail + * + * @return @c 0 on success, otherwise a negative error value + * + * @retval #THUMBNAIL_UTIL_ERROR_NONE Successful + * @retval #THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #THUMBNAIL_UTIL_ERROR_INVALID_OPERATION Invalid operation + * @retval #THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY Not enough memory is available + * @retval #THUMBNAIL_UTIL_ERROR_PERMISSION_DENIED Permission denied + * + */ +int thumbnail_util_extract_to_file(const char *path, unsigned int width, unsigned int height, const char *thumbnail_path); + +/** + * @brief Extracts the thumbnail for the given media into a buffer, synchronously. + * @details This function creates thumbnails from a given media file. \n + * The generated thumbnail is returned as a raw data stream. + * + * @since_tizen 5.0 + * + * @remarks http://tizen.org/privilege/mediastorage is needed if input or output path points to media storage. \n + * http://tizen.org/privilege/externalstorage is needed if input or output path points to external storage. \n + * The width and height of the thumbnail to be generated cannot exceed 2000. \n + * In the case of video file, color space of the generated thumbnail is RGB. \n + * In the case of image file, color space of the generated thumbnail is BGRA. \n + * The @a thumb_buffer should be released using free(). + * + * @param[in] path The path of the original media file + * @param[in] width The width of the thumbnail + * @param[in] height The height of the thumbnail + * @param[out] thumb_buffer The raw data of the thumbnail which is generated + * @param[out] thumb_size The size of the thumbnail which is generated + * @param[out] thumb_width The width of the thumbnail which is generated + * @param[out] thumb_height The height of the thumbnail which is generated + * + * @return @c 0 on success, otherwise a negative error value + * + * @retval #THUMBNAIL_UTIL_ERROR_NONE Successful + * @retval #THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #THUMBNAIL_UTIL_ERROR_INVALID_OPERATION Invalid operation + * @retval #THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY Not enough memory is available + * @retval #THUMBNAIL_UTIL_ERROR_PERMISSION_DENIED Permission denied + * + */ +int thumbnail_util_extract_to_buffer(const char *path, unsigned int width, unsigned int height, unsigned char **thumb_buffer, size_t *thumb_size, unsigned int *thumb_width, unsigned int *thumb_height); + /** * @} */ diff --git a/include/thumbnail_util_private.h b/include/thumbnail_util_private.h index 6fe642a..500aafe 100755 --- a/include/thumbnail_util_private.h +++ b/include/thumbnail_util_private.h @@ -46,6 +46,16 @@ extern "C" { #define SAFE_FREE(src) {if (src) {free(src); src = NULL; } } #define STRING_VALID(str) ((str != NULL && strlen(str) > 0) ? TRUE : FALSE) +typedef enum { + THUMBNAIL_UTIL_BUFFER = 0, + THUMBNAIL_UTIL_FILE, +} thumbnail_util_extract_type_e; + +typedef enum { + THUMBNAIL_UTIL_IMAGE = 0, + THUMBNAIL_UTIL_VIDEO, +} thumbnail_util_media_type_e; + typedef struct { int request_id; char *file_path; @@ -53,6 +63,17 @@ typedef struct { int dst_height; } thumbnail_s; +typedef struct { + char *path; + thumbnail_util_extract_type_e extract_type; + thumbnail_util_media_type_e media_type; + int width; + int height; + char *thumbnail_path; + unsigned char *buffer; + int buffer_size; +} thumbnail_data_s; + typedef struct { thumbnail_extracted_cb thumb_extract_cb; void *user_data; @@ -67,6 +88,22 @@ typedef struct { #define FONT_COLOR_CYAN "\033[36m" #define FONT_COLOR_GRAY "\033[37m" +#define thumbnail_util_gettid() syscall(__NR_gettid) + +#define thumbnail_util_retv_if(expr, val) do { \ + if (expr) { \ + LOGE(FONT_COLOR_RED"[%ld]"FONT_COLOR_RESET, thumbnail_util_gettid()); \ + return (val); \ + } \ + } while (0) + +#define thumbnail_util_retvm_if(expr, val, fmt, arg...) do { \ + if (expr) { \ + LOGE(FONT_COLOR_RED"[%ld]"fmt""FONT_COLOR_RESET, thumbnail_util_gettid(), ##arg); \ + return (val); \ + } \ + } while (0) + #define thumbnail_util_warn(fmt, arg...) do { \ LOGW(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, ##arg); \ } while (0) diff --git a/packaging/capi-media-thumbnail-util.spec b/packaging/capi-media-thumbnail-util.spec index 617caac..4612aa8 100755 --- a/packaging/capi-media-thumbnail-util.spec +++ b/packaging/capi-media-thumbnail-util.spec @@ -1,6 +1,6 @@ Name: capi-media-thumbnail-util Summary: A media thumbnail util library in Tizen Native API -Version: 0.1.11 +Version: 0.1.12 Release: 1 Group: Multimedia/API License: Apache-2.0 @@ -12,6 +12,9 @@ BuildRequires: pkgconfig(libmedia-utils) BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(media-thumbnail) BuildRequires: pkgconfig(storage) +BuildRequires: pkgconfig(aul) +BuildRequires: pkgconfig(mm-fileinfo) +BuildRequires: pkgconfig(mmutil-magick) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/src/thumbnail_util.c b/src/thumbnail_util.c index 506e7fd..d93a309 100755 --- a/src/thumbnail_util.c +++ b/src/thumbnail_util.c @@ -14,11 +14,19 @@ * limitations under the License. */ -#include -#include #include #include + +/* For async API */ #include +#include +#include + +/* For sync API */ +#include +#include +#include +#include #define MAX_SIZE 16 #define MAX_PATH_SIZE 4096 @@ -256,3 +264,414 @@ int thumbnail_util_destroy(thumbnail_h thumb) return ret; } + +////////////////////////////////////////// Sync + +void _thumbnail_util_destroy_thumb_data(thumbnail_data_s *thumb) +{ + SAFE_FREE(thumb->path); + SAFE_FREE(thumb->thumbnail_path); + SAFE_FREE(thumb->buffer); + SAFE_FREE(thumb); +} + +int _thumbnail_util_extract_video(thumbnail_data_s *thumb) +{ + int ret = THUMBNAIL_UTIL_ERROR_NONE; + MMHandleType content = NULL; + MMHandleType tag = NULL; + void *frame = NULL; + int video_track_num = 0; + char *err_msg = NULL; + int size = 0; + int width = 0; + int height = 0; + int cdis_value = 0; + mm_util_image_h img = NULL; + + thumbnail_util_retvm_if(thumb == NULL, THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Data is NULL"); + + //1. get CDIS + ret = mm_file_create_tag_attrs(&tag, thumb->path); + if (ret == FILEINFO_ERROR_NONE) { + ret = mm_file_get_attrs(tag, &err_msg, MM_FILE_TAG_CDIS, &cdis_value, NULL); + if (ret != FILEINFO_ERROR_NONE) { + cdis_value = 0; + SAFE_FREE(err_msg); + } + } else { + cdis_value = 0; + } + + ret = mm_file_destroy_tag_attrs(tag); + if (ret != FILEINFO_ERROR_NONE) { + thumbnail_util_error("fail to free tag attr - err(%x)", ret); + } + + thumbnail_util_warn("CDIS vlaue[%d]", cdis_value); + if (cdis_value == 1) + ret = mm_file_create_content_attrs_safe(&content, thumb->path); + else + ret = mm_file_create_content_attrs(&content, thumb->path); + + thumbnail_util_retvm_if(ret != FILEINFO_ERROR_NONE, THUMBNAIL_UTIL_ERROR_INVALID_OPERATION, "mm_file_create_content_attrs fails"); + + //2. get frame + ret = mm_file_get_attrs(content, &err_msg, MM_FILE_CONTENT_VIDEO_TRACK_COUNT, &video_track_num, NULL); + if (ret != FILEINFO_ERROR_NONE) { + thumbnail_util_error("mm_file_get_attrs fails : %s", err_msg); + SAFE_FREE(err_msg); + goto ERROR; + } + + if (video_track_num > 0) { + ret = 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, + &size, NULL); + + if (ret != FILEINFO_ERROR_NONE) { + thumbnail_util_error("mm_file_get_attrs fails : %s", err_msg); + SAFE_FREE(err_msg); + goto ERROR; + } + + thumbnail_util_debug("W[%d] H[%d] Size[%d] Frame[%p]", width, height, size, frame); + + if (frame == NULL || width == 0 || height == 0) { + thumbnail_util_error("Failed to get frame data"); + goto ERROR; + } + + mm_util_create_handle(&img, frame, width, height, size, MM_UTIL_IMG_FMT_RGB888); + + if (thumb->extract_type == THUMBNAIL_UTIL_FILE) { + ret = mm_util_resize_B_P(img, thumb->width, thumb->height, thumb->thumbnail_path); + mm_util_destroy_handle(img); + if (ret != MM_UTIL_ERROR_NONE) + goto ERROR; + } else { + mm_util_image_h res_img = NULL; + unsigned char *res_buf = NULL; + unsigned int res_width = 0; + unsigned int res_height = 0; + size_t res_buf_size = 0; + mm_util_magick_format res_format = MM_UTIL_IMG_FMT_NUM; + + ret = mm_util_resize_B_B(img, thumb->width, thumb->height, &res_img); + mm_util_destroy_handle(img); + if (ret != MM_UTIL_ERROR_NONE) + goto ERROR; + ret = mm_util_get_image(res_img, &res_buf, &res_width, &res_height, &res_buf_size, &res_format); + mm_util_destroy_handle(res_img); + if (ret != MM_UTIL_ERROR_NONE) + goto ERROR; + + thumb->buffer = malloc(res_buf_size * sizeof(unsigned char)); + if (thumb->buffer != NULL) { + memcpy(thumb->buffer, res_buf, res_buf_size); + thumb->buffer_size = res_buf_size; + thumb->width = res_width; + thumb->height = res_height; + } else { + SAFE_FREE(res_buf); + goto ERROR; + } + + SAFE_FREE(res_buf); + } + } + + mm_file_destroy_content_attrs(content); + return THUMBNAIL_UTIL_ERROR_NONE; +ERROR: + mm_file_destroy_content_attrs(content); + return THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY; +} + +int _thumbnail_util_extract(thumbnail_data_s *thumb) +{ + int ret = 0; + thumbnail_util_retvm_if(thumb == NULL, THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Data is NULL"); + + if (thumb->media_type == THUMBNAIL_UTIL_IMAGE) { + if (thumb->extract_type == THUMBNAIL_UTIL_FILE) { + ret = mm_util_resize_P_P(thumb->path, thumb->width, thumb->height, thumb->thumbnail_path); + if (ret != MM_UTIL_ERROR_NONE) + return THUMBNAIL_UTIL_ERROR_INVALID_OPERATION; + } else { + mm_util_image_h res_img = NULL; + unsigned char *buf = NULL; + unsigned int width = 0; + unsigned int height = 0; + size_t buf_size = 0; + mm_util_magick_format format = MM_UTIL_IMG_FMT_NUM; + + ret = mm_util_resize_P_B(thumb->path, thumb->width, thumb->height, MM_UTIL_IMG_FMT_BGRA8888, &res_img); + if (ret != MM_UTIL_ERROR_NONE) + return THUMBNAIL_UTIL_ERROR_INVALID_OPERATION; + + ret = mm_util_get_image(res_img, &buf, &width, &height, &buf_size, &format); + mm_util_destroy_handle(res_img); + if (ret != MM_UTIL_ERROR_NONE) + return THUMBNAIL_UTIL_ERROR_INVALID_OPERATION; + thumb->buffer = malloc(buf_size * sizeof(unsigned char)); + if (thumb->buffer != NULL) { + memcpy(thumb->buffer, buf, buf_size); + thumb->buffer_size = buf_size; + thumb->width = width; + thumb->height = height; + } else { + return THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY; + } + + SAFE_FREE(buf); + } + } else { + ret = _thumbnail_util_extract_video(thumb); + thumbnail_util_retvm_if(ret != THUMBNAIL_UTIL_ERROR_NONE, ret, "_thumbnail_util_extract_video failed"); + } + + return THUMBNAIL_UTIL_ERROR_NONE; +} + +int __thumbnail_util_get_file_ext(const char *file_path, char *file_ext, int max_len) +{ + int i = 0; + + for (i = (int)strlen(file_path); i >= 0; i--) { + if ((file_path[i] == '.') && (i < (int)strlen(file_path))) { + strncpy(file_ext, &file_path[i + 1], max_len); + return THUMBNAIL_UTIL_ERROR_NONE; + } + + /* meet the dir. no ext */ + if (file_path[i] == '/') + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; +} + +int _thumbnail_util_check_media_type(const char *path, thumbnail_util_media_type_e *type) +{ + int ret = 0; + int exist = 0; + char mimetype[255] = {0,}; + const char *unsupported_type = "image/tiff"; + const char *supported_type = "application/vnd.ms-asf"; + + // Check file is existed + if (path == NULL) + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + + exist = open(path, O_RDONLY); + if (exist < 0) { + thumbnail_util_error("Fail to open path[%s]", path); + if (errno == EACCES || errno == EPERM) + return THUMBNAIL_UTIL_ERROR_PERMISSION_DENIED; + else + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + close(exist); + + // Check media type + ret = aul_get_mime_from_file(path, mimetype, sizeof(mimetype)); + if (ret < 0) { + thumbnail_util_warn("aul_get_mime_from_file fail.. Now trying to get type by extension"); + + char ext[255] = { 0 }; + ret = __thumbnail_util_get_file_ext(path, ext, sizeof(ext)); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) { + thumbnail_util_error("__thumbnail_util_get_file_ext failed"); + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + + if (strcasecmp(ext, "JPG") == 0 || + strcasecmp(ext, "JPEG") == 0 || + strcasecmp(ext, "PNG") == 0 || + strcasecmp(ext, "GIF") == 0 || + strcasecmp(ext, "AGIF") == 0 || + strcasecmp(ext, "XWD") == 0 || + strcasecmp(ext, "BMP") == 0 || + strcasecmp(ext, "WBMP") == 0) { + *type = THUMBNAIL_UTIL_IMAGE; + return THUMBNAIL_UTIL_ERROR_NONE; + } else if (strcasecmp(ext, "AVI") == 0 || + strcasecmp(ext, "MPEG") == 0 || + strcasecmp(ext, "MP4") == 0 || + strcasecmp(ext, "DCF") == 0 || + strcasecmp(ext, "WMV") == 0 || + strcasecmp(ext, "3GPP") == 0 || + strcasecmp(ext, "3GP") == 0) { + *type = THUMBNAIL_UTIL_VIDEO; + return THUMBNAIL_UTIL_ERROR_NONE; + } else { + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + } + + thumbnail_util_debug("mime type : %s", mimetype); + + /* categorize from mimetype */ + if (strstr(mimetype, "image") != NULL) { + if (!strcmp(mimetype, unsupported_type)) { + thumbnail_util_warn("This is unsupport file type"); + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + *type = THUMBNAIL_UTIL_IMAGE; + return THUMBNAIL_UTIL_ERROR_NONE; + } else if (strstr(mimetype, "video") != NULL) { + *type = THUMBNAIL_UTIL_VIDEO; + return THUMBNAIL_UTIL_ERROR_NONE; + } else if (strstr(mimetype, supported_type) != NULL) { + *type = THUMBNAIL_UTIL_VIDEO; + return THUMBNAIL_UTIL_ERROR_NONE; + } + + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; +} + +bool _thumbnail_util_is_support_img(const char *path) +{ + int ret = 0; + ImgCodecType t = IMG_CODEC_NONE; + unsigned int w = 0; + unsigned int h = 0; + + ret = ImgGetImageInfo(path, &t, &w, &h); + if (ret != 0) + return false; + + if (t == IMG_CODEC_AGIF || + t == IMG_CODEC_JPEG || + t == IMG_CODEC_PNG || + t == IMG_CODEC_GIF || + t == IMG_CODEC_BMP || + t == IMG_CODEC_WBMP) + return true; + else + return false; +} + +int thumbnail_util_extract_to_buffer(const char *path, unsigned int width, unsigned int height, unsigned char **thumb_buffer, size_t *thumb_size, unsigned int *thumb_width, unsigned int *thumb_height) +{ + int ret = THUMBNAIL_UTIL_ERROR_NONE; + thumbnail_data_s *thumb = NULL; + thumbnail_util_media_type_e type = -1; + + thumbnail_util_retvm_if(!STRING_VALID(path), THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Wrong path"); + thumbnail_util_retvm_if((width > 2000 || width == 0) || (height > 2000 || width == 0), THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Wrong width/height"); + thumbnail_util_retvm_if(thumb_buffer == NULL || thumb_size == NULL || thumb_width == NULL || thumb_height == NULL, THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Out param is NULL"); + + /* check media type */ + ret = _thumbnail_util_check_media_type(path, &type); + + /* If image, check support format */ + if (type == THUMBNAIL_UTIL_IMAGE) { + if (_thumbnail_util_is_support_img(path) == false) { + thumbnail_util_error("This image format is not supported"); + return THUMBNAIL_UTIL_ERROR_UNSUPPORTED_CONTENT; + } + } + + thumb = calloc(1, sizeof(thumbnail_data_s)); + thumb->extract_type = THUMBNAIL_UTIL_BUFFER; + thumb->media_type = type; + thumb->path = g_strdup(path); + thumb->width = width; + thumb->height = height; + + if (thumb->path == NULL) { + _thumbnail_util_destroy_thumb_data(thumb); + return THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY; + } + + ret = _thumbnail_util_extract(thumb); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) { + thumbnail_util_error("Extract failed"); + _thumbnail_util_destroy_thumb_data(thumb); + } else { + *thumb_buffer = malloc(thumb->buffer_size); + memcpy(*thumb_buffer, thumb->buffer, thumb->buffer_size); + *thumb_size = thumb->buffer_size; + *thumb_width = thumb->width; + *thumb_height = thumb->height; + + _thumbnail_util_destroy_thumb_data(thumb); + } + + return ret; +} + +int thumbnail_util_extract_to_file(const char *path, unsigned int width, unsigned int height, const char *thumbnail_path) +{ + int ret = THUMBNAIL_UTIL_ERROR_NONE; + char *check_str = NULL; + thumbnail_data_s *thumb = NULL; + thumbnail_util_media_type_e type = -1; + + thumbnail_util_retvm_if(!STRING_VALID(path), THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Wrong path"); + thumbnail_util_retvm_if((width > 2000 || width == 0) || (height > 2000 || width == 0), THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Wrong width/height"); + thumbnail_util_retvm_if(!STRING_VALID(thumbnail_path), THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER, "Wrong thumbnail_path"); + + /* check media type */ + ret = _thumbnail_util_check_media_type(path, &type); + thumbnail_util_retvm_if(ret != THUMBNAIL_UTIL_ERROR_NONE, ret, "_thumbnail_util_check_media_type failed"); + + /* If image, check support format */ + if (type == THUMBNAIL_UTIL_IMAGE) { + if (_thumbnail_util_is_support_img(path) == false) { + thumbnail_util_error("This image format is not supported"); + return THUMBNAIL_UTIL_ERROR_UNSUPPORTED_CONTENT; + } + } + + /* check thumbnail path is writable */ + check_str = g_path_get_dirname(thumbnail_path); + if (check_str != NULL) { + if (access(check_str, W_OK) != 0) { + thumbnail_util_error("No permission to write[%s]", check_str); + SAFE_FREE(check_str); + return THUMBNAIL_UTIL_ERROR_PERMISSION_DENIED; + } else { + SAFE_FREE(check_str); + } + } + + /* If video file, thumbnail extension is only JPEG */ + if (type == THUMBNAIL_UTIL_VIDEO) { + if (!g_str_has_suffix(thumbnail_path, ".jpg") && + !g_str_has_suffix(thumbnail_path, ".JPG") && + !g_str_has_suffix(thumbnail_path, ".jpeg") && + !g_str_has_suffix(thumbnail_path, ".JPEG")) { + thumbnail_util_error("Wrong file name[%s]", thumbnail_path); + return THUMBNAIL_UTIL_ERROR_INVALID_PARAMETER; + } + } + + thumb = calloc(1, sizeof(thumbnail_data_s)); + thumb->extract_type = THUMBNAIL_UTIL_FILE; + thumb->media_type = type; + thumb->path = g_strdup(path); + thumb->width = width; + thumb->height = height; + thumb->thumbnail_path = g_strdup(thumbnail_path); + + if (thumb->path == NULL || thumb->thumbnail_path == NULL) { + _thumbnail_util_destroy_thumb_data(thumb); + return THUMBNAIL_UTIL_ERROR_OUT_OF_MEMORY; + } + + ret = _thumbnail_util_extract(thumb); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) + thumbnail_util_error("Extract failed"); + + _thumbnail_util_destroy_thumb_data(thumb); + + return ret; +} + diff --git a/test/thumbnail_util_test.c b/test/thumbnail_util_test.c index 78aff9c..abbf343 100755 --- a/test/thumbnail_util_test.c +++ b/test/thumbnail_util_test.c @@ -24,7 +24,7 @@ #include #include -#define MAX_SIZE 16 +#define MAX_SIZE 4096 GMainLoop *g_loop = NULL; char *g_id = NULL; @@ -159,14 +159,58 @@ int test_extract_thumbnail(bool cancel) int main(int argc, char *argv[]) { int ret = THUMBNAIL_UTIL_ERROR_NONE; + unsigned char *data = NULL; + unsigned int width = 0; + unsigned int height = 0; + size_t size = 0; + FILE *fp; + char file_name[MAX_SIZE + 1] = {0, }; thumbnail_util_debug("--- Thumbnail util test start ---"); - +#if 0 ret = test_extract_thumbnail(false); if (ret != THUMBNAIL_UTIL_ERROR_NONE) - return ret; + thumbnail_util_debug("test_extract_thumbnail failed[%d]", ret); +#endif + thumbnail_util_debug("--- thumbnail_util_extract_to_file start :: IMAGE ---"); + ret = thumbnail_util_extract_to_file(tzplatform_mkpath(TZ_USER_IMAGES, "test_image1.jpg"), 320, 240, tzplatform_mkpath(TZ_USER_IMAGES, "save_image1.jpg")); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) + thumbnail_util_debug("thumbnail_util_extract_to_file failed[%d]", ret); + + thumbnail_util_debug("--- thumbnail_util_extract_to_buffer start :: IMAGE ---"); + ret = thumbnail_util_extract_to_buffer(tzplatform_mkpath(TZ_USER_IMAGES, "test_image1.jpg"), 320, 240, &data, &size, &width, &height); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) { + thumbnail_util_debug("thumbnail_util_extract_to_buffer failed[%d]", ret); + } else { + memset(file_name, 0, sizeof(file_name)); + snprintf(file_name, MAX_SIZE, "%s/test_image1.raw", tzplatform_getenv(TZ_USER_IMAGES)); + fp = fopen(file_name, "w"); + fwrite(data, 1, size, fp); + fclose(fp); + + SAFE_FREE(data); + } + + thumbnail_util_debug("--- thumbnail_util_extract_to_file start :: VIDEO ---"); + ret = thumbnail_util_extract_to_file(tzplatform_mkpath(TZ_USER_IMAGES, "test_video1.mp4"), 320, 240, tzplatform_mkpath(TZ_USER_IMAGES, "save_video1.jpg")); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) + thumbnail_util_debug("thumbnail_util_extract_to_file failed[%d]", ret); + + thumbnail_util_debug("--- thumbnail_util_extract_to_buffer start :: VIDEO ---"); + ret = thumbnail_util_extract_to_buffer(tzplatform_mkpath(TZ_USER_IMAGES, "test_video1.mp4"), 320, 240, &data, &size, &width, &height); + if (ret != THUMBNAIL_UTIL_ERROR_NONE) { + thumbnail_util_debug("thumbnail_util_extract_to_buffer failed[%d]", ret); + } else { + memset(file_name, 0, sizeof(file_name)); + snprintf(file_name, MAX_SIZE, "%s/test_video1.raw", tzplatform_getenv(TZ_USER_IMAGES)); + fp = fopen(file_name, "w"); + fwrite(data, 1, size, fp); + fclose(fp); + + SAFE_FREE(data); + } thumbnail_util_debug("--- Thumbnail util test end ---"); - return ret; + return 0; }