2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
25 #include <image_util.h>
26 #include <image_util_private.h>
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,
35 #define _NUM_OF_SCALE (sizeof(_convert_decode_scale_tbl)/sizeof(int))
36 #define _NOT_SUPPORTED_IMAGE_TYPE (-1)
38 static int _image_util_decode_read_header(const char *path, unsigned char **buffer)
40 #define IMG_HEADER_LENGTH 8
43 unsigned char *read_buffer = NULL;
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");
48 fp = fopen(path, "r");
50 image_util_error("File open failed %s", path);
51 return IMAGE_UTIL_ERROR_NO_SUCH_FILE;
54 read_buffer = (void *)calloc(1, IMG_HEADER_LENGTH + 1);
55 if (read_buffer == NULL) {
56 image_util_error("Allocation fail");
59 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
62 if (fread(read_buffer, 1, IMG_HEADER_LENGTH, fp) != IMG_HEADER_LENGTH) {
63 image_util_error("File read failed");
66 IMAGE_UTIL_SAFE_FREE(read_buffer);
67 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
70 *buffer = read_buffer;
75 return IMAGE_UTIL_ERROR_NONE;
78 static int _image_util_decode_check_image_type(const unsigned char *image_buffer, image_util_type_e *image_type)
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' };
88 image_util_type_e image_type;
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 }
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");
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;
108 return IMAGE_UTIL_ERROR_NONE;
111 static int _image_util_decode_create_jpeg_handle(decode_encode_s * handle)
113 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
115 /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
116 IMAGE_UTIL_SAFE_FREE(handle->image_h);
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");
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;
125 return IMAGE_UTIL_ERROR_NONE;
128 static int _image_util_decode_create_png_handle(decode_encode_s * handle)
130 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
132 /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
133 IMAGE_UTIL_SAFE_FREE(handle->image_h);
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");
138 handle->image_h = (mm_util_imgp_h) _handle;
140 return IMAGE_UTIL_ERROR_NONE;
143 static int _image_util_decode_create_gif_handle(decode_encode_s * handle)
145 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
147 /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
148 IMAGE_UTIL_SAFE_FREE(handle->image_h);
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");
153 handle->image_h = (mm_util_imgp_h) _handle;
155 return IMAGE_UTIL_ERROR_NONE;
158 static int _image_util_decode_create_bmp_handle(decode_encode_s * handle)
160 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
162 /* It is needed to reuse decode handle for C#, so it shoud be reallocated */
163 IMAGE_UTIL_SAFE_FREE(handle->image_h);
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");
168 handle->image_h = (mm_util_imgp_h) _handle;
170 return IMAGE_UTIL_ERROR_NONE;
173 int image_util_decode_create(image_util_decode_h * handle)
177 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
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");
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;
189 *handle = (image_util_decode_h) _handle;
191 return IMAGE_UTIL_ERROR_NONE;
194 static int _image_util_decode_create_image_handle(image_util_decode_h handle)
196 int err = IMAGE_UTIL_ERROR_NONE;
197 decode_encode_s *_handle = (decode_encode_s *) handle;
199 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
201 switch (_handle->image_type) {
202 case IMAGE_UTIL_JPEG:
203 err = _image_util_decode_create_jpeg_handle(_handle);
206 err = _image_util_decode_create_png_handle(_handle);
209 err = _image_util_decode_create_gif_handle(_handle);
212 err = _image_util_decode_create_bmp_handle(_handle);
215 err = IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
219 if (err != IMAGE_UTIL_ERROR_NONE)
220 image_util_error("Error - create image handle");
225 int image_util_decode_set_input_path(image_util_decode_h handle, const char *path)
227 int err = IMAGE_UTIL_ERROR_NONE;
228 decode_encode_s *_handle = (decode_encode_s *) handle;
229 unsigned char *image_header = NULL;
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");
234 if (_handle->src_buffer)
235 _handle->src_buffer = NULL;
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");
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);
250 IMAGE_UTIL_SAFE_FREE(image_header);
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");
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");
264 int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigned char *src_buffer, unsigned long long src_size)
266 int err = IMAGE_UTIL_ERROR_NONE;
267 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
272 IMAGE_UTIL_SAFE_FREE(_handle->path);
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");
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");
286 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
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;
295 _handle->src_buffer[0] = (void *)src_buffer;
296 _handle->src_size = src_size;
301 int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned char **dst_buffer)
303 decode_encode_s *_handle = (decode_encode_s *) handle;
305 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
306 image_util_retvm_if(dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
308 _handle->dst_buffer = (void **)dst_buffer;
310 return IMAGE_UTIL_ERROR_NONE;
313 int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colorspace_e colorspace)
315 decode_encode_s *_handle = (decode_encode_s *) handle;
317 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
318 IMAGE_UTIL_TYPE_CHECK(_handle->image_type);
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");
323 _handle->colorspace = colorspace;
325 return IMAGE_UTIL_ERROR_NONE;
328 int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_scale_e down_scale)
330 decode_encode_s *_handle = (decode_encode_s *) handle;
332 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
333 IMAGE_UTIL_SUPPORT_TYPE_CHECK(_handle->image_type, IMAGE_UTIL_JPEG);
335 image_util_retvm_if((down_scale < 0 || down_scale >= _NUM_OF_SCALE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "downscale is invalid");
337 _handle->down_scale = down_scale;
339 return IMAGE_UTIL_ERROR_NONE;
342 static int _image_util_decode_internal(decode_encode_s * _handle)
344 int err = MM_UTIL_ERROR_NONE;
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:
350 mm_util_jpeg_yuv_data *jpeg_data = (mm_util_jpeg_yuv_data *) _handle->image_h;
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);
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);
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;
367 mm_util_png_data *png_data = (mm_util_png_data *) _handle->image_h;
370 err = mm_util_decode_from_png_file(_handle->path, png_data);
372 err = mm_util_decode_from_png_memory(_handle->src_buffer[0], (size_t)_handle->src_size, png_data);
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;
384 mm_util_gif_data *gif_data = (mm_util_gif_data *) _handle->image_h;
387 err = mm_util_decode_from_gif_file(gif_data, _handle->path);
389 err = mm_util_decode_from_gif_memory(gif_data, _handle->src_buffer[0]);
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;
401 mm_util_bmp_data *bmp_data = (mm_util_bmp_data *) _handle->image_h;
404 err = mm_util_decode_from_bmp_file(_handle->path, bmp_data);
406 err = mm_util_decode_from_bmp_memory(_handle->src_buffer[0], (size_t)_handle->src_size, bmp_data);
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;
417 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
421 return _image_error_capi(ERR_TYPE_DECODE, err);
424 int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsigned long *height, unsigned long long *size)
426 int err = IMAGE_UTIL_ERROR_NONE;
427 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
433 err = _image_util_decode_internal(_handle);
435 if (err != IMAGE_UTIL_ERROR_NONE) {
436 image_util_error("Error - decode run");
441 *width = _handle->width;
443 *height = _handle->height;
445 *size = _handle->dst_size;
450 gpointer _image_util_decode_thread(gpointer data)
452 decode_encode_s *_handle = (decode_encode_s *) data;
453 int err = IMAGE_UTIL_ERROR_NONE;
456 image_util_error("[ERROR] - handle");
460 err = _image_util_decode_internal(_handle);
461 if (err == IMAGE_UTIL_ERROR_NONE)
462 image_util_debug("Success - decode_internal");
464 image_util_error("Error - decode_internal");
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);
471 image_util_debug("exit thread");
476 static int _image_util_decode_create_thread(decode_encode_s * handle)
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");
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;
488 return IMAGE_UTIL_ERROR_NONE;
491 int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_completed_cb completed_cb, void *user_data)
493 int err = IMAGE_UTIL_ERROR_NONE;
494 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
502 if (_handle->_decode_cb != NULL) {
503 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
504 _handle->_decode_cb = NULL;
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");
510 _handle->_decode_cb->user_data = user_data;
511 _handle->_decode_cb->image_decode_completed_cb = completed_cb;
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;
522 int image_util_decode_destroy(image_util_decode_h handle)
524 decode_encode_s *_handle = (decode_encode_s *) handle;
526 image_util_debug("image_util_decode_destroy");
528 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
530 IMAGE_UTIL_SAFE_FREE(_handle->image_h);
532 /* g_thread_exit(handle->thread); */
533 if (_handle->thread) {
534 g_thread_join(_handle->thread);
535 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
537 IMAGE_UTIL_SAFE_FREE(_handle->path);
538 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
539 IMAGE_UTIL_SAFE_FREE(_handle);
541 return IMAGE_UTIL_ERROR_NONE;