[ACR-1157] Add synchronous API to create thumbnails 51/167351/20
authorMinje Ahn <minje.ahn@samsung.com>
Wed, 17 Jan 2018 07:12:43 +0000 (16:12 +0900)
committerMinje Ahn <minje.ahn@samsung.com>
Tue, 30 Jan 2018 04:37:28 +0000 (13:37 +0900)
Change-Id: I4f817d2c97a3f3badcd4356f4aa24888deec7032
Signed-off-by: Minje Ahn <minje.ahn@samsung.com>
CMakeLists.txt
doc/thumbnail_util_doc.h
include/thumbnail_util.h
include/thumbnail_util_private.h
packaging/capi-media-thumbnail-util.spec
src/thumbnail_util.c
test/thumbnail_util_test.c

index 20e0513..4f07ce6 100755 (executable)
@@ -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})
index 77daafa..2290c9d 100755 (executable)
@@ -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 <thumbnail_util.h>
index 670982e..e5b5947 100755 (executable)
@@ -189,6 +189,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);
+
+/**
  * @}
  */
 
index 6fe642a..500aafe 100755 (executable)
@@ -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;
@@ -54,6 +64,17 @@ typedef struct {
 } 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;
 } thumbnail_extract_cb_s;
@@ -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)
index 617caac..4612aa8 100755 (executable)
@@ -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
 
index 506e7fd..d93a309 100755 (executable)
 * limitations under the License.
 */
 
-#include <media-thumbnail.h>
-#include <media-util.h>
 #include <thumbnail_util.h>
 #include <thumbnail_util_private.h>
+
+/* For async API */
 #include <storage.h>
+#include <media-thumbnail.h>
+#include <media-util.h>
+
+/* For sync API */
+#include <aul.h>
+#include <mm_util_magick.h>
+#include <mm_file.h>
+#include <img-codec-parser.h>
 
 #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;
+}
+
index 78aff9c..abbf343 100755 (executable)
@@ -24,7 +24,7 @@
 #include <thumbnail_util_private.h>
 #include <tzplatform_config.h>
 
-#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;
 }