/* maximum width of encoding */
#define ENC_MAX_LEN 8192
-/* 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(); }
-
-const char *subName[TJ_NUMSAMP] = {"444", "422", "420", "GRAY", "440"};
-
-static void __initBuf(unsigned char *buf, int w, int h, int pf, int flags)
-{
- int r_offset = tjRedOffset[pf];
- int g_offset = tjGreenOffset[pf];
- int b_offset = tjBlueOffset[pf];
- int ps = tjPixelSize[pf];
- int index, row, col, halfway = 16;
-
- memset(buf, 0, w*h*ps);
- if (pf == TJPF_GRAY) {
- for (row = 0; row < h; row++) {
- for (col = 0; col < w; col++) {
- if (flags&TJFLAG_BOTTOMUP) index = (h-row-1)*w+col;
- else index = row*w+col;
- if (((row/8) + (col/8)) % 2 == 0) buf[index] = (row < halfway) ? 255 : 0;
- else buf[index] = (row < halfway) ? 76 : 226;
- }
- }
- } else {
- for (row = 0; row < h; row++) {
- for (col = 0; col < w; col++) {
- if (flags&TJFLAG_BOTTOMUP) index = (h-row-1)*w+col;
- else index = row*w+col;
- if (((row/8) + (col/8))%2 == 0) {
- if (row < halfway) {
- buf[index*ps+r_offset] = 255;
- buf[index*ps+g_offset] = 255;
- buf[index*ps+b_offset] = 255;
- }
- } else {
- buf[index*ps+r_offset] = 255;
- if (row >= halfway) buf[index*ps + g_offset] = 255;
- }
- }
- }
- }
-}
-
-static void __mm_decode_libjpeg_turbo_decompress(tjhandle handle, unsigned char *jpegBuf, unsigned long jpegSize, int TD_BU, mm_util_jpeg_yuv_data* decoded_data, mm_util_color_format_e input_fmt)
-{
- int _hdrw = 0, _hdrh = 0, _hdrsubsamp = -1;
- int scaledWidth = 0;
- int scaledHeight = 0;
- unsigned long dstSize = 0;
- int i = 0, n = 0;
- tjscalingfactor _sf;
- tjscalingfactor *sf = tjGetScalingFactors(&n), sf1 = {1, 1};
-
- mm_util_retvm_if(jpegBuf == NULL, MM_UTIL_ERROR_INVALID_PARAMETER, "invalid jpegBuf");
-
- mm_util_debug("0x%2x, 0x%2x ", jpegBuf[0], jpegBuf[1]);
-
- _tj(tjDecompressHeader2(handle, jpegBuf, jpegSize, &_hdrw, &_hdrh, &_hdrsubsamp));
-
- if (!sf || !n) {
- mm_util_error(" scaledfactor is NULL");
- return;
- }
-
- if ((_hdrsubsamp == TJSAMP_444 || _hdrsubsamp == TJSAMP_GRAY) || input_fmt == MM_UTIL_COLOR_RGB24)
- _sf = sf[i];
- else
- _sf = sf1;
-
- scaledWidth = TJSCALED(_hdrw, _sf);
- scaledHeight = TJSCALED(_hdrh, _sf);
- mm_util_debug("_hdrw:%d _hdrh:%d, _hdrsubsamp:%d, scaledWidth:%d, scaledHeight:%d", _hdrw, _hdrh, _hdrsubsamp, scaledWidth, scaledHeight);
-
- if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422)
- mm_util_debug("JPEG -> YUV %s ... ", subName[_hdrsubsamp]);
- else if (input_fmt == MM_UTIL_COLOR_RGB24)
- mm_util_debug("JPEG -> RGB %d/%d ... ", _sf.num, _sf.denom);
-
- if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422) {
- dstSize = TJBUFSIZEYUV(_hdrw, _hdrh, _hdrsubsamp);
- mm_util_debug("MM_UTIL_COLOR_YUV420 dstSize: %d _hdrsubsamp:%d TJBUFSIZEYUV(w, h, _hdrsubsamp): %d",
- dstSize, _hdrsubsamp, TJBUFSIZEYUV(_hdrw, _hdrh, _hdrsubsamp));
- } else if (input_fmt == MM_UTIL_COLOR_RGB24) {
- dstSize = scaledWidth*scaledHeight*tjPixelSize[TJPF_RGB];
- mm_util_debug("MM_UTIL_COLOR_RGB24 dstSize: %d _hdrsubsamp:%d", dstSize, _hdrsubsamp);
- }
-
- if ((decoded_data->data = (void *)calloc(1, dstSize)) == NULL) {
- mm_util_error("dstBuf is NULL");
- return;
- }
-
- mm_util_debug("dstBuf:%p", decoded_data->data);
-
- if (input_fmt == MM_UTIL_COLOR_YUV420 || input_fmt == MM_UTIL_COLOR_YUV422) {
- _tj(tjDecompressToYUV(handle, jpegBuf, jpegSize, decoded_data->data, TD_BU));
- mm_util_debug("MM_UTIL_COLOR_YUV420, dstBuf: %d", decoded_data->data);
- decoded_data->format = input_fmt;
- } else if (input_fmt == MM_UTIL_COLOR_RGB24) {
- _tj(tjDecompress2(handle, jpegBuf, jpegSize, decoded_data->data, scaledWidth, 0, scaledHeight, TJPF_RGB, TD_BU));
- mm_util_debug("MM_UTIL_COLOR_RGB24, dstBuf: %p", decoded_data->data);
- decoded_data->format = MM_UTIL_COLOR_RGB24;
- } else {
- mm_util_error("[%s][%05d] We can't support the IMAGE format");
- return;
- }
-
- decoded_data->size = dstSize;
- if (input_fmt == MM_UTIL_COLOR_RGB24) {
- decoded_data->width = scaledWidth;
- decoded_data->height = scaledHeight;
- decoded_data->size = dstSize;
- } 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_UTIL_ROUND_UP_2(_hdrw);
- } else {
- if (_hdrw % 4 != 0)
- 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_UTIL_ROUND_UP_4(_hdrh);
- else
- decoded_data->height = _hdrh;
- } else {
- decoded_data->height = _hdrh;
- }
- decoded_data->size = dstSize;
- }
-}
-
-static int __mm_image_decode_from_jpeg_file_with_libjpeg_turbo(mm_util_jpeg_yuv_data *decoded_data, const char *pFileName, mm_util_color_format_e input_fmt)
-{
- int iErrorCode = MM_UTIL_ERROR_NONE;
- tjhandle dhandle = NULL;
- unsigned char *srcBuf = NULL;
- int jpegSize;
- int TD_BU = 0;
- size_t read_size = 0;
-
- iErrorCode = mm_util_safe_fopen(pFileName, "rb", &src);
- if (iErrorCode == MM_UTIL_ERROR_NONE) {
- mm_util_error("mm_util_safe_fopen failed (%d)", iErrorCode);
- return iErrorCode;
- }
- fseek(src, 0, SEEK_END);
- jpegSize = ftell(src);
- rewind(src);
-
- if ((dhandle = tjInitDecompress()) == NULL) {
- mm_util_safe_fclose(src);
- mm_util_error("dhandle=tjInitDecompress()) is NULL");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
- srcBuf = (unsigned char *) calloc(1, sizeof(char) * jpegSize);
- if (srcBuf == NULL) {
- mm_util_safe_fclose(src);
- tjDestroy(dhandle);
- mm_util_error("srcBuf is NULL");
- return MM_UTIL_ERROR_OUT_OF_MEMORY;
- }
-
- read_size = fread(srcBuf, 1, jpegSize, src);
- if (read_size <= 0) {
- mm_util_safe_fclose(src);
- tjDestroy(dhandle);
- tjFree(srcBuf);
- mm_util_error("Read from src failed");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
-
- mm_util_debug("srcBuf[0]: 0x%2x, srcBuf[1]: 0x%2x, jpegSize:%d", srcBuf[0], srcBuf[1], jpegSize);
- __mm_decode_libjpeg_turbo_decompress(dhandle, srcBuf, jpegSize, TD_BU, decoded_data, input_fmt);
- mm_util_safe_fclose(src);
- mm_util_debug("fclose");
-
- if (dhandle)
- tjDestroy(dhandle);
- if (srcBuf)
- tjFree(srcBuf);
-
- return iErrorCode;
-}
-
-static int __mm_image_decode_from_jpeg_memory_with_libjpeg_turbo(mm_util_jpeg_yuv_data *decoded_data, void *src, unsigned int size, mm_util_color_format_e input_fmt)
-{
- int iErrorCode = MM_UTIL_ERROR_NONE;
- tjhandle dhandle = NULL;
- unsigned char *srcBuf = NULL;
- int TD_BU = 0;
-
- if ((dhandle = tjInitDecompress()) == NULL) {
- mm_util_error("dhandle=tjInitDecompress()) is NULL");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
- srcBuf = (unsigned char *) calloc(1, sizeof(char) * size);
- if (srcBuf == NULL) {
- mm_util_safe_fclose(src);
- tjDestroy(dhandle);
- mm_util_error("srcBuf is NULL");
- return MM_UTIL_ERROR_OUT_OF_MEMORY;
- }
-
- mm_util_debug("srcBuf[0]: 0x%2x, srcBuf[1]: 0x%2x, jpegSize:%u", srcBuf[0], srcBuf[1], size);
- __mm_decode_libjpeg_turbo_decompress(dhandle, src, size, TD_BU, decoded_data, input_fmt);
-
- if (dhandle)
- tjDestroy(dhandle);
- if (srcBuf)
- tjFree(srcBuf);
-
- return iErrorCode;
-}
-
-static void _mm_encode_libjpeg_turbo_compress(tjhandle handle, void *src, unsigned char **dstBuf, unsigned long *dstSize, int w, int h, int jpegQual, int flags, mm_util_color_format_e fmt)
-{
- unsigned char *srcBuf = NULL;
- unsigned long jpegSize = 0;
-
- jpegSize = w*h*tjPixelSize[TJPF_RGB];
- srcBuf = (unsigned char *)calloc(1, jpegSize);
-
- mm_util_retvm_if(srcBuf == NULL, NULL, "invalid srcBuf");
-
- mm_util_debug("srcBuf: 0x%2x", srcBuf);
- if (fmt == MM_UTIL_COLOR_RGB24) {
- __initBuf(srcBuf, w, h, TJPF_RGB, flags);
- } else if (fmt == MM_UTIL_COLOR_YUV420 || fmt == MM_UTIL_COLOR_YUV422) {
- __initBuf(srcBuf, w, h, TJPF_GRAY, flags);
- } else {
- MMUTIL_SAFE_FREE(srcBuf);
- mm_util_error("[%s][%05d] We can't support the IMAGE format");
- return;
- }
- memcpy(srcBuf, src, jpegSize);
-
- if (*dstBuf && *dstSize > 0) memset(*dstBuf, 0, *dstSize);
- mm_util_debug("Done.");
- *dstSize = TJBUFSIZE(w, h);
- if (fmt == MM_UTIL_COLOR_RGB24) {
- _tj(tjCompress2(handle, srcBuf, w, 0, h, TJPF_RGB, dstBuf, dstSize, TJPF_RGB, jpegQual, flags));
- mm_util_debug("*dstSize: %d", *dstSize);
- } else if (fmt == MM_UTIL_COLOR_YUV420) {
- *dstSize = TJBUFSIZEYUV(w, h, TJSAMP_420);
- _tj(tjEncodeYUV2(handle, srcBuf, w, 0, h, TJPF_RGB, *dstBuf, TJSAMP_420, flags));
- mm_util_debug("*dstSize: %d \t decode_yuv_subsample: %d TJBUFSIZE(w, h):%d", *dstSize, TJSAMP_420, TJBUFSIZE(w, h));
- } else if (fmt == MM_UTIL_COLOR_YUV422) {
- *dstSize = TJBUFSIZEYUV(w, h, TJSAMP_422);
- _tj(tjEncodeYUV2(handle, srcBuf, w, 0, h, TJPF_RGB, *dstBuf, TJSAMP_422, flags));
- mm_util_debug("*dstSize: %d \t decode_yuv_subsample: %d TJBUFSIZE(w, h):%d", *dstSize, TJSAMP_422, TJBUFSIZE(w, h));
- } else {
- mm_util_error("fmt:%d is wrong", fmt);
- }
-
- MMUTIL_SAFE_FREE(srcBuf);
-}
-
-static int __mm_image_encode_to_jpeg_file_with_libjpeg_turbo(const char *filename, void* src, int width, int height, mm_util_color_format_e fmt, int quality)
-{
- int iErrorCode = MM_UTIL_ERROR_NONE;
- tjhandle chandle = NULL;
- unsigned char *dstBuf = NULL;
- unsigned long size = 0;
- int TD_BU = 0;
- FILE *fout = NULL;
-
- iErrorCode = mm_util_safe_fopen(filename, "w+", &fout);
- if (iErrorCode != MM_UTIL_ERROR_NONE) {
- mm_util_error("mm_util_safe_fopen failed (%d)", iErrorCode);
- return iErrorCode;
- }
- mm_util_debug("fmt: %d", fmt);
-
- size = TJBUFSIZE(width, height);
- if ((dstBuf = (unsigned char *)tjAlloc(size)) == NULL) {
- mm_util_safe_fclose(fout);
- mm_util_error("dstBuf is NULL");
- return MM_UTIL_ERROR_OUT_OF_MEMORY;
- }
-
- if ((chandle = tjInitCompress()) == NULL) {
- mm_util_safe_fclose(fout);
- tjFree(dstBuf);
- mm_util_error("dstBuf is NULL");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
- _mm_encode_libjpeg_turbo_compress(chandle, src, &dstBuf, &size, width, height, quality, TD_BU, fmt);
- mm_util_debug("dstBuf: %p\t size: %u", dstBuf, size);
- fwrite(dstBuf, 1, size, fout);
- mm_util_safe_fclose(fout);
- if (chandle)
- tjDestroy(chandle);
- if (dstBuf)
- tjFree(dstBuf);
- mm_util_debug("Done");
- return iErrorCode;
-}
-
-static int __mm_image_encode_to_jpeg_memory_with_libjpeg_turbo(void **mem, unsigned int *csize, void *rawdata, int w, int h, mm_util_color_format_e fmt, int quality)
-{
- int iErrorCode = MM_UTIL_ERROR_NONE;
- tjhandle chandle = NULL;
- int TD_BU = 0;
-
- *csize = TJBUFSIZE(w, h);
- if (fmt == MM_UTIL_COLOR_RGB24) {
- mm_util_debug("MM_UTIL_COLOR_RGB24 size: %u", *csize);
- } else if (fmt == MM_UTIL_COLOR_YUV420 || fmt == MM_UTIL_COLOR_YUV422) {
- mm_util_debug("TJSAMP_420 ||TJSAMP_422 size: %u", *csize);
- } else {
- mm_util_error("We can't support the IMAGE format");
- return MM_UTIL_ERROR_NOT_SUPPORTED_FORMAT;
- }
-
- if ((*mem = (unsigned char *)tjAlloc(*csize)) == NULL) {
- mm_util_error("dstBuf is NULL");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
-
- if ((chandle = tjInitCompress()) == NULL) {
- tjFree(*mem);
- mm_util_error("chandle is NULL");
- return MM_UTIL_ERROR_INVALID_PARAMETER;
- }
-
- mm_util_debug("width: %d height: %d, size: %u", w, h, *csize);
- _mm_encode_libjpeg_turbo_compress(chandle, rawdata, (unsigned char **)mem, (unsigned long *)csize, w, h, quality, TD_BU, fmt);
- mm_util_debug("dstBuf: %p &dstBuf:%p size: %u", *mem, mem, *csize);
- if (chandle)
- tjDestroy(chandle);
- return iErrorCode;
-}
-#else /* libjpeg */
-
-/* OPEN SOURCE */
struct my_error_mgr_s {
struct jpeg_error_mgr pub; /* "public" fields */
jmp_buf setjmp_buffer; /* for return to caller */
return iErrorCode;
}
-#endif
-
int mm_util_jpeg_encode_to_file(mm_util_jpeg_yuv_data *decoded, int quality, const char *filename)
{
int ret = MM_UTIL_ERROR_NONE;
mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(decoded->format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", decoded->format);
mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
-#ifdef LIBJPEG_TURBO
- mm_util_debug("#START# LIBJPEG_TURBO");
- ret = __mm_image_encode_to_jpeg_file_with_libjpeg_turbo(filename, decoded->data, decoded->width, decoded->height, decoded->format, quality);
-#else
mm_util_debug("#START# LIBJPEG");
FILE *fp = NULL;
ret = mm_util_safe_fopen(filename, "wb", &fp);
fsync((int)(fp->_fileno));
mm_util_safe_fclose(fp);
-#endif
mm_util_debug("#End# libjpeg, Success!! ret: %d", ret);
mm_util_retvm_if((IS_MM_UTIL_COLOR_FORMAT(decoded->format) == FALSE), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid fmt [%d]", decoded->format);
mm_util_retvm_if((quality < 1) || (quality > 100), MM_UTIL_ERROR_INVALID_PARAMETER, "invalid quality [%d]", quality);
-#ifdef LIBJPEG_TURBO
- mm_util_debug("#START# libjpeg-turbo");
- ret = __mm_image_encode_to_jpeg_memory_with_libjpeg_turbo(mem, size, decoded->data, decoded->width, decoded->height, decoded->format, quality);
-#else /* LIBJPEG_TURBO */
mm_util_debug("#START# libjpeg");
if (decoded->format == MM_UTIL_COLOR_NV12) {
unsigned int res_w = 0;
} else {
ret = __mm_image_encode_with_libjpeg(MM_UTIL_JPEG_MEM, NULL, mem, size, decoded->data, decoded->width, decoded->height, decoded->format, quality);
}
-#endif /* LIBJPEG_TURBO */
mm_util_debug("#END# libjpeg, Success!! ret: %d", ret);
mm_util_fleave();
return MM_UTIL_ERROR_INVALID_PARAMETER;
}
-#ifdef LIBJPEG_TURBO
- mm_util_debug("#START# libjpeg");
- ret = __mm_image_decode_from_jpeg_memory_with_libjpeg_turbo(decoded, src, size, fmt);
-#else
mm_util_debug("#START# libjpeg");
if (fmt == MM_UTIL_COLOR_NV12) {
ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_MEM, decoded, NULL, src, size, MM_UTIL_COLOR_YUV420, downscale);
} else {
ret = __mm_image_decode_with_libjpeg(MM_UTIL_JPEG_MEM, decoded, NULL, 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);