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_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");
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;
123 *handle = (image_util_decode_h) _handle;
125 return IMAGE_UTIL_ERROR_NONE;
128 static int _image_util_decode_create_image_handle(image_util_decode_h handle)
130 int err = IMAGE_UTIL_ERROR_NONE;
131 decode_s *_handle = (decode_s *) handle;
133 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
135 switch (_handle->image_type) {
136 case IMAGE_UTIL_JPEG:
137 _handle->down_scale = IMAGE_UTIL_DOWNSCALE_1_1;
145 err = IMAGE_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
149 if (err != IMAGE_UTIL_ERROR_NONE)
150 image_util_error("Error - create image handle");
155 int image_util_decode_set_input_path(image_util_decode_h handle, const char *path)
157 int err = IMAGE_UTIL_ERROR_NONE;
158 decode_s *_handle = (decode_s *) handle;
159 unsigned char *image_header = NULL;
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");
164 if (_handle->src_buffer)
165 _handle->src_buffer = NULL;
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");
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);
177 IMAGE_UTIL_SAFE_FREE(image_header);
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");
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");
188 int image_util_decode_set_input_buffer(image_util_decode_h handle, const unsigned char *src_buffer, unsigned long long src_size)
190 int err = IMAGE_UTIL_ERROR_NONE;
191 decode_s *_handle = (decode_s *) handle;
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");
196 IMAGE_UTIL_SAFE_FREE(_handle->path);
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");
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");
204 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
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");
209 _handle->src_buffer[0] = (void *)src_buffer;
210 _handle->src_size = src_size;
215 int image_util_decode_set_output_buffer(image_util_decode_h handle, unsigned char **dst_buffer)
217 decode_s *_handle = (decode_s *) handle;
221 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
222 image_util_retvm_if(dst_buffer == NULL, IMAGE_UTIL_ERROR_INVALID_PARAMETER, "Invalid parameter");
224 _handle->dst_buffer = (void **)dst_buffer;
226 return IMAGE_UTIL_ERROR_NONE;
229 int image_util_decode_set_colorspace(image_util_encode_h handle, image_util_colorspace_e colorspace)
231 decode_s *_handle = (decode_s *) handle;
233 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
234 IMAGE_UTIL_TYPE_CHECK(_handle->image_type);
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");
239 _handle->colorspace = colorspace;
241 return IMAGE_UTIL_ERROR_NONE;
244 int image_util_decode_set_jpeg_downscale(image_util_encode_h handle, image_util_scale_e down_scale)
246 decode_s *_handle = (decode_s *) handle;
248 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
249 IMAGE_UTIL_SUPPORT_TYPE_CHECK(_handle->image_type, IMAGE_UTIL_JPEG);
251 image_util_retvm_if((down_scale < 0 || down_scale >= _NUM_OF_SCALE), IMAGE_UTIL_ERROR_INVALID_PARAMETER, "downscale is invalid");
253 _handle->down_scale = down_scale;
255 return IMAGE_UTIL_ERROR_NONE;
258 static int _image_util_decode_internal(decode_s * _handle)
260 int err = MM_UTIL_ERROR_NONE;
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");
267 switch (_handle->image_type) {
268 case IMAGE_UTIL_JPEG:
270 mm_image_info_s jpeg_data;
271 memset(&jpeg_data, 0, sizeof(mm_image_info_s));
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);
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);
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;
284 image_util_error("fail to decode jpeg [%d]", err);
290 mm_image_info_s png_data;
291 memset(&png_data, 0, sizeof(mm_image_info_s));
294 err = mm_util_decode_from_png_file(_handle->path, &png_data);
296 err = mm_util_decode_from_png_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &png_data);
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;
304 image_util_error("fail to decode png [%d]", err);
310 mm_util_gif_data gif_data;
311 memset(&gif_data, 0, sizeof(mm_util_gif_data));
314 err = mm_util_decode_from_gif_file(&gif_data, _handle->path);
316 err = mm_util_decode_from_gif_memory(&gif_data, _handle->src_buffer[0]);
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;
324 image_util_error("fail to decode gif [%d]", err);
330 mm_image_info_s bmp_data;
331 memset(&bmp_data, 0, sizeof(mm_image_info_s));
334 err = mm_util_decode_from_bmp_file(_handle->path, &bmp_data);
336 err = mm_util_decode_from_bmp_memory(_handle->src_buffer[0], (size_t)_handle->src_size, &bmp_data);
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;
344 image_util_error("fail to decode bmp [%d]", err);
349 image_util_error("Not supported format [%d]", _handle->image_type);
350 return IMAGE_UTIL_ERROR_INVALID_PARAMETER;
354 image_util_debug("dst_buffer(%p) width (%lu) height (%lu) dst_size (%zu)", *(_handle->dst_buffer), _handle->width, _handle->height, _handle->dst_size);
356 return _image_error_capi(ERR_TYPE_DECODE, err);
359 int image_util_decode_run(image_util_decode_h handle, unsigned long *width, unsigned long *height, unsigned long long *size)
361 int err = IMAGE_UTIL_ERROR_NONE;
362 decode_s *_handle = (decode_s *) handle;
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");
368 err = _image_util_decode_internal(_handle);
369 image_util_retvm_if(err != IMAGE_UTIL_ERROR_NONE, err, "_image_util_decode_internal failed");
372 *width = _handle->width;
374 *height = _handle->height;
376 *size = _handle->dst_size;
381 gpointer _image_util_decode_thread(gpointer data)
383 decode_s *_handle = (decode_s *) data;
384 int err = IMAGE_UTIL_ERROR_NONE;
388 image_util_retvm_if((_handle == NULL), NULL, "Invalid Handle");
390 err = _image_util_decode_internal(_handle);
391 if (err == IMAGE_UTIL_ERROR_NONE)
392 image_util_debug("Success - decode_internal");
394 image_util_error("Error - decode_internal");
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);
400 image_util_error("No callback");
408 static int _image_util_decode_create_thread(decode_s * handle)
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");
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;
420 return IMAGE_UTIL_ERROR_NONE;
423 int image_util_decode_run_async(image_util_decode_h handle, image_util_decode_completed_cb completed_cb, void *user_data)
425 int err = IMAGE_UTIL_ERROR_NONE;
426 decode_s *_handle = (decode_s *) handle;
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");
436 if (_handle->_decode_cb != NULL) {
437 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
438 _handle->_decode_cb = NULL;
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");
444 _handle->_decode_cb->user_data = user_data;
445 _handle->_decode_cb->image_decode_completed_cb = completed_cb;
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;
458 int image_util_decode_destroy(image_util_decode_h handle)
460 decode_s *_handle = (decode_s *) handle;
464 IMAGE_UTIL_DECODE_HANDLE_CHECK(handle);
466 /* g_thread_exit(handle->thread); */
467 if (_handle->thread) {
468 g_thread_join(_handle->thread);
469 IMAGE_UTIL_SAFE_FREE(_handle->_decode_cb);
471 IMAGE_UTIL_SAFE_FREE(_handle->path);
472 IMAGE_UTIL_SAFE_FREE(_handle->src_buffer);
473 IMAGE_UTIL_SAFE_FREE(_handle);
477 return IMAGE_UTIL_ERROR_NONE;