summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson_options.txt4
-rw-r--r--po/POTFILES.in1
-rw-r--r--src/lib/evas/common/evas_image_load.c4
-rw-r--r--src/lib/evas/file/evas_module.c4
-rw-r--r--src/lib/evas/meson.build2
-rw-r--r--src/modules/evas/image_loaders/avif/evas_image_load_avif.c290
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
+