raster pushed a commit to branch master.

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

commit dd23a6c84aee249aa5316b48af6956072233bb97
Author: Vincent Torri <[email protected]>
Date:   Sat Jul 11 11:34:01 2020 +0100

    Evas: add avif evas loader
    
    Summary: Add AV1 image file loader to Evas
    
    Test Plan: test executable with avif files found in libavif project
    
    Reviewers: raster
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D12051
---
 meson_options.txt                                  |   4 +-
 po/POTFILES.in                                     |   1 +
 src/lib/evas/common/evas_image_load.c              |   4 +-
 src/lib/evas/file/evas_module.c                    |   4 +
 src/lib/evas/meson.build                           |   2 +
 .../evas/image_loaders/avif/evas_image_load_avif.c | 290 +++++++++++++++++++++
 6 files changed, 302 insertions(+), 3 deletions(-)

diff --git a/meson_options.txt b/meson_options.txt
index c6f749e1f7..c891630f04 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -189,8 +189,8 @@ option('unmount-path',
 option('evas-loaders-disabler',
   type : 'array',
   description : 'List of modular image/vector loaders to disable in efl',
-  choices : ['gst', 'pdf', 'ps', 'raw', 'svg', 'rsvg', 'xcf', 'bmp', 'dds', 
'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 
'tgv', 'tiff', 'wbmp', 'webp', 'xpm', 'json'],
-  value : ['json']
+  choices : ['gst', 'pdf', 'ps', 'raw', 'svg', 'rsvg', 'xcf', 'bmp', 'dds', 
'eet', 'generic', 'gif', 'ico', 'jp2k', 'jpeg', 'pmaps', 'png', 'psd', 'tga', 
'tgv', 'tiff', 'wbmp', 'webp', 'xpm', 'json', 'avif'],
+  value : ['json', 'avif']
 )
 
 option('ecore-imf-loaders-disabler',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index d6879babc1..9700d3c286 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -495,6 +495,7 @@ src/modules/evas/image_loaders/pmaps/evas_image_load_pmaps.c
 src/modules/evas/image_loaders/generic/evas_image_load_generic.c
 src/modules/evas/image_loaders/gif/evas_image_load_gif.c
 src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c
+src/modules/evas/image_loaders/avif/evas_image_load_avif.c
 src/modules/evas/image_savers/jpeg/evas_image_save_jpeg.c
 src/modules/evas/image_savers/png/evas_image_save_png.c
 src/modules/evas/image_savers/tiff/evas_image_save_tiff.c
diff --git a/src/lib/evas/common/evas_image_load.c 
b/src/lib/evas/common/evas_image_load.c
index 1d28253c7e..5d3e3aa30f 100644
--- a/src/lib/evas/common/evas_image_load.c
+++ b/src/lib/evas/common/evas_image_load.c
@@ -66,6 +66,8 @@ static const struct ext_loader_s loaders[] =
 
    MATCHING(".dds", "dds"),
 
+   MATCHING(".avif", "avif"),
+
    /* xcf - gefenric */
    MATCHING(".xcf", "generic"),
    MATCHING(".xcf.gz", "generic"),
@@ -163,7 +165,7 @@ static const struct ext_loader_s loaders[] =
 static const char *loaders_name[] =
 { /* in order of most likely needed */
   "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps",
-  "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "generic"
+  "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "generic"
 };
 
 struct evas_image_foreach_loader_data
diff --git a/src/lib/evas/file/evas_module.c b/src/lib/evas/file/evas_module.c
index a1e8b623af..b99118698e 100644
--- a/src/lib/evas/file/evas_module.c
+++ b/src/lib/evas/file/evas_module.c
@@ -196,6 +196,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(vg_loader, json);
 #endif
 
 #if !EVAS_MODULE_NO_IMAGE_LOADERS
+EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, avif);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet);
@@ -287,6 +288,9 @@ static const struct {
 #endif
 #endif
 #if !EVAS_MODULE_NO_IMAGE_LOADERS
+#ifdef EVAS_STATIC_BUILD_AVIF
+  EVAS_EINA_STATIC_MODULE_USE(image_loader, avif),
+#endif
 #ifdef EVAS_STATIC_BUILD_BMP
   EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp),
 #endif
