From: Jiyong Min Date: Mon, 21 Aug 2017 04:06:32 +0000 (+0900) Subject: Add internal APIs of encoding animated-gif frame by frame X-Git-Tag: submit/tizen/20170824.093048~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d25e12ebe0806b33965bdc6a393595d0c5258e87;p=platform%2Fcore%2Fapi%2Fimage-util.git Add internal APIs of encoding animated-gif frame by frame Change-Id: I6b2126cbc56a41fe04fd21a511e650b3b0abc761 Signed-off-by: Jiyong Min --- diff --git a/include/image_util_internal.h b/include/image_util_internal.h old mode 100644 new mode 100755 index 67933dd..a92f2c5 --- a/include/image_util_internal.h +++ b/include/image_util_internal.h @@ -18,6 +18,7 @@ #define __TIZEN_MEDIA_IMAGE_UTIL_INTERNAL_H__ #include +#include #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 diff --git a/include/image_util_private.h b/include/image_util_private.h index dbbbcad..1ce5ac4 100755 --- a/include/image_util_private.h +++ b/include/image_util_private.h @@ -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; + /** * @} */ diff --git a/include/image_util_type.h b/include/image_util_type.h old mode 100644 new mode 100755 diff --git a/packaging/capi-media-image-util.spec b/packaging/capi-media-image-util.spec index 7b2d49d..a95a38c 100755 --- a/packaging/capi-media-image-util.spec +++ b/packaging/capi-media-image-util.spec @@ -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} \ diff --git a/src/image_util.c b/src/image_util.c index c5907ad..b0854a2 100755 --- a/src/image_util.c +++ b/src/image_util.c @@ -26,11 +26,6 @@ #include #include -#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 index 0000000..5c5163f --- /dev/null +++ b/src/image_util_internal.c @@ -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 +#include +#include + +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; +}