2008-03-07 23:28:12 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
2008-03-28 10:17:43 -07:00
|
|
|
# include <config.h>
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef HAVE_CONFIG_H */
|
2008-03-07 23:28:12 -08:00
|
|
|
|
2013-01-10 12:26:02 -08:00
|
|
|
#ifdef __OpenBSD__
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif /* ifdef __OpenBSD__ */
|
2013-03-10 09:57:23 -07:00
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
# include <netinet/in.h>
|
|
|
|
#endif
|
2008-04-03 12:29:55 -07:00
|
|
|
|
2010-04-02 23:11:19 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <winsock2.h>
|
2011-05-22 22:14:20 -07:00
|
|
|
# define HAVE_BOOLEAN
|
2013-07-09 01:43:26 -07:00
|
|
|
# define XMD_H /* This prevents libjpeg to redefine INT32 */
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef _WIN32 */
|
2010-04-02 23:11:19 -07:00
|
|
|
|
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 <jpeglib.h>
|
2010-04-02 22:29:44 -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
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
#include "rg_etc1.h"
|
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
#ifdef BUILD_NEON
|
|
|
|
#include <arm_neon.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef WORDS_BIGENDIAN
|
|
|
|
/* x86 */
|
|
|
|
#define A_VAL(p) (((uint8_t *)(p))[3])
|
|
|
|
#define R_VAL(p) (((uint8_t *)(p))[2])
|
|
|
|
#define G_VAL(p) (((uint8_t *)(p))[1])
|
|
|
|
#define B_VAL(p) (((uint8_t *)(p))[0])
|
|
|
|
#else
|
|
|
|
/* ppc */
|
|
|
|
#define A_VAL(p) (((uint8_t *)(p))[0])
|
|
|
|
#define R_VAL(p) (((uint8_t *)(p))[1])
|
|
|
|
#define G_VAL(p) (((uint8_t *)(p))[2])
|
|
|
|
#define B_VAL(p) (((uint8_t *)(p))[3])
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define ARGB_JOIN(a,r,g,b) \
|
|
|
|
(((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
|
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
#define OFFSET_BLOCK_SIZE 4
|
2014-06-13 00:56:39 -07:00
|
|
|
#define OFFSET_ALGORITHM 5
|
2014-03-18 02:11:49 -07:00
|
|
|
#define OFFSET_OPTIONS 6
|
|
|
|
#define OFFSET_WIDTH 8
|
|
|
|
#define OFFSET_HEIGHT 12
|
|
|
|
#define OFFSET_BLOCKS 16
|
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
#undef MIN
|
|
|
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
|
|
|
|
|
|
|
#undef MAX
|
|
|
|
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/*---*/
|
|
|
|
|
2011-10-20 22:40:01 -07:00
|
|
|
typedef struct _JPEG_error_mgr *emptr;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
|
|
|
struct _JPEG_error_mgr
|
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
struct jpeg_error_mgr pub;
|
2010-07-30 18:54:48 -07:00
|
|
|
jmp_buf setjmp_buffer;
|
2005-05-07 09:46:26 -07:00
|
|
|
};
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
struct jpeg_membuf_src
|
|
|
|
{
|
2011-10-20 22:40:01 -07:00
|
|
|
struct jpeg_source_mgr pub;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-08-22 15:15:19 -07:00
|
|
|
const unsigned char *buf;
|
|
|
|
size_t len;
|
|
|
|
struct jpeg_membuf_src *self;
|
2008-09-03 04:04:37 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_src_init(j_decompress_ptr cinfo)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
/* FIXME: Use attribute unused */
|
2011-10-20 22:40:01 -07:00
|
|
|
(void)cinfo;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
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 };
|
2010-07-31 11:54:54 -07:00
|
|
|
struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
src->pub.bytes_in_buffer = sizeof(jpeg_eoi);
|
|
|
|
src->pub.next_input_byte = jpeg_eoi;
|
|
|
|
|
|
|
|
return TRUE;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static void
|
2010-07-30 18:54:48 -07:00
|
|
|
_eet_jpeg_membuf_src_skip(j_decompress_ptr cinfo,
|
|
|
|
long num_bytes)
|
2008-09-03 04:04:37 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
struct jpeg_membuf_src *src = (struct jpeg_membuf_src *)cinfo->src;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
src->pub.bytes_in_buffer -= num_bytes;
|
|
|
|
src->pub.next_input_byte += num_bytes;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_src_term(j_decompress_ptr cinfo)
|
|
|
|
{
|
2010-08-22 15:15:19 -07:00
|
|
|
struct jpeg_membuf_src *src = ((struct jpeg_membuf_src *)cinfo->src)->self;
|
2011-07-29 18:40:49 -07:00
|
|
|
|
2010-08-22 15:15:19 -07:00
|
|
|
free(src);
|
2008-09-03 04:04:37 -07:00
|
|
|
cinfo->src = NULL;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static int
|
2010-07-30 18:54:48 -07:00
|
|
|
eet_jpeg_membuf_src(j_decompress_ptr cinfo,
|
2010-07-31 11:57:35 -07:00
|
|
|
const void *buf,
|
2010-07-30 18:54:48 -07:00
|
|
|
size_t len)
|
2008-09-03 04:04:37 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
struct jpeg_membuf_src *src;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-08-22 15:15:19 -07:00
|
|
|
src = calloc(1, sizeof(*src));
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!src)
|
2011-10-20 22:40:01 -07:00
|
|
|
return -1;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-08-22 15:15:19 -07:00
|
|
|
src->self = src;
|
2011-07-29 18:40:49 -07:00
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
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;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
struct jpeg_membuf_dst
|
|
|
|
{
|
2008-09-03 04:04:37 -07:00
|
|
|
struct jpeg_destination_mgr pub;
|
|
|
|
|
2010-07-31 11:57:35 -07:00
|
|
|
void **dst_buf;
|
|
|
|
size_t *dst_len;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-31 11:57:35 -07:00
|
|
|
unsigned char *buf;
|
2010-07-30 18:54:48 -07:00
|
|
|
size_t len;
|
|
|
|
int failed;
|
2010-08-22 15:10:29 -07:00
|
|
|
struct jpeg_membuf_dst *self;
|
2008-09-03 04:04:37 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_dst_init(j_compress_ptr cinfo)
|
|
|
|
{
|
2008-10-13 04:51:10 -07:00
|
|
|
/* FIXME: Use eina attribute */
|
2011-10-20 22:40:01 -07:00
|
|
|
(void)cinfo;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static boolean
|
|
|
|
_eet_jpeg_membuf_dst_flush(j_compress_ptr cinfo)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
struct jpeg_membuf_dst *dst = (struct jpeg_membuf_dst *)cinfo->dest;
|
|
|
|
unsigned char *buf;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
if (dst->len >= 0x40000000 ||
|
2010-08-21 06:52:25 -07:00
|
|
|
!(buf = realloc(dst->buf, dst->len * 2)))
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
|
|
|
dst->failed = 1;
|
|
|
|
dst->pub.next_output_byte = dst->buf;
|
|
|
|
dst->pub.free_in_buffer = dst->len;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
dst->pub.next_output_byte =
|
2011-10-20 22:40:01 -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;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_jpeg_membuf_dst_term(j_compress_ptr cinfo)
|
|
|
|
{
|
2010-08-22 15:10:29 -07:00
|
|
|
struct jpeg_membuf_dst *dst = ((struct jpeg_membuf_dst *)cinfo->dest)->self;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(dst);
|
2008-09-03 04:04:37 -07:00
|
|
|
cinfo->dest = NULL;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
static int
|
2010-07-30 18:54:48 -07:00
|
|
|
eet_jpeg_membuf_dst(j_compress_ptr cinfo,
|
2010-07-31 11:57:35 -07:00
|
|
|
void **buf,
|
|
|
|
size_t *len)
|
2008-09-03 04:04:37 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
struct jpeg_membuf_dst *dst;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-08-22 15:10:29 -07:00
|
|
|
dst = calloc(1, sizeof(*dst));
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!dst)
|
2011-10-20 22:40:01 -07:00
|
|
|
return -1;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
|
|
|
dst->buf = malloc(32768);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!dst->buf)
|
|
|
|
{
|
|
|
|
free(dst);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-08-22 15:10:29 -07:00
|
|
|
dst->self = dst;
|
2008-09-03 04:04:37 -07:00
|
|
|
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;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/*---*/
|
|
|
|
|
2014-10-19 11:26:25 -07:00
|
|
|
static void _eet_image_jpeg_error_exit_cb(j_common_ptr cinfo);
|
|
|
|
static void _eet_image_jpeg_output_message_cb(j_common_ptr cinfo);
|
|
|
|
static void _eet_image_jpeg_emit_message_cb(j_common_ptr cinfo,
|
|
|
|
int msg_level);
|
2011-10-20 22:40:01 -07:00
|
|
|
|
|
|
|
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);
|
2012-01-19 06:54:01 -08:00
|
|
|
static int
|
2011-10-20 22:40:01 -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);
|
|
|
|
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
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
2015-02-04 01:03:20 -08:00
|
|
|
#define SWAP64(x) x = eina_swap64(x)
|
|
|
|
#define SWAP32(x) x = eina_swap32(x)
|
|
|
|
#define SWAP16(x) x = eina_swap16(x)
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2009-11-02 00:41:43 -08:00
|
|
|
#ifdef CONV8
|
|
|
|
# undef CONV8
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef CONV8 */
|
2009-11-02 00:41:43 -08:00
|
|
|
#ifdef CONV16
|
|
|
|
# undef CONV16
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef CONV16 */
|
2009-11-02 00:41:43 -08:00
|
|
|
#ifdef CONV32
|
|
|
|
# undef CONV32
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef CONV32 */
|
2009-11-02 00:41:43 -08:00
|
|
|
#ifdef CONV64
|
|
|
|
# undef CONV64
|
2010-07-30 18:54:48 -07:00
|
|
|
#endif /* ifdef CONV64 */
|
2009-11-02 00:41:43 -08:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
#define CONV8(x)
|
2015-01-14 00:54:58 -08:00
|
|
|
#define CONV16(x) do {if (_eet_image_words_bigendian) {SWAP16(x); }} while(0)
|
|
|
|
#define CONV32(x) do {if (_eet_image_words_bigendian) {SWAP32(x); }} while(0)
|
|
|
|
#define CONV64(x) do {if (_eet_image_words_bigendian) {SWAP64(x); }} while(0)
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
static int _eet_image_words_bigendian = -1;
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
_eet_image_endian_check(void)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
_eet_image_endian_swap(void *data, unsigned int length)
|
|
|
|
{
|
|
|
|
if (_eet_image_words_bigendian)
|
|
|
|
{
|
|
|
|
unsigned int *buffer = data;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < length; i++) SWAP32(buffer[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---*/
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void
|
2014-10-19 11:26:25 -07:00
|
|
|
_eet_image_jpeg_error_exit_cb(j_common_ptr cinfo)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2014-10-19 11:26:25 -07:00
|
|
|
char buffer[JMSG_LENGTH_MAX];
|
2005-05-07 09:46:26 -07:00
|
|
|
emptr errmgr;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2014-10-19 11:26:25 -07:00
|
|
|
(*cinfo->err->format_message)(cinfo, buffer);
|
2014-10-22 13:30:29 -07:00
|
|
|
ERR("%s", buffer);
|
2010-07-27 18:45:57 -07:00
|
|
|
errmgr = (emptr)cinfo->err;
|
2005-05-07 09:46:26 -07:00
|
|
|
longjmp(errmgr->setjmp_buffer, 1);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void
|
2014-10-19 11:26:25 -07:00
|
|
|
_eet_image_jpeg_output_message_cb(j_common_ptr cinfo)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2014-10-19 11:26:25 -07:00
|
|
|
char buffer[JMSG_LENGTH_MAX];
|
2014-10-20 23:55:53 -07:00
|
|
|
/* emptr errmgr; */
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2014-10-19 11:26:25 -07:00
|
|
|
(*cinfo->err->format_message)(cinfo, buffer);
|
2014-10-22 13:30:29 -07:00
|
|
|
ERR("%s", buffer);
|
2014-10-20 23:55:53 -07:00
|
|
|
/*
|
2014-10-19 11:26:25 -07:00
|
|
|
errmgr = (emptr)cinfo->err;
|
|
|
|
longjmp(errmgr->setjmp_buffer, 1);
|
2014-10-20 23:55:53 -07:00
|
|
|
*/
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void
|
2014-10-19 11:26:25 -07:00
|
|
|
_eet_image_jpeg_emit_message_cb(j_common_ptr cinfo,
|
|
|
|
int msg_level)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2014-10-19 11:26:25 -07:00
|
|
|
char buffer[JMSG_LENGTH_MAX];
|
|
|
|
struct jpeg_error_mgr *err;
|
2014-10-20 23:55:53 -07:00
|
|
|
/* emptr errmgr; */
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2014-10-19 11:26:25 -07:00
|
|
|
err = cinfo->err;
|
|
|
|
if (msg_level < 0)
|
|
|
|
{
|
|
|
|
if ((err->num_warnings == 0) || (err->trace_level >= 3))
|
|
|
|
{
|
|
|
|
(*cinfo->err->format_message)(cinfo, buffer);
|
2014-10-22 13:30:29 -07:00
|
|
|
WRN("%s", buffer);
|
2014-10-19 11:26:25 -07:00
|
|
|
}
|
|
|
|
err->num_warnings++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (err->trace_level >= msg_level)
|
|
|
|
{
|
|
|
|
(*cinfo->err->format_message)(cinfo, buffer);
|
2014-10-22 13:30:29 -07:00
|
|
|
INF("%s", buffer);
|
2014-10-19 11:26:25 -07:00
|
|
|
}
|
|
|
|
}
|
2014-10-20 23:55:53 -07:00
|
|
|
/*
|
2014-10-19 11:26:25 -07:00
|
|
|
errmgr = (emptr)cinfo->err;
|
|
|
|
longjmp(errmgr->setjmp_buffer, 1);
|
2014-10-20 23:55:53 -07:00
|
|
|
*/
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
static int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_jpeg_header_decode(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
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));
|
2014-10-19 11:26:25 -07:00
|
|
|
jerr.pub.error_exit = _eet_image_jpeg_error_exit_cb;
|
|
|
|
jerr.pub.emit_message = _eet_image_jpeg_emit_message_cb;
|
|
|
|
jerr.pub.output_message = _eet_image_jpeg_output_message_cb;
|
2010-07-27 18:45:57 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
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);
|
|
|
|
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))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return 1;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
static int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_jpeg_rgb_decode(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
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;
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
|
|
|
unsigned int *ptr2, *tmp;
|
2008-06-02 09:01:18 -07:00
|
|
|
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 */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!d)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2008-06-02 09:01:18 -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));
|
2014-10-19 11:26:25 -07:00
|
|
|
jerr.pub.error_exit = _eet_image_jpeg_error_exit_cb;
|
|
|
|
jerr.pub.emit_message = _eet_image_jpeg_emit_message_cb;
|
|
|
|
jerr.pub.output_message = _eet_image_jpeg_output_message_cb;
|
2010-07-27 18:45:57 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
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);
|
2011-11-16 03:52:47 -08:00
|
|
|
cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return 0;
|
2006-11-25 07:37:45 -08:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* end head decoding */
|
|
|
|
/* data decoding */
|
|
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -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)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
|
2011-10-20 22:40:01 -07:00
|
|
|
line[i] = tdata + (i * (iw) * 3);
|
2010-07-27 18:45:57 -07:00
|
|
|
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)
|
2011-10-20 22:40:01 -07:00
|
|
|
scans = ih - l;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
ptr = tdata;
|
|
|
|
|
|
|
|
if (l + scans >= src_y && l < src_y + h)
|
|
|
|
{
|
|
|
|
y = src_y - l;
|
|
|
|
if (src_y < l)
|
2011-10-20 22:40:01 -07:00
|
|
|
y = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
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 =
|
2011-10-20 22:40:01 -07:00
|
|
|
(0xff000000) |
|
|
|
|
((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
|
2010-07-27 18:45:57 -07:00
|
|
|
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)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
|
2011-10-20 22:40:01 -07:00
|
|
|
line[i] = tdata + (i * (iw));
|
2010-07-27 18:45:57 -07:00
|
|
|
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)
|
2011-10-20 22:40:01 -07:00
|
|
|
scans = (ih) - l;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
ptr = tdata;
|
|
|
|
|
|
|
|
if (l >= src_y && l < src_y + h)
|
|
|
|
{
|
|
|
|
y = src_y - l;
|
|
|
|
if (src_y < l)
|
2011-10-20 22:40:01 -07:00
|
|
|
y = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
|
|
|
|
{
|
|
|
|
tmp = ptr2;
|
|
|
|
ptr += src_x;
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
*ptr2 =
|
2011-10-20 22:40:01 -07:00
|
|
|
(0xff000000) |
|
|
|
|
((ptr[0]) << 16) | ((ptr[0]) << 8) | (ptr[0]);
|
2010-07-27 18:45:57 -07:00
|
|
|
ptr++;
|
|
|
|
ptr2++;
|
|
|
|
}
|
|
|
|
ptr += iw - w;
|
|
|
|
ptr2 = tmp + row_stride / 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
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;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2012-01-19 06:54:01 -08:00
|
|
|
static int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_jpeg_alpha_decode(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
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;
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned char *ptr, *line[16], *tdata = NULL;
|
|
|
|
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
|
|
|
|
2012-01-19 06:54:01 -08: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));
|
2008-09-02 18:34:53 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
2014-10-19 11:26:25 -07:00
|
|
|
jerr.pub.error_exit = _eet_image_jpeg_error_exit_cb;
|
|
|
|
jerr.pub.emit_message = _eet_image_jpeg_emit_message_cb;
|
|
|
|
jerr.pub.output_message = _eet_image_jpeg_output_message_cb;
|
2010-07-27 18:45:57 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer))
|
2012-01-19 06:54:01 -08:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_src(&cinfo, data, (size_t)size))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2012-01-19 06:54:01 -08: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);
|
2011-11-16 03:52:47 -08:00
|
|
|
cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
|
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
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2012-01-19 06:54:01 -08:00
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* end head decoding */
|
|
|
|
/* data decoding */
|
|
|
|
if (cinfo.rec_outbuf_height > 16)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
free(cinfo.src);
|
|
|
|
cinfo.src = NULL;
|
2008-09-03 04:04:37 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2012-01-19 06:54:01 -08:00
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
tdata = alloca(w * 16 * 3);
|
2005-05-07 09:46:26 -07:00
|
|
|
ptr2 = d;
|
2012-01-19 06:54:01 -08:00
|
|
|
|
2005-11-03 19:22:22 -08:00
|
|
|
if (cinfo.output_components == 1)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
for (i = 0; i < (unsigned int)cinfo.rec_outbuf_height; i++)
|
2011-10-20 22:40:01 -07:00
|
|
|
line[i] = tdata + (i * w);
|
2010-07-27 18:45:57 -07:00
|
|
|
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)
|
2011-10-20 22:40:01 -07:00
|
|
|
scans = h - l;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
ptr = tdata;
|
|
|
|
|
|
|
|
if (l >= src_y && l < src_y + h)
|
|
|
|
{
|
|
|
|
y = src_y - l;
|
|
|
|
if (src_y < l)
|
2011-10-20 22:40:01 -07:00
|
|
|
y = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
for (ptr += iw * y; y < scans && (y + l) < (src_y + h); y++)
|
|
|
|
{
|
|
|
|
tmp = ptr2;
|
|
|
|
ptr += src_x;
|
|
|
|
for (x = 0; x < w; x++)
|
|
|
|
{
|
|
|
|
*ptr2 =
|
2011-10-20 22:40:01 -07:00
|
|
|
((*ptr2) & 0x00ffffff) |
|
|
|
|
((ptr[0]) << 24);
|
2010-07-27 18:45:57 -07:00
|
|
|
ptr++;
|
|
|
|
ptr2++;
|
|
|
|
}
|
|
|
|
ptr += iw - w;
|
|
|
|
ptr2 = tmp + row_stride / 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
/* end data decoding */
|
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
2012-01-19 06:54:01 -08:00
|
|
|
return 1;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// FIXME: Importing two functions from evas here: premul & unpremul
|
|
|
|
static void
|
|
|
|
_eet_argb_premul(unsigned int *data, unsigned int len)
|
|
|
|
{
|
|
|
|
unsigned int *de = data + len;
|
|
|
|
|
|
|
|
while (data < de)
|
|
|
|
{
|
|
|
|
unsigned int a = 1 + (*data >> 24);
|
|
|
|
|
|
|
|
*data = (*data & 0xff000000) +
|
|
|
|
(((((*data) >> 8) & 0xff) * a) & 0xff00) +
|
|
|
|
(((((*data) & 0x00ff00ff) * a) >> 8) & 0x00ff00ff);
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_eet_argb_unpremul(unsigned int *data, unsigned int len)
|
|
|
|
{
|
|
|
|
unsigned int *de = data + len;
|
|
|
|
unsigned int p_val = 0x00000000, p_res = 0x00000000;
|
|
|
|
|
|
|
|
while (data < de)
|
|
|
|
{
|
|
|
|
unsigned int a = (*data >> 24) + 1;
|
|
|
|
|
|
|
|
if (p_val == *data) *data = p_res;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
p_val = *data;
|
|
|
|
if ((a > 1) && (a < 256))
|
|
|
|
*data = ARGB_JOIN(a,
|
|
|
|
(R_VAL(data) * 255) / a,
|
|
|
|
(G_VAL(data) * 255) / a,
|
|
|
|
(B_VAL(data) * 255) / a);
|
|
|
|
else if (a == 1)
|
|
|
|
*data = 0x00000000;
|
|
|
|
p_res = *data;
|
|
|
|
}
|
|
|
|
data++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
static inline unsigned int
|
|
|
|
_tgv_length_get(const char *m, unsigned int length, unsigned int *offset)
|
|
|
|
{
|
|
|
|
unsigned int r = 0;
|
|
|
|
unsigned int shift = 0;
|
|
|
|
|
|
|
|
while (*offset < length && ((*m) & 0x80))
|
|
|
|
{
|
|
|
|
r = r | (((*m) & 0x7F) << shift);
|
|
|
|
shift += 7;
|
|
|
|
m++;
|
|
|
|
(*offset)++;
|
|
|
|
}
|
|
|
|
if (*offset < length)
|
|
|
|
{
|
|
|
|
r = r | (((*m) & 0x7F) << shift);
|
|
|
|
(*offset)++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-06-13 00:56:39 -07:00
|
|
|
roundup(int val, int rup)
|
|
|
|
{
|
|
|
|
if (val >= 0 && rup > 0)
|
|
|
|
return (val + rup - 1) - ((val + rup - 1) % rup);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
eet_data_image_etc2_decode(const void *data,
|
2014-03-18 02:11:49 -07:00
|
|
|
unsigned int length,
|
|
|
|
unsigned int *p,
|
|
|
|
unsigned int dst_x,
|
|
|
|
unsigned int dst_y,
|
|
|
|
unsigned int dst_w,
|
|
|
|
unsigned int dst_h,
|
2014-06-13 00:56:39 -07:00
|
|
|
Eina_Bool alpha,
|
|
|
|
Eet_Colorspace cspace,
|
|
|
|
Eet_Image_Encoding lossy)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-06-13 00:56:39 -07:00
|
|
|
const char *m = NULL;
|
|
|
|
unsigned int bwidth, bheight;
|
|
|
|
unsigned char *p_etc;
|
2014-07-10 23:15:52 -07:00
|
|
|
char *buffer = NULL;
|
2014-06-13 00:56:39 -07:00
|
|
|
Eina_Rectangle master;
|
|
|
|
unsigned int block_length;
|
2014-03-18 02:11:49 -07:00
|
|
|
unsigned int offset;
|
2014-06-13 00:56:39 -07:00
|
|
|
unsigned int x, y, w, h;
|
|
|
|
unsigned int block_count;
|
|
|
|
unsigned int etc_width = 0;
|
|
|
|
unsigned int etc_block_size;
|
2014-07-10 23:15:52 -07:00
|
|
|
unsigned int num_planes = 1, plane, alpha_offset = 0;
|
2014-06-13 00:56:39 -07:00
|
|
|
Eet_Colorspace file_cspace;
|
2014-07-10 23:15:52 -07:00
|
|
|
Eina_Bool compress, blockless, unpremul;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
m = data;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-08-11 07:17:05 -07:00
|
|
|
// Fix for ABI incompatibility between 1.10 and 1.11
|
|
|
|
if (cspace == 8) cspace = 9;
|
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
if (strncmp(m, "TGV1", 4) != 0)
|
|
|
|
return 0;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
|
|
|
compress = m[OFFSET_OPTIONS] & 0x1;
|
2014-06-13 00:56:39 -07:00
|
|
|
blockless = (m[OFFSET_OPTIONS] & 0x2) != 0;
|
2014-07-10 23:15:52 -07:00
|
|
|
unpremul = (m[OFFSET_OPTIONS] & 0x4) != 0;
|
2014-06-13 00:56:39 -07:00
|
|
|
w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
|
|
|
|
h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
switch (m[OFFSET_ALGORITHM] & 0xFF)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
if (lossy != EET_IMAGE_ETC1) return 0;
|
|
|
|
file_cspace = EET_COLORSPACE_ETC1;
|
|
|
|
if (alpha != EINA_FALSE) return 0;
|
|
|
|
etc_block_size = 8;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (lossy != EET_IMAGE_ETC2_RGB) return 0;
|
|
|
|
file_cspace = EET_COLORSPACE_RGB8_ETC2;
|
|
|
|
if (alpha != EINA_FALSE) return 0;
|
|
|
|
etc_block_size = 8;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (lossy != EET_IMAGE_ETC2_RGBA) return 0;
|
|
|
|
file_cspace = EET_COLORSPACE_RGBA8_ETC2_EAC;
|
|
|
|
if (alpha != EINA_TRUE) return 0;
|
|
|
|
etc_block_size = 16;
|
2014-07-10 23:15:52 -07:00
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (lossy != EET_IMAGE_ETC1_ALPHA) return 0;
|
|
|
|
file_cspace = EET_COLORSPACE_ETC1_ALPHA;
|
|
|
|
if (alpha != EINA_TRUE) return 0;
|
|
|
|
etc_block_size = 8;
|
|
|
|
num_planes = 2;
|
|
|
|
alpha_offset = ((w + 2 + 3) / 4) * ((h + 2 + 3) / 4) * 8 / sizeof(*p_etc);
|
2014-06-13 00:56:39 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
etc_width = ((w + 2 + 3) / 4) * etc_block_size;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
if (cspace != EET_COLORSPACE_ARGB8888 && cspace != file_cspace)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-06-13 00:56:39 -07:00
|
|
|
if (!((cspace == EET_COLORSPACE_RGB8_ETC2) && (file_cspace == EET_COLORSPACE_ETC1)))
|
|
|
|
return 0;
|
|
|
|
// else: ETC2 is compatible with ETC1 and is preferred
|
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
if (blockless)
|
|
|
|
{
|
|
|
|
bwidth = roundup(w + 2, 4);
|
|
|
|
bheight = roundup(h + 2, 4);
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-06-13 00:56:39 -07:00
|
|
|
bwidth = 4 << (m[OFFSET_BLOCK_SIZE] & 0x0f);
|
|
|
|
bheight = 4 << ((m[OFFSET_BLOCK_SIZE] & 0xf0) >> 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(&master, dst_x, dst_y, dst_w, dst_h);
|
|
|
|
|
|
|
|
switch (cspace)
|
|
|
|
{
|
|
|
|
case EET_COLORSPACE_ETC1:
|
|
|
|
case EET_COLORSPACE_RGB8_ETC2:
|
|
|
|
case EET_COLORSPACE_RGBA8_ETC2_EAC:
|
2014-07-10 23:15:52 -07:00
|
|
|
case EET_COLORSPACE_ETC1_ALPHA:
|
2014-06-13 00:56:39 -07:00
|
|
|
if (master.x % 4 || master.y % 4)
|
|
|
|
abort();
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_ARGB8888:
|
|
|
|
// Offset to take duplicated pixels into account
|
2014-03-18 02:11:49 -07:00
|
|
|
master.x += 1;
|
|
|
|
master.y += 1;
|
2014-06-13 00:56:39 -07:00
|
|
|
break;
|
|
|
|
default: abort();
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
p_etc = (unsigned char*) p;
|
|
|
|
offset = OFFSET_BLOCKS;
|
|
|
|
|
|
|
|
// Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group)
|
|
|
|
block_count = bwidth * bheight / (4 * 4);
|
2014-03-18 02:11:49 -07:00
|
|
|
if (compress)
|
2014-06-13 00:56:39 -07:00
|
|
|
buffer = alloca(etc_block_size * block_count);
|
2014-07-10 23:15:52 -07:00
|
|
|
|
|
|
|
for (plane = 0; plane < num_planes; plane++)
|
|
|
|
for (y = 0; y < h + 2; y += bheight)
|
|
|
|
for (x = 0; x < w + 2; x += bwidth)
|
|
|
|
{
|
|
|
|
Eina_Rectangle current;
|
|
|
|
const char *data_start;
|
|
|
|
const char *it;
|
|
|
|
unsigned int expand_length;
|
|
|
|
unsigned int i, j;
|
|
|
|
|
|
|
|
block_length = _tgv_length_get(m + offset, length, &offset);
|
|
|
|
|
|
|
|
if (block_length == 0) goto on_error;
|
|
|
|
|
|
|
|
data_start = m + offset;
|
|
|
|
offset += block_length;
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(¤t, x, y,
|
|
|
|
bwidth, bheight);
|
|
|
|
|
|
|
|
if (!eina_rectangle_intersection(¤t, &master))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (compress)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-12-10 05:34:42 -08:00
|
|
|
expand_length = LZ4_decompress_fast(data_start, buffer,
|
|
|
|
block_count * etc_block_size);
|
2014-07-10 23:15:52 -07:00
|
|
|
// That's an overhead for now, need to be fixed
|
|
|
|
if (expand_length != block_length)
|
|
|
|
goto on_error;
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer = (void*) data_start;
|
|
|
|
if (block_count * etc_block_size != block_length)
|
|
|
|
goto on_error;
|
|
|
|
}
|
|
|
|
it = buffer;
|
|
|
|
|
|
|
|
for (i = 0; i < bheight; i += 4)
|
|
|
|
for (j = 0; j < bwidth; j += 4, it += etc_block_size)
|
|
|
|
{
|
|
|
|
Eina_Rectangle current_etc;
|
|
|
|
unsigned int temporary[4 * 4];
|
|
|
|
unsigned int offset_x, offset_y;
|
|
|
|
int k, l;
|
|
|
|
|
|
|
|
EINA_RECTANGLE_SET(¤t_etc, x + j, y + i, 4, 4);
|
|
|
|
|
|
|
|
if (!eina_rectangle_intersection(¤t_etc, ¤t))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch (cspace)
|
|
|
|
{
|
|
|
|
case EET_COLORSPACE_ARGB8888:
|
|
|
|
switch (file_cspace)
|
|
|
|
{
|
|
|
|
case EET_COLORSPACE_ETC1:
|
|
|
|
case EET_COLORSPACE_ETC1_ALPHA:
|
|
|
|
if (!rg_etc1_unpack_block(it, temporary, 0))
|
|
|
|
{
|
|
|
|
// TODO: Should we decode as RGB8_ETC2?
|
|
|
|
fprintf(stderr, "ETC1: Block starting at {%i, %i} is corrupted!\n", x + j, y + i);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_RGB8_ETC2:
|
|
|
|
rg_etc2_rgb8_decode_block((uint8_t *) it, temporary);
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_RGBA8_ETC2_EAC:
|
|
|
|
rg_etc2_rgba8_decode_block((uint8_t *) it, temporary);
|
|
|
|
break;
|
|
|
|
default: abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
offset_x = current_etc.x - x - j;
|
|
|
|
offset_y = current_etc.y - y - i;
|
|
|
|
|
|
|
|
if (!plane)
|
|
|
|
{
|
|
|
|
#ifdef BUILD_NEON
|
|
|
|
if (eina_cpu_features_get() & EINA_CPU_NEON)
|
|
|
|
{
|
|
|
|
uint32_t *dst = &p[current_etc.x - 1 + (current_etc.y - 1) * master.w];
|
|
|
|
uint32_t *src = &temporary[offset_x + offset_y * 4];
|
|
|
|
for (k = 0; k < current_etc.h; k++)
|
|
|
|
{
|
|
|
|
if (current_etc.w == 4)
|
|
|
|
vst1q_u32(dst, vld1q_u32(src));
|
|
|
|
else if (current_etc.w == 3)
|
|
|
|
{
|
|
|
|
vst1_u32(dst, vld1_u32(src));
|
|
|
|
*(dst + 2) = *(src + 2);
|
|
|
|
}
|
|
|
|
else if (current_etc.w == 2)
|
|
|
|
vst1_u32(dst, vld1_u32(src));
|
|
|
|
else
|
|
|
|
*dst = *src;
|
|
|
|
dst += master.w;
|
|
|
|
src += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
for (k = 0; k < current_etc.h; k++)
|
|
|
|
{
|
|
|
|
memcpy(&p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w],
|
|
|
|
&temporary[offset_x + (offset_y + k) * 4],
|
|
|
|
current_etc.w * sizeof (unsigned int));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (k = 0; k < current_etc.h; k++)
|
|
|
|
for (l = 0; l < current_etc.w; l++)
|
|
|
|
{
|
|
|
|
unsigned int *rgbdata =
|
|
|
|
&p[current_etc.x - 1 + (current_etc.y - 1 + k) * master.w + l];
|
|
|
|
unsigned int *adata =
|
|
|
|
&temporary[offset_x + (offset_y + k) * 4 + l];
|
|
|
|
A_VAL(rgbdata) = G_VAL(adata);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_ETC1:
|
|
|
|
case EET_COLORSPACE_RGB8_ETC2:
|
|
|
|
case EET_COLORSPACE_RGBA8_ETC2_EAC:
|
|
|
|
memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
|
|
|
|
(current_etc.y / 4) * etc_width],
|
|
|
|
it, etc_block_size);
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_ETC1_ALPHA:
|
|
|
|
memcpy(&p_etc[(current_etc.x / 4) * etc_block_size +
|
|
|
|
(current_etc.y / 4) * etc_width +
|
|
|
|
plane * alpha_offset],
|
|
|
|
it, etc_block_size);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
} // bx,by inside blocks
|
|
|
|
} // x,y macroblocks
|
|
|
|
|
|
|
|
// TODO: Add support for more unpremultiplied modes (ETC2)
|
|
|
|
if ((cspace == EET_COLORSPACE_ARGB8888) && unpremul)
|
|
|
|
_eet_argb_premul(p, w * h);
|
2014-03-18 02:11:49 -07:00
|
|
|
|
|
|
|
return 1;
|
2014-07-10 23:15:52 -07:00
|
|
|
|
|
|
|
on_error:
|
|
|
|
ERR("ETC image data is corrupted in this EET file");
|
|
|
|
return 0;
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_lossless_convert(int *size,
|
|
|
|
const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2015-01-06 02:09:27 -08:00
|
|
|
unsigned char *d;
|
|
|
|
int *header;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_check();
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
d = malloc((w * h * 4) + (8 * 4));
|
|
|
|
if (!d)
|
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
header = (int *)d;
|
|
|
|
memset(d, 0, 32);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
header[0] = 0xac1dfeed;
|
|
|
|
header[1] = w;
|
|
|
|
header[2] = h;
|
|
|
|
header[3] = alpha;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
memcpy(d + 32, data, w * h * 4);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(header, ((w * h) + 8));
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
*size = ((w * h * 4) + (8 * 4));
|
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
|
|
|
static void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_lossless_compressed_convert(int *size,
|
|
|
|
const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha,
|
|
|
|
int compression)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_check();
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
Eina_Binbuf *in;
|
|
|
|
Eina_Binbuf *out;
|
|
|
|
unsigned char *result;
|
|
|
|
int *bigend_data = NULL;
|
|
|
|
int header[8];
|
|
|
|
unsigned int i;
|
2013-01-13 19:54:47 -08:00
|
|
|
|
|
|
|
if (_eet_image_words_bigendian)
|
|
|
|
{
|
|
|
|
bigend_data = (int *) malloc(w * h * 4);
|
|
|
|
if (!bigend_data) return NULL;
|
|
|
|
|
|
|
|
memcpy(bigend_data, data, w * h * 4);
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(bigend_data, w * h);
|
2013-01-13 19:54:47 -08:00
|
|
|
|
|
|
|
data = (const char *) bigend_data;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:50:03 -07:00
|
|
|
in = eina_binbuf_manage_read_only_new_length(data, w * h * 4);
|
|
|
|
if (!in)
|
2012-05-15 05:27:56 -07:00
|
|
|
{
|
2013-05-28 05:31:47 -07:00
|
|
|
free(bigend_data);
|
2012-05-15 05:27:56 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:50:03 -07:00
|
|
|
out = emile_binbuf_compress(in, eet_2_emile_compressor(compression), compression);
|
|
|
|
|
|
|
|
if (!out || (eina_binbuf_length_get(out) > eina_binbuf_length_get(in)))
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
eina_binbuf_free(in);
|
|
|
|
eina_binbuf_free(out);
|
2013-05-28 05:31:47 -07:00
|
|
|
free(bigend_data);
|
2015-03-17 00:50:03 -07:00
|
|
|
*size = -1;
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-17 00:50:03 -07:00
|
|
|
eina_binbuf_free(in);
|
|
|
|
|
|
|
|
memset(header, 0, 8 * sizeof(int));
|
2010-07-27 18:45:57 -07:00
|
|
|
header[0] = 0xac1dfeed;
|
|
|
|
header[1] = w;
|
|
|
|
header[2] = h;
|
|
|
|
header[3] = alpha;
|
|
|
|
header[4] = compression;
|
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(header, 8);
|
|
|
|
free(bigend_data);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-03-17 00:50:03 -07:00
|
|
|
eina_binbuf_insert_length(out, (const unsigned char*) header, sizeof (header), 0);
|
|
|
|
|
|
|
|
*size = eina_binbuf_length_get(out);
|
|
|
|
result = eina_binbuf_string_steal(out);
|
|
|
|
|
|
|
|
eina_binbuf_free(out);
|
|
|
|
|
|
|
|
return result;
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
static int
|
|
|
|
_block_size_get(int size)
|
|
|
|
{
|
|
|
|
static const int MAX_BLOCK = 6; // 256 pixels
|
|
|
|
|
|
|
|
int k = 0;
|
|
|
|
while ((4 << k) < size) k++;
|
|
|
|
k = MAX(0, k - 1);
|
|
|
|
if ((size * 3 / 2) >= (4 << k)) return MAX(0, MIN(k - 1, MAX_BLOCK));
|
|
|
|
return MIN(k, MAX_BLOCK);
|
|
|
|
}
|
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
static inline void
|
|
|
|
_alpha_to_greyscale_convert(uint32_t *data, int len)
|
|
|
|
{
|
|
|
|
for (int k = 0; k < len; k++)
|
|
|
|
{
|
|
|
|
int alpha = A_VAL(data);
|
|
|
|
*data++ = ARGB_JOIN(alpha, alpha, alpha, alpha);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
static void *
|
|
|
|
eet_data_image_etc1_compressed_convert(int *size,
|
2014-04-17 21:12:03 -07:00
|
|
|
const unsigned char *data8,
|
2014-03-18 02:11:49 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
int quality,
|
2014-06-13 00:56:39 -07:00
|
|
|
int compress,
|
|
|
|
Eet_Image_Encoding lossy)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
|
|
|
rg_etc1_pack_params param;
|
2014-06-13 00:56:39 -07:00
|
|
|
uint8_t *comp = NULL;
|
|
|
|
uint8_t *buffer;
|
2014-04-23 02:08:36 -07:00
|
|
|
uint32_t *data;
|
2014-07-10 23:15:52 -07:00
|
|
|
uint32_t nl_width, nl_height;
|
2014-04-23 02:08:36 -07:00
|
|
|
uint8_t header[8] = "TGV1";
|
|
|
|
int block_width, block_height, macro_block_width, macro_block_height;
|
2014-06-13 00:56:39 -07:00
|
|
|
int block_count, image_stride, image_height, etc_block_size;
|
2014-07-10 23:15:52 -07:00
|
|
|
int num_planes = 1;
|
2014-06-13 00:56:39 -07:00
|
|
|
Eet_Colorspace cspace;
|
2014-07-10 23:15:52 -07:00
|
|
|
Eina_Bool unpremul = EINA_FALSE, alpha_texture = EINA_FALSE;
|
|
|
|
Eina_Binbuf *r = NULL;
|
2014-03-18 02:11:49 -07:00
|
|
|
void *result;
|
2014-06-13 01:45:32 -07:00
|
|
|
const char *codec;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
|
|
|
r = eina_binbuf_new();
|
|
|
|
if (!r) return NULL;
|
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
image_stride = w;
|
|
|
|
image_height = h;
|
2014-07-10 23:15:52 -07:00
|
|
|
nl_width = htonl(image_stride);
|
|
|
|
nl_height = htonl(image_height);
|
2014-06-13 00:56:39 -07:00
|
|
|
compress = !!compress;
|
2014-04-17 03:03:19 -07:00
|
|
|
|
|
|
|
// Disable dithering, as it will deteriorate the quality of flat surfaces
|
|
|
|
param.m_dithering = 0;
|
|
|
|
|
|
|
|
if (quality > 95)
|
2014-04-23 02:08:36 -07:00
|
|
|
param.m_quality = rg_etc1_high_quality;
|
2014-04-07 23:57:27 -07:00
|
|
|
else if (quality > 30)
|
2014-04-23 02:08:36 -07:00
|
|
|
param.m_quality = rg_etc1_medium_quality;
|
2014-03-18 02:11:49 -07:00
|
|
|
else
|
2014-04-23 02:08:36 -07:00
|
|
|
param.m_quality = rg_etc1_low_quality;
|
|
|
|
|
|
|
|
// header[4]: 4 bit block width, 4 bit block height
|
|
|
|
block_width = _block_size_get(image_stride + 2);
|
|
|
|
block_height = _block_size_get(image_height + 2);
|
|
|
|
header[4] = (block_height << 4) | block_width;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// header[5]: 0 for ETC1, 1 for RGB8_ETC2, 2 for RGBA8_ETC2_EAC, 3 for ETC1_ALPHA
|
2014-06-13 00:56:39 -07:00
|
|
|
switch (lossy)
|
|
|
|
{
|
|
|
|
case EET_IMAGE_ETC1:
|
|
|
|
cspace = EET_COLORSPACE_ETC1;
|
|
|
|
etc_block_size = 8;
|
|
|
|
header[5] = 0;
|
2014-06-13 01:45:32 -07:00
|
|
|
codec = "ETC1";
|
2014-06-13 00:56:39 -07:00
|
|
|
break;
|
|
|
|
case EET_IMAGE_ETC2_RGB:
|
|
|
|
cspace = EET_COLORSPACE_RGB8_ETC2;
|
|
|
|
etc_block_size = 8;
|
|
|
|
header[5] = 1;
|
2014-06-13 01:45:32 -07:00
|
|
|
codec = "ETC2 (RGB)";
|
2014-06-13 00:56:39 -07:00
|
|
|
break;
|
|
|
|
case EET_IMAGE_ETC2_RGBA:
|
|
|
|
cspace = EET_COLORSPACE_RGBA8_ETC2_EAC;
|
|
|
|
etc_block_size = 16;
|
|
|
|
header[5] = 2;
|
2014-06-13 01:45:32 -07:00
|
|
|
codec = "ETC2 (RGBA)";
|
2014-06-13 00:56:39 -07:00
|
|
|
break;
|
2014-07-10 23:15:52 -07:00
|
|
|
case EET_IMAGE_ETC1_ALPHA:
|
|
|
|
cspace = EET_COLORSPACE_ETC1_ALPHA;
|
|
|
|
etc_block_size = 8;
|
|
|
|
num_planes = 2; // RGB and Alpha
|
|
|
|
header[5] = 3;
|
|
|
|
codec = "ETC1+Alpha";
|
|
|
|
break;
|
2014-06-13 00:56:39 -07:00
|
|
|
default: abort();
|
|
|
|
}
|
2014-04-23 02:08:36 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// header[6]: 0 for raw, 1, for LZ4 compressed, 4 for unpremultiplied RGBA
|
|
|
|
// blockless mode (0x2) is never used here
|
|
|
|
header[6] = (compress ? 0x1 : 0x0) | (unpremul ? 0x4 : 0x0);
|
2014-04-23 02:08:36 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// header[7]: unused options
|
|
|
|
// Note: consider extending the header instead of filling all the bits here
|
2014-03-18 02:11:49 -07:00
|
|
|
header[7] = 0;
|
|
|
|
|
2014-06-13 01:45:32 -07:00
|
|
|
// Encoding being super slow, let's inform the user first.
|
|
|
|
// FIXME: Ctrl+C must be handled
|
|
|
|
INF("Encoding %dx%d image to %s, this may take a while...", w, h, codec);
|
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
// Write header
|
2014-03-18 02:11:49 -07:00
|
|
|
eina_binbuf_append_length(r, header, sizeof (header));
|
2014-07-10 23:15:52 -07:00
|
|
|
eina_binbuf_append_length(r, (unsigned char*) &nl_width, sizeof (nl_width));
|
|
|
|
eina_binbuf_append_length(r, (unsigned char*) &nl_height, sizeof (nl_height));
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
// Real block size in pixels, obviously a multiple of 4
|
|
|
|
macro_block_width = 4 << block_width;
|
|
|
|
macro_block_height = 4 << block_height;
|
|
|
|
|
|
|
|
// Number of ETC1 blocks in a compressed block
|
|
|
|
block_count = (macro_block_width * macro_block_height) / (4 * 4);
|
2014-06-13 00:56:39 -07:00
|
|
|
buffer = alloca(block_count * etc_block_size);
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-04-23 02:08:36 -07:00
|
|
|
if (compress)
|
2014-06-13 00:56:39 -07:00
|
|
|
comp = alloca(LZ4_compressBound(block_count * etc_block_size));
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// Write a whole plane (RGB or Alpha)
|
|
|
|
for (int plane = 0; plane < num_planes; plane++)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
if (!alpha_texture)
|
|
|
|
{
|
|
|
|
// Normal mode
|
|
|
|
data = (uint32_t *) data8;
|
|
|
|
}
|
|
|
|
else if (!plane)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
int len = image_stride * image_height;
|
|
|
|
// RGB plane for ETC1+Alpha
|
|
|
|
data = malloc(len * 4);
|
|
|
|
if (!data) goto finish;
|
|
|
|
memcpy(data, data8, len * 4);
|
|
|
|
if (unpremul) _eet_argb_unpremul(data, len);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Alpha plane for ETC1+Alpha
|
|
|
|
_alpha_to_greyscale_convert(data, image_stride * image_height);
|
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
// Write macro block
|
|
|
|
for (int y = 0; y < image_height + 2; y += macro_block_height)
|
|
|
|
{
|
|
|
|
uint32_t *input, *last_col, *last_row, *last_pix;
|
|
|
|
int real_y;
|
|
|
|
int wlen;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (y == 0) real_y = 0;
|
|
|
|
else if (y < image_height + 1) real_y = y - 1;
|
|
|
|
else real_y = image_height - 1;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
for (int x = 0; x < image_stride + 2; x += macro_block_width)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
uint8_t *offset = buffer;
|
|
|
|
int real_x = x;
|
|
|
|
|
|
|
|
if (x == 0) real_x = 0;
|
|
|
|
else if (x < image_stride + 1) real_x = x - 1;
|
|
|
|
else real_x = image_stride - 1;
|
|
|
|
|
|
|
|
input = data + real_y * image_stride + real_x;
|
|
|
|
last_row = data + image_stride * (image_height - 1) + real_x;
|
|
|
|
last_col = data + (real_y + 1) * image_stride - 1;
|
|
|
|
last_pix = data + image_height * image_stride - 1;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
for (int by = 0; by < macro_block_height; by += 4)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
int dup_top = ((y + by) == 0) ? 1 : 0;
|
|
|
|
int max_row = MAX(0, MIN(4, image_height - real_y - by));
|
|
|
|
int oy = (y == 0) ? 1 : 0;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
for (int bx = 0; bx < macro_block_width; bx += 4)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
int dup_left = ((x + bx) == 0) ? 1 : 0;
|
|
|
|
int max_col = MAX(0, MIN(4, image_stride - real_x - bx));
|
|
|
|
uint32_t todo[16] = { 0 };
|
|
|
|
int row, col;
|
|
|
|
int ox = (x == 0) ? 1 : 0;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (dup_left)
|
|
|
|
{
|
|
|
|
// Duplicate left column
|
|
|
|
for (row = 0; row < max_row; row++)
|
|
|
|
todo[row * 4] = input[row * image_stride];
|
|
|
|
for (row = max_row; row < 4; row++)
|
|
|
|
todo[row * 4] = last_row[0];
|
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (dup_top)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
// Duplicate top row
|
|
|
|
for (col = 0; col < max_col; col++)
|
|
|
|
todo[col] = input[MAX(col + bx - ox, 0)];
|
|
|
|
for (col = max_col; col < 4; col++)
|
|
|
|
todo[col] = last_col[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
for (row = dup_top; row < 4; row++)
|
|
|
|
{
|
|
|
|
for (col = dup_left; col < max_col; col++)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
if (row < max_row)
|
|
|
|
{
|
|
|
|
// Normal copy
|
|
|
|
todo[row * 4 + col] = input[(row + by - oy) * image_stride + bx + col - ox];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Copy last line
|
|
|
|
todo[row * 4 + col] = last_row[col + bx - ox];
|
|
|
|
}
|
2014-04-23 02:08:36 -07:00
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
for (col = max_col; col < 4; col++)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
// Right edge
|
|
|
|
if (row < max_row)
|
|
|
|
{
|
|
|
|
// Duplicate last column
|
|
|
|
todo[row * 4 + col] = last_col[MAX(row + by - oy, 0) * image_stride];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Duplicate very last pixel again and again
|
|
|
|
todo[row * 4 + col] = *last_pix;
|
|
|
|
}
|
2014-04-23 02:08:36 -07:00
|
|
|
}
|
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
|
|
|
|
switch (cspace)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
case EET_COLORSPACE_ETC1:
|
|
|
|
case EET_COLORSPACE_ETC1_ALPHA:
|
|
|
|
rg_etc1_pack_block(offset, (uint32_t *) todo, ¶m);
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_RGB8_ETC2:
|
|
|
|
etc2_rgb8_block_pack(offset, (uint32_t *) todo, ¶m);
|
|
|
|
break;
|
|
|
|
case EET_COLORSPACE_RGBA8_ETC2_EAC:
|
|
|
|
etc2_rgba8_block_pack(offset, (uint32_t *) todo, ¶m);
|
|
|
|
break;
|
|
|
|
default: return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG_STATS
|
|
|
|
if (plane == 0)
|
|
|
|
{
|
|
|
|
// Decode to compute PSNR, this is slow.
|
|
|
|
uint32_t done[16];
|
|
|
|
|
|
|
|
if (alpha)
|
|
|
|
rg_etc2_rgba8_decode_block(offset, done);
|
2014-04-23 02:08:36 -07:00
|
|
|
else
|
2014-07-10 23:15:52 -07:00
|
|
|
rg_etc2_rgb8_decode_block(offset, done);
|
|
|
|
|
|
|
|
for (int k = 0; k < 16; k++)
|
2014-04-23 02:08:36 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
const int r = (R_VAL(&(todo[k])) - R_VAL(&(done[k])));
|
|
|
|
const int g = (G_VAL(&(todo[k])) - G_VAL(&(done[k])));
|
|
|
|
const int b = (B_VAL(&(todo[k])) - B_VAL(&(done[k])));
|
|
|
|
const int a = (A_VAL(&(todo[k])) - A_VAL(&(done[k])));
|
|
|
|
mse += r*r + g*g + b*b;
|
|
|
|
if (alpha) mse_alpha += a*a;
|
|
|
|
mse_div++;
|
2014-04-23 02:08:36 -07:00
|
|
|
}
|
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
#endif
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
offset += etc_block_size;
|
2014-06-13 00:56:39 -07:00
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (compress)
|
|
|
|
{
|
|
|
|
wlen = LZ4_compressHC((char *) buffer, (char *) comp,
|
|
|
|
block_count * etc_block_size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
comp = buffer;
|
|
|
|
wlen = block_count * etc_block_size;
|
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (wlen > 0)
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-07-10 23:15:52 -07:00
|
|
|
unsigned int blen = wlen;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
while (blen)
|
|
|
|
{
|
|
|
|
unsigned char plen;
|
|
|
|
|
|
|
|
plen = blen & 0x7F;
|
|
|
|
blen = blen >> 7;
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (blen) plen = 0x80 | plen;
|
|
|
|
eina_binbuf_append_length(r, &plen, 1);
|
|
|
|
}
|
|
|
|
eina_binbuf_append_length(r, (unsigned char *) comp, wlen);
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
2014-07-10 23:15:52 -07:00
|
|
|
} // 4 rows
|
|
|
|
} // macroblocks
|
|
|
|
} // planes
|
2014-03-18 02:11:49 -07:00
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
finish:
|
|
|
|
if (alpha_texture) free(data);
|
2014-03-18 02:11:49 -07:00
|
|
|
*size = eina_binbuf_length_get(r);
|
|
|
|
result = eina_binbuf_string_steal(r);
|
|
|
|
eina_binbuf_free(r);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2015-01-06 02:42:55 -08:00
|
|
|
static inline void *
|
|
|
|
_eet_data_image_grey_encode(const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2015-01-06 02:42:55 -08:00
|
|
|
int quality,
|
|
|
|
int *size)
|
|
|
|
{
|
|
|
|
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 = _eet_image_jpeg_error_exit_cb;
|
|
|
|
jerr.pub.emit_message = _eet_image_jpeg_emit_message_cb;
|
|
|
|
jerr.pub.output_message = _eet_image_jpeg_output_message_cb;
|
|
|
|
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 = 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);
|
|
|
|
|
|
|
|
*size = sz;
|
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void *
|
|
|
|
_eet_data_image_rgb_encode(const void *data,
|
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
int quality,
|
|
|
|
int *size)
|
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;
|
2010-07-31 11:54:54 -07:00
|
|
|
const int *ptr;
|
|
|
|
void *d = NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
size_t sz = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
JSAMPROW *jbuf;
|
|
|
|
unsigned char *buf;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
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));
|
2014-10-19 11:26:25 -07:00
|
|
|
jerr.pub.error_exit = _eet_image_jpeg_error_exit_cb;
|
|
|
|
jerr.pub.emit_message = _eet_image_jpeg_emit_message_cb;
|
|
|
|
jerr.pub.output_message = _eet_image_jpeg_output_message_cb;
|
2010-07-27 18:45:57 -07:00
|
|
|
if (setjmp(jerr.setjmp_buffer))
|
2011-10-20 22:40:01 -07:00
|
|
|
return NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-09-03 04:04:37 -07:00
|
|
|
jpeg_create_compress(&cinfo);
|
|
|
|
|
|
|
|
if (eet_jpeg_membuf_dst(&cinfo, &d, &sz))
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
jpeg_destroy_compress(&cinfo);
|
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
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;
|
2011-11-16 03:52:47 -08:00
|
|
|
cinfo.optimize_coding = FALSE;
|
|
|
|
cinfo.dct_method = JDCT_ISLOW; // JDCT_FLOAT JDCT_IFAST(quality loss)
|
|
|
|
if (quality < 60) cinfo.dct_method = JDCT_IFAST;
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_set_defaults(&cinfo);
|
|
|
|
jpeg_set_quality(&cinfo, quality, TRUE);
|
2011-11-16 03:52:47 -08:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
if (quality >= 90)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
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;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
jpeg_start_compress(&cinfo, TRUE);
|
|
|
|
|
|
|
|
while (cinfo.next_scanline < cinfo.image_height)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
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);
|
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;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2015-01-06 02:42:55 -08:00
|
|
|
static void *
|
|
|
|
eet_data_image_jpeg_convert(int *size,
|
|
|
|
const void *data,
|
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
int alpha EINA_UNUSED,
|
|
|
|
int quality)
|
|
|
|
{
|
|
|
|
return _eet_data_image_rgb_encode(data, w, h, quality, size);
|
|
|
|
}
|
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
static void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_jpeg_alpha_convert(int *size,
|
|
|
|
const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2015-01-06 02:42:55 -08:00
|
|
|
int alpha EINA_UNUSED,
|
2010-07-30 18:54:48 -07:00
|
|
|
int quality)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned char *d1, *d2;
|
|
|
|
unsigned char *d;
|
|
|
|
int *header;
|
2005-05-07 09:46:26 -07:00
|
|
|
int sz1, sz2;
|
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_check();
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2015-01-06 02:42:55 -08:00
|
|
|
d1 = _eet_data_image_rgb_encode(data, w, h, quality, &sz1);
|
|
|
|
d2 = _eet_data_image_grey_encode(data, w, h, quality, &sz2);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-06 02:42:55 -08:00
|
|
|
if (!d1 || !d2)
|
|
|
|
{
|
|
|
|
free(d1);
|
|
|
|
free(d2);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
d = malloc(12 + sz1 + sz2);
|
|
|
|
if (!d)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
free(d1);
|
|
|
|
free(d2);
|
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
header = (int *)d;
|
|
|
|
header[0] = 0xbeeff00d;
|
|
|
|
header[1] = sz1;
|
|
|
|
header[2] = sz2;
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(header, 3);
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2011-10-20 22:40:01 -07:00
|
|
|
memcpy(d + 12, d1, sz1);
|
2010-07-30 18:54:48 -07:00
|
|
|
memcpy(d + 12 + sz1, d2, sz2);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
free(d1);
|
|
|
|
free(d2);
|
2005-05-07 09:46:26 -07:00
|
|
|
*size = 12 + sz1 + sz2;
|
2005-05-22 21:32:04 -07:00
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_write_cipher(Eet_File *ef,
|
|
|
|
const char *name,
|
|
|
|
const char *cipher_key,
|
|
|
|
const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha,
|
|
|
|
int comp,
|
|
|
|
int quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *d = NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
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)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
int v;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
v = eet_write_cipher(ef, name, d, size, 0, cipher_key);
|
2010-07-30 18:54:48 -07:00
|
|
|
free(d);
|
2010-07-27 18:45:57 -07:00
|
|
|
return v;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return 0;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_write(Eet_File *ef,
|
|
|
|
const char *name,
|
|
|
|
const void *data,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha,
|
|
|
|
int comp,
|
|
|
|
int quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_data_image_write_cipher(ef,
|
|
|
|
name,
|
|
|
|
NULL,
|
|
|
|
data,
|
|
|
|
w,
|
|
|
|
h,
|
|
|
|
alpha,
|
|
|
|
comp,
|
|
|
|
quality,
|
|
|
|
lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_read_cipher(Eet_File *ef,
|
|
|
|
const char *name,
|
|
|
|
const char *cipher_key,
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *d = NULL;
|
|
|
|
void *data = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int free_data = 0;
|
|
|
|
int size;
|
2008-02-29 22:38:09 -08:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2011-10-20 22:40:01 -07:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
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);
|
2010-07-27 18:45:57 -07:00
|
|
|
free_data = 1;
|
|
|
|
if (!data)
|
2011-10-20 22:40:01 -07:00
|
|
|
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)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(data);
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_read(Eet_File *ef,
|
|
|
|
const char *name,
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_read_cipher(ef, name, NULL, w, h, alpha,
|
|
|
|
comp, quality, lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
EAPI int
|
2014-03-28 00:05:45 -07:00
|
|
|
eet_data_image_read_to_cspace_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,
|
|
|
|
Eet_Colorspace cspace,
|
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
|
|
|
Eet_Image_Encoding *lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int free_data = 0;
|
|
|
|
int res = 1;
|
|
|
|
int size;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2011-10-20 22:40:01 -07:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
if (!data)
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
data = eet_read_cipher(ef, name, &size, cipher_key);
|
|
|
|
free_data = 1;
|
|
|
|
if (!data)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2008-06-02 09:01:18 -07:00
|
|
|
}
|
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
res = eet_data_image_decode_to_cspace_surface_cipher(data, NULL, size, src_x, src_y, d,
|
|
|
|
w, h, row_stride, cspace, alpha,
|
|
|
|
comp, quality, lossy);
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
if (free_data)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(data);
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
return res;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
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,
|
|
|
|
Eet_Image_Encoding *lossy)
|
|
|
|
{
|
|
|
|
return eet_data_image_read_to_cspace_surface_cipher(ef, name, cipher_key,
|
|
|
|
src_x, src_y, d, w, h, row_stride,
|
|
|
|
EET_COLORSPACE_ARGB8888,
|
|
|
|
alpha, comp, quality, lossy);
|
|
|
|
}
|
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_read_to_surface(Eet_File *ef,
|
|
|
|
const char *name,
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int src_x,
|
|
|
|
unsigned int src_y,
|
|
|
|
unsigned int *d,
|
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
unsigned int row_stride,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_read_to_surface_cipher(ef, name, NULL,
|
|
|
|
src_x, src_y, d,
|
|
|
|
w, h, row_stride,
|
|
|
|
alpha, comp, quality,
|
2010-07-27 18:45:57 -07:00
|
|
|
lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_header_read_cipher(Eet_File *ef,
|
|
|
|
const char *name,
|
|
|
|
const char *cipher_key,
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *data = NULL;
|
2010-07-27 18:45:57 -07:00
|
|
|
int size = 0;
|
|
|
|
int free_data = 0;
|
|
|
|
int d;
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (!cipher_key)
|
2011-10-20 22:40:01 -07:00
|
|
|
data = (void *)eet_read_direct(ef, name, &size);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
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);
|
2010-07-27 18:45:57 -07:00
|
|
|
free_data = 1;
|
|
|
|
if (!data)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2006-06-13 03:20:22 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-07-30 18:54:48 -07: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)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(data);
|
2006-06-13 03:20:22 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_header_read(Eet_File *ef,
|
|
|
|
const char *name,
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_header_read_cipher(ef, name, NULL,
|
|
|
|
w, h, alpha,
|
|
|
|
comp, quality, lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_encode_cipher(const void *data,
|
|
|
|
const char *cipher_key,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha,
|
|
|
|
int comp,
|
|
|
|
int quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding lossy,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *size_ret)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
void *d = NULL;
|
|
|
|
void *ciphered_d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int ciphered_sz = 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
int size = 0;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
switch (lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2014-03-18 02:11:49 -07:00
|
|
|
case EET_IMAGE_LOSSLESS:
|
|
|
|
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);
|
|
|
|
break;
|
|
|
|
case EET_IMAGE_JPEG:
|
|
|
|
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);
|
|
|
|
break;
|
|
|
|
case EET_IMAGE_ETC1:
|
2014-06-13 00:56:39 -07:00
|
|
|
case EET_IMAGE_ETC2_RGB:
|
|
|
|
if (alpha) abort();
|
|
|
|
// fallthrough
|
|
|
|
case EET_IMAGE_ETC2_RGBA:
|
2014-07-10 23:15:52 -07:00
|
|
|
case EET_IMAGE_ETC1_ALPHA:
|
2014-03-18 02:11:49 -07:00
|
|
|
d = eet_data_image_etc1_compressed_convert(&size, data, w, h,
|
2014-06-13 00:56:39 -07:00
|
|
|
quality, comp, lossy);
|
2014-03-18 02:11:49 -07:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
abort();
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if(!eet_cipher(d, size, cipher_key, strlen(cipher_key), &ciphered_d,
|
|
|
|
&ciphered_sz))
|
|
|
|
{
|
|
|
|
if (d)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(d);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
d = ciphered_d;
|
|
|
|
size = ciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
2013-02-19 03:27:26 -08:00
|
|
|
if (ciphered_d)
|
|
|
|
free(ciphered_d);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (size_ret)
|
2011-10-20 22:40:01 -07:00
|
|
|
*size_ret = size;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_encode(const void *data,
|
|
|
|
int *size_ret,
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
2010-07-30 18:54:48 -07:00
|
|
|
int alpha,
|
|
|
|
int comp,
|
|
|
|
int quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_encode_cipher(data, NULL, w, h, alpha,
|
|
|
|
comp, quality, lossy, size_ret);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-03-07 01:59:37 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_header_decode_cipher(const void *data,
|
|
|
|
const char *cipher_key,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
|
|
|
int header[8];
|
2010-07-31 11:54:54 -07:00
|
|
|
void *deciphered_d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
unsigned int deciphered_sz = 0;
|
2015-01-21 07:07:07 -08:00
|
|
|
int r = 0;
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2010-03-18 13:16:56 -07:00
|
|
|
if (cipher_key)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
|
|
|
|
&deciphered_d, &deciphered_sz))
|
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
2013-07-16 02:20:07 -07:00
|
|
|
{
|
|
|
|
free(deciphered_d);
|
|
|
|
deciphered_d = NULL;
|
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_check();
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
if (size < 32) goto on_error;
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2010-07-30 18:54:48 -07:00
|
|
|
memcpy(header, data, 32);
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(header, 8);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2005-05-22 21:32:04 -07:00
|
|
|
if ((unsigned)header[0] == 0xac1dfeed)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
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))
|
2015-01-21 07:07:07 -08:00
|
|
|
goto on_error;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if ((cp == 0) && (size < ((iw * ih * 4) + 32)))
|
2015-01-21 07:07:07 -08:00
|
|
|
goto on_error;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (w)
|
2011-10-20 22:40:01 -07:00
|
|
|
*w = iw;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (h)
|
2011-10-20 22:40:01 -07:00
|
|
|
*h = ih;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (alpha)
|
2011-10-20 22:40:01 -07:00
|
|
|
*alpha = al ? 1 : 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
*comp = cp;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (lossy)
|
2014-03-18 02:11:49 -07:00
|
|
|
*lossy = EET_IMAGE_LOSSLESS;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (quality)
|
2011-10-20 22:40:01 -07:00
|
|
|
*quality = 100;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
r = 1;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2005-05-22 21:32:04 -07:00
|
|
|
else if ((unsigned)header[0] == 0xbeeff00d)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int iw = 0, ih = 0;
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned const char *dt;
|
2015-01-14 01:11:22 -08:00
|
|
|
int sz1, sz2;
|
2010-07-27 18:45:57 -07:00
|
|
|
int ok;
|
|
|
|
|
|
|
|
sz1 = header[1];
|
2015-01-14 01:11:22 -08:00
|
|
|
sz2 = header[2];
|
|
|
|
if ((sz1 <= 0) || (sz2 <= 0) || ((sz1 + sz2) > (size - 12)))
|
2015-01-21 07:07:07 -08:00
|
|
|
goto on_error;
|
2010-07-27 18:45:57 -07:00
|
|
|
dt = data;
|
|
|
|
dt += 12;
|
|
|
|
ok = eet_data_image_jpeg_header_decode(dt, sz1, &iw, &ih);
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
if (w)
|
2011-10-20 22:40:01 -07:00
|
|
|
*w = iw;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (h)
|
2011-10-20 22:40:01 -07:00
|
|
|
*h = ih;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (alpha)
|
2011-10-20 22:40:01 -07:00
|
|
|
*alpha = 1;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
*comp = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (lossy)
|
2014-03-18 02:11:49 -07:00
|
|
|
*lossy = EET_IMAGE_JPEG;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (quality)
|
2011-10-20 22:40:01 -07:00
|
|
|
*quality = 75;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
r = 1;
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
else if (!strncmp(data, "TGV1", 4))
|
|
|
|
{
|
|
|
|
const char *m = data;
|
|
|
|
|
|
|
|
if (w) *w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
|
|
|
|
if (h) *h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
|
|
|
|
if (comp) *comp = m[OFFSET_OPTIONS] & 0x1;
|
2014-06-13 00:56:39 -07:00
|
|
|
switch (m[OFFSET_ALGORITHM] & 0xFF)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
if (lossy) *lossy = EET_IMAGE_ETC1;
|
|
|
|
if (alpha) *alpha = EINA_FALSE;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if (lossy) *lossy = EET_IMAGE_ETC2_RGB;
|
|
|
|
if (alpha) *alpha = EINA_FALSE;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (alpha) *alpha = EINA_TRUE;
|
|
|
|
if (lossy) *lossy = EET_IMAGE_ETC2_RGBA;
|
|
|
|
break;
|
2014-07-10 23:15:52 -07:00
|
|
|
case 3:
|
|
|
|
if (alpha) *alpha = EINA_TRUE;
|
|
|
|
if (lossy) *lossy = EET_IMAGE_ETC1_ALPHA;
|
|
|
|
break;
|
2014-06-13 00:56:39 -07:00
|
|
|
default:
|
2015-01-21 07:07:07 -08:00
|
|
|
goto on_error;
|
2014-06-13 00:56:39 -07:00
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
if (quality) *quality = 50;
|
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
r = 1;
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
else
|
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int iw = 0, ih = 0;
|
|
|
|
int ok;
|
|
|
|
|
|
|
|
ok = eet_data_image_jpeg_header_decode(data, size, &iw, &ih);
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
if (w)
|
2011-10-20 22:40:01 -07:00
|
|
|
*w = iw;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (h)
|
2011-10-20 22:40:01 -07:00
|
|
|
*h = ih;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (alpha)
|
2011-10-20 22:40:01 -07:00
|
|
|
*alpha = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
*comp = 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (lossy)
|
2014-03-18 02:11:49 -07:00
|
|
|
*lossy = EET_IMAGE_JPEG;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (quality)
|
2011-10-20 22:40:01 -07:00
|
|
|
*quality = 75;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
r = 1;
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2015-01-21 07:07:07 -08:00
|
|
|
on_error:
|
2013-07-16 02:20:07 -07:00
|
|
|
free(deciphered_d);
|
2015-01-21 07:07:07 -08:00
|
|
|
return r;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
static const Eet_Colorspace _eet_etc1_colorspace[] = {
|
|
|
|
EET_COLORSPACE_ETC1,
|
|
|
|
EET_COLORSPACE_ARGB8888
|
|
|
|
};
|
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
static const Eet_Colorspace _eet_etc1_alpha_colorspace[] = {
|
|
|
|
EET_COLORSPACE_ETC1_ALPHA,
|
|
|
|
EET_COLORSPACE_ARGB8888
|
|
|
|
};
|
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
static const Eet_Colorspace _eet_etc2_rgb_colorspace[] = {
|
|
|
|
EET_COLORSPACE_RGB8_ETC2,
|
|
|
|
EET_COLORSPACE_ARGB8888
|
|
|
|
};
|
|
|
|
|
|
|
|
static const Eet_Colorspace _eet_etc2_rgba_colorspace[] = {
|
|
|
|
EET_COLORSPACE_RGBA8_ETC2_EAC,
|
|
|
|
EET_COLORSPACE_ARGB8888
|
|
|
|
};
|
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
EAPI int
|
|
|
|
eet_data_image_colorspace_get(Eet_File *ef,
|
|
|
|
const char *name,
|
|
|
|
const char *cipher_key,
|
|
|
|
const Eet_Colorspace **cspaces)
|
|
|
|
{
|
|
|
|
Eet_Image_Encoding lossy;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
r = eet_data_image_header_read_cipher(ef, name, cipher_key, NULL, NULL, NULL, NULL, NULL, &lossy);
|
|
|
|
if (!r) return r;
|
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
if (cspaces)
|
|
|
|
{
|
|
|
|
if (lossy == EET_IMAGE_ETC1)
|
|
|
|
*cspaces = _eet_etc1_colorspace;
|
|
|
|
else if (lossy == EET_IMAGE_ETC2_RGB)
|
|
|
|
*cspaces = _eet_etc2_rgb_colorspace;
|
|
|
|
else if (lossy == EET_IMAGE_ETC2_RGBA)
|
|
|
|
*cspaces = _eet_etc2_rgba_colorspace;
|
2014-07-10 23:15:52 -07:00
|
|
|
else if (lossy == EET_IMAGE_ETC1_ALPHA)
|
|
|
|
*cspaces = _eet_etc1_alpha_colorspace;
|
2014-06-13 00:56:39 -07:00
|
|
|
}
|
2014-03-28 00:05:45 -07:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_header_decode(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
return eet_data_image_header_decode_cipher(data,
|
|
|
|
NULL,
|
|
|
|
size,
|
|
|
|
w,
|
|
|
|
h,
|
|
|
|
alpha,
|
|
|
|
comp,
|
|
|
|
quality,
|
|
|
|
lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
static void
|
2010-07-31 11:54:54 -07:00
|
|
|
_eet_data_image_copy_buffer(const unsigned int *src,
|
|
|
|
unsigned int src_x,
|
|
|
|
unsigned int src_y,
|
|
|
|
unsigned int src_w,
|
2010-07-31 11:57:35 -07:00
|
|
|
unsigned int *dst,
|
2010-07-31 11:54:54 -07:00
|
|
|
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)
|
2011-10-20 22:40:01 -07:00
|
|
|
memcpy(dst, src, row_stride * h);
|
2008-06-02 09:01:18 -07:00
|
|
|
else
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *over = dst;
|
2010-07-27 18:45:57 -07:00
|
|
|
unsigned int y;
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
for (y = 0; y < h; ++y, src += src_w, over += row_stride)
|
2011-10-20 22:40:01 -07:00
|
|
|
memcpy(over, src, w * 4);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
static int
|
2010-07-31 11:57:35 -07:00
|
|
|
_eet_data_image_decode_inside(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int src_x,
|
|
|
|
unsigned int src_y,
|
|
|
|
unsigned int src_w,
|
2015-03-17 00:50:03 -07:00
|
|
|
EINA_UNUSED unsigned int src_h, /* useful for fast path detection */
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *d,
|
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
unsigned int row_stride,
|
|
|
|
int alpha,
|
|
|
|
int comp,
|
|
|
|
int quality,
|
2014-03-28 00:05:45 -07:00
|
|
|
Eet_Image_Encoding lossy,
|
|
|
|
Eet_Colorspace cspace)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
2015-01-14 01:17:19 -08:00
|
|
|
_eet_image_endian_check();
|
|
|
|
|
2014-03-18 02:11:49 -07:00
|
|
|
if (lossy == EET_IMAGE_LOSSLESS && quality == 100)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *body;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
body = ((unsigned int *)data) + 8;
|
|
|
|
if (!comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
_eet_data_image_copy_buffer(body, src_x, src_y, src_w, d,
|
|
|
|
w, h, row_stride);
|
2010-07-27 18:45:57 -07:00
|
|
|
else
|
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
Eina_Binbuf *in;
|
|
|
|
Eina_Binbuf *out;
|
|
|
|
|
|
|
|
in = eina_binbuf_manage_read_only_new_length((const unsigned char *) body, size - 8 * sizeof (int));
|
|
|
|
if (!in) return 0;
|
|
|
|
|
2012-05-15 05:27:56 -07:00
|
|
|
if ((src_h == h) && (src_w == w) && (row_stride == src_w * 4))
|
2010-07-27 18:45:57 -07:00
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
out = eina_binbuf_manage_read_only_new_length((void*) d,
|
|
|
|
w * h * 4);
|
|
|
|
if (!emile_binbuf_expand(in, out,
|
|
|
|
eet_2_emile_compressor(comp)))
|
2012-05-15 05:27:56 -07:00
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
eina_binbuf_free(in);
|
|
|
|
eina_binbuf_free(out);
|
|
|
|
return 0;
|
2012-05-15 05:27:56 -07:00
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-17 00:50:03 -07:00
|
|
|
/* FIXME: This could create a huge alloc. So
|
|
|
|
compressed data and tile could not always work.*/
|
|
|
|
out = emile_binbuf_uncompress(in,
|
|
|
|
eet_2_emile_compressor(comp),
|
|
|
|
w * h * 4);
|
|
|
|
eina_binbuf_free(in);
|
|
|
|
if (!out) return 0;
|
|
|
|
|
|
|
|
_eet_data_image_copy_buffer((const unsigned int *) eina_binbuf_string_get(out),
|
|
|
|
src_x, src_y, src_w, d,
|
|
|
|
w, h, row_stride);
|
|
|
|
|
|
|
|
eina_binbuf_free(out);
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
}
|
2015-03-17 00:50:03 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
/* Fix swapiness. */
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(d, w * h);
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2014-03-18 02:11:49 -07:00
|
|
|
else if (comp == 0 && lossy == EET_IMAGE_JPEG)
|
2005-05-07 09:46:26 -07:00
|
|
|
{
|
2010-07-27 18:45:57 -07:00
|
|
|
if (alpha)
|
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned const char *dt;
|
2010-07-27 18:45:57 -07:00
|
|
|
int header[8];
|
|
|
|
int sz1, sz2;
|
|
|
|
|
|
|
|
memcpy(header, data, 32);
|
2015-01-06 02:09:27 -08:00
|
|
|
_eet_image_endian_swap(header, 8);
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
sz1 = header[1];
|
|
|
|
sz2 = header[2];
|
2015-01-14 01:11:22 -08:00
|
|
|
if ((sz1 <= 0) || (sz2 <= 0) || ((sz1 + sz2) > (size - 12)))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2010-07-27 18:45:57 -07:00
|
|
|
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))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!eet_data_image_jpeg_rgb_decode(data, size, src_x, src_y, d, w,
|
|
|
|
h, row_stride))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2014-06-13 00:56:39 -07:00
|
|
|
else if ((lossy == EET_IMAGE_ETC1) ||
|
|
|
|
(lossy == EET_IMAGE_ETC2_RGB) ||
|
2014-07-10 23:15:52 -07:00
|
|
|
(lossy == EET_IMAGE_ETC2_RGBA) ||
|
|
|
|
(lossy == EET_IMAGE_ETC1_ALPHA))
|
2014-03-18 02:11:49 -07:00
|
|
|
{
|
2014-06-13 00:56:39 -07:00
|
|
|
return eet_data_image_etc2_decode(data, size, d,
|
2014-03-18 02:11:49 -07:00
|
|
|
src_x, src_y, src_w, src_h,
|
2014-06-13 00:56:39 -07:00
|
|
|
alpha, cspace, lossy);
|
2014-03-18 02:11:49 -07:00
|
|
|
}
|
2005-05-07 09:46:26 -07:00
|
|
|
else
|
2011-10-20 22:40:01 -07:00
|
|
|
abort();
|
2005-05-22 21:32:04 -07:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
return 1;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_decode_cipher(const void *data,
|
|
|
|
const char *cipher_key,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
2010-07-31 11:54:54 -07:00
|
|
|
unsigned int *d = NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
unsigned int iw, ih;
|
2014-03-18 02:11:49 -07:00
|
|
|
int ialpha, icompress, iquality;
|
|
|
|
Eet_Image_Encoding ilossy;
|
2010-07-31 11:54:54 -07:00
|
|
|
void *deciphered_d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
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-07-27 18:45:57 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
|
|
|
|
&deciphered_d, &deciphered_sz))
|
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (deciphered_d)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(deciphered_d);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
/* All check are done during header decode, this simplify the code a lot. */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress,
|
|
|
|
&iquality, &ilossy))
|
2011-10-20 22:40:01 -07:00
|
|
|
return NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
d = malloc(iw * ih * 4);
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!d)
|
2011-10-20 22:40:01 -07:00
|
|
|
return NULL;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!_eet_data_image_decode_inside(data, size, 0, 0, iw, ih, d, iw, ih, iw *
|
2014-03-28 00:05:45 -07:00
|
|
|
4, ialpha, icompress, iquality, ilossy,
|
|
|
|
EET_COLORSPACE_ARGB8888))
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
free(d);
|
2010-07-27 18:45:57 -07:00
|
|
|
return NULL;
|
2005-05-07 09:46:26 -07:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (w)
|
2011-10-20 22:40:01 -07:00
|
|
|
*w = iw;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (h)
|
2011-10-20 22:40:01 -07:00
|
|
|
*h = ih;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (alpha)
|
2011-10-20 22:40:01 -07:00
|
|
|
*alpha = ialpha;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
*comp = icompress;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (quality)
|
2011-10-20 22:40:01 -07:00
|
|
|
*quality = iquality;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (lossy)
|
2011-10-20 22:40:01 -07:00
|
|
|
*lossy = ilossy;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2005-05-07 09:46:26 -07:00
|
|
|
return d;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI void *
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_decode(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int *w,
|
|
|
|
unsigned int *h,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_decode_cipher(data, NULL, size, w, h,
|
|
|
|
alpha, comp, quality, lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2008-06-02 09:01:18 -07:00
|
|
|
EAPI int
|
2014-03-28 00:05:45 -07:00
|
|
|
eet_data_image_decode_to_cspace_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,
|
|
|
|
Eet_Colorspace cspace,
|
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
|
|
|
Eet_Image_Encoding *lossy)
|
2008-06-02 09:01:18 -07:00
|
|
|
{
|
|
|
|
unsigned int iw, ih;
|
2014-03-18 02:11:49 -07:00
|
|
|
int ialpha, icompress, iquality;
|
|
|
|
Eet_Image_Encoding ilossy;
|
2010-07-31 11:54:54 -07:00
|
|
|
void *deciphered_d = NULL;
|
2008-11-13 08:31:13 -08:00
|
|
|
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-07-27 18:45:57 -07:00
|
|
|
if (!eet_decipher(data, size, cipher_key, strlen(cipher_key),
|
|
|
|
&deciphered_d, &deciphered_sz))
|
|
|
|
{
|
|
|
|
data = deciphered_d;
|
|
|
|
size = deciphered_sz;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (deciphered_d)
|
2011-10-20 22:40:01 -07:00
|
|
|
free(deciphered_d);
|
2008-11-13 08:31:13 -08:00
|
|
|
}
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
/* All check are done during header decode, this simplify the code a lot. */
|
2010-07-27 18:45:57 -07:00
|
|
|
if (!eet_data_image_header_decode(data, size, &iw, &ih, &ialpha, &icompress,
|
|
|
|
&iquality, &ilossy))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (!d)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
if (cspace == EET_COLORSPACE_ETC1 &&
|
|
|
|
ilossy != EET_IMAGE_ETC1)
|
|
|
|
return 0;
|
|
|
|
|
2014-06-13 00:56:39 -07:00
|
|
|
if (cspace == EET_COLORSPACE_RGB8_ETC2 &&
|
|
|
|
ilossy != EET_IMAGE_ETC2_RGB)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (cspace == EET_COLORSPACE_RGBA8_ETC2_EAC &&
|
|
|
|
ilossy != EET_IMAGE_ETC2_RGBA)
|
|
|
|
return 0;
|
|
|
|
|
2014-07-10 23:15:52 -07:00
|
|
|
if (cspace == EET_COLORSPACE_ETC1_ALPHA &&
|
|
|
|
ilossy != EET_IMAGE_ETC1_ALPHA)
|
|
|
|
return 0;
|
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
if (cspace == EET_COLORSPACE_ARGB8888 &&
|
|
|
|
w * 4 > row_stride)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (w > iw || h > ih)
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (!_eet_data_image_decode_inside(data, size, src_x, src_y, iw, ih, d, w, h,
|
|
|
|
row_stride, ialpha, icompress, iquality,
|
2014-03-28 00:05:45 -07:00
|
|
|
ilossy, cspace))
|
2011-10-20 22:40:01 -07:00
|
|
|
return 0;
|
2010-07-27 18:45:57 -07:00
|
|
|
|
|
|
|
if (alpha)
|
2011-10-20 22:40:01 -07:00
|
|
|
*alpha = ialpha;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (comp)
|
2011-10-20 22:40:01 -07:00
|
|
|
*comp = icompress;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (quality)
|
2011-10-20 22:40:01 -07:00
|
|
|
*quality = iquality;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
2010-07-27 18:45:57 -07:00
|
|
|
if (lossy)
|
2011-10-20 22:40:01 -07:00
|
|
|
*lossy = ilossy;
|
2008-06-02 09:01:18 -07:00
|
|
|
|
|
|
|
return 1;
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2008-11-13 08:31:13 -08:00
|
|
|
|
2014-03-28 00:05:45 -07:00
|
|
|
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,
|
|
|
|
Eet_Image_Encoding *lossy)
|
|
|
|
{
|
|
|
|
return eet_data_image_decode_to_cspace_surface_cipher(data, cipher_key, size, src_x, src_y, d, w, h, row_stride, EET_COLORSPACE_ARGB8888, alpha, comp, quality, lossy);
|
|
|
|
}
|
|
|
|
|
2008-11-13 08:31:13 -08:00
|
|
|
EAPI int
|
2010-07-31 11:57:35 -07:00
|
|
|
eet_data_image_decode_to_surface(const void *data,
|
2010-07-31 11:54:54 -07:00
|
|
|
int size,
|
|
|
|
unsigned int src_x,
|
|
|
|
unsigned int src_y,
|
|
|
|
unsigned int *d,
|
|
|
|
unsigned int w,
|
|
|
|
unsigned int h,
|
|
|
|
unsigned int row_stride,
|
2010-07-31 11:57:35 -07:00
|
|
|
int *alpha,
|
|
|
|
int *comp,
|
|
|
|
int *quality,
|
2014-03-18 02:11:49 -07:00
|
|
|
Eet_Image_Encoding *lossy)
|
2008-11-13 08:31:13 -08:00
|
|
|
{
|
2010-07-30 18:54:48 -07:00
|
|
|
return eet_data_image_decode_to_surface_cipher(data, NULL, size,
|
2011-10-20 22:40:01 -07:00
|
|
|
src_x, src_y, d,
|
|
|
|
w, h, row_stride,
|
2010-07-30 18:54:48 -07:00
|
|
|
alpha, comp, quality,
|
2010-07-27 18:45:57 -07:00
|
|
|
lossy);
|
2011-12-02 06:42:13 -08:00
|
|
|
}
|
2010-07-30 18:54:48 -07:00
|
|
|
|