Add internal APIs of encoding animated-gif frame by frame 49/145049/4
authorJiyong Min <jiyong.min@samsung.com>
Mon, 21 Aug 2017 04:06:32 +0000 (13:06 +0900)
committerJiyong Min <jiyong.min@samsung.com>
Mon, 21 Aug 2017 05:39:33 +0000 (14:39 +0900)
Change-Id: I6b2126cbc56a41fe04fd21a511e650b3b0abc761
Signed-off-by: Jiyong Min <jiyong.min@samsung.com>
include/image_util_internal.h [changed mode: 0644->0755]
include/image_util_private.h
include/image_util_type.h [changed mode: 0644->0755]
packaging/capi-media-image-util.spec
src/image_util.c
src/image_util_internal.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 67933dd..a92f2c5
@@ -18,6 +18,7 @@
 #define __TIZEN_MEDIA_IMAGE_UTIL_INTERNAL_H__
 
 #include <image_util_type.h>
+#include <mm_util_gif.h>
 
 #ifdef __cplusplus
 extern "C"
@@ -164,6 +165,204 @@ int image_util_rotate(unsigned char *dest, int *dest_width, int *dest_height, im
 */
 int image_util_crop(unsigned char *dest, int x, int y, int *width, int *height, const unsigned char *src, int src_width, int src_height, image_util_colorspace_e colorspace);
 
+/**
+* @internal
+* @brief Image util frame handle.
+* @since_tizen 4.0
+*/
+typedef void *image_util_frame_h;
+
+/**
+* @internal
+* @brief Creates the handle of the frame to encode.
+* @since_tizen 4.0
+*
+* @param[in] encode_h The encode handle
+* @param[in, out] frame_h The frame handle created by encode handle
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @post image_util_encode_frame_destroy()
+* @see image_util_encode_frame_destroy()
+*/
+int image_util_frame_create(void *decode_encode_h, image_util_frame_h *frame_h);
+
+/**
+* @internal
+* @brief Sets the resolution of the frame to encode.
+* @since_tizen 4.0
+*
+* @param[in] frame_h The frame handle to encode
+* @param[in] width The width of the frame
+* @param[in] height The height of the frame
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+int image_util_frame_set_resolution(image_util_frame_h frame_h, const int width, const int height);
+
+/**
+* @internal
+* @brief Sets the delay of the gif.
+* @since_tizen 4.0
+*
+* @remarks The unit of the delay time is 10ms. If the delay time set to 50ms, the value of @delay_time should be 5.
+*                If the delay time set to 1 sec, the value of @delay_time should be 100.
+*
+* @param[in] frame_h The frame handle to encode
+* @param[in] delay_time The delay time of the frame of the gif
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+int image_util_frame_set_gif_delay(image_util_frame_h frame_h, const int delay_time);
+
+#if 0
+/**
+* @internal
+* @brief Sets the position of the frame.
+* @since_tizen 4.0
+*
+* @param[in] frame_h The frame handle to destroy
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+int image_util_frame_set_position(image_util_frame_h frame_h, const int x, const int y, const int width, const int height);
+
+/**
+* @internal
+* @brief Sets the disposal mode of the gif.
+* @since_tizen 4.0
+*
+* @param[in] frame_h The frame handle to destroy
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+int image_util_frame_set_gif_disposal_mode(image_util_frame_h frame_h, const int disposal_mode);
+#endif
+
+/**
+* @internal
+* @brief Sets the delay of the gif.
+* @since_tizen 4.0
+*
+* @remarks The unit of the delay time is 10ms. If the delay time set to 50ms, the value of @delay_time should be 5.
+*                If the delay time set to 1 sec, the value of @delay_time should be 100.
+*
+* @param[in] frame_h The frame handle to encode
+* @param[in] buffer The frame buffer to encode
+* @param[in] buffer The size of the frame buffer to encode
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+int image_util_frame_set_frame(image_util_frame_h frame_h, unsigned char *buffer, const unsigned long size);
+
+/**
+* @internal
+* @brief Destroyes the handle of the frame to encode.
+* @since_tizen 4.0
+*
+* @param[in] frame_h The frame handle to destroy
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_frame_create()
+* @see image_util_encode_frame_create()
+*/
+void image_util_frame_destroy(image_util_frame_h frame_h);
+
+/**
+* @internal
+* @brief Adds the handle of the frame to encode.
+* @since_tizen 4.0
+*
+* @remarks The added frame is encoded to internal space. After frames are added,\n
+*                the application should call @image_util_encode_save function to complete encoding.
+*
+* @param[in] encode_h The encode handle
+* @param[in] frame_h The frame handle to encode
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+*
+* @pre image_util_encode_create()
+* @post image_util_encode_save()
+* @see image_util_encode_create()
+*/
+int image_util_encode_add_frame(image_util_encode_h encode_h, image_util_frame_h frame_h);
+
+/**
+* @internal
+* @brief Saves the enocoded image to the file or the buffer.
+* @since_tizen 4.0
+*
+* @remarks The saved images are encoded with added frames. Before call this function,\n
+*                the application should call @image_util_encode_add_frame function once or more.
+* @param[in] encode_h The encode handle to save
+*
+* @return @c 0 on success,
+*               otherwise a negative error value
+*
+* @retval #IMAGE_UTIL_ERROR_NONE Successful
+* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter
+* @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation
+* @retval #IMAGE_UTIL_ERROR_PERMISSION_DENIED The application does not have the privilege to call this funtion
+*
+* @pre image_util_encode_create()
+* @pre image_util_encode_add_frame()
+* @see image_util_encode_create()
+*/
+int image_util_encode_save(image_util_encode_h encode_h);
+
 #ifdef __cplusplus
 }
 #endif
