Remove unused header file
[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 struct my_error_mgr_s {
37         struct jpeg_error_mgr pub; /* "public" fields */
38         jmp_buf setjmp_buffer; /* for return to caller */
39 } my_error_mgr_s;
40
41 typedef struct my_error_mgr_s *my_error_ptr;
42
43 static void __my_error_exit(j_common_ptr cinfo)
44 {
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 */
48 }
49
50 typedef enum {
51         MM_UTIL_JPEG_FILE,
52         MM_UTIL_JPEG_MEM,
53 } mm_util_jpeg_cont_format_e;
54
55 static gboolean __is_supported_color_format_with_libjpeg(mm_util_color_format_e color_format)
56 {
57         gboolean _bool = FALSE;
58
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) {
67                 _bool = TRUE;
68         }
69
70         if (!_bool)
71                 mm_util_error("not supported color format %d", color_format);
72
73         return _bool;
74 }
75
76 static gboolean _mm_util_is_supported_color_format(mm_util_color_format_e color_format)
77 {
78         gboolean _bool = FALSE;
79
80         if (__is_supported_color_format_with_libjpeg(color_format) ||
81                 color_format == MM_UTIL_COLOR_NV12) {
82                 _bool = TRUE;
83         }
84
85         if (!_bool)
86                 mm_util_error("not supported color format %d", color_format);
87
88         return _bool;
89 }
90
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)
92 {
93         int iErrorCode = MM_UTIL_ERROR_NONE;
94
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");
99
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 */
102
103         struct jpeg_compress_struct cinfo;
104         struct jpeg_error_mgr jerr;
105         int i, j, flag, _height;
106         unsigned long size = 0;
107
108         data[0] = y;
109         data[1] = cb;
110         data[2] = cr;
111
112         mm_util_debug("rawdata[%p] width[%d] height[%d] color_format[%u] quality[%d]", rawdata, width, height, color_format, quality);
113
114         cinfo.err = jpeg_std_error(&jerr); /*  Errors get written to stderr */
115
116         jpeg_create_compress(&cinfo);
117
118         if (control_format == MM_UTIL_JPEG_FILE) {
119                 jpeg_stdio_dest(&cinfo, fp);
120                 mm_util_debug("jpeg_stdio_dest");
121         } else {
122                 jpeg_mem_dest(&cinfo, (unsigned char **)mem, &size);
123                 mm_util_debug("jpeg_mem_dest");
124         }
125
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;
131
132                 cinfo.input_components = 3;
133                 cinfo.in_color_space = JCS_YCbCr;
134                 jpeg_set_defaults(&cinfo);
135                 mm_util_debug("jpeg_set_defaults");
136
137                 cinfo.raw_data_in = TRUE; /* Supply downsampled data */
138                 cinfo.do_fancy_downsampling = FALSE;
139
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;
149
150                 jpeg_set_quality(&cinfo, quality, TRUE);
151                 mm_util_debug("jpeg_set_quality");
152                 cinfo.dct_method = JDCT_FASTEST;
153
154                 jpeg_start_compress(&cinfo, TRUE);
155                 mm_util_debug("jpeg_start_compress");
156
157                 if (flag) {
158                         void *large_rect = calloc(1, width);
159                         void *small_rect = calloc(1, width);
160                         if (large_rect) {
161                                 memset(large_rect, 0x10, width);
162                         } else {
163                                 MMUTIL_SAFE_FREE(small_rect);
164                                 mm_util_error("large rectangle memory");
165                                 return MM_UTIL_ERROR_INVALID_PARAMETER;
166                         }
167                         if (small_rect) {
168                                 memset(small_rect, 0x80, width);
169                         } else {
170                                 MMUTIL_SAFE_FREE(large_rect);
171                                 mm_util_error("small rectangle memory");
172                                 return MM_UTIL_ERROR_INVALID_PARAMETER;
173                         }
174
175                         for (j = 0; j < _height; j += 16) {
176                                 for (i = 0; i < 16; i++) {
177                                         y[i] = (JSAMPROW)rawdata + width * (i + j);
178                                         if (i % 2 == 0) {
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);
181                                         }
182                                 }
183                                 jpeg_write_raw_data(&cinfo, data, 16);
184                         }
185                         for (i = 0; i < flag; i++) {
186                                 y[i] = (JSAMPROW)rawdata + width * (i + j);
187                                 if (i % 2 == 0) {
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);
190                                 }
191                         }
192                         for (; i < 16; i++) {
193                                 y[i] = (JSAMPROW)large_rect;
194                                 if (i % 2 == 0) {
195                                         cb[i / 2] = (JSAMPROW)small_rect;
196                                         cr[i / 2] = (JSAMPROW)small_rect;
197                                 }
198                         }
199                         jpeg_write_raw_data(&cinfo, data, 16);
200                         MMUTIL_SAFE_FREE(large_rect);
201                         MMUTIL_SAFE_FREE(small_rect);
202                 } else {
203                         for (j = 0; j < height; j += 16) {
204                                 for (i = 0; i < 16; i++) {
205                                         y[i] = (JSAMPROW)rawdata + width * (i + j);
206                                         if (i % 2 == 0) {
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);
209                                         }
210                                 }
211                                 jpeg_write_raw_data(&cinfo, data, 16);
212                         }
213                 }
214                 mm_util_debug("#for loop#");
215
216                 jpeg_finish_compress(&cinfo);
217                 mm_util_debug("jpeg_finish_compress");
218
219                 jpeg_destroy_compress(&cinfo);
220                 mm_util_debug("jpeg_destroy_compress");
221         }
222
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;
226
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");
247                 }
248
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)
258                         iRowStride = width;
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;
261
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);
266                 }
267                 mm_util_debug("while");
268
269                 jpeg_finish_compress(&cinfo);
270                 mm_util_debug("jpeg_finish_compress");
271
272                 jpeg_destroy_compress(&cinfo);
273                 mm_util_debug("jpeg_destroy_compress");
274         } else {
275                 mm_util_error("We can't encode the IMAGE format");
276                 return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
277         }
278
279         if (control_format == MM_UTIL_JPEG_MEM)
280                 *csize = (size_t)size;
281
282         return iErrorCode;
283 }
284
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)
286 {
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] */
294
295         mm_util_fenter();
296
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");
301
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 ");
307
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;
314         }
315
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");
320
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");
325         } else {
326                 jpeg_mem_src(&dinfo, src, (unsigned long)size);
327                 mm_util_debug("jpeg_mem_src");
328         }
329
330         /*read file parameters with jpeg_read_header() */
331         jpeg_read_header(&dinfo, TRUE);
332         mm_util_debug("jpeg_read_header");
333
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) {
336                 dinfo.scale_num = 1;
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) {
342                 dinfo.scale_num = 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;
347         }
348
349         dinfo.dct_method = JDCT_FASTEST;
350
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");
370         }
371         decoded_data->color = color_format;
372
373         /* Start decompressor */
374         jpeg_start_decompress(&dinfo);
375         mm_util_debug("jpeg_start_decompress");
376
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);
383         }
384
385         /* JSAMPLEs per row in output buffer */
386         row_stride = dinfo.output_width * dinfo.output_components;
387
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;
401         } else{
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;
406         }
407
408         decoded_data->data = (void *) calloc(1, decoded_data->size);
409         decoded_data->color = color_format;
410
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;
416         }
417         mm_util_debug("decoded_data->data");
418
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;
424                 row = buffer[0];
425                 int i = 0;
426                 int y = 0;
427                 while (dinfo.output_scanline < dinfo.output_height) {
428                         jpeg_read_scanlines(&dinfo, buffer, 1);
429                         for (i = 0; i < row_stride; i += 3) {
430                                 image[i/3] = row[i];
431                                 if (i & 1) {
432                                         u_image[(i/3)/2] = row[i+1];
433                                         v_image[(i/3)/2] = row[i+2];
434                                 }
435                         }
436                         image += row_stride/3;
437                         if (y++ & 1) {
438                                 u_image += dinfo.output_width / 2;
439                                 v_image += dinfo.output_width / 2;
440                         }
441                 }
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) {
443                 int state = 0;
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);
447
448                         memcpy(decoded_data->data + state, buffer[0], row_stride);
449                         state += row_stride;
450                 }
451                 mm_util_debug("jpeg_read_scanlines");
452         }
453
454         /* Finish decompression */
455         jpeg_finish_decompress(&dinfo);
456         mm_util_debug("jpeg_finish_decompress");
457
458         /* Release JPEG decompression object */
459         jpeg_destroy_decompress(&dinfo);
460         mm_util_debug("jpeg_destroy_decompress");
461
462         mm_util_fleave();
463
464         return iErrorCode;
465 }
466
467 int mm_util_jpeg_encode_to_file(mm_image_info_s *decoded, int quality, const char *filename)
468 {
469         int ret = MM_UTIL_ERROR_NONE;
470
471         mm_util_fenter();
472
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);
480
481         mm_util_debug("#START# LIBJPEG");
482         FILE *fp = NULL;
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);
485
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;
491
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);
494
495                 MMUTIL_SAFE_FREE(dst);
496
497         } else {
498                 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_FILE, decoded->data, decoded->width, decoded->height, decoded->color, quality, fp, NULL, NULL);
499         }
500
501         fsync((int)(fp->_fileno));
502         mm_util_safe_fclose(fp);
503
504         mm_util_debug("#End# libjpeg, Success!! ret: %d", ret);
505
506         mm_util_fleave();
507
508         return ret;
509 }
510
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)
512 {
513         int ret = MM_UTIL_ERROR_NONE;
514         size_t encoded_size = 0;
515
516         mm_image_info_s decoded;
517         memset(&decoded, 0, sizeof(mm_image_info_s));
518
519         mm_util_retvm_if(size == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid size");
520
521         decoded.width = (unsigned long)width;
522         decoded.height = (unsigned long)height;
523         decoded.color = color;
524         decoded.data = src;
525
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);
528
529         *size = (unsigned int)encoded_size;
530
531         return ret;
532 }
533
534 int mm_util_encode_to_jpeg_memory(mm_image_info_s *decoded, int quality, void **mem, size_t *size)
535 {
536         int ret = MM_UTIL_ERROR_NONE;
537
538         mm_util_fenter();
539
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);
548
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;
555
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);
558
559                 MMUTIL_SAFE_FREE(dst);
560
561         } else {
562                 ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_MEM, decoded->data, decoded->width, decoded->height, decoded->color, quality, NULL, mem, size);
563         }
564         mm_util_debug("#END# libjpeg, Success!! ret: %d", ret);
565
566         mm_util_fleave();
567
568         return ret;
569 }
570
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)
572 {
573         int ret = MM_UTIL_ERROR_NONE;
574
575         mm_util_fenter();
576
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);
581
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;
586         }
587
588         FILE *fp = NULL;
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);
591
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;
600
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);
602
603                         MMUTIL_SAFE_FREE(decoded->data);
604
605                         decoded->data = dst;
606                         decoded->size = res_buffer_size;
607                 }
608         } else {
609                 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_FILE, fp, NULL, 0, fmt, downscale, decoded);
610         }
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);
613
614         mm_util_safe_fclose(fp);
615
616         mm_util_fleave();
617
618         return ret;
619 }
620
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)
622 {
623         int ret = MM_UTIL_ERROR_NONE;
624
625         mm_util_fenter();
626
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);
631
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;
636         }
637
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;
646
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);
648
649                         MMUTIL_SAFE_FREE(decoded->data);
650
651                         decoded->data = dst;
652                         decoded->size = res_buffer_size;
653                 }
654         } else {
655                 ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_MEM, NULL, src, size, fmt, downscale, decoded);
656         }
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);
659         mm_util_fleave();
660
661         return ret;
662 }