Rename few variables and replace int to unsigned int
[platform/core/multimedia/libmm-utility.git] / jpeg / mm_util_jpeg.c
1 /*
2  * libmm-utility
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: YoungHun Kim <yh8004.kim@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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
20  *
21  */
22
23 #include <stdio.h>
24 #include <unistd.h> /* fsync() */
25 #include <jpeglib.h>
26
27 #include <setjmp.h>
28 #include <glib.h>
29 #include "mm_util_jpeg.h"
30 #include "mm_util_imgp.h"
31 #include "mm_util_private.h"
32
33 /* maximum width of encoding */
34 #define ENC_MAX_LEN 8192
35
36 typedef enum {
37         MM_UTIL_JPEG_FILE,
38         MM_UTIL_JPEG_MEM,
39 } mm_util_jpeg_cont_format_e;
40
41 typedef struct my_error_mgr_s {
42         struct jpeg_error_mgr pub; /* "public" fields */
43         jmp_buf setjmp_buffer; /* for return to caller */
44 } my_error_mgr_s;
45
46 typedef struct my_error_mgr_s *my_error_ptr;
47 typedef struct jpeg_error_mgr *jpeg_error_ptr;
48
49 static void __my_error_exit(j_common_ptr cinfo)
50 {
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 */
54 }
55
56 static gboolean __is_supported_color_format_with_libjpeg(mm_util_color_format_e color_format)
57 {
58         gboolean _bool = FALSE;
59
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) {
68                 _bool = TRUE;
69         }
70
71         if (!_bool)
72                 mm_util_error("not supported color format %d", color_format);
73
74         return _bool;
75 }
76
77 static gboolean _mm_util_is_supported_color_format(mm_util_color_format_e color_format)
78 {
79         gboolean _bool = FALSE;
80
81         if (__is_supported_color_format_with_libjpeg(color_format) ||
82                 color_format == MM_UTIL_COLOR_NV12) {
83                 _bool = TRUE;
84         }
85
86         if (!_bool)
87                 mm_util_error("not supported color format %d", color_format);
88
89         return _bool;
90 }
91
92 static int __jpeg_set_error_handler(my_error_ptr jerr, jpeg_error_ptr *err)
93 {
94         (jerr->pub).error_exit = __my_error_exit;
95         mm_util_debug("jerr.pub.error_exit ");
96
97         *err = jpeg_std_error((jpeg_error_ptr)&(jerr->pub));
98         mm_util_debug("jpeg_std_error ");
99
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;
105         }
106         mm_util_debug("if (setjmp)");
107
108         return MM_UTIL_ERROR_NONE;
109 }
110
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)
112 {
113         int pixel_depth = 0;
114
115         if (mm_color_format == MM_UTIL_COLOR_RGB24) {
116                 pixel_depth = 3;
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) {
124                 pixel_depth = 4;
125                 *j_color_space = JCS_EXT_RGBA;
126                 mm_util_debug("JCS_EXT_RGBA");
127         } else if (mm_color_format == MM_UTIL_COLOR_BGRA) {
128                 pixel_depth = 4;
129                 *j_color_space = JCS_EXT_BGRA;
130                 mm_util_debug("JCS_EXT_BGRA");
131         } else if (mm_color_format == MM_UTIL_COLOR_ARGB) {
132                 pixel_depth = 4;
133                 *j_color_space = JCS_EXT_ARGB;
134                 mm_util_debug("JCS_EXT_ARGB");
135         }
136
137         if (j_color_comp)
138                 *j_color_comp = pixel_depth;
139 }
140
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)
142 {
143         if (control_format == MM_UTIL_JPEG_FILE) {
144                 jpeg_stdio_dest(cinfo, fp);
145                 mm_util_debug("jpeg_stdio_dest");
146         } else {
147                 jpeg_mem_dest(cinfo, (unsigned char **)mem, size);
148                 mm_util_debug("jpeg_mem_dest");
149         }
150 }
151
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)
153 {
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");
158         } else {
159                 jpeg_mem_src(dinfo, src, size);
160                 mm_util_debug("jpeg_mem_src");
161         }
162 }
163
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)
165 {
166         mm_util_debug("image width: %d height: %d color_space: %d, downscale: %d", dinfo->image_width, dinfo->image_height, color_space, downscale);
167
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;
180         }
181
182         dinfo->dct_method = JDCT_FASTEST;
183 }
184
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)
186 {
187         *size = 0;
188
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;
197         } else{
198                 mm_util_error("[%d] We can't decode the IMAGE format", color_format);
199                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
200         }
201
202         return MM_UTIL_ERROR_NONE;
203 }
204
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)
206 {
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 */
211
212         struct jpeg_compress_struct cinfo;
213         my_error_mgr_s jerr;
214         unsigned int i, j, flag, _width, _height;
215         unsigned long size = 0;
216
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");
221
222         mm_util_debug("quality[%d]", quality);
223
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");
226
227         jpeg_create_compress(&cinfo);
228         mm_util_debug("jpeg_create_compress");
229
230         __jpeg_encode_open(&cinfo, control_format, fp, mem, &size);
231
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);
236
237                 cinfo.input_components = 3;
238                 cinfo.in_color_space = JCS_YCbCr;
239                 jpeg_set_defaults(&cinfo);
240                 mm_util_debug("jpeg_set_defaults");
241
242                 cinfo.raw_data_in = TRUE; /* Supply downsampled data */
243                 cinfo.do_fancy_downsampling = FALSE;
244
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;
254
255                 jpeg_set_quality(&cinfo, quality, TRUE);
256                 mm_util_debug("jpeg_set_quality");
257                 cinfo.dct_method = JDCT_FASTEST;
258
259                 jpeg_start_compress(&cinfo, TRUE);
260                 mm_util_debug("jpeg_start_compress");
261
262                 if (flag) {
263                         void *large_rect = calloc(1, _width);
264                         void *small_rect = calloc(1, _width);
265                         if (large_rect) {
266                                 memset(large_rect, 0x10, _width);
267                         } else {
268                                 MMUTIL_SAFE_FREE(small_rect);
269                                 mm_util_error("large rectangle memory");
270                                 return MM_UTIL_ERROR_INVALID_PARAMETER;
271                         }
272                         if (small_rect) {
273                                 memset(small_rect, 0x80, _width);
274                         } else {
275                                 MMUTIL_SAFE_FREE(large_rect);
276                                 mm_util_error("small rectangle memory");
277                                 return MM_UTIL_ERROR_INVALID_PARAMETER;
278                         }
279
280                         for (j = 0; j < _height; j += 16) {
281                                 for (i = 0; i < 16; i++) {
282                                         y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
283                                         if (i % 2 == 0) {
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);
286                                         }
287                                 }
288                                 jpeg_write_raw_data(&cinfo, data, 16);
289                         }
290                         for (i = 0; i < flag; i++) {
291                                 y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
292                                 if (i % 2 == 0) {
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);
295                                 }
296                         }
297                         for (; i < 16; i++) {
298                                 y[i] = (JSAMPROW)large_rect;
299                                 if (i % 2 == 0) {
300                                         cb[i / 2] = (JSAMPROW)small_rect;
301                                         cr[i / 2] = (JSAMPROW)small_rect;
302                                 }
303                         }
304                         jpeg_write_raw_data(&cinfo, data, 16);
305                         MMUTIL_SAFE_FREE(large_rect);
306                         MMUTIL_SAFE_FREE(small_rect);
307                 } else {
308                         for (j = 0; j < _height; j += 16) {
309                                 for (i = 0; i < 16; i++) {
310                                         y[i] = (JSAMPROW)_decoded->data + _width * (i + j);
311                                         if (i % 2 == 0) {
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);
314                                         }
315                                 }
316                                 jpeg_write_raw_data(&cinfo, data, 16);
317                         }
318                 }
319                 mm_util_debug("#for loop#");
320         }
321
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;
326
327                 __jpeg_convert_rgb_colorspace(_decoded->color, &(cinfo.in_color_space), &(cinfo.input_components));
328                 row_stride = _width * cinfo.input_components;
329
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");
336
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);
340                 }
341                 mm_util_debug("while");
342         } else {
343                 mm_util_error("We can't encode the IMAGE format");
344                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
345         }
346
347         jpeg_finish_compress(&cinfo);
348         mm_util_debug("jpeg_finish_compress");
349
350         /* The size should been updated after compress finished. */
351         if (control_format == MM_UTIL_JPEG_MEM)
352                 *csize = (size_t)size;
353
354         jpeg_destroy_compress(&cinfo);
355         mm_util_debug("jpeg_destroy_compress");
356
357         return ret;
358 }
359
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)
361 {
362         int ret = MM_UTIL_ERROR_NONE;
363         struct jpeg_decompress_struct dinfo;
364         my_error_mgr_s jerr;
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;
371
372         mm_util_fenter();
373
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");
378
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");
382
383         /* Now we can initialize the JPEG decompression object. */
384         jpeg_create_decompress(&dinfo);
385         mm_util_debug("jpeg_create_decompress");
386
387         /*specify data source (eg, a file) */
388         __jpeg_decode_open(&dinfo, control_format, fp, src, (unsigned long)size);
389
390         /*read file parameters with jpeg_read_header() */
391         jpeg_read_header(&dinfo, TRUE);
392         mm_util_debug("jpeg_read_header");
393
394         __jpeg_decode_set_common_params(&dinfo, color_format, downscale);
395
396         /* set parameters for decompression */
397         __jpeg_convert_rgb_colorspace(color_format, &dinfo.out_color_space, NULL);
398
399         /* Start decompressor */
400         jpeg_start_decompress(&dinfo);
401         mm_util_debug("jpeg_start_decompress");
402
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);
409         }
410
411         /* JSAMPLEs per row in output buffer */
412         row_stride = dinfo.output_width * dinfo.output_components;
413
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);
417
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");
421                 goto END;
422         }
423
424         image_buffer = (void *) calloc(1, image_buffer_size);
425         if (!image_buffer) {
426                 mm_util_error("image_buf is NULL");
427                 ret = MM_UTIL_ERROR_OUT_OF_MEMORY;
428                 goto END;
429         }
430         mm_util_debug("decoded_data->data");
431
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;
437                 row = buffer[0];
438                 int i = 0;
439                 int y = 0;
440                 while (dinfo.output_scanline < dinfo.output_height) {
441                         jpeg_read_scanlines(&dinfo, buffer, 1);
442                         for (i = 0; i < row_stride; i += 3) {
443                                 image[i/3] = row[i];
444                                 if (i & 1) {
445                                         u_image[(i/3)/2] = row[i+1];
446                                         v_image[(i/3)/2] = row[i+2];
447                                 }
448                         }
449                         image += row_stride/3;
450                         if (y++ & 1) {
451                                 u_image += dinfo.output_width / 2;
452                                 v_image += dinfo.output_width / 2;
453                         }
454                 }
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) {
456                 int state = 0;
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);
460
461                         memcpy(image_buffer + state, buffer[0], row_stride);
462                         state += row_stride;
463                 }
464                 mm_util_debug("jpeg_read_scanlines");
465         }
466
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);
469
470 END:
471         /* Finish decompression */
472         jpeg_finish_decompress(&dinfo);
473         mm_util_debug("jpeg_finish_decompress");
474
475         /* Release JPEG decompression object */
476         jpeg_destroy_decompress(&dinfo);
477         mm_util_debug("jpeg_destroy_decompress");
478
479         mm_util_fleave();
480
481         return ret;
482 }
483
484 int mm_util_jpeg_encode_to_file(mm_util_image_h decoded, int quality, const char *file_path)
485 {
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;
489
490         mm_util_fenter();
491
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);
496
497         FILE *fp = NULL;
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);
500
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);
506                         return ret;
507                 }
508
509                 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_FILE, _converted_image, quality, fp, NULL, NULL);
510                 mm_image_destroy_image(_converted_image);
511         } else {
512                 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_FILE, decoded, quality, fp, NULL, NULL);
513         }
514
515         fsync((int)(fp->_fileno));
516         mm_util_safe_fclose(fp);
517
518         mm_util_fleave();
519
520         return ret;
521 }
522
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)
524 {
525         int ret = MM_UTIL_ERROR_NONE;
526         size_t encoded_size = 0;
527         mm_util_image_h decoded = NULL;
528
529         mm_util_retvm_if(!size, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
530
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);
533
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);
537
538         *size = (unsigned int)encoded_size;
539
540         return ret;
541 }
542
543 int mm_util_encode_to_jpeg_memory(mm_util_image_h decoded, int quality, void **buffer, size_t *size)
544 {
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;
548
549         mm_util_fenter();
550
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);
556
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);
560
561                 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_MEM, _converted_image, quality, NULL, buffer, size);
562                 mm_image_destroy_image(_converted_image);
563         } else {
564                 ret = _mm_util_jpeg_encode(MM_UTIL_JPEG_MEM, decoded, quality, NULL, buffer, size);
565         }
566
567         mm_util_fleave();
568
569         return ret;
570 }
571
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)
573 {
574         int ret = MM_UTIL_ERROR_NONE;
575         FILE *fp = NULL;
576         mm_util_image_h _decoded = NULL;
577
578         mm_util_fenter();
579
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");
584
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;
589         }
590
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);
593
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);
599         } else {
600                 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_FILE, fp, NULL, 0, fmt, downscale, decoded);
601         }
602
603         mm_util_safe_fclose(fp);
604
605         mm_util_fleave();
606
607         return ret;
608 }
609
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)
611 {
612         int ret = MM_UTIL_ERROR_NONE;
613         mm_util_image_h _decoded = NULL;
614
615         mm_util_fenter();
616
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");
622
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;
627         }
628
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);
634         } else {
635                 ret = _mm_util_jpeg_decode(MM_UTIL_JPEG_MEM, NULL, memory, src_size, fmt, downscale, decoded);
636         }
637
638         mm_util_fleave();
639
640         return ret;
641 }