Define new decode_s to use for decoding
[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         image_util_retvm_if(fp == NULL, IMAGE_UTIL_ERROR_NO_SUCH_FILE, "File open failed %s", path);
50
51         read_buffer = (void *)calloc(1, IMG_HEADER_LENGTH + 1);
52         if (read_buffer == NULL) {
53                 image_util_error("Allocation fail");
54                 fclose(fp);
55                 fp = NULL;
56                 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
57         }
58
59         if (fread(read_buffer, 1, IMG_HEADER_LENGTH, fp) != IMG_HEADER_LENGTH) {
60                 image_util_error("File read failed");
61                 fclose(fp);
62                 fp = NULL;
63                 IMAGE_UTIL_SAFE_FREE(read_buffer);
64                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
65         }
66
67         *buffer = read_buffer;
68
69         fclose(fp);
70         fp = NULL;
71
72         return IMAGE_UTIL_ERROR_NONE;
73 }
74
75 static int _image_util_decode_check_image_type(const unsigned char *image_buffer, image_util_type_e *image_type)
76 {
77         static char _JPEG_HEADER[] = { 0xFF, 0xD8 };
78         static char _PNG_HEADER[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
79         static char _GIF_HEADER[] = { 'G', 'I', 'F' };
80         static char _BMP_HEADER[] = { 'B', 'M' };
81
82         static struct {
83                 char *header;
84                 int size;
85                 image_util_type_e image_type;
86         } image_header[] = {
87                 { _JPEG_HEADER, sizeof(_JPEG_HEADER), IMAGE_UTIL_JPEG },
88                 { _PNG_HEADER, sizeof(_PNG_HEADER), IMAGE_UTIL_PNG },
89                 { _GIF_HEADER, sizeof(_GIF_HEADER), IMAGE_UTIL_GIF },
90                 { _BMP_HEADER, sizeof(_BMP_HEADER), IMAGE_UTIL_BMP }
91         ,};
92         unsigned int i = 0;
93
94         image_util_retvm_if((image_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid buffer");
95         image_util_retvm_if((image_type == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid type");
96
97         *image_type = _NOT_SUPPORTED_IMAGE_TYPE;        /* init */
98         for (i = 0; i < sizeof(image_header) / sizeof(image_header[0]); i++) {
99                 if (strncmp((const char *)image_buffer, image_header[i].header, image_header[i].size) == 0) {
100                         *image_type = image_header[i].image_type;
101                         break;
102                 }
103         }
104
105         return IMAGE_UTIL_ERROR_NONE;
106 }
107
108 int image_util_decode_create(image_util_decode_h * handle)
109 {
110         image_util_fenter();
111
112         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
113
114         decode_s *_handle = (decode_s *) calloc(1, sizeof(decode_s));
115         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
116
117         _handle->src_buffer = NULL;
118         _handle->dst_buffer = NULL;
119         _handle->path = NULL;
120         _handle->image_type = _NOT_SUPPORTED_IMAGE_TYPE;
121         _handle->colorspace = IMAGE_UTIL_COLORSPACE_RGBA8888;
122
123         *handle = (image_util_decode_h) _handle;
124
125         return IMAGE_UTIL_ERROR_NONE;
126 }
127
128 static int _image_util_decode_create_image_handle(image_util_decode_h handle)
129 {
130         int err = IMAGE_UTIL_ERROR_NONE;
131         decode_s *_handle = (decode_s *) handle;
132
133         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
134
135         switch (_handle->image_type) {
136         case IMAGE_UTIL_JPEG:
137                 _handle->down_scale = IMAGE_UTIL_DOWNSCALE_1_1;
138                 break;
139         case IMAGE_UTIL_PNG:
140         case IMAGE_UTIL_GIF:
141         case IMAGE_UTIL_BMP:
142                 /* do nothing... */
143                 break;
144         default:
145                 err = IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
146                 break;
147         }
148
149         if (err != IMAGE_UTIL_ERROR_NONE)
150                 image_util_error("Error - create image handle");
151
152         return err;
153 }
154
155 int image_util_decode_set_input_path(image_util_decode_h handle, const char *path)
156 {
157         int err = IMAGE_UTIL_ERROR_NONE;
158         decode_s *_handle = (decode_s *) handle;
159         unsigned char *image_header = NULL;
160
161         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
162         image_util_retvm_if(!IMAGE_UTIL_STRING_VALID(path), IMAGE_UTIL_ERROR_NO_SUCH_FILE, "Invalid path");
163
164         if (_handle->src_buffer)
165                 _handle->src_buffer = NULL;
166
167         err = _image_util_decode_read_header(path, &image_header);
168         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "_image_util_decode_read_header failed");
169
170         err = _image_util_decode_check_image_type(image_header, &_handle->image_type);
171         if (err != IMAGE_UTIL_ERROR_NONE) {
172                 image_util_error("_image_util_decode_check_image_type failed");
173                 IMAGE_UTIL_SAFE_FREE(image_header);
174                 return err;
175         }
176
177         IMAGE_UTIL_SAFE_FREE(image_header);
178
179         err = _image_util_decode_create_image_handle(_handle);
180         image_util_retvm_if((err != IMAGE_UTIL_ERROR_NONE), err, "_image_util_decode_create_image_handle failed");
181
182         _handle->path = g_strndup(path, strlen(path));
183         image_util_retvm_if(_handle->path == NULL, IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "OUT_OF_MEMORY");
184
185         return err;
186 }
187
188 int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigned char *src_buffer, unsigned long long src_size)
189 {
190         int err = IMAGE_UTIL_ERROR_NONE;
191         decode_s *_handle = (decode_s *) handle;
192
193         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
194         image_util_retvm_if((src_buffer == NULL || src_size == 0), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input buffer");
195
196         IMAGE_UTIL_SAFE_FREE(_handle->path);
197
198         err = _image_util_decode_check_image_type(src_buffer, &_handle->image_type);
199         image_util_retvm_if(err != IMAGE_UTIL_ERROR_NONE, err, "_image_util_decode_check_image_type failed");
200
201         err = _image_util_decode_create_image_handle(_handle);
202         image_util_retvm_if(err != IMAGE_UTIL_ERROR_NONE, err, "_image_util_decode_create_image_handle failed");
203
204         IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
205
206         _handle->src_buffer = (void *)calloc(1, sizeof(void *));
207         image_util_retvm_if(_handle->src_buffer == NULL, IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "The memory of input buffer was not allocated");
208
209         _handle->src_buffer[0] = (void *)src_buffer;
210         _handle->src_size = src_size;
211
212         return err;
213 }
214
215 int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned char **dst_buffer)
216 {
217         decode_s *_handle = (decode_s *) handle;
218
219         image_util_fenter();
220
221         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
222         image_util_retvm_if(dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
223
224         _handle->dst_buffer = (void **)dst_buffer;
225
226         return IMAGE_UTIL_ERROR_NONE;
227 }
228
229 int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colorspace_e colorspace)
230 {
231         decode_s *_handle = (decode_s *) handle;
232
233         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
234         IMAGE_UTIL_TYPE_CHECK(_handle->image_type);
235
236         image_util_retvm_if((is_valid_colorspace(colorspace) == FALSE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid colorspace");
237         image_util_retvm_if((is_supported_colorspace(colorspace, _handle->image_type) == FALSE), IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported format");
238
239         _handle->colorspace = colorspace;
240
241         return IMAGE_UTIL_ERROR_NONE;
242 }
243
244 int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_scale_e down_scale)
245 {
246         decode_s *_handle = (decode_s *) handle;
247
248         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
249         IMAGE_UTIL_SUPPORT_TYPE_CHECK(_handle->image_type, IMAGE_UTIL_JPEG);
250
251         image_util_retvm_if((down_scale < 0 || down_scale >= _NUM_OF_SCALE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "downscale is invalid");
252
253         _handle->down_scale = down_scale;
254
255         return IMAGE_UTIL_ERROR_NONE;
256 }
257
258 static int _image_util_decode_internal(decode_s * _handle)
259 {
260         int err = MM_UTIL_ERROR_NONE;
261
262         image_util_fenter();
263
264         image_util_retvm_if((_handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "invalid parameter");
265         image_util_retvm_if(_handle->dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid output");
266
267         switch (_handle->image_type) {
268         case IMAGE_UTIL_JPEG:
269                 {
270                         mm_image_info_s jpeg_data;
271                         memset(&jpeg_data, 0, sizeof(mm_image_info_s));
272
273                         if (_handle->path)
274                                         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);
275                         else
276                                         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);
277
278                         if (err == MM_UTIL_ERROR_NONE) {
279                                 *(_handle->dst_buffer) = jpeg_data.data;
280                                 _handle->dst_size = (unsigned long long)jpeg_data.size;
281                                 _handle->width = jpeg_data.width;
282                                 _handle->height = jpeg_data.height;
283                         } else {
284                                 image_util_error("fail to decode jpeg [%d]", err);
285                         }
286                 }
287                 break;
288         case IMAGE_UTIL_PNG:
289                 {
290                         mm_image_info_s png_data;
291                         memset(&png_data, 0, sizeof(mm_image_info_s));
292
293                         if (_handle->path)
294                                 err = mm_util_decode_from_png_file(_handle->path, &png_data);
295                         else
296                                 err = mm_util_decode_from_png_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &png_data);
297
298                         if (err == MM_UTIL_ERROR_NONE) {
299                                 *(_handle->dst_buffer) = png_data.data;
300                                 _handle->dst_size = (unsigned long long)png_data.size;
301                                 _handle->width = png_data.width;
302                                 _handle->height = png_data.height;
303                         } else {
304                                 image_util_error("fail to decode png [%d]", err);
305                         }
306                 }
307                 break;
308         case IMAGE_UTIL_GIF:
309                 {
310                         mm_util_gif_data gif_data;
311                         memset(&gif_data, 0, sizeof(mm_util_gif_data));
312
313                         if (_handle->path)
314                                 err = mm_util_decode_from_gif_file(&gif_data, _handle->path);
315                         else
316                                 err = mm_util_decode_from_gif_memory(&gif_data, _handle->src_buffer[0]);
317
318                         if (err == MM_UTIL_ERROR_NONE) {
319                                 *(_handle->dst_buffer) = gif_data.data;
320                                 _handle->dst_size = gif_data.size;
321                                 _handle->width = gif_data.width;
322                                 _handle->height = gif_data.height;
323                         } else {
324                                 image_util_error("fail to decode gif [%d]", err);
325                         }
326                 }
327                 break;
328         case IMAGE_UTIL_BMP:
329                 {
330                         mm_image_info_s bmp_data;
331                         memset(&bmp_data, 0, sizeof(mm_image_info_s));
332
333                         if (_handle->path)
334                                 err = mm_util_decode_from_bmp_file(_handle->path, &bmp_data);
335                         else
336                                 err = mm_util_decode_from_bmp_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &bmp_data);
337
338                         if (err == MM_UTIL_ERROR_NONE) {
339                                 *(_handle->dst_buffer) = bmp_data.data;
340                                 _handle->dst_size = (unsigned long long)bmp_data.size;
341                                 _handle->width = bmp_data.width;
342                                 _handle->height = bmp_data.height;
343                         } else {
344                                 image_util_error("fail to decode bmp [%d]", err);
345                         }
346                 }
347                 break;
348         default:
349                 image_util_error("Not supported format [%d]", _handle->image_type);
350                 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
351                 break;
352         }
353
354         image_util_debug("dst_buffer(%p) width (%lu) height (%lu) dst_size (%zu)", *(_handle->dst_buffer), _handle->width, _handle->height, _handle->dst_size);
355
356         return _image_error_capi(ERR_TYPE_DECODE, err);
357 }
358
359 int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsigned long *height, unsigned long long *size)
360 {
361         int err = IMAGE_UTIL_ERROR_NONE;
362         decode_s *_handle = (decode_s *) handle;
363
364         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
365         image_util_retvm_if((_handle->path == NULL && _handle->src_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input");
366         image_util_retvm_if(_handle->dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid output");
367
368         err = _image_util_decode_internal(_handle);
369         image_util_retvm_if(err != IMAGE_UTIL_ERROR_NONE, err, "_image_util_decode_internal failed");
370
371         if (width)
372                 *width = _handle->width;
373         if (height)
374                 *height = _handle->height;
375         if (size)
376                 *size = _handle->dst_size;
377
378         return err;
379 }
380
381 gpointer _image_util_decode_thread(gpointer data)
382 {
383         decode_s *_handle = (decode_s *) data;
384         int err = IMAGE_UTIL_ERROR_NONE;
385
386         image_util_fenter();
387
388         image_util_retvm_if((_handle == NULL), NULL, "Invalid Handle");
389
390         err = _image_util_decode_internal(_handle);
391         if (err == IMAGE_UTIL_ERROR_NONE)
392                 image_util_debug("Success - decode_internal");
393         else
394                 image_util_error("Error - decode_internal");
395
396         if (_handle->_decode_cb) {
397                 image_util_debug("call completed_cb");
398                 _handle->_decode_cb->image_decode_completed_cb(err, _handle->_decode_cb->user_data, _handle->width, _handle->height, _handle->dst_size);
399         } else {
400                 image_util_error("No callback");
401         }
402
403         image_util_fleave();
404
405         return NULL;
406 }
407
408 static int _image_util_decode_create_thread(decode_s * handle)
409 {
410         image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
411         image_util_retvm_if((handle->thread != NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running");
412
413         /*create threads */
414         handle->thread = g_thread_new("decode_thread", (GThreadFunc) _image_util_decode_thread, (gpointer) handle);
415         if (!handle->thread) {
416                 image_util_error("ERROR - create thread");
417                 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
418         }
419
420         return IMAGE_UTIL_ERROR_NONE;
421 }
422
423 int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_completed_cb completed_cb, void *user_data)
424 {
425         int err = IMAGE_UTIL_ERROR_NONE;
426         decode_s *_handle = (decode_s *) handle;
427
428         image_util_fenter();
429
430         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
431         image_util_retvm_if((_handle->path == NULL && _handle->src_buffer == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid input");
432         image_util_retvm_if(_handle->dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid output");
433         image_util_retvm_if((completed_cb == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid callback");
434         image_util_retvm_if((_handle->thread != NULL), IMAGE_UTIL_ERROR_INVALID_OPERATION, "A thread is alread running");
435
436         if (_handle->_decode_cb != NULL) {
437                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
438                 _handle->_decode_cb = NULL;
439         }
440
441         _handle->_decode_cb = (decode_cb_s *) calloc(1, sizeof(decode_cb_s));
442         image_util_retvm_if((_handle->_decode_cb == NULL), IMAGE_UTIL_ERROR_OUT_OF_MEMORY, "Out of memory");
443
444         _handle->_decode_cb->user_data = user_data;
445         _handle->_decode_cb->image_decode_completed_cb = completed_cb;
446
447         err = _image_util_decode_create_thread(_handle);
448         if (err != IMAGE_UTIL_ERROR_NONE) {
449                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
450                 _handle->_decode_cb = NULL;
451         }
452
453         image_util_fleave();
454
455         return err;
456 }
457
458 int image_util_decode_destroy(image_util_decode_h handle)
459 {
460         decode_s *_handle = (decode_s *) handle;
461
462         image_util_fenter();
463
464         IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
465
466         /* g_thread_exit(handle->thread); */
467         if (_handle->thread) {
468                 g_thread_join(_handle->thread);
469                 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
470         }
471         IMAGE_UTIL_SAFE_FREE(_handle->path);
472         IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
473         IMAGE_UTIL_SAFE_FREE(_handle);
474
475         image_util_fleave();
476
477         return IMAGE_UTIL_ERROR_NONE;
478 }