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");
49 image_util_retvm_if(fp == NULL, IMAGE_UTIL_ERROR_NO_SUCH_FILE, "File open failed %s", path);
51 read_buffer = (void *)calloc(1, IMG_HEADER_LENGTH + 1);
52 if (read_buffer == NULL) {
53 image_util_error("Allocation fail");
56 return IMAGE_UTIL_ERROR_OUT_OF_MEMORY;
59 if (fread(read_buffer, 1, IMG_HEADER_LENGTH, fp) != IMG_HEADER_LENGTH) {
60 image_util_error("File read failed");
63 IMAGE_UTIL_SAFE_FREE(read_buffer);
64 return IMAGE_UTIL_ERROR_INVALID_OPERATION;
67 *buffer = read_buffer;
72 return IMAGE_UTIL_ERROR_NONE;
75 static int _image_util_decode_check_image_type(const unsigned char *image_buffer, image_util_type_e *image_type)
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' };
85 image_util_type_e image_type;
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 }
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");
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;
105 return IMAGE_UTIL_ERROR_NONE;
108 int image_util_decode_create(image_util_decode_h * handle)
112 image_util_retvm_if((handle == NULL), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid Handle");
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");
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;
124 *handle = (image_util_decode_h) _handle;
126 return IMAGE_UTIL_ERROR_NONE;
129 static int _image_util_decode_create_image_handle(image_util_decode_h handle)
131 int err = IMAGE_UTIL_ERROR_NONE;
132 decode_encode_s *_handle = (decode_encode_s *) handle;
134 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
136 switch (_handle->image_type) {
137 case IMAGE_UTIL_JPEG:
138 _handle->down_scale = IMAGE_UTIL_DOWNSCALE_1_1;
146 err = IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
150 if (err != IMAGE_UTIL_ERROR_NONE)
151 image_util_error("Error - create image handle");
156 int image_util_decode_set_input_path(image_util_decode_h handle, const char *path)
158 int err = IMAGE_UTIL_ERROR_NONE;
159 decode_encode_s *_handle = (decode_encode_s *) handle;
160 unsigned char *image_header = NULL;
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");
165 if (_handle->src_buffer)
166 _handle->src_buffer = NULL;
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");
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);
178 IMAGE_UTIL_SAFE_FREE(image_header);
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");
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");
189 int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigned char *src_buffer, unsigned long long src_size)
191 int err = IMAGE_UTIL_ERROR_NONE;
192 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
197 IMAGE_UTIL_SAFE_FREE(_handle->path);
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");
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");
205 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
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");
210 _handle->src_buffer[0] = (void *)src_buffer;
211 _handle->src_size = src_size;
216 int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned char **dst_buffer)
218 decode_encode_s *_handle = (decode_encode_s *) handle;
222 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
223 image_util_retvm_if(dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
225 _handle->dst_buffer = (void **)dst_buffer;
227 return IMAGE_UTIL_ERROR_NONE;
230 int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colorspace_e colorspace)
232 decode_encode_s *_handle = (decode_encode_s *) handle;
234 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
235 IMAGE_UTIL_TYPE_CHECK(_handle->image_type);
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");
240 _handle->colorspace = colorspace;
242 return IMAGE_UTIL_ERROR_NONE;
245 int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_scale_e down_scale)
247 decode_encode_s *_handle = (decode_encode_s *) handle;
249 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
250 IMAGE_UTIL_SUPPORT_TYPE_CHECK(_handle->image_type, IMAGE_UTIL_JPEG);
252 image_util_retvm_if((down_scale < 0 || down_scale >= _NUM_OF_SCALE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "downscale is invalid");
254 _handle->down_scale = down_scale;
256 return IMAGE_UTIL_ERROR_NONE;
259 static int _image_util_decode_internal(decode_encode_s * _handle)
261 int err = MM_UTIL_ERROR_NONE;
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");
268 switch (_handle->image_type) {
269 case IMAGE_UTIL_JPEG:
271 mm_image_info_s jpeg_data;
272 memset(&jpeg_data, 0, sizeof(mm_image_info_s));
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);
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);
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;
285 image_util_error("fail to decode jpeg [%d]", err);
291 mm_image_info_s png_data;
292 memset(&png_data, 0, sizeof(mm_image_info_s));
295 err = mm_util_decode_from_png_file(_handle->path, &png_data);
297 err = mm_util_decode_from_png_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &png_data);
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;
305 image_util_error("fail to decode png [%d]", err);
311 mm_util_gif_data gif_data;
312 memset(&gif_data, 0, sizeof(mm_util_gif_data));
315 err = mm_util_decode_from_gif_file(&gif_data, _handle->path);
317 err = mm_util_decode_from_gif_memory(&gif_data, _handle->src_buffer[0]);
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;
325 image_util_error("fail to decode gif [%d]", err);
331 mm_image_info_s bmp_data;
332 memset(&bmp_data, 0, sizeof(mm_image_info_s));
335 err = mm_util_decode_from_bmp_file(_handle->path, &bmp_data);
337 err = mm_util_decode_from_bmp_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &bmp_data);
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;
345 image_util_error("fail to decode bmp [%d]", err);
350 image_util_error("Not supported format [%d]", _handle->image_type);
351 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
355 image_util_debug("dst_buffer(%p) width (%lu) height (%lu) dst_size (%zu)", *(_handle->dst_buffer), _handle->width, _handle->height, _handle->dst_size);
357 return _image_error_capi(ERR_TYPE_DECODE, err);
360 int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsigned long *height, unsigned long long *size)
362 int err = IMAGE_UTIL_ERROR_NONE;
363 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
369 err = _image_util_decode_internal(_handle);
370 image_util_retvm_if(err != IMAGE_UTIL_ERROR_NONE, err, "_image_util_decode_internal failed");
373 *width = _handle->width;
375 *height = _handle->height;
377 *size = _handle->dst_size;
382 gpointer _image_util_decode_thread(gpointer data)
384 decode_encode_s *_handle = (decode_encode_s *) data;
385 int err = IMAGE_UTIL_ERROR_NONE;
389 image_util_retvm_if((_handle == NULL), NULL, "Invalid Handle");
391 err = _image_util_decode_internal(_handle);
392 if (err == IMAGE_UTIL_ERROR_NONE)
393 image_util_debug("Success - decode_internal");
395 image_util_error("Error - decode_internal");
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);
401 image_util_error("No callback");
409 static int _image_util_decode_create_thread(decode_encode_s * handle)
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");
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;
421 return IMAGE_UTIL_ERROR_NONE;
424 int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_completed_cb completed_cb, void *user_data)
426 int err = IMAGE_UTIL_ERROR_NONE;
427 decode_encode_s *_handle = (decode_encode_s *) handle;
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");
437 if (_handle->_decode_cb != NULL) {
438 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
439 _handle->_decode_cb = NULL;
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");
445 _handle->_decode_cb->user_data = user_data;
446 _handle->_decode_cb->image_decode_completed_cb = completed_cb;
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;
459 int image_util_decode_destroy(image_util_decode_h handle)
461 decode_encode_s *_handle = (decode_encode_s *) handle;
465 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
467 /* g_thread_exit(handle->thread); */
468 if (_handle->thread) {
469 g_thread_join(_handle->thread);
470 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
472 IMAGE_UTIL_SAFE_FREE(_handle->path);
473 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
474 IMAGE_UTIL_SAFE_FREE(_handle);
478 return IMAGE_UTIL_ERROR_NONE;