evas: use Emile to decode TGV.
authorCedric BAIL <cedric@osg.samsung.com>
Tue, 17 Mar 2015 07:50:16 +0000 (08:50 +0100)
committerCedric BAIL <cedric@osg.samsung.com>
Tue, 17 Mar 2015 08:58:18 +0000 (09:58 +0100)
configure.ac
doc/previews/Makefile.am
m4/efl.m4
src/Makefile_Evas.am
src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c

index 5df945c0419597756a13352777e9d5bcf75a341a..6b0b799214e6939028c1d277d312f5b419d94b22 100644 (file)
@@ -1673,6 +1673,7 @@ EFL_INTERNAL_DEPEND_PKG([EVAS], [eo])
 EFL_INTERNAL_DEPEND_PKG([EVAS], [eet])
 EFL_INTERNAL_DEPEND_PKG([EVAS], [eina])
 EFL_INTERNAL_DEPEND_PKG([EVAS], [efl])
+EFL_INTERNAL_DEPEND_PKG([EVAS], [emile])
 
 EFL_ADD_LIBS([EVAS], [-lm])
 
index ea0d30789c18d9a3dbd7889bca020beb5a8fa12b..7b3a87e94398ce2da964af83329197d5b5dfe85b 100644 (file)
@@ -23,7 +23,7 @@ AM_CPPFLAGS = \
 -I$(top_builddir)/src/lib/ecore_evas \
 -DEFL_BETA_API_SUPPORT=1 \
 -DEFL_EO_API_SUPPORT=1 \
-@ECORE_EVAS_LDFLAGS@
+@ECORE_EVAS_CFLAGS@
 
 LDADD = \
 $(top_builddir)/src/lib/eina/libeina.la \
index 3598ce78fe1140c15c3608ce0129d575cd171873..3d654c92682c05dd3b5cb3fb0717743b53f5d680 100644 (file)
--- a/m4/efl.m4
+++ b/m4/efl.m4
@@ -152,7 +152,7 @@ case "m4_defn([DOWNOTHER])" in
       ;;
 esac
 requirements_pc_[]m4_defn([DOWNEFL])="${depname} >= ${PACKAGE_VERSION} ${requirements_pc_[][]m4_defn([DOWNEFL])}"
-requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNEFL])}"
+requirements_cflags_[]m4_defn([DOWNEFL])="-I\$(top_srcdir)/src/lib/${libdirname} -I\$(top_builddir)/src/lib/${libdirname} ${requirements_cflags_[][]m4_defn([DOWNOTHER])} ${requirements_cflags_[][]m4_defn([DOWNEFL])}"
 requirements_internal_libs_[]m4_defn([DOWNEFL])="lib/${libdirname}/lib${libname}.la ${requirements_internal_libs_[][]m4_defn([DOWNEFL])}"
 requirements_internal_deps_libs_[]m4_defn([DOWNEFL])="${requirements_public_libs_[]m4_defn([DOWNOTHER])} ${requirements_internal_deps_libs_[][]m4_defn([DOWNEFL])}"
 m4_popdef([DOWNOTHER])dnl
index d8c6edec1da5da41b56bf4e0284fce8b6de897c7..cb79b49c4017657f92859798311c7e911afb6fc9 100644 (file)
@@ -1343,7 +1343,7 @@ bin/evas/evas_cserve2_client.c
 bin_evas_evas_cserve2_client_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
-@EINA_CFLAGS@
+@EVAS_CFLAGS@
 bin_evas_evas_cserve2_client_LDADD = @USE_EINA_LIBS@
 bin_evas_evas_cserve2_client_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
 
@@ -1352,7 +1352,7 @@ bin/evas/evas_cserve2_usage.c
 bin_evas_evas_cserve2_usage_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
-@EINA_CFLAGS@
+@EVAS_CFLAGS@
 bin_evas_evas_cserve2_usage_LDADD = @USE_EINA_LIBS@
 bin_evas_evas_cserve2_usage_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
 
@@ -1361,7 +1361,7 @@ bin/evas/evas_cserve2_debug.c
 bin_evas_evas_cserve2_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
-@EINA_CFLAGS@
+@EVAS_CFLAGS@
 bin_evas_evas_cserve2_debug_LDADD = @USE_EINA_LIBS@
 bin_evas_evas_cserve2_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
 
@@ -1370,7 +1370,7 @@ bin/evas/evas_cserve2_shm_debug.c
 bin_evas_evas_cserve2_shm_debug_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
-@EINA_CFLAGS@
+@EVAS_CFLAGS@
 bin_evas_evas_cserve2_shm_debug_LDADD = @USE_EINA_LIBS@
 bin_evas_evas_cserve2_shm_debug_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@
 
