diff options
Diffstat (limited to 'src/lib/eet_image.c')
-rw-r--r-- | src/lib/eet_image.c | 1881 |
1 files changed, 0 insertions, 1881 deletions
diff --git a/src/lib/eet_image.c b/src/lib/eet_image.c deleted file mode 100644 index 7116a3c..0000000 --- a/src/lib/eet_image.c +++ /dev/null @@ -1,1881 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* ifdef HAVE_CONFIG_H */ - -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -# define alloca __builtin_alloca -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else /* ifdef HAVE_ALLOCA_H */ -# include <stddef.h> -# ifdef __cplusplus -extern "C" -# endif /* ifdef __cplusplus */ -void *alloca(size_t); -#endif /* ifdef HAVE_ALLOCA_H */ - -#ifdef HAVE_NETINET_IN_H -# ifdef __OpenBSD__ -# include <sys/types.h> -# endif /* ifdef __OpenBSD__ */ -# include <netinet/in.h> -#endif /* ifdef HAVE_NETINET_IN_H */ - -#ifdef _WIN32 -# include <winsock2.h> -# define HAVE_BOOLEAN -#endif /* ifdef _WIN32 */ - -#include <stdio.h> -#include <string.h> -#include <setjmp.h> -#include <zlib.h> -#include <jpeglib.h> - -#include "Eet.h" -#include "Eet_private.h" - -#include "lz4.h" -#include "lz4hc.h" - -/*---*/ - -typedef struct _JPEG_error_mgr *emptr; - -/*---*/ - -struct _JPEG_error_mgr -{ - struct jpeg_error_mgr pub; - jmp_buf setjmp_buffer; -}; - -struct jpeg_membuf_src -{ - struct jpeg_source_mgr pub; - - const unsigned char *buf; - size_t len; - struct jpeg_membuf_src *self; -}; - -static void -_eet_jpeg_membuf_src_init(j_decompress_ptr cinfo) -{ - /* FIXME: Use attribute unused */ - (void)cinfo; -} - -static boolean -_eet_jpeg_membuf_src_fill(j_decompress_ptr cinfo) -{ - static const JOCTET jpeg_eoi[2] = { 0xFF, JPEG_EOI }; - struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; - - src->pub.bytes_in_buffer = sizeof(jpeg_eoi); - src->pub.next_input_byte = jpeg_eoi; - - return TRUE; -} - -static void -_eet_jpeg_membuf_src_skip(j_decompress_ptr cinfo, - long num_bytes) -{ - struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src; - - src->pub.bytes_in_buffer -= num_bytes; - src->pub.next_input_byte += num_bytes; -} - -static void -_eet_jpeg_membuf_src_term(j_decompress_ptr cinfo) -{ - struct jpeg_membuf_src *src = ((struct jpeg_membuf_src *)cinfo->src)->self; - - free(src); - cinfo->src = NULL; -} - -static int -eet_jpeg_membuf_src(j_decompress_ptr cinfo, - const void *buf, - size_t len) -{ - struct jpeg_membuf_src *src; - - src = calloc(1, sizeof(*src)); - if (!src) - return -1; - - src->self = src; - - cinfo->src = &src->pub; - src->buf = buf; - src->len = len; - src->pub.init_source = _eet_jpeg_membuf_src_init; - src->pub.fill_input_buffer = _eet_jpeg_membuf_src_fill; - src->pub.skip_input_data = _eet_jpeg_membuf_src_skip; - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = _eet_jpeg_membuf_src_term; - src->pub.bytes_in_buffer = src->len; - src->pub.next_input_byte = src->buf; - - return 0; -} - -struct jpeg_membuf_dst -{ - struct jpeg_destination_mgr pub; - - void **dst_buf; - size_t *dst_len; - - unsigned char *buf; - size_t len; - int failed; - struct jpeg_membuf_dst *self; -}; - -static void -_eet_jpeg_membuf_dst_init(j_compress_ptr cinfo) -{ - /* FIXME: Use eina attribute */ - (void)cinfo; -} - -static boolean -_eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo) -{ - struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest; - unsigned char *buf; - - if (dst->len >= 0x40000000 || - !(buf = realloc(dst->buf, dst->len * 2))) - { - dst->failed = 1; - dst->pub.next_output_byte = dst->buf; - dst->pub.free_in_buffer = dst->len; - return TRUE; - } - - dst->pub.next_output_byte = - buf + ((unsigned char *)dst->pub.next_output_byte - dst->buf); - dst->buf = buf; - dst->pub.free_in_buffer += dst->len; - dst->len *= 2; - - return FALSE; -} - -static void -_eet_jpeg_membuf_dst_term(j_compress_ptr cinfo) -{ - struct jpeg_membuf_dst *dst = ((struct jpeg_membuf_dst *)cinfo->dest)->self; - - if (dst->failed) - { - *dst->dst_buf = NULL; - *dst->dst_len = 0; - free(dst->buf); - } - else - { - *dst->dst_buf = dst->buf; - *dst->dst_len = (unsigned char *)dst->pub.next_output_byte - dst->buf; - } - - free(dst); - cinfo->dest = NULL; -} - -static int -eet_jpeg_membuf_dst(j_compress_ptr cinfo, - void **buf, - size_t *len) -{ - struct jpeg_membuf_dst *dst; - - dst = calloc(1, sizeof(*dst)); - if (!dst) - return -1; - - dst->buf = malloc(32768); - if (!dst->buf) - { - free(dst); - return -1; - } - - dst->self = dst; - dst->len = 32768; - - cinfo->dest = &dst->pub; - dst->pub.init_destination = _eet_jpeg_membuf_dst_init; - dst->pub.empty_output_buffer = _eet_jpeg_membuf_dst_flush; - dst->pub.term_destination = _eet_jpeg_membuf_dst_term; - dst->pub.free_in_buffer = dst->len; - dst->pub.next_output_byte = dst->buf; - dst->dst_buf = buf; - dst->dst_len = len; - dst->failed = 0; - - return 0; -} - -/*---*/ - -static void _JPEGFatalErrorHandler(j_common_ptr cinfo); -static void _JPEGErrorHandler(j_common_ptr cinfo); -static void _JPEGErrorHandler2(j_common_ptr cinfo, - int msg_level); - -static int -eet_data_image_jpeg_header_decode(const void *data, - int size, - unsigned int *w, - unsigned int *h); -static int -eet_data_image_jpeg_rgb_decode(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride); -static int -eet_data_image_jpeg_alpha_decode(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride); -static void * -eet_data_image_lossless_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha); -static void * -eet_data_image_lossless_compressed_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int compression); -static void * -eet_data_image_jpeg_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int quality); -static void * -eet_data_image_jpeg_alpha_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int quality); - -/*---*/ - -static int _eet_image_words_bigendian = -1; - -/*---*/ - -#define SWAP64(x) (x) = \ - ((((unsigned long long)(x) & 0x00000000000000ffULL) << 56) | \ - (((unsigned long long)(x) & 0x000000000000ff00ULL) << 40) | \ - (((unsigned long long)(x) & 0x0000000000ff0000ULL) << 24) | \ - (((unsigned long long)(x) & 0x00000000ff000000ULL) << 8) | \ - (((unsigned long long)(x) & 0x000000ff00000000ULL) >> 8) | \ - (((unsigned long long)(x) & 0x0000ff0000000000ULL) >> 24) | \ - (((unsigned long long)(x) & 0x00ff000000000000ULL) >> 40) | \ - (((unsigned long long)(x) & 0xff00000000000000ULL) >> 56)) -#define SWAP32(x) (x) = \ - ((((int)(x) & 0x000000ff) << 24) | \ - (((int)(x) & 0x0000ff00) << 8) | \ - (((int)(x) & 0x00ff0000) >> 8) | \ - (((int)(x) & 0xff000000) >> 24)) -#define SWAP16(x) (x) = \ - ((((short)(x) & 0x00ff) << 8) | \ - (((short)(x) & 0xff00) >> 8)) - -#ifdef CONV8 -# undef CONV8 -#endif /* ifdef CONV8 */ -#ifdef CONV16 -# undef CONV16 -#endif /* ifdef CONV16 */ -#ifdef CONV32 -# undef CONV32 -#endif /* ifdef CONV32 */ -#ifdef CONV64 -# undef CONV64 -#endif /* ifdef CONV64 */ - -#define CONV8(x) -#define CONV16(x) {if (_eet_image_words_bigendian) {SWAP16(x); }} -#define CONV32(x) {if (_eet_image_words_bigendian) {SWAP32(x); }} -#define CONV64(x) {if (_eet_image_words_bigendian) {SWAP64(x); }} - -/*---*/ - -static void -_JPEGFatalErrorHandler(j_common_ptr cinfo) -{ - emptr errmgr; - - errmgr = (emptr)cinfo->err; - /* cinfo->err->output_message(cinfo);*/ - longjmp(errmgr->setjmp_buffer, 1); - return; -} - -static void -_JPEGErrorHandler(j_common_ptr cinfo __UNUSED__) -{ - /* emptr errmgr; */ - - /* errmgr = (emptr) cinfo->err; */ - /* cinfo->err->output_message(cinfo);*/ - /* longjmp(errmgr->setjmp_buffer, 1);*/ - return; -} - -static void -_JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, - int msg_level __UNUSED__) -{ - /* emptr errmgr; */ - - /* errmgr = (emptr) cinfo->err; */ - /* cinfo->err->output_message(cinfo);*/ - /* longjmp(errmgr->setjmp_buffer, 1);*/ - return; -} - -static int -eet_data_image_jpeg_header_decode(const void *data, - int size, - unsigned int *w, - unsigned int *h) -{ - struct jpeg_decompress_struct cinfo; - struct _JPEG_error_mgr jerr; - - memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - return 0; - - jpeg_create_decompress(&cinfo); - - if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) - { - jpeg_destroy_decompress(&cinfo); - return 0; - } - - jpeg_read_header(&cinfo, TRUE); - cinfo.do_fancy_upsampling = FALSE; - cinfo.do_block_smoothing = FALSE; - jpeg_start_decompress(&cinfo); - - /* head decoding */ - *w = cinfo.output_width; - *h = cinfo.output_height; - - free(cinfo.src); - cinfo.src = NULL; - - jpeg_destroy_decompress(&cinfo); - - if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192)) - return 0; - - return 1; -} - -static int -eet_data_image_jpeg_rgb_decode(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride) -{ - struct jpeg_decompress_struct cinfo; - struct _JPEG_error_mgr jerr; - unsigned char *ptr, *line[16], *tdata = NULL; - unsigned int *ptr2, *tmp; - unsigned int iw, ih; - unsigned int x, y, l, scans; - unsigned int i; - - /* FIXME: handle src_x, src_y and row_stride correctly */ - if (!d) - return 0; - - memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - return 0; - - jpeg_create_decompress(&cinfo); - - if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) - { - jpeg_destroy_decompress(&cinfo); - return 0; - } - - jpeg_read_header(&cinfo, TRUE); - cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) - cinfo.do_fancy_upsampling = FALSE; - cinfo.do_block_smoothing = FALSE; - jpeg_start_decompress(&cinfo); - - /* head decoding */ - iw = cinfo.output_width; - ih = cinfo.output_height; - if ((iw != w) || (ih != h)) - { - free(cinfo.src); - cinfo.src = NULL; - - jpeg_destroy_decompress(&cinfo); - return 0; - } - - /* end head decoding */ - /* data decoding */ - if (cinfo.rec_outbuf_height > 16) - { - free(cinfo.src); - cinfo.src = NULL; - - jpeg_destroy_decompress(&cinfo); - return 0; - } - - tdata = alloca((iw) * 16 * 3); - ptr2 = d; - - if (cinfo.output_components == 3) - { - for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * (iw) * 3); - for (l = 0; l < ih; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((ih - l) < scans) - scans = ih - l; - - ptr = tdata; - - if (l + scans >= src_y && l < src_y + h) - { - y = src_y - l; - if (src_y < l) - y = 0; - - for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h); - y++) - { - tmp = ptr2; - ptr += 3 * src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - (0xff000000) | - ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]); - ptr += 3; - ptr2++; - } - ptr += 3 * (iw - w); - ptr2 = tmp + row_stride / 4; - } - } - } - } - else if (cinfo.output_components == 1) - { - for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * (iw)); - for (l = 0; l < (ih); l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if (((ih) - l) < scans) - scans = (ih) - l; - - ptr = tdata; - - if (l >= src_y && l < src_y + h) - { - y = src_y - l; - if (src_y < l) - y = 0; - - for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) - { - tmp = ptr2; - ptr += src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - (0xff000000) | - ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]); - ptr++; - ptr2++; - } - ptr += iw - w; - ptr2 = tmp + row_stride / 4; - } - } - } - } - - /* end data decoding */ - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - return 1; -} - -static int -eet_data_image_jpeg_alpha_decode(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride) -{ - struct jpeg_decompress_struct cinfo; - struct _JPEG_error_mgr jerr; - unsigned char *ptr, *line[16], *tdata = NULL; - unsigned int *ptr2, *tmp; - unsigned int x, y, l, scans; - unsigned int i, iw; - - /* FIXME: handle src_x, src_y and row_stride correctly */ - if (!d) - return 0; - - memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct)); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - return 0; - - jpeg_create_decompress(&cinfo); - - if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size)) - { - jpeg_destroy_decompress(&cinfo); - return 0; - } - - jpeg_read_header(&cinfo, TRUE); - cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) - cinfo.do_fancy_upsampling = FALSE; - cinfo.do_block_smoothing = FALSE; - jpeg_start_decompress(&cinfo); - - /* head decoding */ - iw = cinfo.output_width; - if (w != cinfo.output_width - || h != cinfo.output_height) - { - free(cinfo.src); - cinfo.src = NULL; - - jpeg_destroy_decompress(&cinfo); - return 0; - } - - /* end head decoding */ - /* data decoding */ - if (cinfo.rec_outbuf_height > 16) - { - free(cinfo.src); - cinfo.src = NULL; - - jpeg_destroy_decompress(&cinfo); - return 0; - } - - tdata = alloca(w * 16 * 3); - ptr2 = d; - - if (cinfo.output_components == 1) - { - for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++) - line[i] = tdata + (i * w); - for (l = 0; l < h; l += cinfo.rec_outbuf_height) - { - jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height); - scans = cinfo.rec_outbuf_height; - if ((h - l) < scans) - scans = h - l; - - ptr = tdata; - - if (l >= src_y && l < src_y + h) - { - y = src_y - l; - if (src_y < l) - y = 0; - - for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++) - { - tmp = ptr2; - ptr += src_x; - for (x = 0; x < w; x++) - { - *ptr2 = - ((*ptr2) & 0x00ffffff) | - ((ptr[0]) << 24); - ptr++; - ptr2++; - } - ptr += iw - w; - ptr2 = tmp + row_stride / 4; - } - } - } - } - - /* end data decoding */ - jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - return 1; -} - -static void * -eet_data_image_lossless_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha) -{ - if (_eet_image_words_bigendian == -1) - { - unsigned long int v; - - v = htonl(0x12345678); - if (v == 0x12345678) - _eet_image_words_bigendian = 1; - else - _eet_image_words_bigendian = 0; - } - - { - unsigned char *d; - int *header; - - d = malloc((w * h * 4) + (8 * 4)); - if (!d) - return NULL; - - header = (int *)d; - memset(d, 0, 32); - - header[0] = 0xac1dfeed; - header[1] = w; - header[2] = h; - header[3] = alpha; - - memcpy(d + 32, data, w * h * 4); - - if (_eet_image_words_bigendian) - { - unsigned int i; - - for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]); - } - - *size = ((w * h * 4) + (8 * 4)); - return d; - } -} - -static void * -eet_data_image_lossless_compressed_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int compression) -{ - if (_eet_image_words_bigendian == -1) - { - unsigned long int v; - - v = htonl(0x12345678); - if (v == 0x12345678) - _eet_image_words_bigendian = 1; - else - _eet_image_words_bigendian = 0; - } - - { - unsigned char *d, *comp; - int *header, ret, ok = 1; - uLongf buflen = 0; - - buflen = (((w * h * 101) / 100) + 3) * 4; - ret = LZ4_compressBound((w * h * 4)); - if ((ret > 0) && ((uLongf)ret > buflen)) buflen = ret; - - comp = malloc(buflen); - if (!comp) return NULL; - - switch (compression) - { - case EET_COMPRESSION_VERYFAST: - ret = LZ4_compressHC((const char *)data, (char *)comp, - (w * h * 4)); - if (ret <= 0) ok = 0; - buflen = ret; - break; - case EET_COMPRESSION_SUPERFAST: - ret = LZ4_compress((const char *)data, (char *)comp, - (w * h * 4)); - if (ret <= 0) ok = 0; - buflen = ret; - break; - default: /* zlib etc. */ - ret = compress2((Bytef *)comp, &buflen, (Bytef *)(data), - (uLong)(w * h * 4), compression); - if (ret != Z_OK) ok = 0; - break; - } - if ((!ok) || (buflen > (w * h * 4))) - { - free(comp); - *size = -1; - return NULL; - } - - d = malloc((8 * sizeof(int)) + buflen); - if (!d) - { - free(comp); - return NULL; - } - - header = (int *)d; - memset(d, 0, 8 * sizeof(int)); - header[0] = 0xac1dfeed; - header[1] = w; - header[2] = h; - header[3] = alpha; - header[4] = compression; - - if (_eet_image_words_bigendian) - { - unsigned int i; - - for (i = 0; i < 8; i++) SWAP32(header[i]); - } - - memcpy(d + (8 * sizeof(int)), comp, buflen); - *size = (8 * sizeof(int)) + buflen; - free(comp); - return d; - } -} - -static void * -eet_data_image_jpeg_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int quality) -{ - struct jpeg_compress_struct cinfo; - struct _JPEG_error_mgr jerr; - const int *ptr; - void *d = NULL; - size_t sz = 0; - JSAMPROW *jbuf; - unsigned char *buf; - - (void)alpha; /* unused */ - - buf = alloca(3 * w); - - memset(&cinfo, 0, sizeof (struct jpeg_compress_struct)); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - return NULL; - - jpeg_create_compress(&cinfo); - - if (eet_jpeg_membuf_dst(&cinfo, &d, &sz)) - { - jpeg_destroy_compress(&cinfo); - return NULL; - } - - cinfo.image_width = w; - cinfo.image_height = h; - cinfo.input_components = 3; - cinfo.in_color_space = JCS_RGB; - cinfo.optimize_coding = FALSE; - cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) - if (quality < 60) cinfo.dct_method = JDCT_IFAST; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - - if (quality >= 90) - { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; - } - - jpeg_start_compress(&cinfo, TRUE); - - while (cinfo.next_scanline < cinfo.image_height) - { - unsigned int i, j; - - /* convert scaline from ARGB to RGB packed */ - ptr = ((const int *)data) + cinfo.next_scanline * w; - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 16) & 0xff; - buf[j++] = ((*ptr) >> 8) & 0xff; - buf[j++] = ((*ptr)) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *)(&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - *size = sz; - return d; -} - -static void * -eet_data_image_jpeg_alpha_convert(int *size, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int quality) -{ - unsigned char *d1, *d2; - unsigned char *d; - int *header; - int sz1, sz2; - - (void)alpha; /* unused */ - - if (_eet_image_words_bigendian == -1) - { - unsigned long int v; - - v = htonl(0x12345678); - if (v == 0x12345678) - _eet_image_words_bigendian = 1; - else - _eet_image_words_bigendian = 0; - } - - { - const int *ptr; - void *dst = NULL; - size_t sz = 0; - struct _JPEG_error_mgr jerr; - JSAMPROW *jbuf; - struct jpeg_compress_struct cinfo; - unsigned char *buf; - - buf = alloca(3 * w); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - return NULL; - - jpeg_create_compress(&cinfo); - if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) - { - jpeg_destroy_compress(&cinfo); - return NULL; - } - - cinfo.image_width = w; - cinfo.image_height = h; - cinfo.input_components = 3; - cinfo.in_color_space = JCS_RGB; - cinfo.optimize_coding = FALSE; - cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss) - if (quality < 60) cinfo.dct_method = JDCT_IFAST; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - if (quality >= 90) - { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; - } - - jpeg_start_compress(&cinfo, TRUE); - - while (cinfo.next_scanline < cinfo.image_height) - { - unsigned int i, j; - - ptr = ((const int *)data) + cinfo.next_scanline * w; - /* convert scaline from ARGB to RGB packed */ - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 16) & 0xff; - buf[j++] = ((*ptr) >> 8) & 0xff; - buf[j++] = ((*ptr)) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *)(&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - d1 = dst; - sz1 = sz; - } - { - const int *ptr; - void *dst = NULL; - size_t sz = 0; - struct _JPEG_error_mgr jerr; - JSAMPROW *jbuf; - struct jpeg_compress_struct cinfo; - unsigned char *buf; - - buf = alloca(3 * w); - - cinfo.err = jpeg_std_error(&(jerr.pub)); - jerr.pub.error_exit = _JPEGFatalErrorHandler; - jerr.pub.emit_message = _JPEGErrorHandler2; - jerr.pub.output_message = _JPEGErrorHandler; - if (setjmp(jerr.setjmp_buffer)) - { - free(d1); - return NULL; - } - - jpeg_create_compress(&cinfo); - if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz)) - { - jpeg_destroy_compress(&cinfo); - free(d1); - return NULL; - } - - cinfo.image_width = w; - cinfo.image_height = h; - cinfo.input_components = 1; - cinfo.in_color_space = JCS_GRAYSCALE; - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - if (quality >= 90) - { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - cinfo.comp_info[1].h_samp_factor = 1; - cinfo.comp_info[1].v_samp_factor = 1; - cinfo.comp_info[2].h_samp_factor = 1; - cinfo.comp_info[2].v_samp_factor = 1; - } - - jpeg_start_compress(&cinfo, TRUE); - - while (cinfo.next_scanline < cinfo.image_height) - { - unsigned int i, j; - - ptr = ((const int *)data) + cinfo.next_scanline * w; - /* convert scaline from ARGB to RGB packed */ - for (j = 0, i = 0; i < w; i++) - { - buf[j++] = ((*ptr) >> 24) & 0xff; - ptr++; - } - jbuf = (JSAMPROW *)(&buf); - jpeg_write_scanlines(&cinfo, jbuf, 1); - } - - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - d2 = dst; - sz2 = sz; - } - d = malloc(12 + sz1 + sz2); - if (!d) - { - free(d1); - free(d2); - return NULL; - } - - header = (int *)d; - header[0] = 0xbeeff00d; - header[1] = sz1; - header[2] = sz2; - if (_eet_image_words_bigendian) - { - int i; - - for (i = 0; i < 3; i++) SWAP32(header[i]); - } - - memcpy(d + 12, d1, sz1); - memcpy(d + 12 + sz1, d2, sz2); - - free(d1); - free(d2); - *size = 12 + sz1 + sz2; - return d; -} - -EAPI int -eet_data_image_write_cipher(Eet_File *ef, - const char *name, - const char *cipher_key, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int comp, - int quality, - int lossy) -{ - void *d = NULL; - int size = 0; - - d = eet_data_image_encode(data, &size, w, h, alpha, comp, quality, lossy); - if (d) - { - int v; - - v = eet_write_cipher(ef, name, d, size, 0, cipher_key); - free(d); - return v; - } - - return 0; -} - -EAPI int -eet_data_image_write(Eet_File *ef, - const char *name, - const void *data, - unsigned int w, - unsigned int h, - int alpha, - int comp, - int quality, - int lossy) -{ - return eet_data_image_write_cipher(ef, - name, - NULL, - data, - w, - h, - alpha, - comp, - quality, - lossy); -} - -EAPI void * -eet_data_image_read_cipher(Eet_File *ef, - const char *name, - const char *cipher_key, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - unsigned int *d = NULL; - void *data = NULL; - int free_data = 0; - int size; - - if (!cipher_key) - data = (void *)eet_read_direct(ef, name, &size); - - if (!data) - { - data = eet_read_cipher(ef, name, &size, cipher_key); - free_data = 1; - if (!data) - return NULL; - } - - d = eet_data_image_decode(data, size, w, h, alpha, comp, quality, lossy); - - if (free_data) - free(data); - - return d; -} - -EAPI void * -eet_data_image_read(Eet_File *ef, - const char *name, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha, - comp, quality, lossy); -} - -EAPI int -eet_data_image_read_to_surface_cipher(Eet_File *ef, - const char *name, - const char *cipher_key, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - void *data = NULL; - int free_data = 0; - int res = 1; - int size; - - if (!cipher_key) - data = (void *)eet_read_direct(ef, name, &size); - - if (!data) - { - data = eet_read_cipher(ef, name, &size, cipher_key); - free_data = 1; - if (!data) - return 0; - } - - res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d, - w, h, row_stride, alpha, - comp, quality, lossy); - - if (free_data) - free(data); - - return res; -} - -EAPI int -eet_data_image_read_to_surface(Eet_File *ef, - const char *name, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_read_to_surface_cipher(ef, name, NULL, - src_x, src_y, d, - w, h, row_stride, - alpha, comp, quality, - lossy); -} - -EAPI int -eet_data_image_header_read_cipher(Eet_File *ef, - const char *name, - const char *cipher_key, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - void *data = NULL; - int size = 0; - int free_data = 0; - int d; - - if (!cipher_key) - data = (void *)eet_read_direct(ef, name, &size); - - if (!data) - { - data = eet_read_cipher(ef, name, &size, cipher_key); - free_data = 1; - if (!data) - return 0; - } - - d = eet_data_image_header_decode(data, size, w, h, alpha, - comp, quality, lossy); - if (free_data) - free(data); - - return d; -} - -EAPI int -eet_data_image_header_read(Eet_File *ef, - const char *name, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_header_read_cipher(ef, name, NULL, - w, h, alpha, - comp, quality, lossy); -} - -EAPI void * -eet_data_image_encode_cipher(const void *data, - const char *cipher_key, - unsigned int w, - unsigned int h, - int alpha, - int comp, - int quality, - int lossy, - int *size_ret) -{ - void *d = NULL; - void *ciphered_d = NULL; - unsigned int ciphered_sz = 0; - int size = 0; - - if (lossy == 0) - { - if (comp > 0) - d = eet_data_image_lossless_compressed_convert(&size, data, - w, h, alpha, comp); - - /* eet_data_image_lossless_compressed_convert will refuse to compress something - if the result is bigger than the entry. */ - if (comp <= 0 || !d) - d = eet_data_image_lossless_convert(&size, data, w, h, alpha); - } - else - { - if (!alpha) - d = eet_data_image_jpeg_convert(&size, data, w, h, alpha, quality); - else - d = eet_data_image_jpeg_alpha_convert(&size, data, - w, h, alpha, quality); - } - - if (cipher_key) - { - if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d, - &ciphered_sz)) - { - if (d) - free(d); - - d = ciphered_d; - size = ciphered_sz; - } - else - if (ciphered_d) - free(ciphered_d); - } - - if (size_ret) - *size_ret = size; - - return d; -} - -EAPI void * -eet_data_image_encode(const void *data, - int *size_ret, - unsigned int w, - unsigned int h, - int alpha, - int comp, - int quality, - int lossy) -{ - return eet_data_image_encode_cipher(data, NULL, w, h, alpha, - comp, quality, lossy, size_ret); -} - -EAPI int -eet_data_image_header_decode_cipher(const void *data, - const char *cipher_key, - int size, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - int header[8]; - void *deciphered_d = NULL; - unsigned int deciphered_sz = 0; - - if (cipher_key) - { - if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), - &deciphered_d, &deciphered_sz)) - { - data = deciphered_d; - size = deciphered_sz; - } - else - if (deciphered_d) - free(deciphered_d); - } - - if (_eet_image_words_bigendian == -1) - { - unsigned long int v; - - v = htonl(0x12345678); - if (v == 0x12345678) - _eet_image_words_bigendian = 1; - else - _eet_image_words_bigendian = 0; - } - - if (size < 32) - return 0; - - memcpy(header, data, 32); - if (_eet_image_words_bigendian) - { - int i; - - for (i = 0; i < 8; i++) SWAP32(header[i]); - } - - if ((unsigned)header[0] == 0xac1dfeed) - { - int iw, ih, al, cp; - - iw = header[1]; - ih = header[2]; - al = header[3]; - cp = header[4]; - if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192)) - return 0; - - if ((cp == 0) && (size < ((iw * ih * 4) + 32))) - return 0; - - if (w) - *w = iw; - - if (h) - *h = ih; - - if (alpha) - *alpha = al ? 1 : 0; - - if (comp) - *comp = cp; - - if (lossy) - *lossy = 0; - - if (quality) - *quality = 100; - - return 1; - } - else if ((unsigned)header[0] == 0xbeeff00d) - { - unsigned int iw = 0, ih = 0; - unsigned const char *dt; - int sz1; - int ok; - - sz1 = header[1]; -/* sz2 = header[2]; */ - dt = data; - dt += 12; - ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih); - if (ok) - { - if (w) - *w = iw; - - if (h) - *h = ih; - - if (alpha) - *alpha = 1; - - if (comp) - *comp = 0; - - if (lossy) - *lossy = 1; - - if (quality) - *quality = 75; - - return 1; - } - } - else - { - unsigned int iw = 0, ih = 0; - int ok; - - ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih); - if (ok) - { - if (w) - *w = iw; - - if (h) - *h = ih; - - if (alpha) - *alpha = 0; - - if (comp) - *comp = 0; - - if (lossy) - *lossy = 1; - - if (quality) - *quality = 75; - - return 1; - } - } - - return 0; -} - -EAPI int -eet_data_image_header_decode(const void *data, - int size, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_header_decode_cipher(data, - NULL, - size, - w, - h, - alpha, - comp, - quality, - lossy); -} - -static void -_eet_data_image_copy_buffer(const unsigned int *src, - unsigned int src_x, - unsigned int src_y, - unsigned int src_w, - unsigned int *dst, - unsigned int w, - unsigned int h, - unsigned int row_stride) -{ - src += src_x + src_y * src_w; - - if (row_stride == src_w * 4 && w == src_w) - memcpy(dst, src, row_stride * h); - else - { - unsigned int *over = dst; - unsigned int y; - - for (y = 0; y < h; ++y, src += src_w, over += row_stride) - memcpy(over, src, w * 4); - } -} - -static int -_eet_data_image_decode_inside(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int src_w, - unsigned int src_h, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride, - int alpha, - int comp, - int quality, - int lossy) -{ - if (lossy == 0 && quality == 100) - { - unsigned int *body; - - body = ((unsigned int *)data) + 8; - if (!comp) - _eet_data_image_copy_buffer(body, src_x, src_y, src_w, d, - w, h, row_stride); - else - { - if ((src_h == h) && (src_w == w) && (row_stride == src_w * 4)) - { - switch (comp) - { - case EET_COMPRESSION_VERYFAST: - case EET_COMPRESSION_SUPERFAST: - if (LZ4_uncompress((const char *)body, - (char *)d, w * h * 4) - != (size - 32)) return 0; - break; - default: - { - uLongf dlen = w * h * 4; - - if (uncompress((Bytef *)d, &dlen, (Bytef *)body, - (uLongf)(size - 32)) != Z_OK) - return 0; - } - break; - } - } - else - { - switch (comp) - { - case EET_COMPRESSION_VERYFAST: - case EET_COMPRESSION_SUPERFAST: - { - char *dtmp; - - dtmp = malloc(src_w * src_h * 4); - if (!dtmp) return 0; - if (LZ4_uncompress((const char *)body, - dtmp, w * h * 4) - != (size - 32)) - { - free(dtmp); - return 0; - } - _eet_data_image_copy_buffer((unsigned int *)dtmp, - src_x, src_y, src_w, d, - w, h, row_stride); - free(dtmp); - } - break; - default: - { - Bytef *dtmp; - uLongf dlen = src_w * src_h * 4; - - /* FIXME: This could create a huge alloc. So - compressed data and tile could not always work.*/ - dtmp = malloc(dlen); - if (!dtmp) return 0; - - if (uncompress(dtmp, &dlen, (Bytef *)body, - (uLongf)(size - 32)) != Z_OK) - { - free(dtmp); - return 0; - } - _eet_data_image_copy_buffer((unsigned int *)dtmp, - src_x, src_y, src_w, d, - w, h, row_stride); - free(dtmp); - } - } - } - } - /* Fix swapiness. */ - if (_eet_image_words_bigendian) - { - unsigned int x; - - for (x = 0; x < (w * h); x++) SWAP32(d[x]); - } - } - else if (comp == 0 && lossy == 1) - { - if (alpha) - { - unsigned const char *dt; - int header[8]; - int sz1, sz2; - - memcpy(header, data, 32); - if (_eet_image_words_bigendian) - { - int i; - - for (i = 0; i < 8; i++) SWAP32(header[i]); - } - - sz1 = header[1]; - sz2 = header[2]; - dt = data; - dt += 12; - - if (eet_data_image_jpeg_rgb_decode(dt, sz1, src_x, src_y, d, w, h, - row_stride)) - { - dt += sz1; - if (!eet_data_image_jpeg_alpha_decode(dt, sz2, src_x, src_y, - d, w, h, row_stride)) - return 0; - } - } - else if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w, - h, row_stride)) - return 0; - } - else - abort(); - - return 1; -} - -EAPI void * -eet_data_image_decode_cipher(const void *data, - const char *cipher_key, - int size, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - unsigned int *d = NULL; - unsigned int iw, ih; - int ialpha, icompress, iquality, ilossy; - void *deciphered_d = NULL; - unsigned int deciphered_sz = 0; - - if (cipher_key) - { - if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), - &deciphered_d, &deciphered_sz)) - { - data = deciphered_d; - size = deciphered_sz; - } - else - if (deciphered_d) - free(deciphered_d); - } - - /* All check are done during header decode, this simplify the code a lot. */ - if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, - &iquality, &ilossy)) - return NULL; - - d = malloc(iw * ih * 4); - if (!d) - return NULL; - - if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw * - 4, ialpha, icompress, iquality, ilossy)) - { - free(d); - return NULL; - } - - if (w) - *w = iw; - - if (h) - *h = ih; - - if (alpha) - *alpha = ialpha; - - if (comp) - *comp = icompress; - - if (quality) - *quality = iquality; - - if (lossy) - *lossy = ilossy; - - return d; -} - -EAPI void * -eet_data_image_decode(const void *data, - int size, - unsigned int *w, - unsigned int *h, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_decode_cipher(data, NULL, size, w, h, - alpha, comp, quality, lossy); -} - -EAPI int -eet_data_image_decode_to_surface_cipher(const void *data, - const char *cipher_key, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - unsigned int iw, ih; - int ialpha, icompress, iquality, ilossy; - void *deciphered_d = NULL; - unsigned int deciphered_sz = 0; - - if (cipher_key) - { - if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), - &deciphered_d, &deciphered_sz)) - { - data = deciphered_d; - size = deciphered_sz; - } - else - if (deciphered_d) - free(deciphered_d); - } - - /* All check are done during header decode, this simplify the code a lot. */ - if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress, - &iquality, &ilossy)) - return 0; - - if (!d) - return 0; - - if (w * 4 > row_stride) - return 0; - - if (w > iw || h > ih) - return 0; - - if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h, - row_stride, ialpha, icompress, iquality, - ilossy)) - return 0; - - if (alpha) - *alpha = ialpha; - - if (comp) - *comp = icompress; - - if (quality) - *quality = iquality; - - if (lossy) - *lossy = ilossy; - - return 1; -} - -EAPI int -eet_data_image_decode_to_surface(const void *data, - int size, - unsigned int src_x, - unsigned int src_y, - unsigned int *d, - unsigned int w, - unsigned int h, - unsigned int row_stride, - int *alpha, - int *comp, - int *quality, - int *lossy) -{ - return eet_data_image_decode_to_surface_cipher(data, NULL, size, - src_x, src_y, d, - w, h, row_stride, - alpha, comp, quality, - lossy); -} - |