jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=7974f674aa9ba18588576a373e1ec0c524bbde9f

commit 7974f674aa9ba18588576a373e1ec0c524bbde9f
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Oct 30 16:41:32 2015 +0900

    Evas: Allow edje_decc to work with ETC images
    
    This reuses the internal function data_get, data_put, image_save
    respecting the border information and adding support for ETC
    formats.
    
    @fix
---
 src/bin/edje/edje_decc.c                           |   2 +-
 src/lib/evas/canvas/evas_object_image.c            | 101 ++++++++++++++++++---
 src/lib/evas/common/evas_image_data.c              | 100 ++++++++++++--------
 src/lib/evas/common/evas_image_main.c              |  30 +++---
 .../evas/engines/software_generic/evas_engine.c    |  16 ++++
 .../evas/image_savers/tgv/evas_image_save_tgv.c    |  14 ++-
 6 files changed, 186 insertions(+), 77 deletions(-)

diff --git a/src/bin/edje/edje_decc.c b/src/bin/edje/edje_decc.c
index 8c0dd3c..5eeb7ef 100644
--- a/src/bin/edje/edje_decc.c
+++ b/src/bin/edje/edje_decc.c
@@ -336,7 +336,7 @@ output(void)
                    }
                  ecore_file_mkpath(pp);
                  free(pp);
