2008-03-07 23:28:12 -08:00
|
|
|
/*
|
|
|
|
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
2008-03-28 10:17:43 -07:00
|
|
|
# include <config.h>
|
2008-03-07 23:28:12 -08:00
|
|
|
#endif
|
|
|
|
|
2008-03-28 10:17:43 -07:00
|
|
|
#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
|
|
|
|
# include <stddef.h>
|
|
|
|
# ifdef __cplusplus
|
|
|
|
extern "C"
|
|
|
|
# endif
|
|
|
|
void *alloca (size_t);
|
|
|
|
#endif
|
|
|
|
|
2008-04-03 12:29:55 -07:00
|
|
|
#ifdef HAVE_NETINET_IN_H
|
2009-03-22 06:37:17 -07:00
|
|
|
# ifdef __OpenBSD__
|
|
|
|
# include <sys/types.h>
|
|
|
|
# endif
|
2008-04-03 12:29:55 -07:00
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
2008-03-28 10:17:43 -07:00
|
|
|
#include <stdio.h>
|
2008-03-28 10:29:22 -07:00
|
|
|
#include <string.h>
|
2010-04-02 22:29:44 -07:00
|
|
|
#include <setjmp.h>
|
2008-03-28 10:17:43 -07:00
|
|
|
#include <zlib.h>
|
|
|
|
#include <jpeglib.h>
|
2010-04-02 22:29:44 -07:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
# include <winsock2.h>
|
|
|
|
#endif
|
2008-03-28 10:17:43 -07:00
|
|
|
|
2008-01-27 05:17:22 -08:00
|
|
|
#include "Eet.h"
|
2008-02-29 22:38:09 -08:00
|
|
|
#include "Eet_private.h"
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
|
|
|
typedef struct _JPEG_error_mgr *emptr;
|
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
|
|
|
struct _JPEG_error_mgr
|
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
struct jpeg_error_mgr pub;
|
|
|
|
jmp_buf setjmp_buffer;
|
2005-05-07 09:46:26 -07:00
|
|
|
};
|
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
struct jpeg_membuf_src {
|
|
|
|
struct jpeg_source_mgr pub;
|
|
|
|
|
2008-10-13 04:51:10 -07:00
|
|
|
const unsigned char *buf;
|
2008-09-03 04:04:37 -07:00
|
|
|
size_t len;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_src_init(j_decompress_ptr cinfo)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
/* FIXME: Use attribute unused */
|
|
|
|
(void) cinfo;
|
2008-09-03 04:04:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
free(cinfo->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 = malloc(sizeof(*src));
|
|
|
|
if (!src) return -1;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2008-10-13 04:51:10 -07:00
|
|
|
unsigned char *buf;
|
2008-09-03 04:04:37 -07:00
|
|
|
size_t len;
|
|
|
|
int failed;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_dst_init(j_compress_ptr cinfo)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
/* FIXME: Use eina attribute */
|
|
|
|
(void) cinfo;
|
2008-09-03 04:04:37 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
_eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo)
|
|
|
|
{
|
|
|
|
struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest;
|
2008-10-13 04:51:10 -07:00
|
|
|
unsigned char *buf;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
if (dst->len >= 0x40000000 ||
|
|
|
|
(buf = realloc(dst->buf, dst->len * 2)) == NULL) {
|
|
|
|
dst->failed = 1;
|
|
|
|
dst->pub.next_output_byte = dst->buf;
|
|
|
|
dst->pub.free_in_buffer = dst->len;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dst->pub.next_output_byte =
|
2008-10-13 04:51:10 -07:00
|
|
|
buf + ((unsigned char *)dst->pub.next_output_byte - dst->buf);
|
2008-09-03 04:04:37 -07:00
|
|
|
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;
|
|
|
|
|
|
|
|
if (dst->failed) {
|
|
|
|
*dst->dst_buf = NULL;
|
|
|
|
*dst->dst_len = 0;
|
|
|
|
free(dst->buf);
|
|
|
|
} else {
|
|
|
|
*dst->dst_buf = dst->buf;
|
2008-10-13 04:51:10 -07:00
|
|
|
*dst->dst_len = (unsigned char *)dst->pub.next_output_byte - dst->buf;
|
2008-09-03 04:04:37 -07:00
|
|
|
}
|
|
|
|
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 = malloc(sizeof(*dst));
|
|
|
|
if (!dst) return -1;
|
|
|
|
|
|
|
|
dst->buf = malloc(32768);
|
|
|
|
if (!dst->buf) {
|
|
|
|
free(dst);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/*---*/
|
|
|
|
|
|
|
|
static void _JPEGFatalErrorHandler(j_common_ptr cinfo);
|
|
|
|
static void _JPEGErrorHandler(j_common_ptr cinfo);
|
|
|
|
static void _JPEGErrorHandler2(j_common_ptr cinfo, int msg_level);
|
|
|
|
|
2006-03-03 18:46:24 -08:00
|
|
|
static int eet_data_image_jpeg_header_decode(const void *data, int size, unsigned int *w, unsigned int *h);
|
2008-06-02 09:01:18 -07:00
|
|
|
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 void *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);
|
2006-03-03 18:46:24 -08:00
|
|
|
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);
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
static int _eet_image_words_bigendian = -1;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
|
|
|
#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))
|
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
#ifdef CONV8
|
|
|
|
# undef CONV8
|
|
|
|
#endif
|
|
|
|
#ifdef CONV16
|
|
|
|
# undef CONV16
|
|
|
|
#endif
|
|
|
|
#ifdef CONV32
|
|
|
|
# undef CONV32
|
|
|
|
#endif
|
|
|
|
#ifdef CONV64
|
|
|
|
# undef CONV64
|
|
|
|
#endif
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
#define CONV8(x)
|
2009-11-02 00:41:43 -08:00
|
|
|
#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);}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
_JPEGFatalErrorHandler(j_common_ptr cinfo)
|
|
|
|
{
|
|
|
|
emptr errmgr;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
errmgr = (emptr) cinfo->err;
|
|
|
|
/* cinfo->err->output_message(cinfo);*/
|
|
|
|
longjmp(errmgr->setjmp_buffer, 1);
|
|
|
|
return;
|
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void
|
2009-02-09 12:46:12 -08:00
|
|
|
_JPEGErrorHandler(j_common_ptr cinfo __UNUSED__)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-12-29 02:47:18 -08:00
|
|
|
/* emptr errmgr; */
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-12-29 02:47:18 -08:00
|
|
|
/* errmgr = (emptr) cinfo->err; */
|
2005-05-07 09:46:26 -07:00
|
|
|
/* cinfo->err->output_message(cinfo);*/
|
|
|
|
/* longjmp(errmgr->setjmp_buffer, 1);*/
|
|
|
|
return;
|
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void
|
2009-02-09 12:46:12 -08:00
|
|
|
_JPEGErrorHandler2(j_common_ptr cinfo __UNUSED__, int msg_level __UNUSED__)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-12-29 02:47:18 -08:00
|
|
|
/* emptr errmgr; */
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-12-29 02:47:18 -08:00
|
|
|
/* errmgr = (emptr) cinfo->err; */
|
2005-05-07 09:46:26 -07:00
|
|
|
/* cinfo->err->output_message(cinfo);*/
|
|
|
|
/* longjmp(errmgr->setjmp_buffer, 1);*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2006-03-03 18:46:24 -08:00
|
|
|
eet_data_image_jpeg_header_decode(const void *data, int size, unsigned int *w, unsigned int *h)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
struct jpeg_decompress_struct cinfo;
|
2005-05-07 09:46:26 -07:00
|
|
|
struct _JPEG_error_mgr jerr;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-10-13 04:51:10 -07:00
|
|
|
memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
|
|
|
jerr.pub.output_message = _JPEGErrorHandler;
|
2008-09-03 04:04:37 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer)) return 0;
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return 0;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
|
|
cinfo.do_block_smoothing = FALSE;
|
|
|
|
jpeg_start_decompress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* head decoding */
|
|
|
|
*w = cinfo.output_width;
|
|
|
|
*h = cinfo.output_height;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
|
|
|
|
2008-09-02 18:34:53 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
if ((*w < 1) || (*h < 1) || (*w > 8192) || (*h > 8192))
|
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
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)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
struct jpeg_decompress_struct cinfo;
|
2005-05-07 09:46:26 -07:00
|
|
|
struct _JPEG_error_mgr jerr;
|
|
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned int *ptr2, *tmp;
|
|
|
|
unsigned int iw, ih;
|
2008-10-13 04:51:10 -07:00
|
|
|
unsigned int x, y, l, scans;
|
2008-12-29 02:47:18 -08:00
|
|
|
unsigned int i;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
/* FIXME: handle src_x, src_y and row_stride correctly */
|
|
|
|
if (!d) return 0;
|
|
|
|
|
2008-10-13 04:51:10 -07:00
|
|
|
memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
|
|
|
jerr.pub.output_message = _JPEGErrorHandler;
|
2008-09-03 04:04:37 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer)) return 0;
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2008-06-02 09:01:18 -07:00
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
2005-05-10 06:35:33 -07:00
|
|
|
cinfo.dct_method = JDCT_FASTEST;
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
|
|
cinfo.do_block_smoothing = FALSE;
|
|
|
|
jpeg_start_decompress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* head decoding */
|
2008-06-02 09:01:18 -07:00
|
|
|
iw = cinfo.output_width;
|
|
|
|
ih = cinfo.output_height;
|
|
|
|
if ((iw != w) || (ih != h))
|
2006-11-25 07:37:45 -08:00
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
|
|
|
|
2006-11-25 07:37:45 -08:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2008-06-02 09:01:18 -07:00
|
|
|
return 0;
|
2006-11-25 07:37:45 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
/* end head decoding */
|
|
|
|
/* data decoding */
|
|
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2008-06-02 09:01:18 -07:00
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
tdata = alloca((iw) * 16 * 3);
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr2 = d;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
if (cinfo.output_components == 3)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
for (i = 0; i < (unsigned int) cinfo.rec_outbuf_height; i++)
|
2008-06-02 09:01:18 -07:00
|
|
|
line[i] = tdata + (i * (iw) * 3);
|
|
|
|
for (l = 0; l < ih; l += cinfo.rec_outbuf_height)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
2008-06-02 09:01:18 -07:00
|
|
|
scans = cinfo.rec_outbuf_height;
|
|
|
|
if ((ih - l) < scans) scans = ih - l;
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr = tdata;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (l + scans >= src_y && l < src_y + h)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
y = src_y - l;
|
2008-10-13 04:51:10 -07:00
|
|
|
if (src_y < l) y = 0;
|
2008-06-02 09:01:18 -07:00
|
|
|
for (ptr += 3 * iw * y; y < scans && (y + l) < (src_y + h); y++)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
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;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cinfo.output_components == 1)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
for (i = 0; i < (unsigned int) cinfo.rec_outbuf_height; i++)
|
2008-06-02 09:01:18 -07:00
|
|
|
line[i] = tdata + (i * (iw));
|
|
|
|
for (l = 0; l < (ih); l += cinfo.rec_outbuf_height)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
|
|
|
scans = cinfo.rec_outbuf_height;
|
2008-06-02 09:01:18 -07:00
|
|
|
if (((ih) - l) < scans) scans = (ih) - l;
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr = tdata;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (l >= src_y && l < src_y + h)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
y = src_y - l;
|
2008-10-13 04:51:10 -07:00
|
|
|
if (src_y < l) y = 0;
|
2008-06-02 09:01:18 -07:00
|
|
|
for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
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;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* end data decoding */
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2008-06-02 09:01:18 -07:00
|
|
|
return 1;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2008-06-02 09:01:18 -07:00
|
|
|
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)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
struct jpeg_decompress_struct cinfo;
|
2005-05-07 09:46:26 -07:00
|
|
|
struct _JPEG_error_mgr jerr;
|
|
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned int *ptr2, *tmp;
|
2008-10-13 04:51:10 -07:00
|
|
|
unsigned int x, y, l, scans;
|
2008-12-29 02:47:18 -08:00
|
|
|
unsigned int i, iw;
|
2008-10-13 04:51:10 -07:00
|
|
|
|
|
|
|
memset(&cinfo, 0, sizeof (struct jpeg_decompress_struct));
|
2008-09-02 18:34:53 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
|
|
|
jerr.pub.output_message = _JPEGErrorHandler;
|
2008-09-03 04:04:37 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer)) return NULL;
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
2005-05-10 06:35:33 -07:00
|
|
|
cinfo.dct_method = JDCT_FASTEST;
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.do_fancy_upsampling = FALSE;
|
|
|
|
cinfo.do_block_smoothing = FALSE;
|
|
|
|
jpeg_start_decompress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* head decoding */
|
2008-06-02 09:01:18 -07:00
|
|
|
iw = cinfo.output_width;
|
|
|
|
if (w != cinfo.output_width
|
|
|
|
|| h != cinfo.output_height)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
/* end head decoding */
|
|
|
|
/* data decoding */
|
|
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
tdata = alloca(w * 16 * 3);
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr2 = d;
|
2005-11-03 19:22:22 -08:00
|
|
|
if (cinfo.output_components == 1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
for (i = 0; i < (unsigned int) cinfo.rec_outbuf_height; i++)
|
2008-06-02 09:01:18 -07:00
|
|
|
line[i] = tdata + (i * w);
|
|
|
|
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
|
|
|
scans = cinfo.rec_outbuf_height;
|
2008-06-02 09:01:18 -07:00
|
|
|
if ((h - l) < scans) scans = h - l;
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr = tdata;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (l >= src_y && l < src_y + h)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
y = src_y - l;
|
2008-10-13 04:51:10 -07:00
|
|
|
if (src_y < l) y = 0;
|
2008-06-02 09:01:18 -07:00
|
|
|
for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
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;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* end data decoding */
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2006-03-03 18:46:24 -08:00
|
|
|
eet_data_image_lossless_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian == -1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned long int v;
|
|
|
|
|
|
|
|
v = htonl(0x12345678);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (v == 0x12345678) _eet_image_words_bigendian = 1;
|
|
|
|
else _eet_image_words_bigendian = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
{
|
|
|
|
unsigned char *d;
|
|
|
|
int *header;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
|
|
|
|
}
|
|
|
|
*size = ((w * h * 4) + (8 * 4));
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2006-03-03 18:46:24 -08:00
|
|
|
eet_data_image_lossless_compressed_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int compression)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian == -1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned long int v;
|
|
|
|
|
|
|
|
v = htonl(0x12345678);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (v == 0x12345678) _eet_image_words_bigendian = 1;
|
|
|
|
else _eet_image_words_bigendian = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
unsigned char *d;
|
|
|
|
unsigned char *comp;
|
|
|
|
int *header;
|
|
|
|
int ret;
|
|
|
|
uLongf buflen;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int i;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
for (i = 0; i < ((w * h) + 8); i++) SWAP32(header[i]);
|
|
|
|
}
|
|
|
|
ret = compress2((Bytef *)comp, &buflen,
|
|
|
|
(Bytef *)(d + 32),
|
|
|
|
(uLong)(w * h * 4),
|
|
|
|
compression);
|
2008-12-29 01:39:03 -08:00
|
|
|
if (ret != Z_OK || buflen > (w * h * 4))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
free(comp);
|
2008-07-24 06:25:18 -07:00
|
|
|
free(d);
|
|
|
|
*size = -1;
|
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
memcpy(d + 32, comp, buflen);
|
|
|
|
*size = (8 * 4) + buflen;
|
|
|
|
free(comp);
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2006-03-03 18:46:24 -08:00
|
|
|
eet_data_image_jpeg_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
struct jpeg_compress_struct cinfo;
|
|
|
|
struct _JPEG_error_mgr jerr;
|
2006-03-03 18:46:24 -08:00
|
|
|
const int *ptr;
|
2005-05-07 09:46:26 -07:00
|
|
|
void *d = NULL;
|
|
|
|
size_t sz = 0;
|
|
|
|
JSAMPROW *jbuf;
|
|
|
|
unsigned char *buf;
|
|
|
|
|
2005-05-22 21:32:04 -07:00
|
|
|
(void) alpha; /* unused */
|
|
|
|
|
2005-11-03 19:22:22 -08:00
|
|
|
buf = alloca(3 * w);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-10-13 04:51:10 -07:00
|
|
|
memset(&cinfo, 0, sizeof (struct jpeg_compress_struct));
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
|
|
|
jerr.pub.output_message = _JPEGErrorHandler;
|
2008-09-03 04:04:37 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer)) return NULL;
|
|
|
|
jpeg_create_compress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_dst(&cinfo, &d, &sz))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
|
|
|
|
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int i, j;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* convert scaline from ARGB to RGB packed */
|
2008-09-03 04:04:37 -07:00
|
|
|
ptr = ((const int*) data) + cinfo.next_scanline * w;
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
2005-05-22 21:32:04 -07:00
|
|
|
jpeg_write_scanlines(&cinfo, jbuf, 1);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_finish_compress(&cinfo);
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
*size = sz;
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2006-03-03 18:46:24 -08:00
|
|
|
eet_data_image_jpeg_alpha_convert(int *size, const void *data, unsigned int w, unsigned int h, int alpha, int quality)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned char *d1, *d2;
|
|
|
|
unsigned char *d;
|
|
|
|
int *header;
|
|
|
|
int sz1, sz2;
|
|
|
|
|
2005-05-22 21:32:04 -07:00
|
|
|
(void) alpha; /* unused */
|
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian == -1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned long int v;
|
|
|
|
|
|
|
|
v = htonl(0x12345678);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (v == 0x12345678) _eet_image_words_bigendian = 1;
|
|
|
|
else _eet_image_words_bigendian = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2006-03-03 18:46:24 -08:00
|
|
|
const int *ptr;
|
2010-03-01 03:03:35 -08:00
|
|
|
void *dst = NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
size_t sz = 0;
|
|
|
|
struct _JPEG_error_mgr jerr;
|
|
|
|
JSAMPROW *jbuf;
|
|
|
|
struct jpeg_compress_struct cinfo;
|
|
|
|
unsigned char *buf;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-11-03 19:22:22 -08:00
|
|
|
buf = alloca(3 * w);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
|
|
|
jerr.pub.error_exit = _JPEGFatalErrorHandler;
|
|
|
|
jerr.pub.emit_message = _JPEGErrorHandler2;
|
|
|
|
jerr.pub.output_message = _JPEGErrorHandler;
|
2008-09-03 04:04:37 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer)) return NULL;
|
|
|
|
|
|
|
|
jpeg_create_compress(&cinfo);
|
2010-03-01 03:03:35 -08:00
|
|
|
if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int i, j;
|
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
ptr = ((const int*) data) + cinfo.next_scanline * w;
|
2005-05-07 09:46:26 -07:00
|
|
|
/* 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);
|
2005-05-22 21:32:04 -07:00
|
|
|
jpeg_write_scanlines(&cinfo, jbuf, 1);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_finish_compress(&cinfo);
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
d1 = dst;
|
2005-05-07 09:46:26 -07:00
|
|
|
sz1 = sz;
|
|
|
|
}
|
|
|
|
{
|
2006-03-03 18:46:24 -08:00
|
|
|
const int *ptr;
|
2010-03-01 03:03:35 -08:00
|
|
|
void *dst = NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
size_t sz = 0;
|
|
|
|
struct _JPEG_error_mgr jerr;
|
|
|
|
JSAMPROW *jbuf;
|
|
|
|
struct jpeg_compress_struct cinfo;
|
|
|
|
unsigned char *buf;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-11-03 19:22:22 -08:00
|
|
|
buf = alloca(3 * w);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_create_compress(&cinfo);
|
2010-03-01 03:03:35 -08:00
|
|
|
if (eet_jpeg_membuf_dst(&cinfo, &dst, &sz))
|
2008-09-03 04:04:37 -07:00
|
|
|
{
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
free(d1);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int i, j;
|
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
ptr = ((const int*) data) + cinfo.next_scanline * w;
|
2005-05-07 09:46:26 -07:00
|
|
|
/* convert scaline from ARGB to RGB packed */
|
|
|
|
for (j = 0, i = 0; i < w; i++)
|
|
|
|
{
|
|
|
|
buf[j++] = ((*ptr) >> 24) & 0xff;
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
jbuf = (JSAMPROW *) (&buf);
|
2005-05-22 21:32:04 -07:00
|
|
|
jpeg_write_scanlines(&cinfo, jbuf, 1);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_finish_compress(&cinfo);
|
|
|
|
jpeg_destroy_compress(&cinfo);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
d2 = dst;
|
2005-05-07 09:46:26 -07:00
|
|
|
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;
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
int i;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
for (i = 0; i < 3; i++) SWAP32(header[i]);
|
|
|
|
}
|
|
|
|
memcpy(d + 12, d1, sz1);
|
|
|
|
memcpy(d + 12 + sz1, d2, sz2);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
free(d1);
|
|
|
|
free(d2);
|
|
|
|
*size = 12 + sz1 + sz2;
|
2005-05-22 21:32:04 -07:00
|
|
|
return d;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-03-18 13:16:56 -07:00
|
|
|
eet_data_image_write_cipher(Eet_File *ef, const char *name, const char *cipher_key,
|
2008-11-13 08:31:13 -08:00
|
|
|
const void *data, unsigned int w, unsigned int h, int alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int comp, int quality, int lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
void *d = NULL;
|
|
|
|
int size = 0;
|
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
d = eet_data_image_encode(data, &size, w, h, alpha, comp, quality, lossy);
|
2005-05-07 09:46:26 -07:00
|
|
|
if (d)
|
|
|
|
{
|
|
|
|
int v;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
v = eet_write_cipher(ef, name, d, size, 0, cipher_key);
|
2005-05-07 09:46:26 -07:00
|
|
|
free(d);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
|
|
|
eet_data_image_write(Eet_File *ef, const char *name,
|
|
|
|
const void *data, unsigned int w, unsigned int h, int alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int comp, int quality, int lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_write_cipher(ef, name, NULL, data, w, h, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI void *
|
2010-03-18 13:16:56 -07:00
|
|
|
eet_data_image_read_cipher(Eet_File *ef, const char *name, const char *cipher_key,
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *comp, int *quality, int *lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned int *d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
void *data = NULL;
|
2008-02-29 22:38:09 -08:00
|
|
|
int free_data = 0;
|
2008-11-13 08:31:13 -08:00
|
|
|
int size;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!data)
|
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
data = eet_read_cipher(ef, name, &size, cipher_key);
|
2006-06-13 03:20:22 -07:00
|
|
|
free_data = 1;
|
2008-11-13 08:31:13 -08:00
|
|
|
if (!data) return NULL;
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
d = eet_data_image_decode(data, size, w, h, alpha, comp, quality, lossy);
|
2006-06-13 03:20:22 -07:00
|
|
|
|
|
|
|
if (free_data)
|
|
|
|
free(data);
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
|
|
|
eet_data_image_read(Eet_File *ef, const char *name,
|
|
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
EAPI int
|
2010-03-18 13:16:56 -07:00
|
|
|
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,
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *alpha, int *comp, int *quality, int *lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
2008-11-13 08:31:13 -08:00
|
|
|
void *data = NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
int free_data = 0;
|
|
|
|
int res = 1;
|
2008-11-13 08:31:13 -08:00
|
|
|
int size;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2008-06-02 09:01:18 -07:00
|
|
|
if (!data)
|
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
data = eet_read_cipher(ef, name, &size, cipher_key);
|
2008-11-13 08:31:13 -08:00
|
|
|
free_data = 1;
|
|
|
|
if (!data) return 0;
|
2008-06-02 09:01:18 -07:00
|
|
|
}
|
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
res = eet_data_image_decode_to_surface(data, size, src_x, src_y, d, w, h, row_stride, alpha, comp, quality, lossy);
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (free_data)
|
|
|
|
free(data);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2008-11-13 08:31:13 -08:00
|
|
|
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,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *alpha, int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_read_to_surface_cipher(ef, name, NULL, src_x, src_y, d, w, h, row_stride, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
2010-03-18 13:16:56 -07:00
|
|
|
eet_data_image_header_read_cipher(Eet_File *ef, const char *name, const char *cipher_key,
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *comp, int *quality, int *lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2006-06-13 03:20:22 -07:00
|
|
|
void *data = NULL;
|
|
|
|
int size = 0;
|
|
|
|
int free_data = 0;
|
2008-11-13 08:31:13 -08:00
|
|
|
int d;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2006-06-13 03:20:22 -07:00
|
|
|
if (!data)
|
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
data = eet_read_cipher(ef, name, &size, cipher_key);
|
2006-06-13 03:20:22 -07:00
|
|
|
free_data = 1;
|
2008-11-13 08:31:13 -08:00
|
|
|
if (!data) return 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-03-01 03:03:35 -08:00
|
|
|
d = eet_data_image_header_decode(data, size, w, h, alpha, comp, quality, lossy);
|
2006-06-13 03:20:22 -07:00
|
|
|
if (free_data)
|
|
|
|
free(data);
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
|
|
|
eet_data_image_header_read(Eet_File *ef, const char *name,
|
|
|
|
unsigned int *w, unsigned int *h, int *alpha,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_header_read_cipher(ef, name, NULL, w, h, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI void *
|
2010-03-18 13:16:56 -07:00
|
|
|
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)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
void *d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
void *ciphered_d = NULL;
|
|
|
|
unsigned int ciphered_sz = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
int size = 0;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
if (lossy == 0)
|
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp > 0)
|
|
|
|
d = eet_data_image_lossless_compressed_convert(&size, data, w, h, alpha, comp);
|
2008-07-24 06:25:18 -07:00
|
|
|
|
|
|
|
/* eet_data_image_lossless_compressed_convert will refuse to compress something
|
|
|
|
if the result is bigger than the entry. */
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp <= 0 || d == NULL)
|
2008-07-24 06:25:18 -07:00
|
|
|
d = eet_data_image_lossless_convert(&size, data, w, h, alpha);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d, &ciphered_sz))
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
|
|
|
if (d) free(d);
|
|
|
|
d = ciphered_d;
|
|
|
|
size = ciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (ciphered_d) free(ciphered_d);
|
|
|
|
}
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
if (size_ret) *size_ret = size;
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-03-01 03:03:35 -08:00
|
|
|
eet_data_image_encode(const void *data, int *size_ret, unsigned int w, unsigned int h, int alpha, int comp, int quality, int lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_encode_cipher(data, NULL, w, h, alpha, comp, quality, lossy, size_ret);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-03-18 13:16:56 -07:00
|
|
|
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)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
int header[8];
|
2008-11-13 08:31:13 -08:00
|
|
|
void *deciphered_d = NULL;
|
|
|
|
unsigned int deciphered_sz = 0;
|
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), &deciphered_d, &deciphered_sz))
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (deciphered_d) free(deciphered_d);
|
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian == -1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned long int v;
|
|
|
|
|
|
|
|
v = htonl(0x12345678);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (v == 0x12345678) _eet_image_words_bigendian = 1;
|
|
|
|
else _eet_image_words_bigendian = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
if (size < 32) return 0;
|
|
|
|
|
|
|
|
memcpy(header, data, 32);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
int i;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) SWAP32(header[i]);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
if ((unsigned)header[0] == 0xac1dfeed)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
int iw, ih, al, cp;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
iw = header[1];
|
|
|
|
ih = header[2];
|
|
|
|
al = header[3];
|
|
|
|
cp = header[4];
|
2006-11-25 07:37:45 -08:00
|
|
|
if ((iw < 1) || (ih < 1) || (iw > 8192) || (ih > 8192)) return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
if ((cp == 0) && (size < ((iw * ih * 4) + 32))) return 0;
|
|
|
|
if (w) *w = iw;
|
|
|
|
if (h) *h = ih;
|
2008-06-02 09:01:18 -07:00
|
|
|
if (alpha) *alpha = al ? 1 : 0;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp) *comp = cp;
|
2005-05-07 09:46:26 -07:00
|
|
|
if (lossy) *lossy = 0;
|
|
|
|
if (quality) *quality = 100;
|
|
|
|
return 1;
|
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
else if ((unsigned)header[0] == 0xbeeff00d)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int iw = 0, ih = 0;
|
2006-03-03 18:46:24 -08:00
|
|
|
unsigned const char *dt;
|
2008-12-29 02:47:18 -08:00
|
|
|
int sz1;
|
2005-05-07 09:46:26 -07:00
|
|
|
int ok;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
sz1 = header[1];
|
2008-12-29 02:47:18 -08:00
|
|
|
/* sz2 = header[2]; */
|
2005-05-07 09:46:26 -07:00
|
|
|
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;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp) *comp = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
if (lossy) *lossy = 1;
|
|
|
|
if (quality) *quality = 75;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-05-22 21:32:04 -07:00
|
|
|
unsigned int iw = 0, ih = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
int ok;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
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;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp) *comp = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
if (lossy) *lossy = 1;
|
|
|
|
if (quality) *quality = 75;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-03-01 03:03:35 -08:00
|
|
|
eet_data_image_header_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_header_decode_cipher(data, NULL, size, w, h, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
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)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
src += src_x + src_y * src_w;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
if (row_stride == src_w * 4 && w == src_w)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
memcpy(dst, src, row_stride * h);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
else
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned int *over = dst;
|
|
|
|
unsigned int y;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
for (y = 0; y < h; ++y, src += src_w, over += row_stride)
|
|
|
|
memcpy(over, src, w * 4);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
2010-03-01 03:03:35 -08:00
|
|
|
int alpha, int comp, int quality, int lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
|
|
|
if (lossy == 0 && quality == 100)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
unsigned int *body;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
body = ((unsigned int *)data) + 8;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (!comp)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
_eet_data_image_copy_buffer(body, src_x, src_y, src_w, d, w, h, row_stride);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
if (src_h == h && src_w == w && row_stride == src_w * 4)
|
|
|
|
{
|
|
|
|
uLongf dlen;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
dlen = w * h * 4;
|
|
|
|
uncompress((Bytef *)d, &dlen, (Bytef *)body,
|
|
|
|
(uLongf)(size - 32));
|
|
|
|
}
|
|
|
|
else
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
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;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
uncompress(dtmp, &dlen, (Bytef *)body, (uLongf)(size - 32));
|
|
|
|
|
|
|
|
_eet_data_image_copy_buffer((unsigned int *) dtmp, src_x, src_y, src_w, d, w, h, row_stride);
|
|
|
|
|
|
|
|
free(dtmp);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
/* Fix swapiness. */
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned int x;
|
|
|
|
|
|
|
|
for (x = 0; x < (w * h); x++) SWAP32(d[x]);
|
2005-05-22 21:32:04 -07:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-03-01 03:03:35 -08:00
|
|
|
else if (comp == 0 && lossy == 1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
if (alpha)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned const char *dt;
|
|
|
|
int header[8];
|
|
|
|
int sz1, sz2;
|
|
|
|
|
|
|
|
memcpy(header, data, 32);
|
2009-11-02 00:41:43 -08:00
|
|
|
if (_eet_image_words_bigendian)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
else
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w, h, row_stride))
|
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-06-02 09:01:18 -07:00
|
|
|
abort();
|
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI void *
|
2010-03-18 13:16:56 -07:00
|
|
|
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)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
|
|
|
unsigned int *d = NULL;
|
|
|
|
unsigned int iw, ih;
|
|
|
|
int ialpha, icompress, iquality, ilossy;
|
2008-11-13 08:31:13 -08:00
|
|
|
void *deciphered_d = NULL;
|
|
|
|
unsigned int deciphered_sz = 0;
|
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), &deciphered_d, &deciphered_sz))
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (deciphered_d) free(deciphered_d);
|
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
/* 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))
|
|
|
|
{
|
|
|
|
if (d) free(d);
|
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (w) *w = iw;
|
|
|
|
if (h) *h = ih;
|
|
|
|
if (alpha) *alpha = ialpha;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp) *comp = icompress;
|
2008-06-02 09:01:18 -07:00
|
|
|
if (quality) *quality = iquality;
|
|
|
|
if (lossy) *lossy = ilossy;
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-03-01 03:03:35 -08:00
|
|
|
eet_data_image_decode(const void *data, int size, unsigned int *w, unsigned int *h, int *alpha, int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_decode_cipher(data, NULL, size, w, h, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
EAPI int
|
2010-03-18 13:16:56 -07:00
|
|
|
eet_data_image_decode_to_surface_cipher(const void *data, const char *cipher_key, int size, unsigned int src_x, unsigned int src_y,
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int *d, unsigned int w, unsigned int h, unsigned int row_stride,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *alpha, int *comp, int *quality, int *lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
|
|
|
unsigned int iw, ih;
|
|
|
|
int ialpha, icompress, iquality, ilossy;
|
2008-11-13 08:31:13 -08:00
|
|
|
void *deciphered_d = NULL;
|
|
|
|
unsigned int deciphered_sz = 0;
|
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key), &deciphered_d, &deciphered_sz))
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (deciphered_d) free(deciphered_d);
|
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
/* 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;
|
2010-03-01 03:03:35 -08:00
|
|
|
if (comp) *comp = icompress;
|
2008-06-02 09:01:18 -07:00
|
|
|
if (quality) *quality = iquality;
|
|
|
|
if (lossy) *lossy = ilossy;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
|
|
|
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,
|
2010-03-01 03:03:35 -08:00
|
|
|
int *alpha, int *comp, int *quality, int *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-03-01 03:03:35 -08:00
|
|
|
return eet_data_image_decode_to_surface_cipher(data, NULL, size, src_x, src_y, d, w, h, row_stride, alpha, comp, quality, lossy);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|