index b715017831b8d09d5b423877da15b5e16b16adff..0b9c65cec51a9400f75c70bd22358d7ae8d18fa1 100644 (file)
@@ -2,77 +2,14 @@
 # include "config.h"
 #endif
 
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
-#ifdef _WIN32
-# include <winsock2.h>
-#endif /* ifdef _WIN32 */
-
-#ifdef ENABLE_LIBLZ4
-# include <lz4.h>
-#else
-# include "lz4.h"
-#endif
+#include <Emile.h>
 
-#include "rg_etc1.h"
 #include "Evas_Loader.h"
 
-#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
-
-/**************************************************************
- * The TGV file format is oriented around compression mecanism
- * that hardware are good at decompressing. We do still provide
- * a fully software implementation in case your hardware doesn't
- * handle it. As OpenGL is pretty bad at handling border of
- * texture, we do duplicate the first pixels of every border.
- *
- * This file format is designed to compress/decompress things
- * in block area. Giving opportunity to store really huge file
- * and only decompress/compress them as we need. Note that region
- * only work with software decompression as we don't have a sane
- * way to duplicate border to avoid artifact when scaling texture.
- *
- * The file format is as follow :
- * - char     magic[4]: "TGV1"
- * - uint8_t  block_size (real block size = (4 << bits[0-3], 4 << bits[4-7])
- * - uint8_t  algorithm (0 -> ETC1, 1 -> ETC2 RGB, 2 -> ETC2 RGBA, 3 -> ETC1+Alpha)
- * - uint8_t  options[2] (bitmask: 1 -> lz4, 2 for block-less, 4 -> unpremultiplied)
- * - uint32_t width
- * - uint32_t height
- * - blocks[]
- *   - 0 length encoded compress size (if length == 64 * block_size => no compression)
- *   - lzma encoded etc1 block
- *
- * If the format is ETC1+Alpha (algo = 3), then a second image is encoded
- * in ETC1 right after the first one, and it contains grey-scale alpha
- * values.
- **************************************************************/
-
-// FIXME: wondering if we should support mipmap
-// TODO: support ETC1+ETC2 images (RGB only)
-
 typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
 struct _Evas_Loader_Internal
 {
-   Eina_File *f;
+   Emile_Image *image;
 
    Eina_Rectangle region;
 
@@ -92,26 +29,6 @@ struct _Evas_Loader_Internal
    Eina_Bool unpremul : 1;
 };
 
-static const Evas_Colorspace cspaces_etc1[2] = {
-  EVAS_COLORSPACE_ETC1,
-  EVAS_COLORSPACE_ARGB8888
-};
-
-static const Evas_Colorspace cspaces_rgb8_etc2[2] = {
-  EVAS_COLORSPACE_RGB8_ETC2,
-  EVAS_COLORSPACE_ARGB8888
-};
-
-static const Evas_Colorspace cspaces_rgba8_etc2_eac[2] = {
-  EVAS_COLORSPACE_RGBA8_ETC2_EAC,
-  EVAS_COLORSPACE_ARGB8888
-};
-
-static const Evas_Colorspace cspaces_etc1_alpha[2] = {
-  EVAS_COLORSPACE_ETC1_ALPHA,
-  EVAS_COLORSPACE_ARGB8888
-};
-
 static void *
 evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
                               Evas_Image_Load_Opts *opts,