diff --git a/src/lib/evas/meson.build b/src/lib/evas/meson.build
index fca88309ad..315aa57a63 100644
--- a/src/lib/evas/meson.build
+++ b/src/lib/evas/meson.build
@@ -10,8 +10,10 @@ giflib = cc.find_library('gif')
 webp = dependency('libwebp', version: ['>=0.5.0'], required: 
get_option('evas-loaders-disabler').contains('webp') == false)
 webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: 
get_option('evas-loaders-disabler').contains('webp') == false)
 libopenjp2 = dependency('libopenjp2', required: 
get_option('evas-loaders-disabler').contains('jp2k') == false)
+libavif = dependency('libavif', required: 
get_option('evas-loaders-disabler').contains('avif') == false)
 
 evas_image_loaders_file = [
+     ['avif',    'shared', [libavif]],
      ['bmp',     'shared', []],
      ['eet',     'static', [eet]],
      ['generic', 'shared', [rt]],
diff --git a/src/modules/evas/image_loaders/avif/evas_image_load_avif.c 
b/src/modules/evas/image_loaders/avif/evas_image_load_avif.c
new file mode 100644
index 0000000000..88469ddf04
--- /dev/null
+++ b/src/modules/evas/image_loaders/avif/evas_image_load_avif.c
@@ -0,0 +1,290 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+
+#include <avif/avif.h>
+
+#include "Evas_Loader.h"
+
+typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
+struct _Evas_Loader_Internal
+{
+   Eina_File *f;
+   Evas_Image_Load_Opts *opts;
+};
+
+static int _evas_loader_avif_log_dom = -1;
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_avif_log_dom, __VA_ARGS__)
+
+#ifdef WRN
+# undef WRN
+#endif
+#define WRN(...) EINA_LOG_DOM_WARN(_evas_loader_avif_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_avif_log_dom, __VA_ARGS__)
+
+static Eina_Bool
+evas_image_load_file_head_avif_internal(unsigned int *w, unsigned int *h,
+                                       unsigned char *alpha,
+                                        void *map, size_t length,
+                                        int *error)
+{
+   avifROData raw;
+   avifDecoder *decoder;
+   avifImage *image;
+   avifResult res;
+
+   raw.size = length;
+   raw.data = (const uint8_t *)map;
+
+   decoder = avifDecoderCreate();
+   if (!decoder)
+     {
+        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        return EINA_FALSE;
+     }
+
+   image = avifImageCreateEmpty();
+   if (!image)
+     {
+        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        goto destroy_decoder;
+     }
+
+   res = avifDecoderRead(decoder, image, &raw);
+   if (res != AVIF_RESULT_OK)
+     {
+        ERR("avif file format invalid");
+        *error = EVAS_LOAD_ERROR_GENERIC;
+        goto destroy_image;
+     }
+
+   *w = image->width;
+   *h = image->height;
+   *alpha = !!image->alphaPlane;
+   *error = EVAS_LOAD_ERROR_NONE;
+
+   avifImageDestroy(image);
+   avifDecoderDestroy(decoder);
+
+   return EINA_TRUE;
+
+ destroy_image:
+   avifImageDestroy(image);
+ destroy_decoder:
+   avifDecoderDestroy(decoder);
+
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+evas_image_load_file_data_avif_internal(void *pixels,
+                                        void *map, size_t length,
+                                        int *error)
+{
+   avifRGBImage rgb;
+   avifROData raw;
+   avifDecoder *decoder;
+   avifImage *image;
+   avifResult res;
+
+   raw.size = length;
+   raw.data = (const uint8_t *)map;
+
+   decoder = avifDecoderCreate();
+   if (!decoder)
+     {
+        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        return EINA_FALSE;
+     }
+
+   image = avifImageCreateEmpty();
+   if (!image)
+     {
+        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        goto destroy_decoder;
+     }
+
+   res = avifDecoderRead(decoder, image, &raw);
+   if (res != AVIF_RESULT_OK)
+     {
+        ERR("avif file format invalid");
+        *error = EVAS_LOAD_ERROR_GENERIC;
+        goto destroy_image;
+     }
+
+   avifRGBImageSetDefaults(&rgb, image);
+   rgb.format = AVIF_RGB_FORMAT_BGRA;
+   rgb.depth = 8;
+   rgb.pixels = pixels;
+   rgb.rowBytes = 4 * image->width;
+
+   avifImageYUVToRGB(image, &rgb);
+
+   *error = EVAS_LOAD_ERROR_NONE;
+
+   avifImageDestroy(image);
+   avifDecoderDestroy(decoder);
+
+   return EINA_TRUE;
+
+ destroy_image:
+   avifImageDestroy(image);
+ destroy_decoder:
+   avifDecoderDestroy(decoder);
+
+   return EINA_FALSE;
+}
+
+static void *
+evas_image_load_file_open_avif(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
+                              Evas_Image_Load_Opts *opts,
+                              Evas_Image_Animated *animated EINA_UNUSED,
+                              int *error)
+{
+   Evas_Loader_Internal *loader;
+
+   loader = calloc(1, sizeof (Evas_Loader_Internal));
+   if (!loader)
+     {
+        *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        return NULL;
+     }
+
+   loader->f = f;
+   loader->opts = opts;
+
+   return loader;
+}
+
+static void
+evas_image_load_file_close_avif(void *loader_data)
+{
+   free(loader_data);
+}
+
+static Eina_Bool
+evas_image_load_file_head_avif(void *loader_data,
+                               Emile_Image_Property *prop,
+                               int *error)
+{
+   Evas_Loader_Internal *loader = loader_data;
+   Eina_File *f;
+   void *map;
+   Eina_Bool val;
+
+   f = loader->f;
+
+   map = eina_file_map_all(f, EINA_FILE_RANDOM);
+   if (!map)
+     {
+       *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+        return EINA_FALSE;
+     }
+
+   val = evas_image_load_file_head_avif_internal(&prop->w, &prop->h,
+                                                &prop->alpha,
+                                                 map, eina_file_size_get(f),
+                                                 error);
+
+   eina_file_map_free(f, map);
+
+   return val;
+}
+
+static Eina_Bool
+evas_image_load_file_data_avif(void *loader_data,
+                               Emile_Image_Property *prop EINA_UNUSED,
+                              void *pixels,
+                              int *error)
+{
+   Evas_Loader_Internal *loader = loader_data;
+   Eina_File *f;
+   void *map;
+   Eina_Bool val = EINA_FALSE;
+
+   f = loader->f;
+
+   map = eina_file_map_all(f, EINA_FILE_WILLNEED);
+   if (!map)
+     {
+        *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+        goto on_error;
+     }
+
+   val = evas_image_load_file_data_avif_internal(pixels,
+                                                 map, eina_file_size_get(f),
+                                                 error);
+
+   eina_file_map_free(f, map);
+
+ on_error:
+   return val;
+}
+
+static Evas_Image_Load_Func evas_image_load_avif_func =
+{
+  EVAS_IMAGE_LOAD_VERSION,
+  evas_image_load_file_open_avif,
+  evas_image_load_file_close_avif,
+  (void*) evas_image_load_file_head_avif,
+  NULL,
+  (void*) evas_image_load_file_data_avif,
+  NULL,
+  EINA_TRUE,
+  EINA_TRUE
+};
+
+static int
+module_open(Evas_Module *em)
+{
+   if (!em) return 0;
+
+   _evas_loader_avif_log_dom = eina_log_domain_register("evas-avif", 
EINA_COLOR_BLUE);
+   if (_evas_loader_avif_log_dom < 0)
+     {
+        EINA_LOG_ERR("Can not create a module log domain.");
+        return 0;
+     }
+
+   em->functions = (void *)(&evas_image_load_avif_func);
+
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em EINA_UNUSED)
+{
+   if (_evas_loader_avif_log_dom >= 0)
+     {
+        eina_log_domain_unregister(_evas_loader_avif_log_dom);
+        _evas_loader_avif_log_dom = -1;
+     }
+}
+
+static Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION,
+   "avif",
+   "none",
+   {
+     module_open,
+     module_close
+   }
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, avif);
+
+#ifndef EVAS_STATIC_BUILD_AVIF
+EVAS_EINA_MODULE_DEFINE(image_loader, avif);
+#endif
+

-- 


Reply via email to