index dbbbcadf5d73d34d6a571ce19fe3c64391865c00..1ce5ac48e8cc30d8daf214b15c75ffaa5115bc77 100755 (executable)
@@ -67,6 +67,11 @@ extern "C"
                image_util_warning("DEPRECATION WARNING: %s is deprecated and will be removed from next release. Use %s instead.", deprecated, instead);     \
        } while (0)
 
+#define IMAGE_UTIL_STRING_VALID(str)   \
+       ((str != NULL && strlen(str) > 0) ? true : false)
+
+#define IMAGE_UTIL_SAFE_FREE(src)      { if (src) {free(src); src = NULL; } }
+
 #define IMGCV_FUNC_NAME "mm_util_cv_extract_representative_color"
 #define PATH_MMUTIL_IMGCV_LIB PATH_LIBDIR"/libmmutil_imgcv.so"
 
@@ -118,13 +123,12 @@ typedef struct {
        void **dst_buffer;
        unsigned long long dst_size;
        char *path;
-       mm_util_imgp_h image_h;
+       void *image_h;
        unsigned long width;
        unsigned long height;
        bool is_decode;
        bool is_encoded;
        int quality;
-       unsigned int image_count;
        unsigned int current_buffer_count;
        unsigned int current_resolution_count;
        unsigned int current_delay_count;
@@ -138,6 +142,10 @@ typedef struct {
        GAsyncQueue *async_queue;
 } decode_encode_s;
 
+typedef struct {
+       void *frame_h;
+} frame_s;
+
 /**
 * @}
 */
old mode 100644 (file)
new mode 100755 (executable)
index 7b2d49d5e9e12eeab889f7f2b2ffe047e0c160ac..a95a38c9bc970d928f54df5314afdbada0eedfdd 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-image-util
 Summary:    A Image Utility library in Tizen Native API
-Version:    0.1.23
+Version:    0.1.24
 Release:    2
 Group:      Multimedia/API
 License:    Apache-2.0
@@ -57,6 +57,7 @@ cp %{SOURCE1001} .
 export CFLAGS+=" -Wextra -Wno-array-bounds"
 export CFLAGS+=" -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow"
 export CFLAGS+=" -Wwrite-strings -Wswitch-default"
+export CFLAGS+=" -DGIF_ENCODER_V2"
 export CFLAGS+=" -DPATH_LIBDIR=\\\"%{_libdir}\\\""
 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'`
 %cmake . -DFULLVER=%{version} -DMAJORVER=${MAJORVER} \
index c5907ad41081391fd2d3b90960fcddeb07e27d9d..b0854a2c428bcbb610af90a6fbc8491471dd8cf5 100755 (executable)
 #include <stdio.h>
 #include <stdlib.h>
 
-#define IMAGE_UTIL_STRING_VALID(str)   \
-       ((str != NULL && strlen(str) > 0) ? true : false)
-
-#define IMAGE_UTIL_SAFE_FREE(src)      { if (src) {free(src); src = NULL; } }
-
 static int _convert_colorspace_tbl[] = {
        MM_UTIL_IMG_FMT_YUV420,         /* IMAGE_UTIL_COLORSPACE_YUV420 */
        MM_UTIL_IMG_FMT_YUV422,         /* IMAGE_UTIL_COLORSPACE_YUV422 */
@@ -983,7 +978,6 @@ int image_util_decode_create(image_util_decode_h * handle)
        _handle->image_h = 0;
        _handle->is_decode = TRUE;
        _handle->image_type = -1;
-       _handle->image_count = 1;
 
        *handle = (image_util_decode_h) _handle;
 
@@ -1462,38 +1456,31 @@ int image_util_decode_destroy(image_util_decode_h handle)
        return err;
 }
 
-static int _image_util_encode_create_gif_buffer(void *data)
+static int _image_util_encode_get_gif_frame(mm_gif_file_h gif_data, unsigned int index, mm_gif_image_h *frame)
 {
-       mm_util_gif_data *gif_data = (mm_util_gif_data *) data;
-       image_util_retvm_if((gif_data == NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "Invalid Operation");
+       int err = MM_UTIL_ERROR_NONE;
+       image_util_retvm_if((gif_data == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((frame == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
 
-       gif_data->frames = (mm_util_gif_frame_data **) calloc(1, sizeof(mm_util_gif_frame_data *));
-       if (gif_data->frames == NULL) {
-               image_util_error("Error - OUT_OF_MEMORY");
-               IMAGE_UTIL_SAFE_FREE(gif_data);
-               return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
+       err = mm_util_gif_enocde_get_image_handle(gif_data, (int)index, frame);
+       if (err != MM_UTIL_ERROR_NONE) {
+               image_util_error("mm_util_gif_enocde_get_image_handle is failed %d", err);
+               return _convert_image_util_error_code(__func__, err);
        }
-       gif_data->frames[0] = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data));
-       if (gif_data->frames[0] == NULL) {
-               image_util_error("Error - OUT_OF_MEMORY");
-               IMAGE_UTIL_SAFE_FREE(gif_data->frames);
-               IMAGE_UTIL_SAFE_FREE(gif_data);
-               return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
+       if (*frame == NULL) {
+               err = mm_util_gif_image_create(gif_data, frame);
+               if (err != MM_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_image_create is failed %d", err);
+                       return _convert_image_util_error_code(__func__, err);
+               }
+               err = mm_util_gif_enocde_set_image_handle(gif_data, *frame);
+               if (err != MM_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_enocde_set_image_handle is failed %d", err);
+                       mm_util_gif_image_destory(*frame);
+                       return _convert_image_util_error_code(__func__, err);
+               }
        }
-
-       return IMAGE_UTIL_ERROR_NONE;
-}
-
-static void _image_util_encode_destroy_gif_buffer(void *data)
-{
-       mm_util_gif_data *gif_data = (mm_util_gif_data *)data;
-       unsigned int i = 0;
-       image_util_retm_if((gif_data == NULL), "Invalid GIF data");
-
-       for (i = 1; i < gif_data->image_count; i++)
-               IMAGE_UTIL_SAFE_FREE(gif_data->frames[i]);
-       IMAGE_UTIL_SAFE_FREE(gif_data->frames[0]);
-       IMAGE_UTIL_SAFE_FREE(gif_data->frames);
+       return err;
 }
 
 static void _image_util_encode_destroy_image_handle(decode_encode_s * handle)
@@ -1502,10 +1489,9 @@ static void _image_util_encode_destroy_image_handle(decode_encode_s * handle)
        void *image_handle = (void *)(handle->image_h);
        image_util_retm_if((image_handle == NULL), "Invalid image handle");
 
-       if (handle->image_type == IMAGE_UTIL_GIF) {
-               mm_util_encode_close_gif((mm_util_gif_data *) image_handle);
-               _image_util_encode_destroy_gif_buffer(image_handle);
-       }
+       if (handle->image_type == IMAGE_UTIL_GIF)
+               mm_util_gif_encode_destroy(image_handle);
+
        IMAGE_UTIL_SAFE_FREE(image_handle);
 }
 
@@ -1544,18 +1530,12 @@ static int _image_util_encode_create_png_handle(decode_encode_s * handle)
 static int _image_util_encode_create_gif_handle(decode_encode_s * handle)
 {
        int err = MM_UTIL_ERROR_NONE;
+       mm_gif_file_h _handle = NULL;
 
        image_util_retvm_if((handle == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
 
-       mm_util_gif_data *_handle = (mm_util_gif_data *) calloc(1, sizeof(mm_util_gif_data));
-       image_util_retvm_if((_handle == NULL), MM_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY(0x%08x)", MM_UTIL_ERROR_OUT_OF_MEMORY);
-
-       err = _image_util_encode_create_gif_buffer(_handle);
-       if (err != IMAGE_UTIL_ERROR_NONE) {
-               image_util_error("Error - _image_util_encode_init_gif_buffer is failed (%d)", err);
-               IMAGE_UTIL_SAFE_FREE(_handle);
-               return err;
-       }
+       err = mm_util_gif_encode_create(&_handle);
+       image_util_retvm_if((err != MM_UTIL_ERROR_NONE), _convert_image_util_error_code(__func__, err), "Error - mm_util_gif_encode_create is failed (%d)", err);
 
        handle->image_h = (mm_util_imgp_h) _handle;
 
@@ -1594,7 +1574,6 @@ int image_util_encode_create(image_util_type_e image_type, image_util_encode_h *
        _handle->image_h = 0;
        _handle->is_decode = FALSE;
        _handle->is_encoded = FALSE;
-       _handle->image_count = 1;
        _handle->current_buffer_count = 0;
        _handle->current_resolution_count = 0;
        _handle->current_delay_count = 0;
@@ -1668,43 +1647,30 @@ int image_util_encode_set_resolution(image_util_encode_h handle, unsigned long w
                break;
        case IMAGE_UTIL_GIF:
                {
-                       mm_util_gif_data *gif_data;
-
-                       gif_data = (mm_util_gif_data *) _handle->image_h;
+                       mm_gif_file_h gif_data = (mm_gif_file_h)_handle->image_h;
                        if (gif_data == NULL) {
                                image_util_error("Invalid gif data");
                                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
                        }
 
-                       if (!_handle->current_resolution_count) {
-                               gif_data->width = width;
-                               gif_data->height = height;
+                       image_util_retvm_if((width > INT_MAX) || (height > INT_MAX), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid resolution");
+
+                       if (_handle->current_resolution_count == 0) {
                                _handle->width = width;
                                _handle->height = height;
-                       } else if ((width > gif_data->frames[0]->width) || (height > gif_data->frames[0]->height)) {
-                               image_util_error("Image resolution cannot be more than the resolution of the first image");
-                               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+                               mm_util_gif_encode_set_resolution(gif_data, width, height);
                        }
-
-                       if (_handle->image_count <= _handle->current_resolution_count) {
-                               mm_util_gif_frame_data **tmp_buffer = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *));
-                               if (tmp_buffer == NULL) {
-                                       image_util_error("Error - OUT_OF_MEMORY");
-                                       _image_util_encode_destroy_gif_buffer(gif_data);
-                                       return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-                               }
-                               gif_data->frames = tmp_buffer;
-                               gif_data->frames[_handle->image_count] = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data));
-                               if (gif_data->frames[_handle->image_count] == NULL) {
-                                       image_util_error("Error - OUT_OF_MEMORY");
-                                       _image_util_encode_destroy_gif_buffer(gif_data);
-                                       return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-                               }
-                               _handle->image_count++;
+                       mm_gif_image_h frame = NULL;
+                       err = _image_util_encode_get_gif_frame(gif_data, _handle->current_resolution_count, &frame);
+                       if (err != MM_UTIL_ERROR_NONE) {
+                               image_util_error("_image_util_encode_get_gif_frame is failed %d", err);
+                               return _convert_image_util_error_code(__func__, err);
+                       }
+                       err = mm_util_gif_image_set_position(frame, 0, 0, (int)width, (int)height);
+                       if (err != MM_UTIL_ERROR_NONE) {
+                               image_util_error("mm_util_gif_image_set_position is failed %d", err);
+                               return _convert_image_util_error_code(__func__, err);
                        }
-
-                       gif_data->frames[_handle->current_resolution_count]->width = width;
-                       gif_data->frames[_handle->current_resolution_count]->height = height;
                        _handle->current_resolution_count++;
 
                        return err;
@@ -1810,7 +1776,7 @@ int image_util_encode_set_gif_frame_delay_time(image_util_encode_h handle, unsig
 {
        int err = IMAGE_UTIL_ERROR_NONE;
        decode_encode_s *_handle = (decode_encode_s *) handle;
-       mm_util_gif_data *gif_data;
+       mm_gif_file_h gif_data = NULL;
 
        if (_handle == NULL || _handle->is_decode == TRUE) {
                image_util_error("Invalid Handle");
@@ -1821,33 +1787,25 @@ int image_util_encode_set_gif_frame_delay_time(image_util_encode_h handle, unsig
                return IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
        }
 
-       gif_data = (mm_util_gif_data *) _handle->image_h;
+       gif_data = (mm_gif_file_h) _handle->image_h;
        if (gif_data == NULL) {
                image_util_error("Invalid gif data");
                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
-       if (gif_data->frames == NULL) {
-               image_util_error("Error allocating gif frames.");
-               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+
+       image_util_retvm_if((delay_time > INT_MAX), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid delay time");
+
+       mm_gif_image_h frame = NULL;
+       err = _image_util_encode_get_gif_frame(gif_data, _handle->current_delay_count, &frame);
+       if (err != MM_UTIL_ERROR_NONE) {
+               image_util_error("_image_util_encode_get_gif_frame is failed %d", err);
+               return _convert_image_util_error_code(__func__, err);
        }
-       if (_handle->image_count <= _handle->current_delay_count) {
-               mm_util_gif_frame_data **tmp_buffer = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *));
-               if (tmp_buffer == NULL) {
-                       image_util_error("Error - OUT_OF_MEMORY");
-                       _image_util_encode_destroy_gif_buffer(gif_data);
-                       return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-               }
-               gif_data->frames = tmp_buffer;
-               gif_data->frames[_handle->image_count] = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data));
-               if (gif_data->frames[_handle->image_count] == NULL) {
-                       image_util_error("Error - OUT_OF_MEMORY");
-                       _image_util_encode_destroy_gif_buffer(gif_data);
-                       return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-               }
-               _handle->image_count++;
+       err = mm_util_gif_image_set_delay_time(frame, (int)delay_time);
+       if (err != MM_UTIL_ERROR_NONE) {
+               image_util_error("mm_util_gif_image_set_delay_time is failed %d", err);
+               return _convert_image_util_error_code(__func__, err);
        }
-
-       gif_data->frames[_handle->current_delay_count]->delay_time = delay_time;
        _handle->current_delay_count++;
 
        return err;
@@ -1869,24 +1827,23 @@ int image_util_encode_set_input_buffer(image_util_encode_h handle, const unsigne
 
        /* initialize buffer and value for source buffer */
        if (_handle->image_type == IMAGE_UTIL_GIF) {
-               void **tmp_buffer = NULL;
-               if (_handle->is_encoded) {
-                       _image_util_encode_destroy_gif_buffer(_handle->image_h);
-                       err = _image_util_encode_create_gif_buffer(_handle->image_h);
-                       if (err != IMAGE_UTIL_ERROR_NONE) {
-                               image_util_error("Error - _image_util_encode_init_gif_buffer is failed (%d)", err);
-                               return err;
-                       }
-                       _handle->is_encoded = FALSE;
-                       _handle->image_count = 1;
-                       _handle->current_buffer_count = 0;
-                       _handle->current_resolution_count = 0;
-                       _handle->current_delay_count = 0;
+               mm_gif_file_h gif_data = (mm_gif_file_h) _handle->image_h;
+               mm_gif_image_h frame = NULL;
+               if (gif_data == NULL) {
+                       image_util_error("Invalid gif data");
+                       return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
                }
-               tmp_buffer = (void **)realloc(_handle->src_buffer, (_handle->current_buffer_count + 1) * sizeof(void *));
-               image_util_retvm_if((tmp_buffer == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "memory reallocation failed");
-               _handle->src_buffer = tmp_buffer;
-               _handle->src_buffer[_handle->current_buffer_count] = (void *)src_buffer;
+               err = _image_util_encode_get_gif_frame(gif_data, _handle->current_buffer_count, &frame);
+               if (err != MM_UTIL_ERROR_NONE) {
+                       image_util_error("_image_util_encode_get_gif_frame is failed %d", err);
+                       return _convert_image_util_error_code(__func__, err);
+               }
+               err = mm_util_gif_image_set_image(frame, src_buffer, (unsigned long)sizeof(src_buffer));
+               if (err != MM_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_image_set_delay_time is failed %d", err);
+                       return _convert_image_util_error_code(__func__, err);
+               }
+               _handle->current_buffer_count++;
        } else {
                if (_handle->src_buffer == NULL)
                        _handle->src_buffer = (void *)calloc(1, sizeof(void *));
@@ -1895,37 +1852,6 @@ int image_util_encode_set_input_buffer(image_util_encode_h handle, const unsigne
                _handle->src_buffer[_handle->current_buffer_count] = (void *)src_buffer;
        }
 
-       /* put the source buffer for animated-gif into array */
-       if (_handle->image_type == IMAGE_UTIL_GIF) {
-               mm_util_gif_data *gif_data;
-
-               gif_data = (mm_util_gif_data *) _handle->image_h;
-
-               if (gif_data->frames == NULL) {
-                       image_util_error("Error allocating gif frames.");
-                       return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
-               }
-               if (_handle->image_count <= _handle->current_buffer_count) {
-                       mm_util_gif_frame_data **tmp_buffer = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *));
-                       if (tmp_buffer == NULL) {
-                               image_util_error("Error - OUT_OF_MEMORY");
-                               _image_util_encode_destroy_gif_buffer(gif_data);
-                               return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-                       }
-                       gif_data->frames = tmp_buffer;
-                       gif_data->frames[_handle->image_count] = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data));
-                       if (gif_data->frames[_handle->image_count] == NULL) {
-                               image_util_error("Error - OUT_OF_MEMORY");
-                               _image_util_encode_destroy_gif_buffer(gif_data);
-                               return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
-                       }
-                       _handle->image_count++;
-               }
-
-               gif_data->frames[_handle->current_buffer_count]->data = _handle->src_buffer[_handle->current_buffer_count];
-               _handle->current_buffer_count++;
-       }
-
        return err;
 }
 
@@ -1947,18 +1873,6 @@ int image_util_encode_set_output_path(image_util_encode_h handle, const char *pa
 
        _handle->path = g_strndup(path, strlen(path));
 
-       if (_handle->image_type == IMAGE_UTIL_GIF) {
-               mm_util_gif_data *gif_data;
-
-               gif_data = (mm_util_gif_data *) _handle->image_h;
-
-               if (gif_data->frames == NULL) {
-                       image_util_error("Error allocating gif frames.");
-                       return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
-               }
-               mm_util_encode_open_gif_file(gif_data, path);
-       }
-
        return err;
 }
 
@@ -1979,17 +1893,6 @@ int image_util_encode_set_output_buffer(image_util_encode_h handle, unsigned cha
        IMAGE_UTIL_SAFE_FREE(_handle->path);
 
        _handle->dst_buffer = (void **)dst_buffer;
-       if (_handle->image_type == IMAGE_UTIL_GIF) {
-               mm_util_gif_data *gif_data;
-
-               gif_data = (mm_util_gif_data *) _handle->image_h;
-
-               if (gif_data->frames == NULL) {
-                       image_util_error("Error allocating gif frames.");
-                       return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
-               }
-               mm_util_encode_open_gif_memory(gif_data, _handle->dst_buffer);
-       }
 
        return err;
 }
@@ -2033,26 +1936,35 @@ static int _image_util_encode_internal(decode_encode_s * _handle)
                break;
        case IMAGE_UTIL_GIF:
                {
-                       mm_util_gif_data *gif_data;
-
-                       gif_data = (mm_util_gif_data *) _handle->image_h;
+                       mm_gif_file_h gif_data = (mm_gif_file_h)_handle->image_h;
+                       unsigned long encoded_buffer_size = 0;
                        if (gif_data == NULL) {
                                image_util_error("Invalid gif data");
                                return MM_UTIL_ERROR_INVALID_PARAMETER;
                        }
-                       if ((_handle->image_count > 1) && ((_handle->image_count != _handle->current_buffer_count) || (_handle->image_count != _handle->current_resolution_count) || (_handle->image_count != _handle->current_delay_count))) {
+                       image_util_debug("[Count] buffer:%d, resolution:%d, delay:%d", _handle->current_buffer_count, _handle->current_resolution_count, _handle->current_delay_count);
+                       if ((_handle->current_buffer_count > 1) && ((_handle->current_buffer_count != _handle->current_resolution_count) || (_handle->current_buffer_count != _handle->current_delay_count))) {
                                image_util_error("Total frame count does not match with the data set, for animated gif encoding");
                                return MM_UTIL_ERROR_INVALID_OPERATION;
+                       } else if ((_handle->current_buffer_count > 0) && ((_handle->current_buffer_count != _handle->current_resolution_count))) {
+                               image_util_error("Total frame count does not match with the data set, for gif encoding");
+                               return MM_UTIL_ERROR_INVALID_OPERATION;
                        }
-
-                       gif_data->image_count = _handle->image_count;
-                       err = mm_util_encode_gif(gif_data);
-
-                       if (err == MM_UTIL_ERROR_NONE) {
-                               _handle->dst_size = gif_data->size;
-                               _handle->width = gif_data->width;
-                               _handle->height = gif_data->height;
+                       if (_handle->path)
+                               err = mm_util_gif_encode_set_file(gif_data, _handle->path);
+                       else
+                               err = mm_util_gif_encode_set_mem(gif_data, _handle->dst_buffer, &encoded_buffer_size);
+                       if (err != MM_UTIL_ERROR_NONE) {
+                               image_util_error("mm_util_gif_encode_set_file | mm_util_gif_encode_set_mem is failed(%d)", err);
+                               return _convert_image_util_error_code(__func__, err);
+                       }
+                       err = mm_util_gif_encode(gif_data);
+                       if (err != MM_UTIL_ERROR_NONE) {
+                               image_util_error("mm_util_gif_encode is failed(%d)", err);
+                               return _convert_image_util_error_code(__func__, err);
                        }
+                       if (encoded_buffer_size != 0)
+                               _handle->dst_size = (unsigned long long)encoded_buffer_size;
                }
                break;
        case IMAGE_UTIL_BMP:
@@ -2102,8 +2014,12 @@ int image_util_encode_run(image_util_encode_h handle, unsigned long long *size)
                image_util_error("Invalid Handle");
                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
-       if ((_handle->path == NULL && _handle->dst_buffer == NULL) || _handle->src_buffer == NULL) {
-               image_util_error("Invalid input/output");
+       if (_handle->path == NULL && _handle->dst_buffer == NULL) {
+               image_util_error("Invalid output");
+               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+       }
+       if (_handle->image_type != IMAGE_UTIL_GIF && _handle->src_buffer == NULL) {
+               image_util_error("Invalid input");
                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
        image_util_retvm_if((_image_util_check_resolution(_handle->width, _handle->height) == false), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid resolution");
@@ -2178,8 +2094,12 @@ int image_util_encode_run_async(image_util_encode_h handle, image_util_encode_co
                image_util_error("Invalid Handle");
                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
-       if ((_handle->path == NULL && _handle->dst_buffer == NULL) || _handle->src_buffer == NULL) {
-               image_util_error("Invalid input/output");
+       if (_handle->path == NULL && _handle->dst_buffer == NULL) {
+               image_util_error("Invalid output");
+               return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
+       }
+       if (_handle->image_type != IMAGE_UTIL_GIF && _handle->src_buffer == NULL) {
+               image_util_error("Invalid input");
                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
        }
        image_util_retvm_if((_image_util_check_resolution(_handle->width, _handle->height) == false), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid resolution");
diff --git a/src/image_util_internal.c b/src/image_util_internal.c
new file mode 100755 (executable)
index 0000000..5c5163f
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+*
+* 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 <image_util.h>
+#include <image_util_internal.h>
+#include <image_util_private.h>
+
+int image_util_frame_create(void *decode_encode_h, image_util_frame_h *frame_h)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((decode_encode_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((frame_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+
+       decode_encode_s *image = (decode_encode_s *)decode_encode_h;
+       image_util_retvm_if((image->image_h == NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The image handle is wrong");
+       image_util_retvm_if((image->width == 0) || (image->height == 0), MM_UTIL_ERROR_INVALID_OPERATION, "The resolution is wrong");
+
+       frame_s *frame = calloc(1, sizeof(frame_s));
+       if (frame == NULL) {
+               image_util_error("Memory allocation is failed.");
+               return MM_UTIL_ERROR_OUT_OF_MEMORY;
+       }
+
+       if (image->image_type == IMAGE_UTIL_GIF) {
+               mm_gif_file_h gif_data = (mm_gif_file_h)image->image_h;
+               mm_gif_image_h gif_frame = NULL;
+
+               ret = mm_util_gif_image_create(gif_data, &gif_frame);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_image_create is failed(%d).", ret);
+                       IMAGE_UTIL_SAFE_FREE(frame);
+                       return MM_UTIL_ERROR_INVALID_OPERATION;
+               }
+               frame->frame_h = gif_frame;
+       } else {
+               image_util_error("The image type(%d) is not supported.", image->image_type);
+               IMAGE_UTIL_SAFE_FREE(frame);
+               return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
+       }
+
+       *frame_h = frame;
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+int image_util_frame_set_resolution(image_util_frame_h frame_h, const int width, const int height)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((frame_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((width <= 0) || (height <= 0), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Width or Height");
+
+       frame_s *frame = (frame_s *)frame_h;
+
+       ret = mm_util_gif_image_set_position(frame->frame_h, 0, 0, width, height);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               image_util_error("mm_util_gif_image_set_position is failed(%d).", ret);
+               return MM_UTIL_ERROR_INVALID_OPERATION;
+       }
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+int image_util_frame_set_gif_delay(image_util_frame_h frame_h, const int delay_time)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((frame_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((delay_time <= 0), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Delay Time");
+
+       frame_s *frame = (frame_s *)frame_h;
+
+       ret = mm_util_gif_image_set_delay_time(frame->frame_h, delay_time);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               image_util_error("mm_util_gif_image_set_delay_time is failed(%d).", ret);
+               return MM_UTIL_ERROR_INVALID_OPERATION;
+       }
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+int image_util_frame_set_frame(image_util_frame_h frame_h, unsigned char *buffer, const unsigned long size)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((frame_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((buffer == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Buffer");
+       image_util_retvm_if((size == 0), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Buffer Size");
+
+       frame_s *frame = (frame_s *)frame_h;
+
+       ret = mm_util_gif_image_set_image(frame->frame_h, buffer, size);
+       if (ret != IMAGE_UTIL_ERROR_NONE) {
+               image_util_error("mm_util_gif_image_set_image is failed(%d).", ret);
+               return MM_UTIL_ERROR_INVALID_OPERATION;
+       }
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+void image_util_frame_destroy(image_util_frame_h frame_h)
+{
+       image_util_retm_if((frame_h == NULL), "Invalid Handle");
+
+       frame_s *frame = (frame_s *)frame_h;
+       mm_util_gif_image_destory(frame->frame_h);
+}
+
+int image_util_encode_add_frame(image_util_encode_h encode_h, image_util_frame_h frame_h)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((encode_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+       image_util_retvm_if((frame_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+
+       decode_encode_s *encode = (decode_encode_s *)encode_h;
+       frame_s *frame = (frame_s *)frame_h;
+       image_util_retvm_if((encode->image_h == NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The image handle is wrong");
+       image_util_retvm_if((frame->frame_h == NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The frame handle is wrong");
+
+       if (encode->image_type == IMAGE_UTIL_GIF) {
+               mm_gif_file_h gif_data = (mm_gif_file_h)encode->image_h;
+
+               ret = mm_util_gif_encode_add_image(gif_data, (mm_gif_image_h)frame->frame_h);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_encode_add_image is failed(%d).", ret);
+                       mm_util_gif_encode_destroy(gif_data);
+                       return MM_UTIL_ERROR_INVALID_OPERATION;
+               }
+       } else {
+               image_util_error("The image type(%d) is not supported.", encode->image_type);
+               return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
+       }
+
+       return IMAGE_UTIL_ERROR_NONE;
+}
+
+int image_util_encode_save(image_util_encode_h encode_h)
+{
+       int ret = IMAGE_UTIL_ERROR_NONE;
+
+       image_util_retvm_if((encode_h == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
+
+       decode_encode_s *encode = (decode_encode_s *)encode_h;
+       image_util_retvm_if((encode->image_h == NULL), MM_UTIL_ERROR_INVALID_OPERATION, "The image handle is wrong");
+
+       if (encode->image_type == IMAGE_UTIL_GIF) {
+               mm_gif_file_h gif_data = (mm_gif_file_h)encode->image_h;
+
+               ret = mm_util_gif_encode_save(gif_data);
+               if (ret != IMAGE_UTIL_ERROR_NONE) {
+                       image_util_error("mm_util_gif_encode_save is failed(%d).", ret);
+                       mm_util_gif_encode_destroy(gif_data);
+                       return MM_UTIL_ERROR_INVALID_OPERATION;
+               }
+       } else {
+               image_util_error("The image type(%d) is not supported.", encode->image_type);
+               return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
+       }
+
+       return IMAGE_UTIL_ERROR_NONE;
+}