#include <stdio.h>
#include <unistd.h> /* fsync() */
#include <jpeglib.h>
-#define LIBJPEG_TURBO 0
-#define ENC_MAX_LEN 8192
-#if LIBJPEG_TURBO
+
+#ifdef LIBJPEG_TURBO
#include <turbojpeg.h>
#endif
#include "mm_util_common.h"
#include "mm_util_private.h"
-#ifndef YUV420_SIZE
-#define YUV420_SIZE(width, height) (width*height*3>>1)
-#endif
-#ifndef YUV422_SIZE
-#define YUV422_SIZE(width, height) (width*height<<1)
-#endif
+/* maximum width of encoding */
+#define ENC_MAX_LEN 8192
-#define PARTIAL_DECODE 1
-#define LIBJPEG 1
-#define MM_JPEG_ROUND_UP_2(num) (((num)+1)&~1)
-#define MM_JPEG_ROUND_UP_4(num) (((num)+3)&~3)
-#define MM_JPEG_ROUND_UP_8(num) (((num)+7)&~7)
-#define MM_JPEG_ROUND_DOWN_2(num) ((num)&(~1))
-#define MM_JPEG_ROUND_DOWN_4(num) ((num)&(~3))
-#define MM_JPEG_ROUND_DOWN_16(num) ((num)&(~15))
-
-#if LIBJPEG_TURBO
-#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
+/* libjpeg_turbo is faster than libjpeg, but libjpeg is more stable. */
+/* Encoding/Decoding jpeg image with libjpeg_turbo has been developed, but it is not tested yet. */
+#ifdef LIBJPEG_TURBO
#define _throwtj() {printf("TurboJPEG ERROR:\n%s\n", tjGetErrorStr()); }
#define _tj(f) {if ((f) == -1) _throwtj(); }
} else if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422) {
if (_hdrsubsamp == TJSAMP_422) {
mm_util_debug("_hdrsubsamp == TJSAMP_422", decoded_data->width, _hdrw);
- decoded_data->width = MM_JPEG_ROUND_UP_2(_hdrw);
+ decoded_data->width = MM_UTIL_ROUND_UP_2(_hdrw);
} else {
if (_hdrw % 4 != 0)
- decoded_data->width = MM_JPEG_ROUND_UP_4(_hdrw);
+ decoded_data->width = MM_UTIL_ROUND_UP_4(_hdrw);
else
decoded_data->width = _hdrw;
}
if (_hdrsubsamp == TJSAMP_420) {
mm_util_debug("_hdrsubsamp == TJSAMP_420", decoded_data->width, _hdrw);
if (_hdrh % 4 != 0)
- decoded_data->height = MM_JPEG_ROUND_UP_4(_hdrh);
+ decoded_data->height = MM_UTIL_ROUND_UP_4(_hdrh);
else
decoded_data->height = _hdrh;
} else {
tjDestroy(chandle);
return iErrorCode;
}
-#endif
+#else /* libjpeg */
/* OPEN SOURCE */
struct my_error_mgr_s {
typedef struct my_error_mgr_s *my_error_ptr;
-struct {
- struct jpeg_destination_mgr pub; /* public fields */
- FILE *outfile; /* target stream */
- JOCTET *buffer; /* start of buffer */
-} my_destination_mgr_s;
-
-typedef struct my_destination_mgr_s *my_dest_ptr;
-
-#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
-
-/* Expanded data destination object for memory output */
-
-struct {
- struct jpeg_destination_mgr pub; /* public fields */
-
- unsigned char **outbuffer; /* target buffer */
- unsigned long *outsize;
- unsigned char *newbuffer; /* newly allocated buffer */
- JOCTET *buffer; /* start of buffer */
- size_t bufsize;
-} my_mem_destination_mgr;
-
-typedef struct my_mem_destination_mgr *my_mem_dest_ptr;
-
-#if LIBJPEG_TURBO == 0
static void __my_error_exit(j_common_ptr cinfo)
{
my_error_ptr myerr = (my_error_ptr) cinfo->err; /* cinfo->err really points to a my_error_mgr_s struct, so coerce pointer */
if (fmt == MM_UTIL_COLOR_YUV420 || fmt == MM_UTIL_COLOR_YUV422 || fmt == MM_UTIL_COLOR_UYVY) {
mm_util_debug("[__mm_image_encode_to_jpeg_file_with_libjpeg] jpeg_stdio_dest for YUV");
mm_util_debug("[Height] %d", height);
- _height = MM_JPEG_ROUND_DOWN_16(height);
+ _height = MM_UTIL_ROUND_DOWN_16(height);
flag = height - _height;
cinfo.input_components = 3;
cinfo.image_height = height;
if (fmt == MM_UTIL_COLOR_YUV420 || fmt == MM_UTIL_COLOR_YUV422 || fmt == MM_UTIL_COLOR_UYVY) {
mm_util_debug("[__mm_image_encode_to_jpeg_file_with_libjpeg] jpeg_stdio_dest for YUV");
- _height = MM_JPEG_ROUND_DOWN_16(height);
+ _height = MM_UTIL_ROUND_DOWN_16(height);
flag = height - _height;
cinfo.input_components = 3;
/*read file parameters with jpeg_read_header() */
jpeg_read_header(&dinfo, TRUE);
-#if PARTIAL_DECODE
+
mm_util_debug("image width: %d height: %d", dinfo.image_width, dinfo.image_height);
if (dinfo.image_width > ENC_MAX_LEN || dinfo.image_height > ENC_MAX_LEN) {
dinfo.scale_num = 1;
dinfo.do_block_smoothing = FALSE;
dinfo.dither_mode = JDITHER_ORDERED;
}
-#endif
+
dinfo.dct_method = JDCT_FASTEST;
/* set parameters for decompression */
/* byte-align for YUV format */
if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422) {
if (dinfo.output_width % 2 != 0)
- dinfo.output_width = MM_JPEG_ROUND_DOWN_2(dinfo.output_width);
+ dinfo.output_width = MM_UTIL_ROUND_DOWN_2(dinfo.output_width);
if (dinfo.output_height % 2 != 0)
- dinfo.output_height = MM_JPEG_ROUND_DOWN_2(dinfo.output_height);
+ dinfo.output_height = MM_UTIL_ROUND_DOWN_2(dinfo.output_height);
}
/* JSAMPLEs per row in output buffer */
/*read file parameters with jpeg_read_header() */
jpeg_read_header(&dinfo, TRUE);
mm_util_debug("jpeg_read_header");
-#if PARTIAL_DECODE
+
mm_util_debug("image width: %d height: %d", dinfo.image_width, dinfo.image_height);
if (dinfo.image_width > ENC_MAX_LEN || dinfo.image_height > ENC_MAX_LEN) {
dinfo.scale_num = 1;
dinfo.do_block_smoothing = FALSE;
dinfo.dither_mode = JDITHER_ORDERED;
}
-#endif
+
dinfo.dct_method = JDCT_FASTEST;
/* set parameters for decompression */
/* byte-align for YUV format */
if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422) {
if (dinfo.output_width % 2 != 0)
- dinfo.output_width = MM_JPEG_ROUND_DOWN_2(dinfo.output_width);
+ dinfo.output_width = MM_UTIL_ROUND_DOWN_2(dinfo.output_width);
if (dinfo.output_height % 2 != 0)
- dinfo.output_height = MM_JPEG_ROUND_DOWN_2(dinfo.output_height);
+ dinfo.output_height = MM_UTIL_ROUND_DOWN_2(dinfo.output_height);
}
/* JSAMPLEs per row in output buffer */
return iErrorCode;
}
#endif
+
int mm_util_jpeg_encode_to_file(const char *filename, void* src, int width, int height, mm_util_color_format_e fmt, int quality)
{
int ret = MM_UTIL_ERROR_NONE;
mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# LIBJPEG_TURBO");
ret = __mm_image_encode_to_jpeg_file_with_libjpeg_turbo(filename, src, width, height, fmt, quality);
#else
mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# libjpeg-turbo");
ret = __mm_image_encode_to_jpeg_memory_with_libjpeg_turbo(mem, size, src, width, height, fmt, quality);
#else /* LIBJPEG_TURBO */
}
if (magic[0] == 0xff && magic[1] == 0xd8) {
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# LIBJPEG_TURBO");
ret = __mm_image_decode_from_jpeg_file_with_libjpeg_turbo(decoded, filename, fmt);
#else
mm_util_retvm_if(src == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid src");
mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(fmt) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", fmt);
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# libjpeg");
ret = __mm_image_decode_from_jpeg_memory_with_libjpeg_turbo(decoded, src, size, fmt);
#else
return MM_UTIL_ERROR_NO_SUCH_FILE;
}
if (magic[0] == 0xff && magic[1] == 0xd8) {
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# LIBJPEG_TURBO");
ret = __mm_image_decode_from_jpeg_file_with_libjpeg_turbo(decoded, filename, fmt);
#else
return MM_UTIL_ERROR_INVALID_PARAMETER;
}
-#if LIBJPEG_TURBO
+#ifdef LIBJPEG_TURBO
mm_util_debug("#START# libjpeg");
ret = __mm_image_decode_from_jpeg_memory_with_libjpeg_turbo(decoded, src, size, fmt);
#else
ret = __mm_image_decode_from_jpeg_memory_with_libjpeg(decoded, src, size, fmt, downscale);
}
#endif
-
mm_util_debug("decoded->data: %p\t width: %d\t height: %d\t size: %u", decoded->data, decoded->width, decoded->height, decoded->size);
mm_util_debug("#END# libjpeg, Success!! ret: %d", ret);