raster pushed a commit to branch master.

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

commit 97f95e736269fcdf5511077135ede9b37dd06854
Author: thierry1970 <thie...@ordissimo.com>
Date:   Sat Feb 6 15:45:42 2021 +0000

    Added the heif loader
    
    Summary: that supports images : *.heif, *hiec and *.avif I have disabled 
*.avif images, there is already a loader.
    
    Reviewers: stefan_schmidt, raster
    
    Subscribers: raster, vtorri, cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D12135
---
 README                                             |   9 +
 data/evas/evas.xml                                 |  13 +
 data/evas/meson.build                              |   4 +
 data/meson.build                                   |   3 +-
 meson_options.txt                                  |   4 +-
 src/lib/evas/common/evas_image_load.c              |   7 +-
 src/lib/evas/file/evas_module.c                    |   4 +
 src/lib/evas/meson.build                           |   2 +
 .../evas/image_loaders/heif/evas_image_load_heif.c | 300 +++++++++++++++++++++
 src/tests/evas/evas_test_image.c                   |   5 +
 10 files changed, 347 insertions(+), 4 deletions(-)

diff --git a/README b/README
index ec3b27a737..03085056d3 100644
--- a/README
+++ b/README
@@ -404,6 +404,15 @@ This library acts as a porting library for Windows to 
provide missing
 libc calls not in Mingw32 that EFL needs.
 
 
+**Heif:**
+
+//LGPL v3 license//
+
+The license doesnt affect efl or apps using efl, but gpl3 or lgpl3
+affects the entire os requiring any gpl/lgpl3 component be
+user-replacable.
+The end user must be able to modify the libheif code and still be
+able to use the efl.
 
 
 COMPILING AND INSTALLING
diff --git a/data/evas/evas.xml b/data/evas/evas.xml
new file mode 100644
index 0000000000..7764c0c05e
--- /dev/null
+++ b/data/evas/evas.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info";>
+>------<mime-type type="image/heif">
+>------>-------<comment>HEIF image file</comment>
+>------>-------<glob pattern="*.heif"/>
+>------>-------<glob pattern="*.heic"/>
+>------</mime-type>
+>------<mime-type type="image/avif">
+>------>-------<comment>AVIF image file</comment>
+>------>--------<glob pattern="*.avif"/>
+>------</mime-type>
+</mime-info>
+
diff --git a/data/evas/meson.build b/data/evas/meson.build
new file mode 100644
index 0000000000..ddcc57dcad
--- /dev/null
+++ b/data/evas/meson.build
@@ -0,0 +1,4 @@
+install_data(files('evas.xml'),
+  install_dir : join_paths(dir_data, 'mime', 'packages')
+)
+
diff --git a/data/meson.build b/data/meson.build
index 4e1f68d406..5944dad07c 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -1,4 +1,4 @@
-checkme_files = ['ecore', 'ecore_imf', 'ecore_x', 'eeze', 'efreet', 'elua', 
'emotion', 'ethumb', 'ethumb_client', 'evas']
+checkme_files = ['ecore', 'ecore_imf', 'ecore_x', 'eeze', 'efreet', 'elua', 
'emotion', 'ethumb', 'ethumb_client']
 foreach checkme : checkme_files
   install_data(join_paths(checkme, 'checkme'),
     install_dir : join_paths(dir_data, checkme)
@@ -10,3 +10,4 @@ subdir('edje')
 subdir('embryo')
 subdir(join_paths('ethumb', 'frames'))
 subdir('elementary')
+subdir('evas')
diff --git a/meson_options.txt b/meson_options.txt
index f5ffb0e134..b224179366 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', 'avif'],
-  value : ['json', 'avif']
+  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', 'heif'],
+  value : ['json', 'avif', 'heif']
 )
 
 option('ecore-imf-loaders-disabler',
diff --git a/src/lib/evas/common/evas_image_load.c 
b/src/lib/evas/common/evas_image_load.c
index 8ed04dda2e..797fae37ea 100644
--- a/src/lib/evas/common/evas_image_load.c
+++ b/src/lib/evas/common/evas_image_load.c
@@ -69,6 +69,10 @@ static const struct ext_loader_s loaders[] =
    MATCHING(".avif", "avif"),
    MATCHING(".avifs", "avif"),
 
+   MATCHING(".heif", "heif"),
+   MATCHING(".heic", "heif"),
+   // MATCHING(".avif", "heif"),
+
    /* xcf - gefenric */
    MATCHING(".xcf", "generic"),
    MATCHING(".xcf.gz", "generic"),
@@ -167,7 +171,8 @@ 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", "avif", "generic"
+  "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "heif",
+  "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 6292c1bb42..1362a004d8 100644
--- a/src/lib/evas/file/evas_module.c
+++ b/src/lib/evas/file/evas_module.c
@@ -202,6 +202,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, generic);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, gif);
+EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, heif);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, ico);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jpeg);
 EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, jp2k);
