4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: YoungHun Kim <yh8004.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *ranklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <unistd.h> /* fsync() */
29 #include "mm_util_jpeg.h"
30 #include "mm_util_imgp.h"
31 #include "mm_util_private.h"
33 /* maximum width of encoding */
34 #define ENC_MAX_LEN 8192
39 } mm_util_jpeg_cont_format_e;
41 typedef struct my_error_mgr_s {
42 struct jpeg_error_mgr pub; /* "public" fields */
43 jmp_buf setjmp_buffer; /* for return to caller */
46 typedef struct my_error_mgr_s *my_error_ptr;
47 typedef struct jpeg_error_mgr *jpeg_error_ptr;
49 static void __my_error_exit(j_common_ptr cinfo)
51 my_error_ptr myerr = (my_error_ptr) cinfo->err; /* cinfo->err really points to a my_error_mgr_s struct, so coerce pointer */
52 (*cinfo->err->output_message) (cinfo); /* Always display the message. We could postpone this until after returning, if we chose. */
53 longjmp(myerr->setjmp_buffer, 1); /* Return control to the setjmp point */
56 static gboolean __is_supported_color_format_with_libjpeg(mm_util_color_format_e color_format)
58 gboolean _bool = FALSE;
60 if (color_format == MM_UTIL_COLOR_RGB24 ||
61 color_format == MM_UTIL_COLOR_RGBA ||
62 color_format == MM_UTIL_COLOR_BGRA ||
63 color_format == MM_UTIL_COLOR_ARGB ||
64 color_format == MM_UTIL_COLOR_YUV420 ||
65 color_format == MM_UTIL_COLOR_YUV422 ||
66 color_format == MM_UTIL_COLOR_UYVY ||
67 color_format == MM_UTIL_COLOR_GRAYSCALE) {
72 mm_util_error("not supported color format %d", color_format);
77 static gboolean _mm_util_is_supported_color_format(mm_util_color_format_e color_format)
79 gboolean _bool = FALSE;
81 if (__is_supported_color_format_with_libjpeg(color_format) ||
82 color_format == MM_UTIL_COLOR_NV12) {
87 mm_util_error("not supported color format %d", color_format);
92 static int __jpeg_set_error_handler(my_error_ptr jerr, jpeg_error_ptr *err)
94 (jerr->pub).error_exit = __my_error_exit;
95 mm_util_debug("jerr.pub.error_exit ");
97 *err = jpeg_std_error((jpeg_error_ptr)&(jerr->pub));
98 mm_util_debug("jpeg_std_error ");
100 /* Establish the setjmp return context for __my_error_exit to use. */
101 if (setjmp(jerr->setjmp_buffer)) {
102 /* If we get here, the JPEG code has signaled an error. We need to clean up the JPEG object, close the input file, and return.*/
103 mm_util_error("ERROR setjmp");
104 return MM_UTIL_ERROR_INVALID_OPERATION;
106 mm_util_debug("if (setjmp)");
108 return MM_UTIL_ERROR_NONE;
111 static void __jpeg_convert_rgb_colorspace(mm_util_color_format_e mm_color_format, J_COLOR_SPACE *j_color_space, int *j_color_comp)
115 if (mm_color_format == MM_UTIL_COLOR_RGB24) {
117 *j_color_space = JCS_RGB;
118 mm_util_debug("JCS_RGB");
119 } else if (mm_color_format == MM_UTIL_COLOR_GRAYSCALE) {
120 pixel_depth = 1; /* one colour component */
121 *j_color_space = JCS_GRAYSCALE;
122 mm_util_debug("JCS_GRAYSCALE");
123 } else if (mm_color_format == MM_UTIL_COLOR_RGBA) {
125 *j_color_space = JCS_EXT_RGBA;
126 mm_util_debug("JCS_EXT_RGBA");
127 } else if (mm_color_format == MM_UTIL_COLOR_BGRA) {
129 *j_color_space = JCS_EXT_BGRA;
130 mm_util_debug("JCS_EXT_BGRA");
131 } else if (mm_color_format == MM_UTIL_COLOR_ARGB) {
133 *j_color_space = JCS_EXT_ARGB;
134 mm_util_debug("JCS_EXT_ARGB");
138 *j_color_comp = pixel_depth;
141 static void __jpeg_encode_open(j_compress_ptr cinfo, mm_util_jpeg_cont_format_e control_format, FILE *fp, void **mem, unsigned long *size)
143 if (control_format == MM_UTIL_JPEG_FILE) {
144 jpeg_stdio_dest(cinfo, fp);
145 mm_util_debug("jpeg_stdio_dest");
147 jpeg_mem_dest(cinfo, (unsigned char **)mem, size);
148 mm_util_debug("jpeg_mem_dest");
152 static void __jpeg_decode_open(j_decompress_ptr dinfo, mm_util_jpeg_cont_format_e control_format, FILE *fp, void *src, unsigned long size)
154 /*specify data source (eg, a file) */
155 if (control_format == MM_UTIL_JPEG_FILE) {
156 jpeg_stdio_src(dinfo, fp);
157 mm_util_debug("jpeg_stdio_src");
159 jpeg_mem_src(dinfo, src, size);
160 mm_util_debug("jpeg_mem_src");
164 static void __jpeg_decode_set_common_params(j_decompress_ptr dinfo, mm_util_color_format_e color_space, mm_util_jpeg_decode_downscale downscale)
166 mm_util_debug("image width: %d height: %d color_space: %d, downscale: %d", dinfo->image_width, dinfo->image_height, color_space, downscale);
168 if (dinfo->image_width > ENC_MAX_LEN || dinfo->image_height > ENC_MAX_LEN) {
169 dinfo->scale_num = 1;
170 dinfo->scale_denom = 8;
171 dinfo->do_fancy_upsampling = FALSE;
172 dinfo->do_block_smoothing = FALSE;
173 dinfo->dither_mode = JDITHER_ORDERED;
174 } else if (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) {
175 dinfo->scale_num = 1;
176 dinfo->scale_denom = (unsigned int)downscale;
177 dinfo->do_fancy_upsampling = FALSE;
178 dinfo->do_block_smoothing = FALSE;
179 dinfo->dither_mode = JDITHER_ORDERED;
182 dinfo->dct_method = JDCT_FASTEST;
185 static int __jpeg_decode_get_buffer_size(j_decompress_ptr dinfo, unsigned int row_stride, mm_util_color_format_e color_format, size_t *size)
189 if (color_format == MM_UTIL_COLOR_RGB24 || color_format == MM_UTIL_COLOR_RGBA || color_format == MM_UTIL_COLOR_BGRA || color_format == MM_UTIL_COLOR_ARGB) {
190 *size = dinfo->output_height * row_stride;
191 } else if (color_format == MM_UTIL_COLOR_YUV420) {
192 *size = dinfo->output_height * row_stride / 2;
193 } else if (color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
194 *size = dinfo->output_height * dinfo->output_width * 2;
195 } else if (color_format == MM_UTIL_COLOR_GRAYSCALE) {
196 *size = dinfo->output_height * dinfo->output_width;
198 mm_util_error("[%d] We can't decode the IMAGE format", color_format);
199 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
202 return MM_UTIL_ERROR_NONE;
205 static int _mm_util_jpeg_encode(mm_util_jpeg_cont_format_e control_format, mm_util_image_h decoded, int quality, FILE *fp, void **mem, size_t *csize)
207 int ret = MM_UTIL_ERROR_NONE;
208 mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
209 JSAMPROW y[16], cb[16], cr[16]; /* y[2][5] = color sample of row 2 and pixel column 5; (one plane) */
210 JSAMPARRAY data[3] = { y, cb, cr }; /* t[0][2][5] = color sample 0 of row 2 and column 5 */
212 struct jpeg_compress_struct cinfo;
214 unsigned int i, j, flag, _width, _height;
215 unsigned long size = 0;
217 mm_util_retvm_if((control_format != MM_UTIL_JPEG_FILE) && (control_format != MM_UTIL_JPEG_MEM), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid control_format [%u]", control_format);
218 mm_util_retvm_if((control_format == MM_UTIL_JPEG_FILE) && (!fp), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fp");
219 mm_util_retvm_if((control_format == MM_UTIL_JPEG_MEM) && ((!mem) || (!csize)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src or csize");
220 mm_util_retvm_if(!IS_VALID_IMAGE(decoded), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
222 mm_util_debug("quality[%d]", quality);
224 ret = __jpeg_set_error_handler(&jerr, &cinfo.err);
225 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Can't set error handler");
227 jpeg_create_compress(&cinfo);
228 mm_util_debug("jpeg_create_compress");
230 __jpeg_encode_open(&cinfo, control_format, fp, mem, &size);
232 _width = cinfo.image_width = _decoded->width;
233 _height = cinfo.image_height = _decoded->height;
234 if (_decoded->color == MM_UTIL_COLOR_YUV420 || _decoded->color == MM_UTIL_COLOR_YUV422 || _decoded->color == MM_UTIL_COLOR_UYVY) {
235 flag = cinfo.image_height - MM_UTIL_ROUND_DOWN_16(_height);
237 cinfo.input_components = 3;
238 cinfo.in_color_space = JCS_YCbCr;
239 jpeg_set_defaults(&cinfo);
240 mm_util_debug("jpeg_set_defaults");
242 cinfo.raw_data_in = TRUE; /* Supply downsampled data */
243 cinfo.do_fancy_downsampling = FALSE;
245 cinfo.comp_info[0].h_samp_factor = 2;
246 if (_decoded->color == MM_UTIL_COLOR_YUV420)
247 cinfo.comp_info[0].v_samp_factor = 2;
248 else if (_decoded->color == MM_UTIL_COLOR_YUV422 || _decoded->color == MM_UTIL_COLOR_UYVY)
249 cinfo.comp_info[0].v_samp_factor = 1;
250 cinfo.comp_info[1].h_samp_factor = 1;
251 cinfo.comp_info[1].v_samp_factor = 1;
252 cinfo.comp_info[2].h_samp_factor = 1;
253 cinfo.comp_info[2].v_samp_factor = 1;
255 jpeg_set_quality(&cinfo, quality, TRUE);
256 mm_util_debug("jpeg_set_quality");
257 cinfo.dct_method = JDCT_FASTEST;
259 jpeg_start_compress(&cinfo, TRUE);
260 mm_util_debug("jpeg_start_compress");
263 void *large_rect = calloc(1, _width);
264 void *small_rect = calloc(1, _width);
266 memset(large_rect, 0x10, _width);
268 MMUTIL_SAFE_FREE(small_rect);
269 mm_util_error("large rectangle memory");
270 return MM_UTIL_ERROR_INVALID_PARAMETER;
273 memset(small_rect, 0x80, _width);
275 MMUTIL_SAFE_FREE(large_rect);
276 mm_util_error("small rectangle memory");
277 return MM_UTIL_ERROR_INVALID_PARAMETER;
280 for (j = 0; j < _height; j += 16) {
281 for (i = 0; i < 16; i++) {
282 y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
284 cb[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width / 2 * ((i + j) / 2);
285 cr[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width * _height / 4 + _width / 2 * ((i + j) / 2);
288 jpeg_write_raw_data(&cinfo, data, 16);
290 for (i = 0; i < flag; i++) {
291 y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
293 cb[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width / 2 * ((i + j) / 2);
294 cr[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width * _height / 4 + _width / 2 * ((i + j) / 2);
297 for (; i < 16; i++) {
298 y[i] = (JSAMPROW)large_rect;
300 cb[i / 2] = (JSAMPROW)small_rect;
301 cr[i / 2] = (JSAMPROW)small_rect;
304 jpeg_write_raw_data(&cinfo, data, 16);
305 MMUTIL_SAFE_FREE(large_rect);
306 MMUTIL_SAFE_FREE(small_rect);
308 for (j = 0; j < _height; j += 16) {
309 for (i = 0; i < 16; i++) {
310 y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
312 cb[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width / 2 * ((i + j) / 2);
313 cr[i / 2] = (JSAMPROW)_decoded->data + _width * _height + _width * _height / 4 + _width / 2 * ((i + j) / 2);
316 jpeg_write_raw_data(&cinfo, data, 16);
319 mm_util_debug("#for loop#");
322 else if (_decoded->color == MM_UTIL_COLOR_RGB24 || _decoded->color == MM_UTIL_COLOR_GRAYSCALE || _decoded->color == MM_UTIL_COLOR_RGBA || _decoded->color == MM_UTIL_COLOR_BGRA || _decoded->color == MM_UTIL_COLOR_ARGB) {
323 unsigned int row_stride = 0;
324 JSAMPROW row_pointer[1];
325 JSAMPLE *image_buffer = (JSAMPLE *)_decoded->data;
327 __jpeg_convert_rgb_colorspace(_decoded->color, &(cinfo.in_color_space), &(cinfo.input_components));
328 row_stride = _width * cinfo.input_components;
330 jpeg_set_defaults(&cinfo);
331 mm_util_debug("jpeg_set_defaults");
332 jpeg_set_quality(&cinfo, quality, TRUE);
333 mm_util_debug("jpeg_set_quality");
334 jpeg_start_compress(&cinfo, TRUE);
335 mm_util_debug("jpeg_start_compress");
337 while (cinfo.next_scanline < cinfo.image_height) {
338 row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride];
339 jpeg_write_scanlines(&cinfo, row_pointer, 1);
341 mm_util_debug("while");
343 mm_util_error("We can't encode the IMAGE format");
344 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
347 jpeg_finish_compress(&cinfo);
348 mm_util_debug("jpeg_finish_compress");
350 /* The size should been updated after compress finished. */
351 if (control_format == MM_UTIL_JPEG_MEM)
352 *csize = (size_t)size;
354 jpeg_destroy_compress(&cinfo);
355 mm_util_debug("jpeg_destroy_compress");
360 static int _mm_util_jpeg_decode(mm_util_jpeg_cont_format_e control_format, FILE *fp, void *src, size_t size, mm_util_color_format_e color_format, mm_util_jpeg_decode_downscale downscale, mm_util_image_h *decoded)
362 int ret = MM_UTIL_ERROR_NONE;
363 struct jpeg_decompress_struct dinfo;
365 JSAMPARRAY buffer; /* Output row buffer */
366 unsigned int row_stride = 0; /* physical row width in output buffer */
367 JSAMPROW image, u_image, v_image;
368 JSAMPROW row; /* point to buffer[0] */
369 size_t image_buffer_size = 0;
370 void *image_buffer = NULL;
374 mm_util_retvm_if((control_format != MM_UTIL_JPEG_FILE) && (control_format != MM_UTIL_JPEG_MEM), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid control_format [%u]", control_format);
375 mm_util_retvm_if((control_format == MM_UTIL_JPEG_FILE) && (!fp), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fp");
376 mm_util_retvm_if((control_format == MM_UTIL_JPEG_MEM) && ((!src) || (size == 0)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src or size");
377 mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image handle");
379 /* allocate and initialize JPEG decompression object We set up the normal JPEG error routines, then override error_exit. */
380 ret = __jpeg_set_error_handler(&jerr, &dinfo.err);
381 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "Can't set error handler");
383 /* Now we can initialize the JPEG decompression object. */
384 jpeg_create_decompress(&dinfo);
385 mm_util_debug("jpeg_create_decompress");
387 /*specify data source (eg, a file) */
388 __jpeg_decode_open(&dinfo, control_format, fp, src, (unsigned long)size);
390 /*read file parameters with jpeg_read_header() */
391 jpeg_read_header(&dinfo, TRUE);
392 mm_util_debug("jpeg_read_header");
394 __jpeg_decode_set_common_params(&dinfo, color_format, downscale);
396 /* set parameters for decompression */
397 __jpeg_convert_rgb_colorspace(color_format, &dinfo.out_color_space, NULL);
399 /* Start decompressor */
400 jpeg_start_decompress(&dinfo);
401 mm_util_debug("jpeg_start_decompress");
403 /* byte-align for YUV format */
404 if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422) {
405 if (dinfo.output_width % 2 != 0)
406 dinfo.output_width = MM_UTIL_ROUND_DOWN_2(dinfo.output_width);
407 if (dinfo.output_height % 2 != 0)
408 dinfo.output_height = MM_UTIL_ROUND_DOWN_2(dinfo.output_height);
411 /* JSAMPLEs per row in output buffer */
412 row_stride = dinfo.output_width * dinfo.output_components;
414 /* Make a one-row-high sample array that will go away when done with image */
415 buffer = (*dinfo.mem->alloc_sarray) ((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, 1);
416 mm_util_debug("JPOOL_IMAGE BUFFER (color_format: %d)", color_format);
418 ret = __jpeg_decode_get_buffer_size(&dinfo, row_stride, color_format, &image_buffer_size);
419 if (ret != MM_UTIL_ERROR_NONE) {
420 mm_util_error("__jpeg_decode_calc_buffer_size failed");
424 image_buffer = (void *) calloc(1, image_buffer_size);
426 mm_util_error("image_buf is NULL");
427 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
430 mm_util_debug("decoded_data->data");
432 /* while (scan lines remain to be read) jpeg_read_scanlines(...); */
433 if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
434 image = image_buffer;
435 u_image = image + (dinfo.output_width * dinfo.output_height);
436 v_image = u_image + (dinfo.output_width*dinfo.output_height)/4;
440 while (dinfo.output_scanline < dinfo.output_height) {
441 jpeg_read_scanlines(&dinfo, buffer, 1);
442 for (i = 0; i < row_stride; i += 3) {
445 u_image[(i/3)/2] = row[i+1];
446 v_image[(i/3)/2] = row[i+2];
449 image += row_stride/3;
451 u_image += dinfo.output_width / 2;
452 v_image += dinfo.output_width / 2;
455 } else if (color_format == MM_UTIL_COLOR_RGB24 || color_format == MM_UTIL_COLOR_GRAYSCALE || color_format == MM_UTIL_COLOR_RGBA || color_format == MM_UTIL_COLOR_BGRA || color_format == MM_UTIL_COLOR_ARGB) {
457 while (dinfo.output_scanline < dinfo.output_height) {
458 /* jpeg_read_scanlines expects an array of pointers to scanlines. Here the array is only one element long, but you could ask formore than one scanline at a time if that's more convenient. */
459 jpeg_read_scanlines(&dinfo, buffer, 1);
461 memcpy(image_buffer + state, buffer[0], row_stride);
464 mm_util_debug("jpeg_read_scanlines");
467 ret = mm_image_create_image(dinfo.output_width, dinfo.output_height, color_format, image_buffer, image_buffer_size, decoded);
468 MMUTIL_SAFE_FREE(image_buffer);
471 /* Finish decompression */
472 jpeg_finish_decompress(&dinfo);
473 mm_util_debug("jpeg_finish_decompress");
475 /* Release JPEG decompression object */
476 jpeg_destroy_decompress(&dinfo);
477 mm_util_debug("jpeg_destroy_decompress");
484 int mm_util_jpeg_encode_to_file(mm_util_image_h decoded, int quality, const char *file_path)
486 int ret = MM_UTIL_ERROR_NONE;
487 mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
488 mm_util_image_h _converted_image = NULL;
492 mm_util_retvm_if(!file_path, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
493 mm_util_retvm_if(!IS_VALID_IMAGE(decoded), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
494 mm_util_retvm_if((!_mm_util_is_supported_color_format(_decoded->color)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", _decoded->color);
495 mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
498 ret = mm_util_safe_fopen(file_path, "wb", &fp);
499 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_safe_fopen fail (%d)", ret);
501 if (_decoded->color == MM_UTIL_COLOR_NV12) {
502 ret = mm_util_convert_colorspace(decoded, MM_UTIL_COLOR_YUV420, &_converted_image);
503 if (ret != MM_UTIL_ERROR_NONE) {
504 mm_util_error("mm_util_convert_image failed (%d)", ret);
505 mm_util_safe_fclose(fp);
509 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_FILE, _converted_image, quality, fp, NULL, NULL);
510 mm_image_destroy_image(_converted_image);
512 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_FILE, decoded, quality, fp, NULL, NULL);
515 fsync((int)(fp->_fileno));
516 mm_util_safe_fclose(fp);
523 int mm_util_jpeg_encode_to_memory(void **buffer, unsigned int *size, unsigned char *src, unsigned int width, unsigned int height, mm_util_color_format_e color, int quality)
525 int ret = MM_UTIL_ERROR_NONE;
526 size_t encoded_size = 0;
527 mm_util_image_h decoded = NULL;
529 mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
531 ret = mm_image_create_image(width, height, color, src, TEMP_DATA_SIZE, &decoded);
532 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_image_create_image fail (%d)", ret);
534 ret = mm_util_encode_to_jpeg_memory(decoded, quality, buffer, &encoded_size);
535 mm_image_destroy_image(decoded);
536 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_encode_to_jpeg_memory fail (%d)", ret);
538 *size = (unsigned int)encoded_size;
543 int mm_util_encode_to_jpeg_memory(mm_util_image_h decoded, int quality, void **buffer, size_t *size)
545 int ret = MM_UTIL_ERROR_NONE;
546 mm_image_info_s *_decoded = (mm_image_info_s *)decoded;
547 mm_util_image_h _converted_image = NULL;
551 mm_util_retvm_if(!buffer, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid buffer");
552 mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
553 mm_util_retvm_if(!IS_VALID_IMAGE(decoded), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image");
554 mm_util_retvm_if((!_mm_util_is_supported_color_format(_decoded->color)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported color [%d]", _decoded->color);
555 mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
557 if (_decoded->color == MM_UTIL_COLOR_NV12) {
558 ret = mm_util_convert_colorspace(decoded, MM_UTIL_COLOR_YUV420, &_converted_image);
559 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_convert_image fail (%d)", ret);
561 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_MEM, _converted_image, quality, NULL, buffer, size);
562 mm_image_destroy_image(_converted_image);
564 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_MEM, decoded, quality, NULL, buffer, size);
572 int mm_util_decode_from_jpeg_file(const char *file_path, mm_util_color_format_e fmt, mm_util_jpeg_decode_downscale downscale, mm_util_image_h *decoded)
574 int ret = MM_UTIL_ERROR_NONE;
576 mm_util_image_h _decoded = NULL;
580 mm_util_retvm_if(!MMUTIL_STRING_VALID(file_path), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid file_path");
581 mm_util_retvm_if((IS_VALID_COLOR(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
582 mm_util_retvm_if((!_mm_util_is_supported_color_format(fmt)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", fmt);
583 mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image handle");
585 if ((downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2)
586 && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8)) {
587 mm_util_error("#ERROR# downscale value [%d]", downscale);
588 return MM_UTIL_ERROR_INVALID_PARAMETER;
591 ret = mm_util_safe_fopen(file_path, "rb", &fp);
592 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_safe_fopen fail (%d)", ret);
594 if (fmt == MM_UTIL_COLOR_NV12) {
595 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_FILE, fp, NULL, 0, MM_UTIL_COLOR_YUV420, downscale, &_decoded);
596 if (ret == MM_UTIL_ERROR_NONE)
597 ret = mm_util_convert_colorspace(_decoded, MM_UTIL_COLOR_NV12, decoded);
598 mm_image_destroy_image(_decoded);
600 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_FILE, fp, NULL, 0, fmt, downscale, decoded);
603 mm_util_safe_fclose(fp);
610 int mm_util_decode_from_jpeg_memory(void *memory, const size_t src_size, mm_util_color_format_e fmt, mm_util_jpeg_decode_downscale downscale, mm_util_image_h *decoded)
612 int ret = MM_UTIL_ERROR_NONE;
613 mm_util_image_h _decoded = NULL;
617 mm_util_retvm_if(!memory, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid jpeg image");
618 mm_util_retvm_if(!src_size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src_size");
619 mm_util_retvm_if((IS_VALID_COLOR(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
620 mm_util_retvm_if((!_mm_util_is_supported_color_format(fmt)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", fmt);
621 mm_util_retvm_if(!decoded, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid image handle");
623 if ((downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2)
624 && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8)) {
625 mm_util_error("#ERROR# downscale value [%d]", downscale);
626 return MM_UTIL_ERROR_INVALID_PARAMETER;
629 if (fmt == MM_UTIL_COLOR_NV12) {
630 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_MEM, NULL, memory, src_size, MM_UTIL_COLOR_YUV420, downscale, &_decoded);
631 if (ret == MM_UTIL_ERROR_NONE)
632 ret = mm_util_convert_colorspace(_decoded, MM_UTIL_COLOR_NV12, decoded);
633 mm_image_destroy_image(_decoded);
635 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_MEM, NULL, memory, src_size, fmt, downscale, decoded);