forked from enlightenment/efl
1001 lines
23 KiB
C
1001 lines
23 KiB
C
#include "Eet.h"
|
|
#include "Eet_private.h"
|
|
|
|
/*---*/
|
|
|
|
typedef struct _JPEG_error_mgr *emptr;
|
|
|
|
/*---*/
|
|
|
|
struct _JPEG_error_mgr
|
|
{
|
|
struct jpeg_error_mgr pub;
|
|
jmp_buf setjmp_buffer;
|
|
};
|
|
|
|
/*---*/
|
|
|
|
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 void *eet_data_image_jpeg_rgb_decode(const void *data, int size, unsigned int *w, unsigned int *h);
|
|
static void *eet_data_image_jpeg_alpha_decode(const void *data, int size, unsigned int *d, unsigned int *w, unsigned int *h);
|
|
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 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))
|
|
|
|
#define CONV8(x)
|
|
#define CONV16(x) {if (words_bigendian) SWAP16(x);}
|
|
#define CONV32(x) {if (words_bigendian) SWAP32(x);}
|
|
#define CONV64(x) {if (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)
|
|
{
|
|
emptr errmgr;
|
|
|
|
errmgr = (emptr) cinfo->err;
|
|
/* cinfo->err->output_message(cinfo);*/
|
|
/* longjmp(errmgr->setjmp_buffer, 1);*/
|
|
return;
|
|
}
|
|
|
|
static void
|
|
_JPEGErrorHandler2(j_common_ptr cinfo, int msg_level)
|
|
{
|
|
emptr errmgr;
|
|
|
|
errmgr = (emptr) cinfo->err;
|
|
/* cinfo->err->output_message(cinfo);*/
|
|
/* longjmp(errmgr->setjmp_buffer, 1);*/
|
|
return;
|
|
msg_level = 0;
|
|
}
|
|
|
|
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;
|
|
FILE *f;
|
|
|
|
f = _eet_memfile_read_open(data, (size_t)size);
|
|
if (!f) return 0;
|
|
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))
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return 0;
|
|
}
|
|
jpeg_create_decompress(&cinfo);
|
|
jpeg_stdio_src(&cinfo, f);
|
|
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;
|
|
if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192))
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return 0;
|
|
}
|
|
/* end head decoding */
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return 1;
|
|
}
|
|
|
|
static void *
|
|
eet_data_image_jpeg_rgb_decode(const void *data, int size, unsigned int *w, unsigned int *h)
|
|
{
|
|
unsigned int *d;
|
|
struct jpeg_decompress_struct cinfo;
|
|
struct _JPEG_error_mgr jerr;
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
|
unsigned int *ptr2;
|
|
unsigned int x, y, l, scans;
|
|
int i, count, prevy;
|
|
FILE *f;
|
|
|
|
f = _eet_memfile_read_open(data, (size_t)size);
|
|
if (!f) return NULL;
|
|
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))
|
|
{
|
|
if (tdata) free(tdata);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
jpeg_create_decompress(&cinfo);
|
|
jpeg_stdio_src(&cinfo, f);
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
cinfo.dct_method = JDCT_FASTEST;
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
cinfo.do_block_smoothing = FALSE;
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
/* head decoding */
|
|
*w = cinfo.output_width;
|
|
*h = cinfo.output_height;
|
|
if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192))
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
/* end head decoding */
|
|
/* data decoding */
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
tdata = alloca((*w) * 16 * 3);
|
|
d = malloc((*w) * (*h) * 4);
|
|
if (!d)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
ptr2 = d;
|
|
count = 0;
|
|
prevy = 0;
|
|
if (cinfo.output_components == 3)
|
|
{
|
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
|
line[i] = tdata + (i * (*w) * 3);
|
|
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;
|
|
for (y = 0; y < scans; y++)
|
|
{
|
|
for (x = 0; x < (*w); x++)
|
|
{
|
|
*ptr2 =
|
|
(0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
|
|
ptr += 3;
|
|
ptr2++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (cinfo.output_components == 1)
|
|
{
|
|
for (i = 0; i < 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;
|
|
for (y = 0; y < scans; y++)
|
|
{
|
|
for (x = 0; x < (*w); x++)
|
|
{
|
|
*ptr2 =
|
|
(0xff000000) | ((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
|
|
ptr++;
|
|
ptr2++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* end data decoding */
|
|
jpeg_finish_decompress(&cinfo);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return d;
|
|
}
|
|
|
|
static void *
|
|
eet_data_image_jpeg_alpha_decode(const void *data, int size, unsigned int *d, unsigned int *w, unsigned int *h)
|
|
{
|
|
struct jpeg_decompress_struct cinfo;
|
|
struct _JPEG_error_mgr jerr;
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
|
unsigned int *ptr2;
|
|
unsigned int x, y, l, scans;
|
|
int i, count, prevy;
|
|
FILE *f;
|
|
|
|
f = _eet_memfile_read_open(data, (size_t)size);
|
|
if (!f) return NULL;
|
|
|
|
if (0)
|
|
{
|
|
char buf[1];
|
|
|
|
while (fread(buf, 1, 1, f));
|
|
_eet_memfile_read_close(f);
|
|
return d;
|
|
}
|
|
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))
|
|
{
|
|
if (tdata) free(tdata);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
jpeg_create_decompress(&cinfo);
|
|
jpeg_stdio_src(&cinfo, f);
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
cinfo.dct_method = JDCT_FASTEST;
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
cinfo.do_block_smoothing = FALSE;
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
/* head decoding */
|
|
if ((*w) != cinfo.output_width)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
if ((*h) != cinfo.output_height)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
*w = cinfo.output_width;
|
|
*h = cinfo.output_height;
|
|
/* end head decoding */
|
|
/* data decoding */
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
{
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return NULL;
|
|
}
|
|
tdata = alloca((*w) * 16 * 3);
|
|
ptr2 = d;
|
|
count = 0;
|
|
prevy = 0;
|
|
if (cinfo.output_components == 1)
|
|
{
|
|
for (i = 0; i < 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;
|
|
for (y = 0; y < scans; y++)
|
|
{
|
|
for (x = 0; x < (*w); x++)
|
|
{
|
|
*ptr2 =
|
|
((*ptr2) & 0x00ffffff) |
|
|
((ptr[0]) << 24);
|
|
ptr++;
|
|
ptr2++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* end data decoding */
|
|
jpeg_finish_decompress(&cinfo);
|
|
jpeg_destroy_decompress(&cinfo);
|
|
_eet_memfile_read_close(f);
|
|
return d;
|
|
}
|
|
|
|
static void *
|
|
eet_data_image_lossless_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha)
|
|
{
|
|
if (words_bigendian == -1)
|
|
{
|
|
unsigned long int v;
|
|
|
|
v = htonl(0x12345678);
|
|
if (v == 0x12345678) words_bigendian = 1;
|
|
else 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 (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 (words_bigendian == -1)
|
|
{
|
|
unsigned long int v;
|
|
|
|
v = htonl(0x12345678);
|
|
if (v == 0x12345678) words_bigendian = 1;
|
|
else words_bigendian = 0;
|
|
}
|
|
|
|
{
|
|
unsigned char *d;
|
|
unsigned char *comp;
|
|
int *header;
|
|
int ret;
|
|
uLongf buflen;
|
|
|
|
d = malloc((w * h * 4) + (8 * 4));
|
|
if (!d) return NULL;
|
|
buflen = (((w * h * 101) / 100) + 3) * 4;
|
|
comp = malloc(buflen);
|
|
if (!comp)
|
|
{
|
|
free(d);
|
|
return NULL;
|
|
}
|
|
header = (int *)d;
|
|
memset(d, 0, 32);
|
|
|
|
header[0] = 0xac1dfeed;
|
|
header[1] = w;
|
|
header[2] = h;
|
|
header[3] = alpha;
|
|
header[4] = compression;
|
|
memcpy(d + 32, data, w * h * 4);
|
|
|
|
if (words_bigendian)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
|
|
}
|
|
ret = compress2((Bytef *)comp, &buflen,
|
|
(Bytef *)(d + 32),
|
|
(uLong)(w * h * 4),
|
|
compression);
|
|
if (buflen > (w * h * 4))
|
|
{
|
|
free(comp);
|
|
*size = ((w * h * 4) + (8 * 4));
|
|
return d;
|
|
}
|
|
memcpy(d + 32, comp, buflen);
|
|
*size = (8 * 4) + 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)
|
|
{
|
|
const int *ptr;
|
|
void *d = NULL;
|
|
size_t sz = 0;
|
|
struct _JPEG_error_mgr jerr;
|
|
JSAMPROW *jbuf;
|
|
struct jpeg_compress_struct cinfo;
|
|
FILE *f;
|
|
unsigned char *buf;
|
|
|
|
(void) alpha; /* unused */
|
|
|
|
f =_eet_memfile_write_open(&d, &sz);
|
|
if (!f) return NULL;
|
|
|
|
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))
|
|
{
|
|
jpeg_destroy_compress(&cinfo);
|
|
_eet_memfile_write_close(f);
|
|
if (d) free(d);
|
|
return NULL;
|
|
}
|
|
jpeg_create_compress(&cinfo);
|
|
jpeg_stdio_dest(&cinfo, f);
|
|
cinfo.image_width = w;
|
|
cinfo.image_height = h;
|
|
cinfo.input_components = 3;
|
|
cinfo.in_color_space = JCS_RGB;
|
|
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);
|
|
|
|
ptr = data;
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
{
|
|
unsigned int i, j;
|
|
|
|
/* 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);
|
|
|
|
_eet_memfile_write_close(f);
|
|
*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 (words_bigendian == -1)
|
|
{
|
|
unsigned long int v;
|
|
|
|
v = htonl(0x12345678);
|
|
if (v == 0x12345678) words_bigendian = 1;
|
|
else words_bigendian = 0;
|
|
}
|
|
|
|
{
|
|
const int *ptr;
|
|
void *d = NULL;
|
|
size_t sz = 0;
|
|
struct _JPEG_error_mgr jerr;
|
|
JSAMPROW *jbuf;
|
|
struct jpeg_compress_struct cinfo;
|
|
FILE *f;
|
|
unsigned char *buf;
|
|
|
|
f = _eet_memfile_write_open(&d, &sz);
|
|
if (!f) return NULL;
|
|
|
|
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))
|
|
{
|
|
jpeg_destroy_compress(&cinfo);
|
|
_eet_memfile_write_close(f);
|
|
if (d) free(d);
|
|
return NULL;
|
|
}
|
|
jpeg_create_compress(&cinfo);
|
|
jpeg_stdio_dest(&cinfo, f);
|
|
cinfo.image_width = w;
|
|
cinfo.image_height = h;
|
|
cinfo.input_components = 3;
|
|
cinfo.in_color_space = JCS_RGB;
|
|
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);
|
|
|
|
ptr = data;
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
{
|
|
unsigned int i, j;
|
|
|
|
/* 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);
|
|
|
|
_eet_memfile_write_close(f);
|
|
d1 = d;
|
|
sz1 = sz;
|
|
}
|
|
{
|
|
const int *ptr;
|
|
void *d = NULL;
|
|
size_t sz = 0;
|
|
struct _JPEG_error_mgr jerr;
|
|
JSAMPROW *jbuf;
|
|
struct jpeg_compress_struct cinfo;
|
|
FILE *f;
|
|
unsigned char *buf;
|
|
|
|
f = _eet_memfile_write_open(&d, &sz);
|
|
if (!f)
|
|
{
|
|
free(d1);
|
|
return NULL;
|
|
}
|
|
|
|
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))
|
|
{
|
|
jpeg_destroy_compress(&cinfo);
|
|
_eet_memfile_write_close(f);
|
|
if (d) free(d);
|
|
free(d1);
|
|
return NULL;
|
|
}
|
|
jpeg_create_compress(&cinfo);
|
|
jpeg_stdio_dest(&cinfo, f);
|
|
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);
|
|
|
|
ptr = data;
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
{
|
|
unsigned int i, j;
|
|
|
|
/* 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);
|
|
|
|
_eet_memfile_write_close(f);
|
|
d2 = d;
|
|
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 (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_DEF int
|
|
eet_data_image_write(Eet_File *ef, const char *name,
|
|
const void *data, unsigned int w, unsigned int h, int alpha,
|
|
int compress, int quality, int lossy)
|
|
{
|
|
void *d = NULL;
|
|
int size = 0;
|
|
|
|
d = eet_data_image_encode(data, &size, w, h, alpha, compress, quality, lossy);
|
|
if (d)
|
|
{
|
|
int v;
|
|
|
|
v = eet_write(ef, name, d, size, 0);
|
|
free(d);
|
|
return v;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
EAPI_DEF void *
|
|
eet_data_image_read(Eet_File *ef, const char *name,
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
|
int *compress, int *quality, int *lossy)
|
|
{
|
|
unsigned int *d = NULL;
|
|
void *data;
|
|
int size;
|
|
int free_data = 0;
|
|
|
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
|
if (!data)
|
|
{
|
|
data = eet_read(ef, name, &size);
|
|
free_data = 1;
|
|
}
|
|
|
|
if (!data) return NULL;
|
|
d = eet_data_image_decode(data, size, w, h, alpha, compress, quality, lossy);
|
|
|
|
if (free_data)
|
|
free(data);
|
|
|
|
return d;
|
|
}
|
|
|
|
EAPI_DEF int
|
|
eet_data_image_header_read(Eet_File *ef, const char *name,
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
|
int *compress, int *quality, int *lossy)
|
|
{
|
|
void *data = NULL;
|
|
int size = 0;
|
|
int d;
|
|
int free_data = 0;
|
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
|
if (!data)
|
|
{
|
|
data = eet_read(ef, name, &size);
|
|
free_data = 1;
|
|
}
|
|
|
|
if (!data) return 0;
|
|
d = eet_data_image_header_decode(data, size, w, h, alpha, compress, quality, lossy);
|
|
if (free_data)
|
|
free(data);
|
|
|
|
return d;
|
|
}
|
|
|
|
EAPI_DEF void *
|
|
eet_data_image_encode(const void *data, int *size_ret, unsigned int w, unsigned int h, int alpha, int compress, int quality, int lossy)
|
|
{
|
|
void *d = NULL;
|
|
int size = 0;
|
|
|
|
if (lossy == 0)
|
|
{
|
|
if (compress <= 0)
|
|
d = eet_data_image_lossless_convert(&size, data, w, h, alpha);
|
|
else
|
|
d = eet_data_image_lossless_compressed_convert(&size, data, w, h, alpha, compress);
|
|
}
|
|
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 (size_ret) *size_ret = size;
|
|
return d;
|
|
}
|
|
|
|
EAPI_DEF int
|
|
eet_data_image_header_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy)
|
|
{
|
|
int header[8];
|
|
|
|
if (words_bigendian == -1)
|
|
{
|
|
unsigned long int v;
|
|
|
|
v = htonl(0x12345678);
|
|
if (v == 0x12345678) words_bigendian = 1;
|
|
else words_bigendian = 0;
|
|
}
|
|
|
|
if (size < 32) return 0;
|
|
|
|
memcpy(header, data, 32);
|
|
if (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;
|
|
if (compress) *compress = 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, sz2;
|
|
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 (compress) *compress = 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 (compress) *compress = 0;
|
|
if (lossy) *lossy = 1;
|
|
if (quality) *quality = 75;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
EAPI_DEF void *
|
|
eet_data_image_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *compress, int *quality, int *lossy)
|
|
{
|
|
unsigned int *d = NULL;
|
|
int header[8];
|
|
|
|
if (words_bigendian == -1)
|
|
{
|
|
unsigned long int v;
|
|
|
|
v = htonl(0x12345678);
|
|
if (v == 0x12345678) words_bigendian = 1;
|
|
else words_bigendian = 0;
|
|
}
|
|
|
|
if (size < 32) return NULL;
|
|
|
|
memcpy(header, data, 32);
|
|
if (words_bigendian)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 8; i++) SWAP32(header[i]);
|
|
}
|
|
if ((unsigned)header[0] == 0xac1dfeed)
|
|
{
|
|
int iw, ih, al, cp;
|
|
unsigned int *body;
|
|
|
|
iw = header[1];
|
|
ih = header[2];
|
|
al = header[3];
|
|
cp = header[4];
|
|
if ((iw > 8192) || (ih > 8192)) return NULL;
|
|
if ((cp == 0) && (size < ((iw * ih * 4) + 32))) return NULL;
|
|
body = ((unsigned int *)data) + 8;
|
|
d = malloc(iw * ih * 4);
|
|
if (!d) return NULL;
|
|
if (!cp)
|
|
{
|
|
memcpy(d, body, iw * ih * 4);
|
|
if (words_bigendian)
|
|
{
|
|
int x;
|
|
|
|
for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uLongf dlen;
|
|
|
|
dlen = iw * ih * 4;
|
|
uncompress((Bytef *)d, &dlen, (Bytef *)body,
|
|
(uLongf)(size - 32));
|
|
if (words_bigendian)
|
|
{
|
|
int x;
|
|
|
|
for (x = 0; x < (iw * ih); x++) SWAP32(d[x]);
|
|
}
|
|
}
|
|
if (d)
|
|
{
|
|
if (w) *w = iw;
|
|
if (h) *h = ih;
|
|
if (alpha) *alpha = al;
|
|
if (compress) *compress = cp;
|
|
if (lossy) *lossy = 0;
|
|
if (quality) *quality = 100;
|
|
}
|
|
}
|
|
else if ((unsigned)header[0] == 0xbeeff00d)
|
|
{
|
|
unsigned int iw = 0, ih = 0;
|
|
unsigned const char *dt;
|
|
int sz1, sz2;
|
|
|
|
sz1 = header[1];
|
|
sz2 = header[2];
|
|
dt = data;
|
|
dt += 12;
|
|
d = eet_data_image_jpeg_rgb_decode(dt, sz1, &iw, &ih);
|
|
if (d)
|
|
{
|
|
dt += sz1;
|
|
eet_data_image_jpeg_alpha_decode(dt, sz2, d, &iw, &ih);
|
|
}
|
|
if (d)
|
|
{
|
|
if (w) *w = iw;
|
|
if (h) *h = ih;
|
|
if (alpha) *alpha = 1;
|
|
if (compress) *compress = 0;
|
|
if (lossy) *lossy = 1;
|
|
if (quality) *quality = 75;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
unsigned int iw = 0, ih = 0;
|
|
|
|
d = eet_data_image_jpeg_rgb_decode(data, size, &iw, &ih);
|
|
if (d)
|
|
{
|
|
if (w) *w = iw;
|
|
if (h) *h = ih;
|
|
if (alpha) *alpha = 0;
|
|
if (compress) *compress = 0;
|
|
if (lossy) *lossy = 1;
|
|
if (quality) *quality = 75;
|
|
}
|
|
}
|
|
return d;
|
|
}
|