forked from enlightenment/efl
eet: use Emile to decode TGV image section.
This commit is contained in:
parent
a865d41181
commit
f9125499f9
|
@ -96,8 +96,9 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <Eina.h>
|
|
||||||
#include <Efl_Config.h>
|
#include <Efl_Config.h>
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <Emile.h>
|
||||||
|
|
||||||
#ifdef EAPI
|
#ifdef EAPI
|
||||||
# undef EAPI
|
# undef EAPI
|
||||||
|
@ -491,15 +492,13 @@ typedef enum _Eet_Image_Encoding
|
||||||
EET_IMAGE_ETC1_ALPHA = 5,
|
EET_IMAGE_ETC1_ALPHA = 5,
|
||||||
} Eet_Image_Encoding;
|
} Eet_Image_Encoding;
|
||||||
|
|
||||||
typedef enum _Eet_Colorspace
|
typedef Emile_Colorspace Eet_Colorspace;
|
||||||
{
|
|
||||||
EET_COLORSPACE_ARGB8888 = 0,
|
#define EET_COLORSPACE_ARGB8888 EMILE_COLORSPACE_ARGB8888
|
||||||
/* The number between are reserved to preserve compatibility with evas */
|
#define EET_COLORSPACE_ETC1 EMILE_COLORSPACE_ETC1
|
||||||
EET_COLORSPACE_ETC1 = 9,
|
#define EET_COLORSPACE_RGB8_ETC2 EMILE_COLORSPACE_RGB8_ETC2
|
||||||
EET_COLORSPACE_RGB8_ETC2 = 10,
|
#define EET_COLORSPACE_RGBA8_ETC2_EAC EMILE_COLORSPACE_RGBA8_ETC2_EAC
|
||||||
EET_COLORSPACE_RGBA8_ETC2_EAC = 11,
|
#define EET_COLORSPACE_ETC1_ALPHA EMILE_COLORSPACE_ETC1_ALPHA
|
||||||
EET_COLORSPACE_ETC1_ALPHA = 12
|
|
||||||
} Eet_Colorspace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef Eet_File
|
* @typedef Eet_File
|
||||||
|
|
|
@ -775,36 +775,6 @@ _eet_argb_unpremul(unsigned int *data, unsigned int len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
roundup(int val, int rup)
|
|
||||||
{
|
|
||||||
if (val >= 0 && rup > 0)
|
|
||||||
return (val + rup - 1) - ((val + rup - 1) % rup);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
eet_data_image_etc2_decode(const void *data,
|
eet_data_image_etc2_decode(const void *data,
|
||||||
unsigned int length,
|
unsigned int length,
|
||||||
|
@ -817,266 +787,71 @@ eet_data_image_etc2_decode(const void *data,
|
||||||
Eet_Colorspace cspace,
|
Eet_Colorspace cspace,
|
||||||
Eet_Image_Encoding lossy)
|
Eet_Image_Encoding lossy)
|
||||||
{
|
{
|
||||||
const char *m = NULL;
|
Emile_Image_Load_Opts opts;
|
||||||
unsigned int bwidth, bheight;
|
Emile_Image_Property prop;
|
||||||
unsigned char *p_etc;
|
Emile_Image *image;
|
||||||
Eina_Binbuf *buffer = NULL;
|
Eina_Binbuf *bin;
|
||||||
Eina_Rectangle master;
|
Emile_Image_Load_Error error;
|
||||||
unsigned int block_length;
|
int i;
|
||||||
unsigned int offset;
|
|
||||||
unsigned int x, y, w, h;
|
|
||||||
unsigned int block_count;
|
|
||||||
unsigned int etc_width = 0;
|
|
||||||
unsigned int etc_block_size;
|
|
||||||
unsigned int num_planes = 1, plane, alpha_offset = 0;
|
|
||||||
Eet_Colorspace file_cspace;
|
|
||||||
Eina_Bool compress, blockless, unpremul;
|
|
||||||
|
|
||||||
m = data;
|
|
||||||
|
|
||||||
// Fix for ABI incompatibility between 1.10 and 1.11
|
// Fix for ABI incompatibility between 1.10 and 1.11
|
||||||
if (cspace == 8) cspace = 9;
|
if (cspace == 8) cspace = 9;
|
||||||
|
|
||||||
if (strncmp(m, "TGV1", 4) != 0)
|
bin = eina_binbuf_manage_read_only_new_length(data, length);
|
||||||
|
if (!bin) return 0;
|
||||||
|
|
||||||
|
opts.region.x = dst_x;
|
||||||
|
opts.region.y = dst_y;
|
||||||
|
opts.region.w = dst_w;
|
||||||
|
opts.region.h = dst_h;
|
||||||
|
|
||||||
|
image = emile_image_tgv_memory_open(bin, &opts, NULL, &error);
|
||||||
|
if (!image) return 0;
|
||||||
|
|
||||||
|
memset(&prop, sizeof (prop), 0);
|
||||||
|
|
||||||
|
if (!emile_image_head(image, &prop, sizeof (Emile_Image_Load_Opts), &error))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
compress = m[OFFSET_OPTIONS] & 0x1;
|
for (i = 0; prop.cspaces[i] != EMILE_COLORSPACE_ARGB8888; i++)
|
||||||
blockless = (m[OFFSET_OPTIONS] & 0x2) != 0;
|
|
||||||
unpremul = (m[OFFSET_OPTIONS] & 0x4) != 0;
|
|
||||||
w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
|
|
||||||
h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
|
|
||||||
|
|
||||||
switch (m[OFFSET_ALGORITHM] & 0xFF)
|
|
||||||
{
|
{
|
||||||
case 0:
|
if (prop.cspaces[i] == cspace) break;
|
||||||
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;
|
|
||||||
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);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
etc_width = ((w + 2 + 3) / 4) * etc_block_size;
|
|
||||||
|
|
||||||
if (cspace != EET_COLORSPACE_ARGB8888 && cspace != file_cspace)
|
|
||||||
{
|
|
||||||
if (!((cspace == EET_COLORSPACE_RGB8_ETC2) && (file_cspace == EET_COLORSPACE_ETC1)))
|
|
||||||
return 0;
|
|
||||||
// else: ETC2 is compatible with ETC1 and is preferred
|
|
||||||
}
|
|
||||||
|
|
||||||
if (blockless)
|
|
||||||
{
|
|
||||||
bwidth = roundup(w + 2, 4);
|
|
||||||
bheight = roundup(h + 2, 4);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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)
|
switch (cspace)
|
||||||
{
|
{
|
||||||
case EET_COLORSPACE_ETC1:
|
case EMILE_COLORSPACE_ETC1:
|
||||||
case EET_COLORSPACE_RGB8_ETC2:
|
if (lossy != EET_IMAGE_ETC1) return 0;
|
||||||
case EET_COLORSPACE_RGBA8_ETC2_EAC:
|
if (alpha != EINA_FALSE) return 0;
|
||||||
case EET_COLORSPACE_ETC1_ALPHA:
|
break;
|
||||||
if (master.x % 4 || master.y % 4)
|
case EMILE_COLORSPACE_RGB8_ETC2:
|
||||||
abort();
|
if (lossy != EET_IMAGE_ETC2_RGB) return 0;
|
||||||
break;
|
if (alpha != EINA_FALSE) return 0;
|
||||||
|
break;
|
||||||
|
case EMILE_COLORSPACE_RGBA8_ETC2_EAC:
|
||||||
|
if (lossy != EET_IMAGE_ETC2_RGBA) return 0;
|
||||||
|
if (alpha != EINA_TRUE) return 0;
|
||||||
|
break;
|
||||||
|
case EMILE_COLORSPACE_ETC1_ALPHA:
|
||||||
|
if (lossy != EET_IMAGE_ETC1_ALPHA) return 0;
|
||||||
|
if (alpha != EINA_TRUE) return 0;
|
||||||
|
break;
|
||||||
case EET_COLORSPACE_ARGB8888:
|
case EET_COLORSPACE_ARGB8888:
|
||||||
// Offset to take duplicated pixels into account
|
break;
|
||||||
master.x += 1;
|
default:
|
||||||
master.y += 1;
|
return 0;
|
||||||
break;
|
|
||||||
default: abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p_etc = (unsigned char*) p;
|
prop.cspace = cspace;
|
||||||
offset = OFFSET_BLOCKS;
|
|
||||||
|
|
||||||
// Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group)
|
if (!emile_image_data(image, &prop, sizeof (Emile_Image_Load_Opts), p, &error))
|
||||||
block_count = bwidth * bheight / (4 * 4);
|
return 0;
|
||||||
if (compress)
|
|
||||||
buffer = eina_binbuf_manage_read_only_new_length(alloca(etc_block_size * block_count), etc_block_size * block_count);
|
|
||||||
|
|
||||||
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;
|
|
||||||
Eina_Binbuf *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 = eina_binbuf_manage_read_only_new_length(m + offset, block_length);
|
|
||||||
offset += block_length;
|
|
||||||
|
|
||||||
EINA_RECTANGLE_SET(¤t, x, y,
|
|
||||||
bwidth, bheight);
|
|
||||||
|
|
||||||
if (!eina_rectangle_intersection(¤t, &master))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (compress)
|
|
||||||
{
|
|
||||||
if (!emile_binbuf_expand(data_start, buffer, EMILE_LZ4HC))
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer = data_start;
|
|
||||||
if (block_count * etc_block_size != block_length)
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
it = eina_binbuf_string_get(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
|
|
||||||
|
|
||||||
eina_binbuf_free(data_start);
|
|
||||||
} // x,y macroblocks
|
|
||||||
|
|
||||||
if (compress) eina_binbuf_free(buffer);
|
|
||||||
|
|
||||||
// TODO: Add support for more unpremultiplied modes (ETC2)
|
// TODO: Add support for more unpremultiplied modes (ETC2)
|
||||||
if ((cspace == EET_COLORSPACE_ARGB8888) && unpremul)
|
if ((cspace == EET_COLORSPACE_ARGB8888) && !prop.premul)
|
||||||
_eet_argb_premul(p, w * h);
|
_eet_argb_premul(p, prop.w * prop.h);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
on_error:
|
|
||||||
ERR("ETC image data is corrupted in this EET file");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
|
@ -2145,6 +1920,7 @@ eet_data_image_header_decode_cipher(const void *data,
|
||||||
{
|
{
|
||||||
const char *m = data;
|
const char *m = data;
|
||||||
|
|
||||||
|
// We only use Emile for decoding the actual data, seems simpler this way.
|
||||||
if (w) *w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
|
if (w) *w = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
|
||||||
if (h) *h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
|
if (h) *h = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
|
||||||
if (comp) *comp = m[OFFSET_OPTIONS] & 0x1;
|
if (comp) *comp = m[OFFSET_OPTIONS] & 0x1;
|
||||||
|
@ -2306,7 +2082,7 @@ _eet_data_image_decode_inside(const void *data,
|
||||||
unsigned int src_x,
|
unsigned int src_x,
|
||||||
unsigned int src_y,
|
unsigned int src_y,
|
||||||
unsigned int src_w,
|
unsigned int src_w,
|
||||||
EINA_UNUSED unsigned int src_h, /* useful for fast path detection */
|
unsigned int src_h, /* useful for fast path detection */
|
||||||
unsigned int *d,
|
unsigned int *d,
|
||||||
unsigned int w,
|
unsigned int w,
|
||||||
unsigned int h,
|
unsigned int h,
|
||||||
|
|
Loading…
Reference in New Issue