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