@@ -307,6 +308,9 @@ static const struct {
 #ifdef EVAS_STATIC_BUILD_GIF
   EVAS_EINA_STATIC_MODULE_USE(image_loader, gif),
 #endif
+#ifdef EVAS_STATIC_BUILD_HEIF
+  EVAS_EINA_STATIC_MODULE_USE(image_loader, heif),
+#endif
 #ifdef EVAS_STATIC_BUILD_ICO
   EVAS_EINA_STATIC_MODULE_USE(image_loader, ico),
 #endif
diff --git a/src/lib/evas/meson.build b/src/lib/evas/meson.build
index 8dcfd98713..1bf5fa0801 100644
--- a/src/lib/evas/meson.build
+++ b/src/lib/evas/meson.build
@@ -11,6 +11,7 @@ webp = dependency('libwebp', version: ['>=0.5.0'], required: 
get_option('evas-lo
 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, version: '>= 
0.8.2')
+heif= dependency('libheif', required: 
get_option('evas-loaders-disabler').contains('heif') == false)
 
 evas_image_loaders_file = [
      ['avif',    'shared', [libavif]],
@@ -18,6 +19,7 @@ evas_image_loaders_file = [
      ['eet',     'static', [eet]],
      ['generic', 'shared', [rt]],
      ['gif',     'shared', [giflib]],
+     ['heif',    'shared', [heif]],
      ['ico',     'shared', []],
      ['jpeg',    'static', [jpeg]],
      ['jp2k',    'shared', [libopenjp2]],
diff --git a/src/modules/evas/image_loaders/heif/evas_image_load_heif.c 
b/src/modules/evas/image_loaders/heif/evas_image_load_heif.c
new file mode 100644
index 0000000000..bc9f2a1e06
--- /dev/null
+++ b/src/modules/evas/image_loaders/heif/evas_image_load_heif.c
@@ -0,0 +1,300 @@
+#define _XOPEN_SOURCE 600
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+
+#include <libheif/heif.h>
+
+#include "evas_common_private.h"
+#include "evas_private.h"
+
+static int _evas_loader_heif_log_dom = -1;
+
+#ifdef ERR
+# undef ERR
+#endif
+#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_heif_log_dom, __VA_ARGS__)
+
+#ifdef INF
+# undef INF
+#endif
+#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_heif_log_dom, __VA_ARGS__)
+
+
+static void *
+evas_image_load_file_open_heif(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
+                             Evas_Image_Load_Opts *opts EINA_UNUSED,
+                             Evas_Image_Animated *animated EINA_UNUSED,
+                             int *error EINA_UNUSED)
+{
+   return f;
+}
+
+static void
+evas_image_load_file_close_heif(void *loader_data EINA_UNUSED)
+{
+}
+
+static Eina_Bool
+evas_image_load_file_head_heif(void *loader_data,
+                             Emile_Image_Property *prop,
+                             int *error)
+{
+   Eina_File *f = loader_data;
+   void *map;
+   size_t length;
+   struct heif_error err;
+   struct heif_context* hc = NULL;
+   struct heif_image_handle* hdl = NULL;
+   struct heif_image* img = NULL;
+   Eina_Bool r = EINA_FALSE;
+
+   *error = EVAS_LOAD_ERROR_NONE;
+
+   map = eina_file_map_all(f, EINA_FILE_RANDOM);
+   length = eina_file_size_get(f);
+
+   // init prop struct with some default null values
+   prop->w = 0;
+   prop->h = 0;
+
+   if (!map || length < 1)
+     {
+        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+       goto on_error;
+     }
+
+   hc = heif_context_alloc();
+   if (!hc) {
+     INF("cannot allocate heif_context");
+     *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+     goto on_error;
+   }
+
+   err = heif_context_read_from_memory_without_copy(hc, map, length, NULL);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+
+   err = heif_context_get_primary_image_handle(hc, &hdl);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+
+   int has_alpha = heif_image_handle_has_alpha_channel(hdl);
+
+   err = heif_decode_image(hdl, &img, heif_colorspace_RGB,
+                           has_alpha ? heif_chroma_interleaved_RGBA : 
heif_chroma_interleaved_RGB,
+                           NULL);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+
+   prop->w = heif_image_get_width(img, heif_channel_interleaved);
+   prop->h = heif_image_get_height(img, heif_channel_interleaved);
+   if (has_alpha != 3)
+     prop->alpha = 1;
+
+   r = EINA_TRUE;
+
+ on_error:
+   if (img) {
+     heif_image_release(img);
+   }
+
+   if (hdl) {
+     heif_image_handle_release(hdl);
+   }
+
+   if (hc) {
+     heif_context_free(hc);
+   }
+   eina_file_map_free(f, map);
+   return r;
+}
+
+static Eina_Bool
+evas_image_load_file_data_heif(void *loader_data,
+                             Emile_Image_Property *prop,
+                             void *pixels,
+                             int *error)
+{
+   Eina_File *f = loader_data;
+
+   void *map;
+   size_t length;
+   struct heif_error err;
+   struct heif_context* hc = NULL;
+   struct heif_image_handle* hdl = NULL;
+   struct heif_image* img = NULL;
+   unsigned int x, y;
+   int stride, bps = 3;
+   const uint8_t* data;
+   uint8_t* dd = (uint8_t*)pixels, *ds = NULL;
+   Eina_Bool result = EINA_FALSE;
+
+   map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
+   length = eina_file_size_get(f);
+   *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+   if (!map || length < 1)
+     goto on_error;
+
+   *error = EVAS_LOAD_ERROR_GENERIC;
+   result = EINA_FALSE;
+
+   hc = heif_context_alloc();
+   if (!hc) {
+     INF("cannot allocate heif_context");
+     *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+     goto on_error;
+   }
+
+   err = heif_context_read_from_memory_without_copy(hc, map, length, NULL);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+
+   err = heif_context_get_primary_image_handle(hc, &hdl);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+
+   err = heif_decode_image(hdl, &img, heif_colorspace_RGB,
+                           prop->alpha ? heif_chroma_interleaved_RGBA : 
heif_chroma_interleaved_RGB,
+                           NULL);
+   if (err.code != heif_error_Ok) {
+     INF("%s", err.message);
+     *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+     goto on_error;
+   }
+   if (prop->alpha) bps = 4;
+   data = heif_image_get_plane_readonly(img, heif_channel_interleaved, 
&stride);
+   ds = (uint8_t*)data;
+   for (y = 0; y < prop->h; y++)
+      for (x = 0; x < prop->w; x++)
+        {
+           if (bps == 3)
+             {
+               dd[3] = 0xff;
+               dd[0] = ds[2];
+               dd[1] = ds[1];
+               dd[2] = ds[0];
+               ds+=3;
+               dd+=4;
+             }
+           else
+             {
+               dd[0] = ds[2];
+               dd[1] = ds[1];
+               dd[2] = ds[0];
+               dd[3] = ds[3];
+               ds+=4;
+               dd+=4;
+             }
+        }
+  result = EINA_TRUE;
+
+  *error = EVAS_LOAD_ERROR_NONE;
+  prop->premul = EINA_TRUE;
+
+on_error:
+
+  if (map) eina_file_map_free(f, map);
+
+  if (img) {
+    // Do not free the image here when we pass it to gdk-pixbuf, as its memory 
will still be used by gdk-pixbuf.
+    heif_image_release(img);
+  }
+
+  if (hdl) {
+    heif_image_handle_release(hdl);
+  }
+
+  if (hc) {
+    heif_context_free(hc);
+  }
+
+  return result;
+}
+
+static const Evas_Image_Load_Func evas_image_load_heif_func = {
+  EVAS_IMAGE_LOAD_VERSION,
+  evas_image_load_file_open_heif,
+  evas_image_load_file_close_heif,
+  (void*) evas_image_load_file_head_heif,
+  NULL,
+  (void*) evas_image_load_file_data_heif,
+  NULL,
+  EINA_TRUE,
+  EINA_FALSE
+};
+
+static int
+module_open(Evas_Module *em)
+{
+   if (!em) return 0;
+   _evas_loader_heif_log_dom = eina_log_domain_register
+     ("evas-heif", EVAS_DEFAULT_LOG_COLOR);
+   if (_evas_loader_heif_log_dom < 0)
+     {
+        EINA_LOG_ERR("Can not create a module log domain.");
+        return 0;
+     }
+
+   em->functions = (void *)(&evas_image_load_heif_func);
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em EINA_UNUSED)
+{
+   if (_evas_loader_heif_log_dom >= 0)
+     {
+        eina_log_domain_unregister(_evas_loader_heif_log_dom);
+        _evas_loader_heif_log_dom = -1;
+     }
+}
+
+static Evas_Module_Api evas_modapi =
+  {
+    EVAS_MODULE_API_VERSION,
+    "heif",
+    "none",
+    {
+      module_open,
+      module_close
+    }
+  };
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, heif);
+
+
+#ifndef EVAS_STATIC_BUILD_HEIF
+EVAS_EINA_MODULE_DEFINE(image_loader, heif);
+#endif
diff --git a/src/tests/evas/evas_test_image.c b/src/tests/evas/evas_test_image.c
index c2530632a3..5753651f30 100644
--- a/src/tests/evas/evas_test_image.c
+++ b/src/tests/evas/evas_test_image.c
@@ -53,6 +53,11 @@ static const char *exts[] = {
   ,"jpeg"
   ,"jpg"
 #endif
+#ifdef BUILD_LOADER_HEIF
+  ,"heif"
+  ,"heic"
+//   ,"avif"
+#endif
 };
 
 EFL_START_TEST(evas_object_image_loader)

-- 


Reply via email to