-                 if (!evas_object_image_save(im, out, NULL, "quality=100 
compress=9"))
+                  if (!evas_object_image_save(im, out, NULL, "quality=100 
compress=9 encoding=auto"))
                    {
                       ERR("Cannot write file %s. Perhaps missing JPEG or PNG 
saver modules for Evas.", out);
                       exit(-1);
diff --git a/src/lib/evas/canvas/evas_object_image.c 
b/src/lib/evas/canvas/evas_object_image.c
index e174353..b4a8f19 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -1648,7 +1648,9 @@ _evas_image_efl_file_save(const Eo *eo_obj, 
Evas_Image_Data *o, const char *file
    int quality = 80, compress = 9, ok = 0;
    char *encoding = NULL;
    Image_Entry *ie;
-   Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE;
+   Eina_Bool putback = EINA_FALSE, tofree = EINA_FALSE, no_convert = 
EINA_FALSE;
+   Evas_Colorspace cspace = EVAS_COLORSPACE_ARGB8888;
+   int want_cspace = EVAS_COLORSPACE_ARGB8888;
    int imagew, imageh;
    void *pixels;
 
@@ -1698,16 +1700,9 @@ _evas_image_efl_file_save(const Eo *eo_obj, 
Evas_Image_Data *o, const char *file
         o->proxyrendering = EINA_FALSE;
      }
 
-   pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
-
-   if (!pixels)
-     {
-        WRN("Could not get image pixels.");
-        return EINA_FALSE;
-     }
-
    if (flags)
      {
+        const char *ext = NULL;
         char *p, *pp;
         char *tflags;
 
@@ -1724,23 +1719,99 @@ _evas_image_efl_file_save(const Eo *eo_obj, 
Evas_Image_Data *o, const char *file
              if (pp) p = pp + 1;
              else break;
           }
+
+        if (file) ext = strrchr(file, '.');
+        if (encoding && ext && !strcasecmp(ext, ".tgv"))
+          {
+             if (!strcmp(encoding, "auto"))
+               want_cspace = -1;
+             else if (!strcmp(encoding, "etc1"))
+               want_cspace = EVAS_COLORSPACE_ETC1;
+             else if (!strcmp(encoding, "etc2"))
+               {
+                  if (!ENFN->image_alpha_get(ENDT, pixels))
+                    want_cspace = EVAS_COLORSPACE_RGB8_ETC2;
+                  else
+                    want_cspace = EVAS_COLORSPACE_RGBA8_ETC2_EAC;
+               }
+             else if (!strcmp(encoding, "etc1+alpha"))
+               want_cspace = EVAS_COLORSPACE_ETC1_ALPHA;
+          }
+        else
+          {
+             free(encoding);
+             encoding = NULL;
+          }
+     }
+
+   if (!ENFN->image_data_has)
+     pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
+   else
+     {
+        if (ENFN->image_data_has(ENDT, pixels, &cspace))
+          {
+             if ((want_cspace != (int) cspace) && (want_cspace != -1))
+               cspace = EVAS_COLORSPACE_ARGB8888;
+          }
+        else
+          {
+             cspace = ENFN->image_file_colorspace_get(ENDT, pixels);
+             if ((want_cspace != (int) cspace) && (want_cspace != -1))
+               cspace = EVAS_COLORSPACE_ARGB8888;
+             else
+               {
+                  ENFN->image_colorspace_set(ENDT, pixels, cspace);
+                  no_convert = EINA_TRUE;
+               }
+          }
+        pixels = ENFN->image_data_get(ENDT, pixels, 0, &data, &o->load_error, 
&tofree);
+     }
+
+   if (!pixels)
+     {
+        WRN("Could not get image pixels.");
+        return EINA_FALSE;
+     }
+
+   switch (cspace)
+     {
+      case EVAS_COLORSPACE_ARGB8888:
+        break;
+      case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+      case EVAS_COLORSPACE_RGB8_ETC2:
+      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+        break;
+      default:
+        DBG("Need to convert colorspace before saving");
+        cspace = EVAS_COLORSPACE_ARGB8888;
+        break;
      }
+
    ie = evas_cache_image_data(evas_common_image_cache_get(),
-                              imagew, imageh, data, o->cur->has_alpha,
-                              EVAS_COLORSPACE_ARGB8888);
+                              imagew, imageh, data, o->cur->has_alpha, cspace);
    if (ie)
      {
         RGBA_Image *im = (RGBA_Image *) ie;
-        if (o->cur->cspace == EVAS_COLORSPACE_ARGB8888)
+        DATA32 *old_data = NULL;
+
+        // FIXME: Something is fishy here... what about the previous pointer?
+        if ((o->cur->cspace == cspace) || no_convert)
           im->image.data = data;
         else
-          im->image.data = evas_object_image_data_convert_internal(o, data, 
EVAS_COLORSPACE_ARGB8888);
+          {
+             old_data = im->image.data;
+             im->image.data = evas_object_image_data_convert_internal(o, data, 
EVAS_COLORSPACE_ARGB8888);
+          }
         if (im->image.data)
           {
              ok = evas_common_save_image_to_file(im, file, key, quality, 
compress, encoding);
 
-             if (o->cur->cspace != EVAS_COLORSPACE_ARGB8888)
-               free(im->image.data);
+             if (old_data)
+               {
+                  free(im->image.data);
+                  im->image.data = old_data;
+               }
           }
         evas_cache_image_drop(ie);
      }
diff --git a/src/lib/evas/common/evas_image_data.c 
b/src/lib/evas/common/evas_image_data.c
index b6e2bdc..1269818 100644
--- a/src/lib/evas/common/evas_image_data.c
+++ b/src/lib/evas/common/evas_image_data.c
@@ -41,6 +41,21 @@ evas_common_rgba_image_from_data(Image_Entry* ie_dst, int w, 
int h, DATA32 *imag
        dst->cs.data = image_data;
        dst->cs.no_free = 1;
         break;
+      case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+      case EVAS_COLORSPACE_RGB8_ETC2:
+      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+        // FIXME: Borders are just guessed, not passed in (they should be)
+        dst->cache_entry.w = w;
+        dst->cache_entry.h = h;
+        dst->cache_entry.borders.l = 1;
+        dst->cache_entry.borders.t = 1;
+        dst->cache_entry.borders.r = ((w + 2 + 3) & ~0x3) - w - 1;
+        dst->cache_entry.borders.b = ((h + 2 + 3) & ~0x3) - h - 1;
+        dst->image.data = image_data;
+        dst->image.no_free = 1;
+        dst->cache_entry.flags.alpha = alpha ? 1 : 0;
+        break;
       default:
        abort();
        break;
@@ -119,58 +134,67 @@ evas_common_rgba_image_size_set(Image_Entry *ie_dst, 
const Image_Entry *ie_im, u
 }
 
 int
-evas_common_rgba_image_colorspace_set(Image_Entry* ie_dst, Evas_Colorspace 
cspace)
+evas_common_rgba_image_colorspace_set(Image_Entry* ie, Evas_Colorspace cspace)
 {
-   RGBA_Image   *dst = (RGBA_Image *) ie_dst;
-   Eina_Bool change = (dst->cache_entry.space != cspace);
+   RGBA_Image *im = (RGBA_Image *) ie;
+
+   // FIXME: This function looks extremely dubious now, trying to free the
+   // data pointer without even knowing how it was allocated (malloc / mmap).
+   // Also, lacks support for S3TC and exotic formats.
+
+   if (im->cache_entry.space == cspace)
+     return 1;
+
+   if (ie->references > 1)
+     WRN("Releasing data of image with >1 refs. Bad things may happen.");
+
+   if (im->cs.data)
+     {
+        if (!im->cs.no_free) free(im->cs.data);
+        im->cs.data = NULL;
+     }
+   im->cs.no_free = 0;
+   if (im->image.data && !im->image.no_free)
+     {
+        // FIXME: Call _evas_common_rgba_image_surface_munmap
+        free(im->image.data);
+     }
+   ie->allocated.w = 0;
+   ie->allocated.h = 0;
+   ie->flags.preload_done = 0;
+   ie->flags.loaded = 0;
+   im->image.data = NULL;
+   im->image.no_free = 0;
 
    switch (cspace)
      {
       case EVAS_COLORSPACE_ARGB8888:
       case EVAS_COLORSPACE_AGRY88:
       case EVAS_COLORSPACE_GRY8:
-       if (dst->cs.data)
-         {
-            if (!dst->cs.no_free) free(dst->cs.data);
-            dst->cs.data = NULL;
-            dst->cs.no_free = 0;
-         }
-        if (change && dst->image.data)
-          {
-             if (!dst->image.no_free) free(dst->image.data);
-             dst->image.data = NULL;
-             dst->image.no_free = 0;
-          }
+        // all good
+        break;
+      case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_ETC1_ALPHA:
+      case EVAS_COLORSPACE_RGB8_ETC2:
+      case EVAS_COLORSPACE_RGBA8_ETC2_EAC:
+        // living on the edge (no conversion atm)
         break;
       case EVAS_COLORSPACE_YCBCR422P601_PL:
       case EVAS_COLORSPACE_YCBCR422P709_PL:
       case EVAS_COLORSPACE_YCBCR422601_PL:
       case EVAS_COLORSPACE_YCBCR420TM12601_PL:
       case EVAS_COLORSPACE_YCBCR420NV12601_PL:
-       if (dst->image.no_free)
-         {
-             ie_dst->allocated.w = 0;
-             ie_dst->allocated.h = 0;
-             ie_dst->flags.preload_done = 0;
-             ie_dst->flags.loaded = 0;
-             dst->image.data = NULL;
-            dst->image.no_free = 0;
-             /* FIXME: Must allocate image.data surface cleanly. */
-         }
-       if (dst->cs.data)
-         {
-            if (!dst->cs.no_free) free(dst->cs.data);
-         }
-       dst->cs.data = calloc(1, dst->cache_entry.h * sizeof(unsigned char *) * 
2);
-       dst->cs.no_free = 0;
+        // prepare cspace conversion buffer
+        im->cs.data = calloc(1, im->cache_entry.h * sizeof(unsigned char *) * 
2);
+        im->cs.no_free = 0;
         break;
       default:
-       abort();
-       break;
+        CRI("Can't set colorspace to %u: unsupported", (unsigned) cspace);
+        abort();
+        return 0;
      }
-   dst->cache_entry.space = cspace;
-   evas_common_image_colorspace_dirty(dst);
-
-   _evas_common_rgba_image_post_surface(ie_dst);
-   return 0;
+   im->cache_entry.space = cspace;
+   evas_common_image_colorspace_dirty(im);
+   _evas_common_rgba_image_post_surface(ie);
+   return 1;
 }
diff --git a/src/lib/evas/common/evas_image_main.c 
b/src/lib/evas/common/evas_image_main.c
index 5cf5335..b82a851 100644
--- a/src/lib/evas/common/evas_image_main.c
+++ b/src/lib/evas/common/evas_image_main.c
@@ -213,8 +213,8 @@ _evas_common_rgba_image_surface_mmap(Image_Entry *ie, 
unsigned int w, unsigned i
 #endif
 }
 
-static void
-_evas_common_rgba_image_surface_munmap(void *data, unsigned int w, unsigned 
int h, Evas_Colorspace cspace)
+void
+evas_common_rgba_image_surface_munmap(void *data, unsigned int w, unsigned int 
h, Evas_Colorspace cspace)
 {
    if (!data) return ;
 #if defined (HAVE_SYS_MMAN_H) && (!defined (_WIN32))
@@ -379,9 +379,9 @@ evas_common_rgba_image_unload_real(Image_Entry *ie)
 
    if (im->image.data && !im->image.no_free)
      {
-        _evas_common_rgba_image_surface_munmap(im->image.data,
-                                               ie->allocated.w, 
ie->allocated.h,
-                                               ie->space);
+        evas_common_rgba_image_surface_munmap(im->image.data,
+                                              ie->allocated.w, ie->allocated.h,
+                                              ie->space);
 #ifdef SURFDBG
         surfs = eina_list_remove(surfs, ie);
 #endif        
@@ -532,9 +532,9 @@ _evas_common_rgba_image_surface_alloc(Image_Entry *ie, 
unsigned int w, unsigned
 
    if (im->image.data)
      {
-        _evas_common_rgba_image_surface_munmap(im->image.data,
-                                               ie->allocated.w, 
ie->allocated.h,
-                                               ie->space);
+        evas_common_rgba_image_surface_munmap(im->image.data,
+                                              ie->allocated.w, ie->allocated.h,
+                                              ie->space);
        im->image.data = NULL;
 #ifdef SURFDBG
         surfs = eina_list_remove(surfs, ie);
@@ -605,9 +605,9 @@ _evas_common_rgba_image_surface_delete(Image_Entry *ie)
 
    if (im->image.data && !im->image.no_free)
      {
-        _evas_common_rgba_image_surface_munmap(im->image.data,
-                                               ie->allocated.w, 
ie->allocated.h,
-                                               ie->space);
+        evas_common_rgba_image_surface_munmap(im->image.data,
+                                              ie->allocated.w, ie->allocated.h,
+                                              ie->space);
 #ifdef SURFDBG
         surfs = eina_list_remove(surfs, ie);
 #endif
@@ -854,10 +854,10 @@ evas_common_image_colorspace_normalize(RGBA_Image *im)
 #endif
              if (!im->image.no_free)
                {
-                  _evas_common_rgba_image_surface_munmap(im->image.data,
-                                                         
im->cache_entry.allocated.w,
-                                                         
im->cache_entry.allocated.h,
-                                                         
im->cache_entry.space);
+                  evas_common_rgba_image_surface_munmap(im->image.data,
+                                                        
im->cache_entry.allocated.w,
+                                                        
im->cache_entry.allocated.h,
+                                                        im->cache_entry.space);
 #ifdef SURFDBG
                   surfs = eina_list_remove(surfs, im);
 #endif
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index e1f73cb..9570a51 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1344,6 +1344,18 @@ eng_image_data_get(void *data EINA_UNUSED, void *image, 
int to_write, DATA32 **i
       case EVAS_COLORSPACE_YCBCR420TM12601_PL:
        *image_data = im->cs.data;
         break;
+      case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_RGB8_ETC2:
+      case EVAS_COLORSPACE_RGB_S3TC_DXT1:
+      case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
+        if (to_write)
+          {
+             // abort() ?
+             error = EVAS_LOAD_ERROR_GENERIC;
+             return NULL;
+          }
+        *image_data = im->image.data;
+        break;
       default:
        abort();
        break;
@@ -1362,6 +1374,10 @@ eng_image_data_put(void *data, void *image, DATA32 
*image_data)
    switch (im->cache_entry.space)
      {
       case EVAS_COLORSPACE_ARGB8888:
+      case EVAS_COLORSPACE_ETC1:
+      case EVAS_COLORSPACE_RGB8_ETC2:
+      case EVAS_COLORSPACE_RGB_S3TC_DXT1:
+      case EVAS_COLORSPACE_RGBA_S3TC_DXT1:
        if (image_data != im->image.data)
          {
             int w, h;
diff --git a/src/modules/evas/image_savers/tgv/evas_image_save_tgv.c 
b/src/modules/evas/image_savers/tgv/evas_image_save_tgv.c
index 2ce6ab0..44b38e0 100644
--- a/src/modules/evas/image_savers/tgv/evas_image_save_tgv.c
+++ b/src/modules/evas/image_savers/tgv/evas_image_save_tgv.c
@@ -53,12 +53,6 @@ _alpha_to_greyscale_convert(uint32_t *data, int len)
 static int
 _save_direct_tgv(RGBA_Image *im, const char *file, int compress)
 {
-   // FIXME: Now we have border information, this comment isn't valid anymore:
-
-   // In case we are directly copying ETC1/2 data, we can't properly
-   // duplicate the 1 pixel borders. So we just assume the image contains
-   // them already.
-
    // TODO: Add block by block compression.
 
    int image_width, image_height, planes = 1;
@@ -69,8 +63,12 @@ _save_direct_tgv(RGBA_Image *im, const char *file, int 
compress)
    uint8_t *data, *ptr;
    FILE *f;
 
-   image_width = im->cache_entry.w;
-   image_height = im->cache_entry.h;
+   if (!im->cache_entry.borders.l || !im->cache_entry.borders.t ||
+       !im->cache_entry.borders.r || !im->cache_entry.borders.b)
+     WRN("No im->cache_entry.borders on ETC image. Final image may have wrong 
dimensions.");
+
+   image_width = im->cache_entry.w + im->cache_entry.borders.l + 
im->cache_entry.borders.r;
+   image_height = im->cache_entry.h + im->cache_entry.borders.t + 
im->cache_entry.borders.b;
    data = im->image.data8;
    width = htonl(image_width);
    height = htonl(image_height);

-- 


Reply via email to