Rename jpeg decoding function
[platform/core/api/image-util.git] / src / image_util_decode.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18
19 #include <mm_util_imgp.h>
20 #include <mm_util_jpeg.h>
21 #include <mm_util_png.h>
22 #include <mm_util_gif.h>
23 #include <mm_util_bmp.h>
24
25 #include <image_util.h>
26 #include <image_util_private.h>
27
28 static int _convert_decode_scale_tbl[] = {
29         MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1,
30         MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2,
31         MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4,
32         MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8,
33 };
34
35 #define _NUM_OF_SCALE                   (sizeof(_convert_decode_scale_tbl)/sizeof(int))
36 #define _NOT_SUPPORTED_IMAGE_TYPE (-1)
37
38 static int _image_util_decode_read_header(const char *path, unsigned char **buffer)
39 {
40 #define IMG_HEADER_LENGTH 8
41
42         FILE *fp = NULL;
43         unsigned char *read_buffer = NULL;
44
45         image_util_retvm_if(!IMAGE_UTIL_STRING_VALID(path), IMAGE_UTIL_ERROR_NO_SUCH_FILE, "Invalid path");
46         image_util_retvm_if(buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid buffer");
47
48         fp = fopen(path, "r");
49         if (fp == NULL) {
50                 image_util_error("File open failed %s", path);
51                 return IMAGE_UTIL_ERROR_NO_SUCH_FILE;
52         }
53
54         read_buffer = (void *)calloc(1, IMG_HEADER_LENGTH + 1);
55         if (read_buffer == NULL) {
56                 image_util_error("Allocation fail");
57                 fclose(fp);
58                 fp = NULL;
59                 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
60         }
61
62         if (fread(read_buffer, 1, IMG_HEADER_LENGTH, fp) != IMG_HEADER_LENGTH) {
63                 image_util_error("File read failed");
64                 fclose(fp);
65                 fp = NULL;
66                 IMAGE_UTIL_SAFE_FREE(read_buffer);
67                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
68         }
69
70         *buffer = read_buffer;
71
72         fclose(fp);
73         fp = NULL;
74
75         return IMAGE_UTIL_ERROR_NONE;
76 }
77
78 static int _image_util_decode_check_image_type(const unsigned char *image_buffer, image_util_type_e *image_type)
79 {
80         static char _JPEG_HEADER[] = { 0xFF, 0xD8 };
81         static char _PNG_HEADER[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
82         static char _GIF_HEADER[] = { 'G', 'I', 'F' };
83         static char _BMP_HEADER[] = { 'B', 'M' };
84
85         static struct {
86                 char *header;
87                 int size;
88                 image_util_type_e image_type;
89         } image_header[] = {
90                 { _JPEG_HEADER, sizeof(_JPEG_HEADER), IMAGE_UTIL_JPEG },
91                 { _PNG_HEADER, sizeof(_PNG_HEADER), IMAGE_UTIL_PNG },
92                 { _GIF_HEADER, sizeof(_GIF_HEADER), IMAGE_UTIL_GIF },
93                 { _BMP_HEADER, sizeof(_BMP_HEADER), IMAGE_UTIL_BMP }
94         ,};
95         unsigned int i = 0;
96
97         image_util_retvm_if((image_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid buffer");
98         image_util_retvm_if((image_type == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid type");
99
100         *image_type = _NOT_SUPPORTED_IMAGE_TYPE;        /* init */
101         for (i = 0; i < sizeof(image_header) / sizeof(image_header[0]); i++) {
102                 if (strncmp((const char *)image_buffer, image_header[i].header, image_header[i].size) == 0) {
103                         *image_type = image_header[i].image_type;
104                         break;
105                 }
106         }
107
108         return IMAGE_UTIL_ERROR_NONE;
109 }
110
111 static int _image_util_decode_create_jpeg_handle(decode_encode_s * handle)
112 {
113         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
114
115         /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
116         IMAGE_UTIL_SAFE_FREE(handle->image_h);
117
118         mm_util_jpeg_yuv_data *_handle = (mm_util_jpeg_yuv_data *) calloc(1, sizeof(mm_util_jpeg_yuv_data));
119         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
120
121         handle->image_h = (mm_util_imgp_h) _handle;
122         handle->colorspace = IMAGE_UTIL_COLORSPACE_RGBA8888;
123         handle->down_scale = IMAGE_UTIL_DOWNSCALE_1_1;
124
125         return IMAGE_UTIL_ERROR_NONE;
126 }
127
128 static int _image_util_decode_create_png_handle(decode_encode_s * handle)
129 {
130         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
131
132         /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
133         IMAGE_UTIL_SAFE_FREE(handle->image_h);
134
135         mm_util_png_data *_handle = (mm_util_png_data *) calloc(1, sizeof(mm_util_png_data));
136         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
137
138         handle->image_h = (mm_util_imgp_h) _handle;
139
140         return IMAGE_UTIL_ERROR_NONE;
141 }
142
143 static int _image_util_decode_create_gif_handle(decode_encode_s * handle)
144 {
145         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
146
147         /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
148         IMAGE_UTIL_SAFE_FREE(handle->image_h);
149
150         mm_util_gif_data *_handle = (mm_util_gif_data *) calloc(1, sizeof(mm_util_gif_data));
151         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
152
153         handle->image_h = (mm_util_imgp_h) _handle;
154
155         return IMAGE_UTIL_ERROR_NONE;
156 }
157
158 static int _image_util_decode_create_bmp_handle(decode_encode_s * handle)
159 {
160         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
161
162         /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
163         IMAGE_UTIL_SAFE_FREE(handle->image_h);
164
165         mm_util_bmp_data *_handle = (mm_util_bmp_data *) calloc(1, sizeof(mm_util_bmp_data));
166         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
167
168         handle->image_h = (mm_util_imgp_h) _handle;
169
170         return IMAGE_UTIL_ERROR_NONE;
171 }
172
173 int image_util_decode_create(image_util_decode_h * handle)
174 {
175         image_util_fenter();
176
177         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
178
179         decode_encode_s *_handle = (decode_encode_s *) calloc(1, sizeof(decode_encode_s));
180         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
181
182         _handle->src_buffer = NULL;
183         _handle->dst_buffer = NULL;
184         _handle->path = NULL;
185         _handle->image_h = NULL;
186         _handle->mode = MODE_DECODE;
187         _handle->image_type = _NOT_SUPPORTED_IMAGE_TYPE;
188
189         *handle = (image_util_decode_h) _handle;
190
191         return IMAGE_UTIL_ERROR_NONE;
192 }
193
194 static int _image_util_decode_create_image_handle(image_util_decode_h handle)
195 {
196         int err = IMAGE_UTIL_ERROR_NONE;
197         decode_encode_s *_handle = (decode_encode_s *) handle;
198
199         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
200
201         switch (_handle->image_type) {
202         case IMAGE_UTIL_JPEG:
203                 err = _image_util_decode_create_jpeg_handle(_handle);
204                 break;
205         case IMAGE_UTIL_PNG:
206                 err = _image_util_decode_create_png_handle(_handle);
207                 break;
208         case IMAGE_UTIL_GIF:
209                 err = _image_util_decode_create_gif_handle(_handle);
210                 break;
211         case IMAGE_UTIL_BMP:
212                 err = _image_util_decode_create_bmp_handle(_handle);
213                 break;
214         default:
215                 err = IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
216                 break;
217         }
218
219         if (err != IMAGE_UTIL_ERROR_NONE)
220                 image_util_error("Error - create image handle");
221
222         return err;
223 }
224
225 int image_util_decode_set_input_path(image_util_decode_h handle, const char *path)
226 {
227         int err = IMAGE_UTIL_ERROR_NONE;
228         decode_encode_s *_handle = (decode_encode_s *) handle;
229         unsigned char *image_header = NULL;
230
231         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
232         image_util_retvm_if(!IMAGE_UTIL_STRING_VALID(path), IMAGE_UTIL_ERROR_NO_SUCH_FILE, "Invalid path");
233
234         if (_handle->src_buffer)
235                 _handle->src_buffer = NULL;
236
237         err = _image_util_decode_read_header(path, &image_header);
238         if (err != IMAGE_UTIL_ERROR_NONE) {
239                 image_util_error("_image_util_decode_read_header failed");
240                 return err;
241         }
242
243         err = _image_util_decode_check_image_type(image_header, &_handle->image_type);
244         if (err != IMAGE_UTIL_ERROR_NONE) {
245                 image_util_error("_image_util_decode_check_image_type failed");
246                 IMAGE_UTIL_SAFE_FREE(image_header);
247                 return err;
248         }
249
250         IMAGE_UTIL_SAFE_FREE(image_header);
251
252         err = _image_util_decode_create_image_handle(_handle);
253         if (err != IMAGE_UTIL_ERROR_NONE) {
254                 image_util_error("_image_util_decode_create_image_handle failed");
255                 return err;
256         }
257
258         _handle->path = g_strndup(path, strlen(path));
259         image_util_retvm_if(_handle->path == NULL, IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
260
261         return err;
262 }
263
264 int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigned char *src_buffer, unsigned long long src_size)
265 {
266         int err = IMAGE_UTIL_ERROR_NONE;
267         decode_encode_s *_handle = (decode_encode_s *) handle;
268
269         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
270         image_util_retvm_if((src_buffer == NULL || src_size == 0), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input buffer");
271
272         IMAGE_UTIL_SAFE_FREE(_handle->path);
273
274         err = _image_util_decode_check_image_type(src_buffer, &_handle->image_type);
275         if (err != IMAGE_UTIL_ERROR_NONE) {
276                 image_util_error("_image_util_decode_check_image_type failed");
277                 return err;
278         }
279
280         err = _image_util_decode_create_image_handle(_handle);
281         if (err != IMAGE_UTIL_ERROR_NONE) {
282                 image_util_error("_image_util_decode_create_image_handle failed");
283                 return err;
284         }
285
286         IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
287
288         _handle->src_buffer = (void *)calloc(1, sizeof(void *));
289         if (_handle->src_buffer == NULL) {
290                 image_util_error("The memory of input buffer was not allocated");
291                 IMAGE_UTIL_SAFE_FREE(_handle->image_h);
292                 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
293         }
294
295         _handle->src_buffer[0] = (void *)src_buffer;
296         _handle->src_size = src_size;
297
298         return err;
299 }
300
301 int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned char **dst_buffer)
302 {
303         decode_encode_s *_handle = (decode_encode_s *) handle;
304
305         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
306         image_util_retvm_if(dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
307
308         _handle->dst_buffer = (void **)dst_buffer;
309
310         return IMAGE_UTIL_ERROR_NONE;
311 }
312
313 int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colorspace_e colorspace)
314 {
315         decode_encode_s *_handle = (decode_encode_s *) handle;
316
317         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
318         IMAGE_UTIL_TYPE_CHECK(_handle->image_type);
319
320         image_util_retvm_if((is_valid_colorspace(colorspace) == FALSE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid colorspace");
321         image_util_retvm_if((is_supported_colorspace(colorspace, _handle->image_type) == FALSE), IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported format");
322
323         _handle->colorspace = colorspace;
324
325         return IMAGE_UTIL_ERROR_NONE;
326 }
327
328 int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_scale_e down_scale)
329 {
330         decode_encode_s *_handle = (decode_encode_s *) handle;
331
332         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
333         IMAGE_UTIL_SUPPORT_TYPE_CHECK(_handle->image_type, IMAGE_UTIL_JPEG);
334
335         image_util_retvm_if((down_scale < 0 || down_scale >= _NUM_OF_SCALE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "downscale is invalid");
336
337         _handle->down_scale = down_scale;
338
339         return IMAGE_UTIL_ERROR_NONE;
340 }
341
342 static int _image_util_decode_internal(decode_encode_s * _handle)
343 {
344         int err = MM_UTIL_ERROR_NONE;
345
346         image_util_retvm_if((_handle == NULL || _handle->image_h == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid parameter");
347         switch (_handle->image_type) {
348         case IMAGE_UTIL_JPEG:
349                 {
350                         mm_util_jpeg_yuv_data *jpeg_data = (mm_util_jpeg_yuv_data *) _handle->image_h;
351
352                         if (_handle->path)
353                                         err = mm_util_decode_from_jpeg_file(_handle->path, TYPECAST_COLOR_BY_TYPE(_handle->colorspace, IMAGE_UTIL_JPEG), _convert_decode_scale_tbl[_handle->down_scale], jpeg_data);
354                         else
355                                         err = mm_util_decode_from_jpeg_memory(_handle->src_buffer[0], _handle->src_size, TYPECAST_COLOR_BY_TYPE(_handle->colorspace, IMAGE_UTIL_JPEG), _convert_decode_scale_tbl[_handle->down_scale], jpeg_data);
356
357                         if (err == MM_UTIL_ERROR_NONE) {
358                                 *(_handle->dst_buffer) = jpeg_data->data;
359                                 _handle->dst_size = (unsigned long long)jpeg_data->size;
360                                 _handle->width = jpeg_data->width;
361                                 _handle->height = jpeg_data->height;
362                         }
363                 }
364                 break;
365         case IMAGE_UTIL_PNG:
366                 {
367                         mm_util_png_data *png_data = (mm_util_png_data *) _handle->image_h;
368
369                         if (_handle->path)
370                                 err = mm_util_decode_from_png_file(_handle->path, png_data);
371                         else
372                                 err = mm_util_decode_from_png_memory(_handle->src_buffer[0], (size_t)_handle->src_size, png_data);
373
374                         if (err == MM_UTIL_ERROR_NONE) {
375                                 *(_handle->dst_buffer) = png_data->data;
376                                 _handle->dst_size = (unsigned long long)png_data->size;
377                                 _handle->width = png_data->width;
378                                 _handle->height = png_data->height;
379                         }
380                 }
381                 break;
382         case IMAGE_UTIL_GIF:
383                 {
384                         mm_util_gif_data *gif_data = (mm_util_gif_data *) _handle->image_h;
385
386                         if (_handle->path)
387                                 err = mm_util_decode_from_gif_file(gif_data, _handle->path);
388                         else
389                                 err = mm_util_decode_from_gif_memory(gif_data, _handle->src_buffer[0]);
390
391                         if (err == MM_UTIL_ERROR_NONE) {
392                                 *(_handle->dst_buffer) = gif_data->data;
393                                 _handle->dst_size = gif_data->size;
394                                 _handle->width = gif_data->width;
395                                 _handle->height = gif_data->height;
396                         }
397                 }
398                 break;
399         case IMAGE_UTIL_BMP:
400                 {
401                         mm_util_bmp_data *bmp_data = (mm_util_bmp_data *) _handle->image_h;
402
403                         if (_handle->path)
404                                 err = mm_util_decode_from_bmp_file(_handle->path, bmp_data);
405                         else
406                                 err = mm_util_decode_from_bmp_memory(_handle->src_buffer[0], (size_t)_handle->src_size, bmp_data);
407
408                         if (err == MM_UTIL_ERROR_NONE) {
409                                 *(_handle->dst_buffer) = bmp_data->data;
410                                 _handle->dst_size = (unsigned long long)bmp_data->size;
411                                 _handle->width = bmp_data->width;
412                                 _handle->height = bmp_data->height;
413                         }
414                 }
415                 break;
416         default:
417                 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
418                 break;
419         }
420
421         return _image_error_capi(ERR_TYPE_DECODE, err);
422 }
423
424 int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsigned long *height, unsigned long long *size)
425 {
426         int err = IMAGE_UTIL_ERROR_NONE;
427         decode_encode_s *_handle = (decode_encode_s *) handle;
428
429         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
430         image_util_retvm_if((_handle->path == NULL && _handle->src_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input");
431         image_util_retvm_if(_handle->dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid output");
432
433         err = _image_util_decode_internal(_handle);
434
435         if (err != IMAGE_UTIL_ERROR_NONE) {
436                 image_util_error("Error - decode run");
437                 return err;
438         }
439
440         if (width)
441                 *width = _handle->width;
442         if (height)
443                 *height = _handle->height;
444         if (size)
445                 *size = _handle->dst_size;
446
447         return err;
448 }
449
450 gpointer _image_util_decode_thread(gpointer data)
451 {
452         decode_encode_s *_handle = (decode_encode_s *) data;
453         int err = IMAGE_UTIL_ERROR_NONE;
454
455         if (!_handle) {
456                 image_util_error("[ERROR] - handle");
457                 return NULL;
458         }
459
460         err = _image_util_decode_internal(_handle);
461         if (err == IMAGE_UTIL_ERROR_NONE)
462                 image_util_debug("Success - decode_internal");
463         else
464                 image_util_error("Error - decode_internal");
465
466         if (_handle->_decode_cb) {
467                 image_util_debug("completed_cb");
468                 _handle->_decode_cb->image_decode_completed_cb(err, _handle->_decode_cb->user_data, _handle->width, _handle->height, _handle->dst_size);
469         }
470
471         image_util_debug("exit thread");
472
473         return NULL;
474 }
475
476 static int _image_util_decode_create_thread(decode_encode_s * handle)
477 {
478         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
479         image_util_retvm_if((handle->thread != NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running");
480
481         /*create threads */
482         handle->thread = g_thread_new("decode_thread", (GThreadFunc) _image_util_decode_thread, (gpointer) handle);
483         if (!handle->thread) {
484                 image_util_error("ERROR - create thread");
485                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
486         }
487
488         return IMAGE_UTIL_ERROR_NONE;
489 }
490
491 int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_completed_cb completed_cb, void *user_data)
492 {
493         int err = IMAGE_UTIL_ERROR_NONE;
494         decode_encode_s *_handle = (decode_encode_s *) handle;
495
496         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
497         image_util_retvm_if((_handle->path == NULL && _handle->src_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input");
498         image_util_retvm_if(_handle->dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid output");
499         image_util_retvm_if((completed_cb == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid callback");
500         image_util_retvm_if((_handle->thread != NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running");
501
502         if (_handle->_decode_cb != NULL) {
503                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
504                 _handle->_decode_cb = NULL;
505         }
506
507         _handle->_decode_cb = (decode_cb_s *) calloc(1, sizeof(decode_cb_s));
508         image_util_retvm_if((_handle->_decode_cb == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "Out of memory");
509
510         _handle->_decode_cb->user_data = user_data;
511         _handle->_decode_cb->image_decode_completed_cb = completed_cb;
512
513         err = _image_util_decode_create_thread(_handle);
514         if (err != IMAGE_UTIL_ERROR_NONE) {
515                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
516                 _handle->_decode_cb = NULL;
517         }
518
519         return err;
520 }
521
522 int image_util_decode_destroy(image_util_decode_h handle)
523 {
524         decode_encode_s *_handle = (decode_encode_s *) handle;
525
526         image_util_debug("image_util_decode_destroy");
527
528         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
529
530         IMAGE_UTIL_SAFE_FREE(_handle->image_h);
531
532         /* g_thread_exit(handle->thread); */
533         if (_handle->thread) {
534                 g_thread_join(_handle->thread);
535                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
536         }
537         IMAGE_UTIL_SAFE_FREE(_handle->path);
538         IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
539         IMAGE_UTIL_SAFE_FREE(_handle);
540
541         return IMAGE_UTIL_ERROR_NONE;
542 }