Gif: Add support for progressive gif animation encoding. 84/60384/4 accepted/tizen/common/20160315.221106 accepted/tizen/ivi/20160310.063012 accepted/tizen/ivi/20160315.002149 accepted/tizen/mobile/20160310.062838 accepted/tizen/mobile/20160315.002056 accepted/tizen/tv/20160310.062907 accepted/tizen/tv/20160315.002114 accepted/tizen/wearable/20160310.062941 accepted/tizen/wearable/20160315.002131 submit/tizen/20160310.030656 submit/tizen/20160314.051739
authorVineeth TM <vineeth.tm@samsung.com>
Thu, 25 Feb 2016 22:57:40 +0000 (07:57 +0900)
committerVineeth T M <vineeth.tm@samsung.com>
Fri, 26 Feb 2016 02:00:24 +0000 (18:00 -0800)
In case of systems with memory limitations, there should be a way to
continue with encoding as soon as we get each frame, instead of waiting for
all the frames.
By calling encode_run for each frame this can be achieved.

Change-Id: I38b52c528d0c3b59b552888faa5a6de8cb053596
Signed-off-by: Vineeth TM <vineeth.tm@samsung.com>
decode-test/image_util_decode_encode_testsuite.c
include/image_util.h
src/image_util.c

index c0dae25..105853d 100755 (executable)
@@ -166,7 +166,7 @@ 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 *animated_data = NULL;
        unsigned char *dst = NULL;
        unsigned long long src_size = 0;
        int encode_image_type = -1;
@@ -218,8 +218,21 @@ int main(int argc, char *argv[])
                        return 0;
                }
 
+               ret = image_util_encode_create(IMAGE_UTIL_GIF, &encoded);
+               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;
+               }
+
                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;
@@ -230,7 +243,7 @@ int main(int argc, char *argv[])
                        if (ret != IMAGE_UTIL_ERROR_NONE)
                                return 0;
 
-                       ret = image_util_decode_set_output_buffer(decoded, &animated_data[i]);
+                       ret = image_util_decode_set_output_buffer(decoded, &animated_data);
                        if (ret != IMAGE_UTIL_ERROR_NONE)
                                return 0;
 
@@ -241,53 +254,35 @@ int main(int argc, char *argv[])
                        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]);
+                       ret = image_util_encode_set_input_buffer(encoded, animated_data);
                        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);
+
+                       ret = image_util_encode_run(encoded, &image_size);
                        if (ret != IMAGE_UTIL_ERROR_NONE)
                                return 0;
+
+                       free(animated_data);
                }
-               ret = image_util_encode_run(encoded, &image_size);
+
+               ret = image_util_encode_destroy(encoded);
                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);
+                       dst = NULL;
                }
-
-               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) {
@@ -400,15 +395,14 @@ int main(int argc, char *argv[])
                if (ret != IMAGE_UTIL_ERROR_NONE)
                        return 0;
 
-               if (!strcmp("decode-mem", argv[1]) && (encode_image_type != IMAGE_UTIL_BMP)) {
-                       _write_file(filename, (void *)dst, image_size);
-                       free(dst);
-               }
-
                ret = image_util_encode_destroy(encoded);
                if (ret != IMAGE_UTIL_ERROR_NONE)
                        return 0;
 
+               if (!strcmp("decode-mem", argv[1]) && (encode_image_type != IMAGE_UTIL_BMP)) {
+                       _write_file(filename, (void *)dst, image_size);
+                       free(dst);
+               }
                free(data);
        } else {
                fprintf(stderr, "\tDECODED data is NULL\n");
index dc45078..4d98207 100755 (executable)
@@ -1360,7 +1360,8 @@ int image_util_encode_set_output_path(image_util_encode_h handle, const char *pa
 *
 * @remarks One of image_util_encode_set_output_path() or image_util_encode_set_output_buffer() should be set.\n
 *          If both are set then the latest output set is considered.\n
-*          Output buffer setting is not supported for bmp. IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT will be returned for bmp.
+*          Output buffer setting is not supported for bmp. IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT will be returned for bmp.\n
+*          In case of gif encoding, the output buffer will be completely available only after image_util_encode_destroy().
 *
 * @param[in] handle The handle to image util encoding
 * @param[in] dst_buffer The output image buffer
@@ -1396,6 +1397,7 @@ int image_util_encode_set_output_buffer(image_util_encode_h handle, unsigned cha
 *              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.
+*              In case of animated gif encoding, call image_util_encode_run() for each frame to encode progressively.
 *
 * @param[in] handle The handle to image util encoding
 * @param[out] size Size of the encoded image
@@ -1433,6 +1435,7 @@ int image_util_encode_run(image_util_encode_h handle, unsigned long long *size);
 *              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.
+*              In case of animated gif encoding, call image_util_encode_run_async() for each frame to encode progressively.
 *
 * @param[in] handle The handle to image util encoding
 * @param[in] callback The callback function to be invoked
index 92ac54b..649df80 100755 (executable)
@@ -1925,6 +1925,17 @@ int image_util_encode_set_output_path(image_util_encode_h handle, const char *pa
                _handle->dst_buffer = NULL;
 
        _handle->path = 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;
 }
@@ -1951,6 +1962,17 @@ int image_util_encode_set_output_buffer(image_util_encode_h handle, unsigned cha
                _handle->path = NULL;
 
        _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;
 }
@@ -1995,7 +2017,6 @@ static int _image_util_encode_internal(decode_encode_s * _handle)
        case IMAGE_UTIL_GIF:
                {
                        mm_util_gif_data *gif_data;
-                       void *dst_buffer = NULL;
 
                        gif_data = (mm_util_gif_data *) _handle->image_h;
                        if (gif_data == NULL) {
@@ -2008,14 +2029,9 @@ static int _image_util_encode_internal(decode_encode_s * _handle)
                        }
 
                        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
-                               err = mm_util_encode_gif_to_memory(gif_data, &dst_buffer);
+                       err = mm_util_encode_gif(gif_data);
 
                        if (err == MM_UTIL_ERROR_NONE) {
-                               if (_handle->dst_buffer)
-                                       *(_handle->dst_buffer) = (unsigned char *)dst_buffer;
                                _handle->dst_size = gif_data->size;
                                _handle->width = gif_data->width;
                                _handle->height = gif_data->height;
@@ -2229,6 +2245,7 @@ int image_util_encode_destroy(image_util_encode_h handle)
                                image_util_error("Invalid gif data");
                                return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
                        }
+                       mm_util_encode_close_gif(gif_data);
                        for (i = 1; i < _handle->image_count; i++)
                                IMAGE_UTIL_SAFE_FREE(gif_data->frames[i]);
                        IMAGE_UTIL_SAFE_FREE(gif_data->frames[0]);