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
36 struct my_error_mgr_s {
37 struct jpeg_error_mgr pub; /* "public" fields */
38 jmp_buf setjmp_buffer; /* for return to caller */
41 typedef struct my_error_mgr_s *my_error_ptr;
43 static void __my_error_exit(j_common_ptr cinfo)
45 my_error_ptr myerr = (my_error_ptr) cinfo->err; /* cinfo->err really points to a my_error_mgr_s struct, so coerce pointer */
46 (*cinfo->err->output_message) (cinfo); /* Always display the message. We could postpone this until after returning, if we chose. */
47 longjmp(myerr->setjmp_buffer, 1); /* Return control to the setjmp point */
53 } mm_util_jpeg_cont_format_e;
55 static gboolean __is_supported_color_format_with_libjpeg(mm_util_color_format_e color_format)
57 gboolean _bool = FALSE;
59 if (color_format == MM_UTIL_COLOR_RGB24 ||
60 color_format == MM_UTIL_COLOR_RGBA ||
61 color_format == MM_UTIL_COLOR_BGRA ||
62 color_format == MM_UTIL_COLOR_ARGB ||
63 color_format == MM_UTIL_COLOR_YUV420 ||
64 color_format == MM_UTIL_COLOR_YUV422 ||
65 color_format == MM_UTIL_COLOR_UYVY ||
66 color_format == MM_UTIL_COLOR_GRAYSCALE) {
71 mm_util_error("not supported color format %d", color_format);
76 static gboolean _mm_util_is_supported_color_format(mm_util_color_format_e color_format)
78 gboolean _bool = FALSE;
80 if (__is_supported_color_format_with_libjpeg(color_format) ||
81 color_format == MM_UTIL_COLOR_NV12) {
86 mm_util_error("not supported color format %d", color_format);
91 static int __mm_image_encode_with_libjpeg(mm_util_jpeg_cont_format_e control_format, void *rawdata, unsigned int width, unsigned int height, mm_util_color_format_e color_format, int quality, FILE *fp, void **mem, size_t *csize)
93 int iErrorCode = MM_UTIL_ERROR_NONE;
95 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);
96 mm_util_retvm_if((control_format == MM_UTIL_JPEG_FILE) && (fp == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fp");
97 mm_util_retvm_if((control_format == MM_UTIL_JPEG_MEM) && ((mem == NULL) || (csize == NULL)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src or csize");
98 mm_util_retvm_if(rawdata == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid rawdata");
100 JSAMPROW y[16], cb[16], cr[16]; /* y[2][5] = color sample of row 2 and pixel column 5; (one plane) */
101 JSAMPARRAY data[3]; /* t[0][2][5] = color sample 0 of row 2 and column 5 */
103 struct jpeg_compress_struct cinfo;
104 struct jpeg_error_mgr jerr;
105 int i, j, flag, _height;
106 unsigned long size = 0;
112 mm_util_debug("rawdata[%p] width[%d] height[%d] color_format[%u] quality[%d]", rawdata, width, height, color_format, quality);
114 cinfo.err = jpeg_std_error(&jerr); /* Errors get written to stderr */
116 jpeg_create_compress(&cinfo);
118 if (control_format == MM_UTIL_JPEG_FILE) {
119 jpeg_stdio_dest(&cinfo, fp);
120 mm_util_debug("jpeg_stdio_dest");
122 jpeg_mem_dest(&cinfo, (unsigned char **)mem, &size);
123 mm_util_debug("jpeg_mem_dest");
126 cinfo.image_width = width;
127 cinfo.image_height = height;
128 if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
129 _height = MM_UTIL_ROUND_DOWN_16(height);
130 flag = height - _height;
132 cinfo.input_components = 3;
133 cinfo.in_color_space = JCS_YCbCr;
134 jpeg_set_defaults(&cinfo);
135 mm_util_debug("jpeg_set_defaults");
137 cinfo.raw_data_in = TRUE; /* Supply downsampled data */
138 cinfo.do_fancy_downsampling = FALSE;
140 cinfo.comp_info[0].h_samp_factor = 2;
141 if (color_format == MM_UTIL_COLOR_YUV420)
142 cinfo.comp_info[0].v_samp_factor = 2;
143 else if (color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY)
144 cinfo.comp_info[0].v_samp_factor = 1;
145 cinfo.comp_info[1].h_samp_factor = 1;
146 cinfo.comp_info[1].v_samp_factor = 1;
147 cinfo.comp_info[2].h_samp_factor = 1;
148 cinfo.comp_info[2].v_samp_factor = 1;
150 jpeg_set_quality(&cinfo, quality, TRUE);
151 mm_util_debug("jpeg_set_quality");
152 cinfo.dct_method = JDCT_FASTEST;
154 jpeg_start_compress(&cinfo, TRUE);
155 mm_util_debug("jpeg_start_compress");
158 void *large_rect = calloc(1, width);
159 void *small_rect = calloc(1, width);
161 memset(large_rect, 0x10, width);
163 MMUTIL_SAFE_FREE(small_rect);
164 mm_util_error("large rectangle memory");
165 return MM_UTIL_ERROR_INVALID_PARAMETER;
168 memset(small_rect, 0x80, width);
170 MMUTIL_SAFE_FREE(large_rect);
171 mm_util_error("small rectangle memory");
172 return MM_UTIL_ERROR_INVALID_PARAMETER;
175 for (j = 0; j < _height; j += 16) {
176 for (i = 0; i < 16; i++) {
177 y[i] = (JSAMPROW)rawdata + width * (i + j);
179 cb[i / 2] = (JSAMPROW)rawdata + width * height + width / 2 * ((i + j) / 2);
180 cr[i / 2] = (JSAMPROW)rawdata + width * height + width * height / 4 + width / 2 * ((i + j) / 2);
183 jpeg_write_raw_data(&cinfo, data, 16);
185 for (i = 0; i < flag; i++) {
186 y[i] = (JSAMPROW)rawdata + width * (i + j);
188 cb[i / 2] = (JSAMPROW)rawdata + width * height + width / 2 * ((i + j) / 2);
189 cr[i / 2] = (JSAMPROW)rawdata + width * height + width * height / 4 + width / 2 * ((i + j) / 2);
192 for (; i < 16; i++) {
193 y[i] = (JSAMPROW)large_rect;
195 cb[i / 2] = (JSAMPROW)small_rect;
196 cr[i / 2] = (JSAMPROW)small_rect;
199 jpeg_write_raw_data(&cinfo, data, 16);
200 MMUTIL_SAFE_FREE(large_rect);
201 MMUTIL_SAFE_FREE(small_rect);
203 for (j = 0; j < height; j += 16) {
204 for (i = 0; i < 16; i++) {
205 y[i] = (JSAMPROW)rawdata + width * (i + j);
207 cb[i / 2] = (JSAMPROW)rawdata + width * height + width / 2 * ((i + j) / 2);
208 cr[i / 2] = (JSAMPROW)rawdata + width * height + width * height / 4 + width / 2 * ((i + j) / 2);
211 jpeg_write_raw_data(&cinfo, data, 16);
214 mm_util_debug("#for loop#");
216 jpeg_finish_compress(&cinfo);
217 mm_util_debug("jpeg_finish_compress");
219 jpeg_destroy_compress(&cinfo);
220 mm_util_debug("jpeg_destroy_compress");
223 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) {
224 JSAMPROW row_pointer[1];
225 unsigned int iRowStride = 0;
227 if (color_format == MM_UTIL_COLOR_RGB24) {
228 cinfo.input_components = 3;
229 cinfo.in_color_space = JCS_RGB;
230 mm_util_debug("JCS_RGB");
231 } else if (color_format == MM_UTIL_COLOR_GRAYSCALE) {
232 cinfo.input_components = 1; /* one colour component */
233 cinfo.in_color_space = JCS_GRAYSCALE;
234 mm_util_debug("JCS_GRAYSCALE");
235 } else if (color_format == MM_UTIL_COLOR_RGBA) {
236 cinfo.input_components = 4;
237 cinfo.in_color_space = JCS_EXT_RGBA;
238 mm_util_debug("JCS_EXT_RGBA");
239 } else if (color_format == MM_UTIL_COLOR_BGRA) {
240 cinfo.input_components = 4;
241 cinfo.in_color_space = JCS_EXT_BGRA;
242 mm_util_debug("JCS_EXT_BGRA");
243 } else if (color_format == MM_UTIL_COLOR_ARGB) {
244 cinfo.input_components = 4;
245 cinfo.in_color_space = JCS_EXT_ARGB;
246 mm_util_debug("JCS_EXT_ARGB");
249 jpeg_set_defaults(&cinfo);
250 mm_util_debug("jpeg_set_defaults");
251 jpeg_set_quality(&cinfo, quality, TRUE);
252 mm_util_debug("jpeg_set_quality");
253 jpeg_start_compress(&cinfo, TRUE);
254 mm_util_debug("jpeg_start_compress");
255 if (color_format == MM_UTIL_COLOR_RGB24)
256 iRowStride = width * 3;
257 else if (color_format == MM_UTIL_COLOR_GRAYSCALE)
259 else if (color_format == MM_UTIL_COLOR_RGBA || color_format == MM_UTIL_COLOR_BGRA || color_format == MM_UTIL_COLOR_ARGB)
260 iRowStride = width * 4;
262 JSAMPLE *image_buffer = (JSAMPLE *)rawdata;
263 while (cinfo.next_scanline < cinfo.image_height) {
264 row_pointer[0] = &image_buffer[cinfo.next_scanline * iRowStride];
265 jpeg_write_scanlines(&cinfo, row_pointer, 1);
267 mm_util_debug("while");
269 jpeg_finish_compress(&cinfo);
270 mm_util_debug("jpeg_finish_compress");
272 jpeg_destroy_compress(&cinfo);
273 mm_util_debug("jpeg_destroy_compress");
275 mm_util_error("We can't encode the IMAGE format");
276 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
279 if (control_format == MM_UTIL_JPEG_MEM)
280 *csize = (size_t)size;
285 static int __mm_image_decode_with_libjpeg(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_image_info_s *decoded_data)
287 int iErrorCode = MM_UTIL_ERROR_NONE;
288 struct jpeg_decompress_struct dinfo;
289 struct my_error_mgr_s jerr;
290 JSAMPARRAY buffer; /* Output row buffer */
291 int row_stride = 0; /* physical row width in output buffer */
292 JSAMPROW image, u_image, v_image;
293 JSAMPROW row; /* point to buffer[0] */
297 mm_util_retvm_if(decoded_data == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded_data");
298 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);
299 mm_util_retvm_if((control_format == MM_UTIL_JPEG_FILE) && (fp == NULL), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fp");
300 mm_util_retvm_if((control_format == MM_UTIL_JPEG_MEM) && ((src == NULL) || (size == 0)), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src or size");
302 /* allocate and initialize JPEG decompression object We set up the normal JPEG error routines, then override error_exit. */
303 dinfo.err = jpeg_std_error(&jerr.pub);
304 mm_util_debug("jpeg_std_error ");
305 jerr.pub.error_exit = __my_error_exit;
306 mm_util_debug("jerr.pub.error_exit ");
308 /* Establish the setjmp return context for __my_error_exit to use. */
309 if (setjmp(jerr.setjmp_buffer)) {
310 /* 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.*/
311 mm_util_error("ERROR setjmp");
312 jpeg_destroy_decompress(&dinfo);
313 return MM_UTIL_ERROR_NO_SUCH_FILE;
316 mm_util_debug("if (setjmp)");
317 /* Now we can initialize the JPEG decompression object. */
318 jpeg_create_decompress(&dinfo);
319 mm_util_debug("jpeg_create_decompress");
321 /*specify data source (eg, a file) */
322 if (control_format == MM_UTIL_JPEG_FILE) {
323 jpeg_stdio_src(&dinfo, fp);
324 mm_util_debug("jpeg_stdio_src");
326 jpeg_mem_src(&dinfo, src, (unsigned long)size);
327 mm_util_debug("jpeg_mem_src");
330 /*read file parameters with jpeg_read_header() */
331 jpeg_read_header(&dinfo, TRUE);
332 mm_util_debug("jpeg_read_header");
334 mm_util_debug("image width: %d height: %d", dinfo.image_width, dinfo.image_height);
335 if (dinfo.image_width > ENC_MAX_LEN || dinfo.image_height > ENC_MAX_LEN) {
337 dinfo.scale_denom = 8;
338 dinfo.do_fancy_upsampling = FALSE;
339 dinfo.do_block_smoothing = FALSE;
340 dinfo.dither_mode = JDITHER_ORDERED;
341 } else if (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) {
343 dinfo.scale_denom = (unsigned int)downscale;
344 dinfo.do_fancy_upsampling = FALSE;
345 dinfo.do_block_smoothing = FALSE;
346 dinfo.dither_mode = JDITHER_ORDERED;
349 dinfo.dct_method = JDCT_FASTEST;
351 /* set parameters for decompression */
352 if (color_format == MM_UTIL_COLOR_RGB24) {
353 dinfo.out_color_space = JCS_RGB;
354 mm_util_debug("cinfo.out_color_space = JCS_RGB");
355 } else if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
356 dinfo.out_color_space = JCS_YCbCr;
357 mm_util_debug("cinfo.out_color_space = JCS_YCbCr");
358 } else if (color_format == MM_UTIL_COLOR_GRAYSCALE) {
359 dinfo.out_color_space = JCS_GRAYSCALE;
360 mm_util_debug("cinfo.out_color_space = JCS_GRAYSCALE");
361 } else if (color_format == MM_UTIL_COLOR_RGBA) {
362 dinfo.out_color_space = JCS_EXT_RGBA;
363 mm_util_debug("cinfo.out_color_space = JCS_EXT_RGBA");
364 } else if (color_format == MM_UTIL_COLOR_BGRA) {
365 dinfo.out_color_space = JCS_EXT_BGRA;
366 mm_util_debug("cinfo.out_color_space = JCS_EXT_BGRA");
367 } else if (color_format == MM_UTIL_COLOR_ARGB) {
368 dinfo.out_color_space = JCS_EXT_ARGB;
369 mm_util_debug("cinfo.out_color_space = JCS_EXT_ARGB");
371 decoded_data->color = color_format;
373 /* Start decompressor */
374 jpeg_start_decompress(&dinfo);
375 mm_util_debug("jpeg_start_decompress");
377 /* byte-align for YUV format */
378 if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422) {
379 if (dinfo.output_width % 2 != 0)
380 dinfo.output_width = MM_UTIL_ROUND_DOWN_2(dinfo.output_width);
381 if (dinfo.output_height % 2 != 0)
382 dinfo.output_height = MM_UTIL_ROUND_DOWN_2(dinfo.output_height);
385 /* JSAMPLEs per row in output buffer */
386 row_stride = dinfo.output_width * dinfo.output_components;
388 /* Make a one-row-high sample array that will go away when done with image */
389 buffer = (*dinfo.mem->alloc_sarray) ((j_common_ptr) &dinfo, JPOOL_IMAGE, row_stride, 1);
390 mm_util_debug("JPOOL_IMAGE BUFFER (color_format: %d)", color_format);
391 decoded_data->width = dinfo.output_width;
392 decoded_data->height = dinfo.output_height;
393 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) {
394 decoded_data->size = dinfo.output_height * row_stride;
395 } else if (color_format == MM_UTIL_COLOR_YUV420) {
396 decoded_data->size = dinfo.output_height * row_stride / 2;
397 } else if (color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
398 decoded_data->size = dinfo.output_height * dinfo.output_width * 2;
399 } else if (color_format == MM_UTIL_COLOR_GRAYSCALE) {
400 decoded_data->size = dinfo.output_height * dinfo.output_width;
402 jpeg_finish_decompress(&dinfo);
403 jpeg_destroy_decompress(&dinfo);
404 mm_util_error("[%d] We can't decode the IMAGE format", color_format);
405 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
408 decoded_data->data = (void *) calloc(1, decoded_data->size);
409 decoded_data->color = color_format;
411 if (decoded_data->data == NULL) {
412 jpeg_finish_decompress(&dinfo);
413 jpeg_destroy_decompress(&dinfo);
414 mm_util_error("decoded_data->data is NULL");
415 return MM_UTIL_ERROR_OUT_OF_MEMORY;
417 mm_util_debug("decoded_data->data");
419 /* while (scan lines remain to be read) jpeg_read_scanlines(...); */
420 if (color_format == MM_UTIL_COLOR_YUV420 || color_format == MM_UTIL_COLOR_YUV422 || color_format == MM_UTIL_COLOR_UYVY) {
421 image = decoded_data->data;
422 u_image = image + (dinfo.output_width * dinfo.output_height);
423 v_image = u_image + (dinfo.output_width*dinfo.output_height)/4;
427 while (dinfo.output_scanline < dinfo.output_height) {
428 jpeg_read_scanlines(&dinfo, buffer, 1);
429 for (i = 0; i < row_stride; i += 3) {
432 u_image[(i/3)/2] = row[i+1];
433 v_image[(i/3)/2] = row[i+2];
436 image += row_stride/3;
438 u_image += dinfo.output_width / 2;
439 v_image += dinfo.output_width / 2;
442 } 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) {
444 while (dinfo.output_scanline < dinfo.output_height) {
445 /* 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. */
446 jpeg_read_scanlines(&dinfo, buffer, 1);
448 memcpy(decoded_data->data + state, buffer[0], row_stride);
451 mm_util_debug("jpeg_read_scanlines");
454 /* Finish decompression */
455 jpeg_finish_decompress(&dinfo);
456 mm_util_debug("jpeg_finish_decompress");
458 /* Release JPEG decompression object */
459 jpeg_destroy_decompress(&dinfo);
460 mm_util_debug("jpeg_destroy_decompress");
467 int mm_util_jpeg_encode_to_file(mm_image_info_s *decoded, int quality, const char *filename)
469 int ret = MM_UTIL_ERROR_NONE;
473 mm_util_retvm_if(filename == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid filename");
474 mm_util_retvm_if(decoded == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
475 mm_util_retvm_if(decoded->data == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src data");
476 mm_util_retvm_if((decoded->width <= 0) || (decoded->height <= 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid width[%lu] height[%lu]", decoded->width, decoded->height);
477 mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(decoded->color) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", decoded->color);
478 mm_util_retvm_if((!_mm_util_is_supported_color_format(decoded->color)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", decoded->color);
479 mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
481 mm_util_debug("#START# LIBJPEG");
483 ret = mm_util_safe_fopen(filename, "wb", &fp);
484 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_safe_fopen fail (%d)", ret);
486 if (decoded->color == MM_UTIL_COLOR_NV12) {
487 unsigned int res_w = 0;
488 unsigned int res_h = 0;
489 size_t res_buffer_size = 0;
490 unsigned char *dst = NULL;
492 ret = mm_util_convert_colorspace(decoded->data, decoded->width, decoded->height, MM_UTIL_COLOR_NV12, MM_UTIL_COLOR_YUV420, &dst, &res_w, &res_h, &res_buffer_size);
493 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_FILE, dst, res_w, res_h, MM_UTIL_COLOR_YUV420, quality, fp, NULL, NULL);
495 MMUTIL_SAFE_FREE(dst);
498 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_FILE, decoded->data, decoded->width, decoded->height, decoded->color, quality, fp, NULL, NULL);
501 fsync((int)(fp->_fileno));
502 mm_util_safe_fclose(fp);
504 mm_util_debug("#End# libjpeg, Success!! ret: %d", ret);
511 int mm_util_jpeg_encode_to_memory(void **mem, unsigned int *size, unsigned char *src, unsigned int width, unsigned int height, mm_util_color_format_e color, int quality)
513 int ret = MM_UTIL_ERROR_NONE;
514 size_t encoded_size = 0;
516 mm_image_info_s decoded;
517 memset(&decoded, 0, sizeof(mm_image_info_s));
519 mm_util_retvm_if(size == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
521 decoded.width = (unsigned long)width;
522 decoded.height = (unsigned long)height;
523 decoded.color = color;
526 ret = mm_util_encode_to_jpeg_memory(&decoded, quality, mem, &encoded_size);
527 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_encode_to_jpeg_memory fail (%d)", ret);
529 *size = (unsigned int)encoded_size;
534 int mm_util_encode_to_jpeg_memory(mm_image_info_s *decoded, int quality, void **mem, size_t *size)
536 int ret = MM_UTIL_ERROR_NONE;
540 mm_util_retvm_if(mem == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid filename");
541 mm_util_retvm_if(size == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
542 mm_util_retvm_if(decoded == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
543 mm_util_retvm_if(decoded->data == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src data");
544 mm_util_retvm_if((decoded->width <= 0) || (decoded->height <= 0), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid width[%lu] height[%lu]", decoded->width, decoded->height);
545 mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(decoded->color) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", decoded->color);
546 mm_util_retvm_if((!_mm_util_is_supported_color_format(decoded->color)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", decoded->color);
547 mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
549 mm_util_debug("#START# libjpeg");
550 if (decoded->color == MM_UTIL_COLOR_NV12) {
551 unsigned int res_w = 0;
552 unsigned int res_h = 0;
553 size_t res_buffer_size = 0;
554 unsigned char *dst = NULL;
556 ret = mm_util_convert_colorspace(decoded->data, decoded->width, decoded->height, MM_UTIL_COLOR_NV12, MM_UTIL_COLOR_YUV420, &dst, &res_w, &res_h, &res_buffer_size);
557 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_MEM, dst, res_w, res_h, MM_UTIL_COLOR_YUV420, quality, NULL, mem, size);
559 MMUTIL_SAFE_FREE(dst);
562 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_MEM, decoded->data, decoded->width, decoded->height, decoded->color, quality, NULL, mem, size);
564 mm_util_debug("#END# libjpeg, Success!! ret: %d", ret);
571 int mm_util_decode_from_jpeg_file(const char *filename, mm_util_color_format_e fmt, mm_util_jpeg_decode_downscale downscale, mm_image_info_s *decoded)
573 int ret = MM_UTIL_ERROR_NONE;
577 mm_util_retvm_if(decoded == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded");
578 mm_util_retvm_if(filename == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid filename");
579 mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
580 mm_util_retvm_if((!_mm_util_is_supported_color_format(fmt)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", fmt);
582 if ((downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2)
583 && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8)) {
584 mm_util_error("#ERROR# downscale value [%d]", downscale);
585 return MM_UTIL_ERROR_INVALID_PARAMETER;
589 ret = mm_util_safe_fopen(filename, "rb", &fp);
590 mm_util_retvm_if(ret != MM_UTIL_ERROR_NONE, ret, "mm_util_safe_fopen fail (%d)", ret);
592 mm_util_debug("#START# libjpeg fmt [%d]", fmt);
593 if (fmt == MM_UTIL_COLOR_NV12) {
594 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_FILE, fp, NULL, 0, MM_UTIL_COLOR_YUV420, downscale, decoded);
595 if (ret == MM_UTIL_ERROR_NONE) {
596 unsigned int res_w = 0;
597 unsigned int res_h = 0;
598 size_t res_buffer_size = 0;
599 unsigned char *dst = NULL;
601 ret = mm_util_convert_colorspace(decoded->data, decoded->width, decoded->height, MM_UTIL_COLOR_YUV420, MM_UTIL_COLOR_NV12, &dst, &res_w, &res_h, &res_buffer_size);
603 MMUTIL_SAFE_FREE(decoded->data);
606 decoded->size = res_buffer_size;
609 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_FILE, fp, NULL, 0, fmt, downscale, decoded);
611 mm_util_debug("decoded->data: %p\t width: %lu\t height: %lu\t size: %zu", decoded->data, decoded->width, decoded->height, decoded->size);
612 mm_util_debug("#End# libjpeg, Success!! ret: %d", ret);
614 mm_util_safe_fclose(fp);
621 int mm_util_decode_from_jpeg_memory(void *src, const size_t size, mm_util_color_format_e fmt, mm_util_jpeg_decode_downscale downscale, mm_image_info_s *decoded)
623 int ret = MM_UTIL_ERROR_NONE;
627 mm_util_retvm_if(decoded == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid decoded");
628 mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid filename");
629 mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
630 mm_util_retvm_if((!_mm_util_is_supported_color_format(fmt)), MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT, "not supported fmt [%d]", fmt);
632 if ((downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_1) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_2)
633 && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_4) && (downscale != MM_UTIL_JPEG_DECODE_DOWNSCALE_1_8)) {
634 mm_util_error("#ERROR# downscale value [%d]", downscale);
635 return MM_UTIL_ERROR_INVALID_PARAMETER;
638 mm_util_debug("#START# libjpeg");
639 if (fmt == MM_UTIL_COLOR_NV12) {
640 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_MEM, NULL, src, size, MM_UTIL_COLOR_YUV420, downscale, decoded);
641 if (ret == MM_UTIL_ERROR_NONE) {
642 unsigned int res_w = 0;
643 unsigned int res_h = 0;
644 size_t res_buffer_size = 0;
645 unsigned char *dst = NULL;
647 ret = mm_util_convert_colorspace(decoded->data, decoded->width, decoded->height, MM_UTIL_COLOR_YUV420, MM_UTIL_COLOR_NV12, &dst, &res_w, &res_h, &res_buffer_size);
649 MMUTIL_SAFE_FREE(decoded->data);
652 decoded->size = res_buffer_size;
655 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_MEM, NULL, src, size, fmt, downscale, decoded);
657 mm_util_debug("decoded->data: %p\t width: %lu\t height: %lu\t size: %zu", decoded->data, decoded->width, decoded->height, decoded->size);
658 mm_util_debug("#END# libjpeg, Success!! ret: %d", ret);