@@ -119,10 +36,13 @@ evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
                               int *error)
 {
    Evas_Loader_Internal *loader;
+   Emile_Image *image;
+   Emile_Image_Load_Error image_error;
 
-   if (eina_file_size_get(f) <= 16)
+   image = emile_image_tgv_file_open(f, opts, NULL, &image_error);
+   if (!image)
      {
-        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+        *error = image_error;
         return NULL;
      }
 
@@ -133,14 +53,7 @@ evas_image_load_file_open_tgv(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
         return NULL;
      }
 
-   loader->f = eina_file_dup(f);
-   if (!loader->f)
-     {
-        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
-        free(loader);
-        return NULL;
-     }
-
+   loader->image = image;
    if (opts && (opts->region.w > 0) && (opts->region.h > 0))
      {
         EINA_RECTANGLE_SET(&loader->region,
@@ -165,149 +78,27 @@ evas_image_load_file_close_tgv(void *loader_data)
 {
    Evas_Loader_Internal *loader = loader_data;
 
-   eina_file_close(loader->f);
+   emile_image_close(loader->image);
    free(loader);
 }
 
-static int
-roundup(int val, int rup)
-{
-   if (val >= 0 && rup > 0)
-     return (val + rup - 1) - ((val + rup - 1) % rup);
-   return 0;
-}
-
-#define OFFSET_BLOCK_SIZE 4
-#define OFFSET_ALGORITHM 5
-#define OFFSET_OPTIONS 6
-#define OFFSET_WIDTH 8
-#define OFFSET_HEIGHT 12
-#define OFFSET_BLOCKS 16
-
 static Eina_Bool
 evas_image_load_file_head_tgv(void *loader_data,
                               Evas_Image_Property *prop,
                               int *error)
 {
    Evas_Loader_Internal *loader = loader_data;
-   Eina_Bool ret = EINA_FALSE;
-   char *m;
-
-   m = eina_file_map_all(loader->f, EINA_FILE_SEQUENTIAL);
-   if (!m)
-     {
-        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-        return EINA_FALSE;
-     }
-
-   if (strncmp(m, "TGV1", 4) != 0)
-     {
-        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-        goto on_error;
-     }
-
-   switch (m[OFFSET_ALGORITHM] & 0xFF)
-     {
-      case 0:
-        prop->cspaces = cspaces_etc1;
-        loader->cspace = EVAS_COLORSPACE_ETC1;
-        prop->alpha = EINA_FALSE;
-        break;
-      case 1:
-        prop->cspaces = cspaces_rgb8_etc2;
-        loader->cspace = EVAS_COLORSPACE_RGB8_ETC2;
-        prop->alpha = EINA_FALSE;
-        break;
-      case 2:
-        prop->cspaces = cspaces_rgba8_etc2_eac;
-        loader->cspace = EVAS_COLORSPACE_RGBA8_ETC2_EAC;
-        prop->alpha = EINA_TRUE;
-        break;
-      case 3:
-        prop->cspaces = cspaces_etc1_alpha;
-        loader->cspace = EVAS_COLORSPACE_ETC1_ALPHA;
-        loader->unpremul = !!(m[OFFSET_OPTIONS] & 0x4);
-        prop->alpha = EINA_TRUE;
-        prop->premul = loader->unpremul;
-        break;
-      default:
-        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-        goto on_error;
-     }
-
-   loader->compress = m[OFFSET_OPTIONS] & 0x1;
-   loader->blockless = (m[OFFSET_OPTIONS] & 0x2) != 0;
-
-   loader->size.width = ntohl(*((unsigned int*) &(m[OFFSET_WIDTH])));
-   loader->size.height = ntohl(*((unsigned int*) &(m[OFFSET_HEIGHT])));
+   Emile_Image_Load_Error image_error;
+   Eina_Bool ret;
 
-   if (loader->blockless)
-     {
-        loader->block.width = roundup(loader->size.width + 2, 4);
-        loader->block.height = roundup(loader->size.height + 2, 4);
-     }
-   else
-     {
-        loader->block.width = 4 << (m[OFFSET_BLOCK_SIZE] & 0x0f);
-        loader->block.height = 4 << ((m[OFFSET_BLOCK_SIZE] & 0xf0) >> 4);
-     }
+   ret = emile_image_head(loader->image,
+                          prop, sizeof (Emile_Image_Property),
+                          &image_error);
+   *error = image_error;
 
-   if (loader->region.w == -1 && loader->region.h == -1)
-     {
-        loader->region.w = loader->size.width;
-        loader->region.h = loader->size.height;
-     }
-   else
-     {
-        Eina_Rectangle r;
-
-        // ETC1 colorspace doesn't work with region
-        prop->cspaces = NULL;
-
-        EINA_RECTANGLE_SET(&r, 0, 0, loader->size.width, loader->size.height);
-        if (!eina_rectangle_intersection(&loader->region, &r))
-          {
-             *error = EVAS_LOAD_ERROR_GENERIC;
-             goto on_error;
-          }
-     }
-
-   prop->w = loader->size.width;
-   prop->h = loader->size.height;
-   prop->borders.l = 1;
-   prop->borders.t = 1;
-   prop->borders.r = roundup(prop->w + 2, 4) - prop->w - 1;
-   prop->borders.b = roundup(prop->h + 2, 4) - prop->h - 1;
-
-   ret = EINA_TRUE;
-
-on_error:
-   eina_file_map_free(loader->f, m);
    return ret;
 }
 
-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;
-}
-
 Eina_Bool
 evas_image_load_file_data_tgv(void *loader_data,
                               Evas_Image_Property *prop,
@@ -315,234 +106,15 @@ evas_image_load_file_data_tgv(void *loader_data,
                               int *error)
 {
    Evas_Loader_Internal *loader = loader_data;
-   const char *m;
-   unsigned int *p = pixels;
-   unsigned char *p_etc = pixels;
-   char *buffer = NULL;
-   Eina_Rectangle master;
-   unsigned int block_length;
-   unsigned int length, offset;
-   unsigned int x, y;
-   unsigned int block_count;
-   unsigned int etc_width = 0;
-   unsigned int etc_block_size;
-   Eina_Bool r = EINA_FALSE;
-   int num_planes = 1, plane, alpha_offset = 0;
-
-   length = eina_file_size_get(loader->f);
-   offset = OFFSET_BLOCKS;
-
-   *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
-
-   m = eina_file_map_all(loader->f, EINA_FILE_WILLNEED);
-   if (!m) return EINA_FALSE;
-
-   // By definition, prop{.w, .h} == region{.w, .h}
-   EINA_RECTANGLE_SET(&master,
-                      loader->region.x, loader->region.y,
-                      prop->w, prop->h);
-
-   switch (loader->cspace)
-     {
-      case EVAS_COLORSPACE_ETC1:
-      case EVAS_COLORSPACE_RGB8_ETC2:
-        etc_block_size = 8;
-        break;
-      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
-        etc_block_size = 16;
-        break;
-      case EVAS_COLORSPACE_ETC1_ALPHA:
-        etc_block_size = 8;
-        num_planes = 2;
-        alpha_offset = ((prop->w + 2 + 3) / 4) * ((prop->h + 2 + 3) / 4) * 8 / sizeof(*p_etc);
-        break;
-      default: abort();
-     }
-   etc_width = ((prop->w + 2 + 3) / 4) * etc_block_size;
-
-   switch (prop->cspace)
-     {
-      case EVAS_COLORSPACE_ETC1:
-      case EVAS_COLORSPACE_RGB8_ETC2:
-      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
-      case EVAS_COLORSPACE_ETC1_ALPHA:
-        if (master.x % 4 || master.y % 4)
-          abort();
-        break;
-      case EVAS_COLORSPACE_ARGB8888:
-        // Offset to take duplicated pixels into account
-        master.x += 1;
-        master.y += 1;
-        break;
-      default: abort();
-     }
-
-   if (prop->cspace != EVAS_COLORSPACE_ARGB8888 && prop->cspace != loader->cspace)
-     {
-        if (!((prop->cspace == EVAS_COLORSPACE_RGB8_ETC2) &&
-              (loader->cspace == EVAS_COLORSPACE_ETC1)))
-          goto on_error;
-        // else: ETC2 is compatible with ETC1 and is preferred
-     }
-
-   // Allocate space for each ETC block (8 or 16 bytes per 4 * 4 pixels group)
-   block_count = loader->block.width * loader->block.height / (4 * 4);
-   if (loader->compress)
-     buffer = alloca(etc_block_size * block_count);
-
-   for (plane = 0; plane < num_planes; plane++)
-     for (y = 0; y < loader->size.height + 2; y += loader->block.height)
-       for (x = 0; x < loader->size.width + 2; x += loader->block.width)
-         {
-            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(&current, x, y,
-                               loader->block.width, loader->block.height);
-
-            if (!eina_rectangle_intersection(&current, &master))
-              continue;
-
-            if (loader->compress)
-              {
-                 expand_length = LZ4_decompress_fast(data_start, buffer,
-                                                     block_count * etc_block_size);
-                 // That's an overhead for now, need to be fixed
-                 if (expand_length != block_length)
-                   goto on_error;
-              }
-            else
-              {
-                 buffer = (void*) data_start;
-                 if (block_count * etc_block_size != block_length)
-                   goto on_error;
-              }
-            it = buffer;
-
-            for (i = 0; i < loader->block.height; i += 4)
-              for (j = 0; j < loader->block.width; 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(&current_etc, x + j, y + i, 4, 4);
-
-                   if (!eina_rectangle_intersection(&current_etc, &current))
-                     continue;
-
-                   switch (prop->cspace)
-                     {
-                      case EVAS_COLORSPACE_ARGB8888:
-                        switch (loader->cspace)
-                          {
-                           case EVAS_COLORSPACE_ETC1:
-                           case EVAS_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 EVAS_COLORSPACE_RGB8_ETC2:
-                             rg_etc2_rgb8_decode_block((uint8_t *) it, temporary);
-                             break;
-                           case EVAS_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 EVAS_COLORSPACE_ETC1:
-                      case EVAS_COLORSPACE_RGB8_ETC2:
-                      case EVAS_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 EVAS_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 (prop->cspace == EVAS_COLORSPACE_ARGB8888)
-     prop->premul = loader->unpremul; // call premul if unpremul data
-
-   r = EINA_TRUE;
-   *error = EVAS_LOAD_ERROR_NONE;
-
- on_error:
-   eina_file_map_free(loader->f, (void*) m);
-   return r;
+   Emile_Image_Load_Error image_error;
+   Eina_Bool ret;
+
+   ret = emile_image_data(loader->image,
+                          prop, sizeof (Emile_Image_Property),
+                          pixels,
+                          &image_error);
+   *error = image_error;
+   return ret;
 }
 
 Evas_Image_Load_Func evas_image_load_tgv_func =