From: Vineeth TM Date: Mon, 1 Feb 2016 07:10:30 +0000 (+0900) Subject: [ACR-512] Add APIs for supporting animated gif encoding utility X-Git-Tag: submit/tizen/20160223.021211~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7af2417c306b2c908c6f2cd5fb6c49b2879bfb5d;p=platform%2Fcore%2Fapi%2Fimage-util.git [ACR-512] Add APIs for supporting animated gif encoding utility Change-Id: I0887c5fc1433f2629579f17a810bb8617d59677d Signed-off-by: Vineeth TM --- diff --git a/decode-test/image_util_decode_encode_testsuite.c b/decode-test/image_util_decode_encode_testsuite.c index 2d1d808..26fcede 100755 --- a/decode-test/image_util_decode_encode_testsuite.c +++ b/decode-test/image_util_decode_encode_testsuite.c @@ -166,20 +166,135 @@ int main(int argc, char *argv[]) image_util_encode_h encoded = NULL; void *src = NULL; unsigned char *data = NULL; + unsigned char **animated_data = NULL; unsigned char *dst = NULL; unsigned long long src_size = 0; int encode_image_type = -1; - if (argc < 4) { + if (argc < 3) { fprintf(stderr, "\t[usage]\n"); - fprintf(stderr, "\t\t1. decode : mm_util_png_testsuite decode filepath encode_image_type\n"); + fprintf(stderr, "\t\t1. decode/encode : capi-media-image-util-decode-test decode/decode-mem/decode-async filepath encode_image_type\n"); + fprintf(stderr, "\t\t2. encode gif : capi-media-image-util-decode-test encode-gif/encode-gif-mem 'folderpath containing png images named \ + with number prefix according to the animation order'\n"); return 0; } if (argv[3]) encode_image_type = atoi(argv[3]); - if (!strcmp("decode", argv[1]) || !strcmp("decode-mem", argv[1]) || !strcmp("decode-async", argv[1])) { + if (!strcmp("encode-gif", argv[1]) || !strcmp("encode-gif-mem", argv[1])) { + struct dirent *dp; + DIR *fd; + int number_files = 0, i = 0; + char gif_filename[BUFFER_SIZE] = { 0, }, temp_filename[BUFFER_SIZE] = { + 0,}, temp[BUFFER_SIZE] = {0,}, file_format[BUFFER_SIZE] = {0,}; + unsigned long gif_image_width[1000] = { 0, }, gif_image_height[1000] = { + 0,}; + memset(gif_filename, 0, BUFFER_SIZE); + { + snprintf(gif_filename, BUFFER_SIZE, "%s%s", DECODE_RESULT_PATH, "gif"); + } + + if ((fd = opendir(argv[2])) == NULL) { + fprintf(stderr, "listdir: can't open %s\n", argv[2]); + return 0; + } + + while ((dp = readdir(fd)) != NULL) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; /* skip self and parent */ + if(!number_files) { + char *temp1 = strstr(dp->d_name, "-"); + char *temp2 = strstr(dp->d_name, "."); + + strncpy(temp_filename, dp->d_name, strlen(dp->d_name) - strlen(temp1)); + strncpy(file_format, temp2, strlen(temp2)); + } + number_files++; + } + closedir(fd); + if (!number_files) { + fprintf(stderr, "\t\tCannot open directory\n"); + return 0; + } + + for (i = 0; i < number_files; i++) { + animated_data = (unsigned char **)realloc(animated_data, (i + 1) * sizeof(unsigned char *)); + ret = image_util_decode_create(&decoded); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + snprintf(temp, BUFFER_SIZE, "%s%s-%d%s", argv[2], temp_filename, i, file_format); + + ret = image_util_decode_set_input_path(decoded, temp); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + ret = image_util_decode_set_output_buffer(decoded, &animated_data[i]); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + ret = image_util_decode_run(decoded, &gif_image_width[i], &gif_image_height[i], NULL); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + ret = image_util_decode_destroy(decoded); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } + + ret = image_util_encode_create(IMAGE_UTIL_GIF, &encoded); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + for (i = 0; i < number_files; i++) { + ret = image_util_encode_set_input_buffer(encoded, animated_data[i]); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } + for (i = 0; i < number_files; i++) { + ret = image_util_encode_set_resolution(encoded, gif_image_width[i], gif_image_height[i]); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } + for (i = 0; i < number_files; i++) { + ret = image_util_encode_set_gif_frame_delay_time(encoded, 10); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } + if (!strcmp("encode-gif-mem", argv[1])) { + ret = image_util_encode_set_output_buffer(encoded, &dst); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } else { + ret = image_util_encode_set_output_path(encoded, gif_filename); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + } + ret = image_util_encode_run(encoded, &image_size); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + if (!strcmp("encode-gif-mem", argv[1])) { + _write_file(gif_filename, (void *)dst, image_size); + free(dst); + } + + ret = image_util_encode_destroy(encoded); + if (ret != IMAGE_UTIL_ERROR_NONE) + return 0; + + for (i = 0; i < number_files; i++) + free(animated_data[i]); + free(animated_data); + + return 0; + } else if (!strcmp("decode", argv[1]) || !strcmp("decode-mem", argv[1]) || !strcmp("decode-async", argv[1])) { + if (argc < 4) { + fprintf(stderr, "\t[usage]\n"); + fprintf(stderr, "\t\t1. decode/encode : capi-media-image-util-decode-test decode/decode-mem/decode-async filepath encode_image_type\n"); + return 0; + } ret = image_util_decode_create(&decoded); if (ret != IMAGE_UTIL_ERROR_NONE) return 0; @@ -204,7 +319,7 @@ int main(int argc, char *argv[]) ret = image_util_decode_run_async(decoded, (image_util_decode_completed_cb) decode_completed_cb, NULL); _wait(); } else - ret = image_util_decode_run(decoded, &image_width, &image_height, NULL); + ret = image_util_decode_run(decoded, &image_width, &image_height, &image_size); if (ret != IMAGE_UTIL_ERROR_NONE) return 0; @@ -224,6 +339,10 @@ int main(int argc, char *argv[]) 0,}; memset(filename, 0, BUFFER_SIZE); + snprintf(filename, BUFFER_SIZE, "%s%s", DECODE_RESULT_PATH, "raw"); + _write_file(filename, (void *)data, image_size); + memset(filename, 0, BUFFER_SIZE); + switch (encode_image_type) { case IMAGE_UTIL_JPEG: snprintf(type, 4, "%s", "jpg"); diff --git a/include/image_util.h b/include/image_util.h index 0511f34..369653b 100755 --- a/include/image_util.h +++ b/include/image_util.h @@ -846,7 +846,7 @@ int image_util_decode_create(image_util_decode_h *handle); * * @pre image_util_decode_create() * -* @post image_util_decode_run()/image_util_decode_run_async() +* @post image_util_decode_run() / image_util_decode_run_async() * @post image_util_decode_destroy() * * @see image_util_decode_create() @@ -880,7 +880,7 @@ int image_util_decode_set_input_path(image_util_decode_h handle, const char *pat * * @pre image_util_decode_create() * -* @post image_util_decode_run()/image_util_decode_run_async() +* @post image_util_decode_run() / image_util_decode_run_async() * @post image_util_decode_destroy() * * @see image_util_decode_create() @@ -911,7 +911,7 @@ int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigne * * @pre image_util_decode_create() * -* @post image_util_decode_run()/image_util_decode_run_async() +* @post image_util_decode_run() / image_util_decode_run_async() * @post image_util_decode_destroy() * * @see image_util_decode_create() @@ -943,7 +943,7 @@ int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned cha * * @pre image_util_decode_create() * -* @post image_util_decode_run()/image_util_decode_run_async() +* @post image_util_decode_run() / image_util_decode_run_async() * @post image_util_decode_destroy() * * @see image_util_supported_colorspace_cb() @@ -976,7 +976,7 @@ int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colo * * @pre image_util_decode_create() * -* @post image_util_decode_run()/image_util_decode_run_async() +* @post image_util_decode_run() / image_util_decode_run_async() * @post image_util_decode_destroy() * * @see image_util_decode_create() @@ -1010,7 +1010,7 @@ int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_ * @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation * * @pre image_util_decode_create() -* @pre image_util_decode_set_input_buffer()/image_util_decode_set_input_path(). +* @pre image_util_decode_set_input_buffer() / image_util_decode_set_input_path(). * @pre image_util_decode_set_output_buffer() * * @post image_util_decode_destroy() @@ -1043,7 +1043,7 @@ int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsi * @retval #IMAGE_UTIL_ERROR_INVALID_OPERATION Invalid operation * * @pre image_util_decode_create() -* @pre image_util_decode_set_input_buffer()/image_util_decode_set_input_path(). +* @pre image_util_decode_set_input_buffer() / image_util_decode_set_input_path(). * @pre image_util_decode_set_output_buffer() * * @post image_util_decode_destroy() @@ -1104,7 +1104,8 @@ int image_util_encode_create(image_util_type_e image_type, image_util_encode_h * * @brief Sets the resolution of the encoded image. * @since_tizen 3.0 * -* @remarks This should be called before calling image_util_encode_run(). +* @remarks This should be called before calling image_util_encode_run().\n +* While encoding animated gif image, resolution should be set for each frame. * * @param[in] handle The handle to image util encoding * @param[in] width Width of the original image @@ -1119,7 +1120,7 @@ int image_util_encode_create(image_util_type_e image_type, image_util_encode_h * * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1152,7 +1153,7 @@ int image_util_encode_set_resolution(image_util_encode_h handle, unsigned long w * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_supported_colorspace_cb() @@ -1187,7 +1188,7 @@ int image_util_encode_set_colorspace(image_util_encode_h handle, image_util_colo * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1220,7 +1221,7 @@ int image_util_encode_set_quality(image_util_encode_h handle, int quality); * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1234,13 +1235,48 @@ int image_util_encode_set_quality(image_util_encode_h handle, int quality); */ int image_util_encode_set_png_compression(image_util_encode_h handle, image_util_png_compression_e compression); +/** +* @brief Sets the time delay between each frame in the encoded animated gif image. +* @since_tizen 3.0 +* +* @remarks In case animated gif image if this is not set then there will be no delay between each frame.\n +* This should be set for each frame in the animated gif image.\n +* This can be set a different value for each frame, which results in different delay time between different frames. +* +* @param[in] handle The handle to image util encoding +* @param[in] delay_time Time delay between each frame in the encoded image, in 0.01sec units. +* +* @return @c 0 on success, +* otherwise a negative error value +* +* @retval #IMAGE_UTIL_ERROR_NONE Successful +* @retval #IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT Format not supported +* @retval #IMAGE_UTIL_ERROR_INVALID_PARAMETER Invalid parameter +* +* @pre image_util_encode_create() +* +* @post image_util_encode_run() / image_util_encode_run_async() +* @post image_util_encode_destroy() +* +* @see image_util_encode_create() +* @see image_util_encode_set_resolution() +* @see image_util_encode_set_input_buffer() +* @see image_util_encode_set_output_path() +* @see image_util_encode_set_output_buffer() +* @see image_util_encode_run() +* @see image_util_encode_run_async() +* @see image_util_encode_destroy() +*/ +int image_util_encode_set_gif_frame_delay_time(image_util_encode_h handle, unsigned long long delay_time); + /** * @brief Sets the input buffer from which to encode. * @since_tizen 3.0 * * @remarks Either image_util_encode_set_output_path() or image_util_encode_set_output_buffer() should be set.\n * By default the input buffer colorspace will be considered as IMAGE_UTIL_COLORSPACE_RGBA8888.\n -* Use image_util_encode_set_colorspace to change the colorspace. +* Use image_util_encode_set_colorspace to change the colorspace.\n +* While encoding animated gif image, input buffer should be set for each frame. * * @param[in] handle The handle to image util decoding * @param[in] src_buffer The input image buffer @@ -1254,7 +1290,7 @@ int image_util_encode_set_png_compression(image_util_encode_h handle, image_util * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1291,7 +1327,7 @@ int image_util_encode_set_input_buffer(image_util_encode_h handle, const unsigne * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1324,7 +1360,7 @@ int image_util_encode_set_output_path(image_util_encode_h handle, const char *pa * * @pre image_util_encode_create() * -* @post image_util_encode_run()/image_util_encode_run_async() +* @post image_util_encode_run() / image_util_encode_run_async() * @post image_util_encode_destroy() * * @see image_util_encode_create() @@ -1342,7 +1378,9 @@ int image_util_encode_set_output_buffer(image_util_encode_h handle, unsigned cha * * @remarks The output will be stored in the pointer set to image_util_encode_set_output_buffer() or image_util_encode_set_output_path().\n * The function executes synchronously.\n -* When any of the @pre functions are not called, IMAGE_UTIL_ERROR_INVALID_PARAMETER is returned. +* When any of the @pre functions are not called, IMAGE_UTIL_ERROR_INVALID_PARAMETER is returned.\n +* In case of animated gif encoding, image_util_encode_set_resolution(), image_util_encode_set_input_buffer() and\n +* image_util_encode_set_gif_frame_delay_time() MUST be called for each frame. * * @param[in] handle The handle to image util encoding * @param[out] size Size of the encoded image @@ -1357,13 +1395,14 @@ int image_util_encode_set_output_buffer(image_util_encode_h handle, unsigned cha * @pre image_util_encode_create() * @pre image_util_encode_set_resolution() * @pre image_util_encode_set_input_buffer() -* @pre image_util_encode_set_output_buffer()/image_util_encode_set_output_path() +* @pre image_util_encode_set_output_buffer() / image_util_encode_set_output_path() * * @post image_util_encode_destroy() * * @see image_util_encode_create() * @see image_util_encode_set_resolution() * @see image_util_encode_set_input_buffer() +* @see image_util_encode_set_gif_frame_delay_time() * @see image_util_encode_set_output_path() * @see image_util_encode_set_output_buffer() * @see image_util_encode_destroy() @@ -1376,7 +1415,9 @@ int image_util_encode_run(image_util_encode_h handle, unsigned long long *size); * * @remarks The output will be stored in the pointer set to image_util_encode_set_output_buffer() or image_util_encode_set_output_path().\n * The function executes asynchronously, which contains complete callback.\n -* When any of the @pre functions are not called, IMAGE_UTIL_ERROR_INVALID_PARAMETER is returned. +* When any of the @pre functions are not called, IMAGE_UTIL_ERROR_INVALID_PARAMETER is returned.\n +* In case of animated gif encoding, image_util_encode_set_resolution(), image_util_encode_set_input_buffer() and\n +* image_util_encode_set_gif_frame_delay_time() MUST be called for each frame. * * @param[in] handle The handle to image util encoding * @param[in] callback The callback function to be invoked @@ -1392,13 +1433,14 @@ int image_util_encode_run(image_util_encode_h handle, unsigned long long *size); * @pre image_util_encode_create() * @pre image_util_encode_set_resolution() * @pre image_util_encode_set_input_buffer() -* @pre image_util_encode_set_output_buffer()/image_util_encode_set_output_path() +* @pre image_util_encode_set_output_buffer() / image_util_encode_set_output_path() * * @post image_util_encode_destroy() * * @see image_util_encode_create() * @see image_util_encode_set_resolution() * @see image_util_encode_set_input_buffer() +* @see image_util_encode_set_gif_frame_delay_time() * @see image_util_encode_set_output_path() * @see image_util_encode_set_output_buffer() * @see image_util_encode_destroy() diff --git a/include/image_util_private.h b/include/image_util_private.h index f4ae7fe..ea42eb4 100755 --- a/include/image_util_private.h +++ b/include/image_util_private.h @@ -102,7 +102,7 @@ typedef struct { typedef struct { image_util_type_e image_type; - void *src_buffer; + void **src_buffer; unsigned long long src_size; void **dst_buffer; unsigned long long dst_size; @@ -112,6 +112,10 @@ typedef struct { unsigned long height; bool is_decode; int quality; + unsigned int image_count; + unsigned int current_buffer_count; + unsigned int current_resolution_count; + unsigned int current_delay_count; image_util_colorspace_e colorspace; image_util_scale_e down_scale; decode_cb_s *_decode_cb; diff --git a/src/image_util.c b/src/image_util.c index 2345178..9e3a68d 100755 --- a/src/image_util.c +++ b/src/image_util.c @@ -963,6 +963,7 @@ 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; @@ -1058,7 +1059,7 @@ int image_util_decode_set_input_path(image_util_decode_h handle, const char *pat fp = fopen(path, "r"); if (fp == NULL) { - image_util_error("File open failed"); + image_util_error("File open failed %s", path); return IMAGE_UTIL_ERROR_NO_SUCH_FILE; } src_buffer = (void *)malloc(sizeof(_PNG_HEADER)); @@ -1100,7 +1101,9 @@ int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigne err = _image_util_decode_create_image_handle(_handle, src_buffer); - _handle->src_buffer = (void *)src_buffer; + if (!_handle->src_buffer) + _handle->src_buffer = (void *)calloc(1, sizeof(void *)); + _handle->src_buffer[0] = (void *)src_buffer; _handle->src_size = src_size; return err; @@ -1201,9 +1204,9 @@ static int _image_util_decode_internal(decode_encode_s * _handle) err = mm_util_decode_from_jpeg_file(jpeg_data, _handle->path, _convert_jpeg_colorspace_tbl[_handle->colorspace]); } else { if (_handle->down_scale < sizeof(image_util_scale_e)) - err = mm_util_decode_from_jpeg_memory_with_downscale(jpeg_data, _handle->src_buffer, _handle->src_size, _convert_jpeg_colorspace_tbl[_handle->colorspace], _convert_decode_scale_tbl[_handle->down_scale]); + err = mm_util_decode_from_jpeg_memory_with_downscale(jpeg_data, _handle->src_buffer[0], _handle->src_size, _convert_jpeg_colorspace_tbl[_handle->colorspace], _convert_decode_scale_tbl[_handle->down_scale]); else - err = mm_util_decode_from_jpeg_memory(jpeg_data, _handle->src_buffer, _handle->src_size, _convert_jpeg_colorspace_tbl[_handle->colorspace]); + err = mm_util_decode_from_jpeg_memory(jpeg_data, _handle->src_buffer[0], _handle->src_size, _convert_jpeg_colorspace_tbl[_handle->colorspace]); } if (err == MM_UTIL_ERROR_NONE) { @@ -1227,7 +1230,7 @@ static int _image_util_decode_internal(decode_encode_s * _handle) if (_handle->path) err = mm_util_decode_from_png_file(png_data, _handle->path); else - err = mm_util_decode_from_png_memory(png_data, &_handle->src_buffer, _handle->src_size); + err = mm_util_decode_from_png_memory(png_data, &_handle->src_buffer[0], _handle->src_size); if (err == MM_UTIL_ERROR_NONE) { *(_handle->dst_buffer) = png_data->data; @@ -1250,10 +1253,10 @@ static int _image_util_decode_internal(decode_encode_s * _handle) if (_handle->path) err = mm_util_decode_from_gif_file(gif_data, _handle->path); else - err = mm_util_decode_from_gif_memory(gif_data, &_handle->src_buffer); + err = mm_util_decode_from_gif_memory(gif_data, &_handle->src_buffer[0]); if (err == MM_UTIL_ERROR_NONE) { - *(_handle->dst_buffer) = gif_data->frames[0].data; + *(_handle->dst_buffer) = gif_data->frames[0]->data; _handle->dst_size = gif_data->size; _handle->width = gif_data->width; _handle->height = gif_data->height; @@ -1273,7 +1276,7 @@ static int _image_util_decode_internal(decode_encode_s * _handle) if (_handle->path) err = mm_util_decode_from_bmp_file(bmp_data, _handle->path); else - err = mm_util_decode_from_bmp_memory(bmp_data, &_handle->src_buffer, _handle->src_size); + err = mm_util_decode_from_bmp_memory(bmp_data, &_handle->src_buffer[0], _handle->src_size); if (err == MM_UTIL_ERROR_NONE) { *(_handle->dst_buffer) = bmp_data->data; @@ -1422,7 +1425,7 @@ int image_util_decode_destroy(image_util_decode_h handle) int err = IMAGE_UTIL_ERROR_NONE; decode_encode_s *_handle = (decode_encode_s *) handle; - image_util_debug("image_util_encode_png_destroy"); + image_util_debug("image_util_decode_destroy"); if (_handle == NULL || _handle->is_decode == FALSE) { image_util_error("Invalid Handle"); @@ -1496,7 +1499,7 @@ int image_util_decode_destroy(image_util_decode_h handle) g_cond_clear(&(_handle->thread_cond)); } - + IMAGE_UTIL_SAFE_FREE(_handle->src_buffer); IMAGE_UTIL_SAFE_FREE(_handle); return err; @@ -1543,14 +1546,19 @@ static int _image_util_encode_create_gif_handle(decode_encode_s * 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); - _handle->frames = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data)); + _handle->frames = (mm_util_gif_frame_data **) calloc(1, sizeof(mm_util_gif_frame_data *)); if (_handle->frames == NULL) { image_util_error("Error - OUT_OF_MEMORY"); IMAGE_UTIL_SAFE_FREE(_handle); return MM_UTIL_ERROR_OUT_OF_MEMORY; } + _handle->frames[0] = (mm_util_gif_frame_data *) calloc(1, sizeof(mm_util_gif_frame_data)); + if (_handle->frames[0] == NULL) { + image_util_error("Error - OUT_OF_MEMORY"); + IMAGE_UTIL_SAFE_FREE(_handle); + return MM_UTIL_ERROR_OUT_OF_MEMORY; + } - mm_util_gif_encode_set_image_count(_handle, 1); handle->image_h = (mm_util_imgp_h) _handle; return err; @@ -1587,6 +1595,10 @@ int image_util_encode_create(image_util_type_e image_type, image_util_encode_h * _handle->path = NULL; _handle->image_h = 0; _handle->is_decode = FALSE; + _handle->image_count = 1; + _handle->current_buffer_count = 0; + _handle->current_resolution_count = 0; + _handle->current_delay_count = 0; switch (image_type) { case IMAGE_UTIL_JPEG: @@ -1664,8 +1676,38 @@ int image_util_encode_set_resolution(image_util_encode_h handle, unsigned long w image_util_error("Invalid gif data"); return IMAGE_UTIL_ERROR_INVALID_PARAMETER; } - mm_util_gif_encode_set_width(gif_data, width); - mm_util_gif_encode_set_height(gif_data, height); + + if (!_handle->current_resolution_count) { + mm_util_gif_encode_set_width(gif_data, width); + mm_util_gif_encode_set_height(gif_data, height); + _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; + } + + if(_handle->image_count <= _handle->current_resolution_count) { + gif_data->frames = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *)); + if (gif_data->frames == NULL) { + image_util_error("Error - OUT_OF_MEMORY"); + IMAGE_UTIL_SAFE_FREE(_handle); + return IMAGE_UTIL_ERROR_OUT_OF_MEMORY; + } + 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_SAFE_FREE(_handle); + return IMAGE_UTIL_ERROR_OUT_OF_MEMORY; + } + _handle->image_count++; + } + + gif_data->frames[_handle->current_resolution_count]->width = width; + gif_data->frames[_handle->current_resolution_count]->height = height; + _handle->current_resolution_count++; + + return err; } break; case IMAGE_UTIL_BMP: @@ -1773,6 +1815,52 @@ int image_util_encode_set_png_compression(image_util_encode_h handle, image_util return err; } +int image_util_encode_set_gif_frame_delay_time(image_util_encode_h handle, unsigned long long delay_time) +{ + int err = IMAGE_UTIL_ERROR_NONE; + decode_encode_s *_handle = (decode_encode_s *) handle; + mm_util_gif_data *gif_data; + + if (_handle == NULL || _handle->is_decode == TRUE) { + image_util_error("Invalid Handle"); + return IMAGE_UTIL_ERROR_INVALID_PARAMETER; + } + if (_handle->image_type != IMAGE_UTIL_GIF) { + image_util_error("Wrong image format"); + return IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT; + } + + gif_data = (mm_util_gif_data *) _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; + } + if(_handle->image_count <= _handle->current_delay_count) { + gif_data->frames = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *)); + if (gif_data->frames == NULL) { + image_util_error("Error - OUT_OF_MEMORY"); + IMAGE_UTIL_SAFE_FREE(_handle); + return IMAGE_UTIL_ERROR_OUT_OF_MEMORY; + } + 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_SAFE_FREE(_handle); + return IMAGE_UTIL_ERROR_OUT_OF_MEMORY; + } + _handle->image_count++; + } + + mm_util_gif_encode_set_frame_delay_time(gif_data->frames[_handle->current_delay_count], delay_time); + _handle->current_delay_count++; + + return err; +} + int image_util_encode_set_input_buffer(image_util_encode_h handle, const unsigned char *src_buffer) { int err = IMAGE_UTIL_ERROR_NONE; @@ -1787,7 +1875,37 @@ int image_util_encode_set_input_buffer(image_util_encode_h handle, const unsigne return IMAGE_UTIL_ERROR_INVALID_PARAMETER; } - _handle->src_buffer = (void *)src_buffer; + _handle->src_buffer = (void *)realloc(_handle->src_buffer, (_handle->current_buffer_count + 1) * sizeof(void *)); + _handle->src_buffer[_handle->current_buffer_count] = (void *)src_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; + } + if(_handle->image_count <= _handle->current_buffer_count) { + gif_data->frames = (mm_util_gif_frame_data **) realloc(gif_data->frames, (_handle->image_count + 1) * sizeof(mm_util_gif_frame_data *)); + if (gif_data->frames == NULL) { + image_util_error("Error - OUT_OF_MEMORY"); + IMAGE_UTIL_SAFE_FREE(_handle); + return IMAGE_UTIL_ERROR_OUT_OF_MEMORY; + } + 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_SAFE_FREE(_handle); + 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; } @@ -1845,9 +1963,9 @@ static int _image_util_encode_internal(decode_encode_s * _handle) case IMAGE_UTIL_JPEG: { if (_handle->path) - err = mm_util_jpeg_encode_to_file(_handle->path, _handle->src_buffer, _handle->width, _handle->height, _convert_jpeg_colorspace_tbl[_handle->colorspace], _handle->quality); + err = mm_util_jpeg_encode_to_file(_handle->path, _handle->src_buffer[0], _handle->width, _handle->height, _convert_jpeg_colorspace_tbl[_handle->colorspace], _handle->quality); else - err = mm_util_jpeg_encode_to_memory(_handle->dst_buffer, (int *)&(_handle->dst_size), _handle->src_buffer, _handle->width, _handle->height, _convert_jpeg_colorspace_tbl[_handle->colorspace], _handle->quality); + err = mm_util_jpeg_encode_to_memory(_handle->dst_buffer, (int *)&(_handle->dst_size), _handle->src_buffer[0], _handle->width, _handle->height, _convert_jpeg_colorspace_tbl[_handle->colorspace], _handle->quality); } break; case IMAGE_UTIL_PNG: @@ -1861,9 +1979,9 @@ static int _image_util_encode_internal(decode_encode_s * _handle) } if (_handle->path) - err = mm_util_encode_to_png_file(&(_handle->src_buffer), png_data, _handle->path); + err = mm_util_encode_to_png_file(&(_handle->src_buffer[0]), png_data, _handle->path); else - err = mm_util_encode_to_png_memory(&(_handle->src_buffer), png_data); + err = mm_util_encode_to_png_memory(&(_handle->src_buffer[0]), png_data); if (err == MM_UTIL_ERROR_NONE) { if (_handle->dst_buffer) @@ -1880,12 +1998,16 @@ static int _image_util_encode_internal(decode_encode_s * _handle) void *dst_buffer = NULL; gif_data = (mm_util_gif_data *) _handle->image_h; - if (gif_data == NULL || gif_data->frames == NULL) { + 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_error("Total frame count does not match with the data set, for animated gif encoding"); + return MM_UTIL_ERROR_INVALID_OPERATION; + } - gif_data->frames[0].data = _handle->src_buffer; + mm_util_gif_encode_set_image_count(gif_data, _handle->image_count); if (_handle->path) err = mm_util_encode_gif_to_file(gif_data, _handle->path); else @@ -1910,7 +2032,7 @@ static int _image_util_encode_internal(decode_encode_s * _handle) return MM_UTIL_ERROR_INVALID_PARAMETER; } - bmp_data->data = _handle->src_buffer; + bmp_data->data = _handle->src_buffer[0]; if (_handle->path) err = mm_util_encode_bmp_to_file(bmp_data, _handle->path); else { @@ -2100,12 +2222,16 @@ int image_util_encode_destroy(image_util_encode_h handle) case IMAGE_UTIL_GIF: { mm_util_gif_data *gif_data; + unsigned int i = 0; gif_data = (mm_util_gif_data *) _handle->image_h; if (gif_data == NULL) { image_util_error("Invalid gif data"); return IMAGE_UTIL_ERROR_INVALID_PARAMETER; } + for (i = 1; i < _handle->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); IMAGE_UTIL_SAFE_FREE(gif_data); } @@ -2142,6 +2268,7 @@ int image_util_encode_destroy(image_util_encode_h handle) g_cond_clear(&(_handle->thread_cond)); } + IMAGE_UTIL_SAFE_FREE(_handle->src_buffer); IMAGE_UTIL_SAFE_FREE(_handle); return err;