summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2020-07-11 11:34:01 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-07-14 10:09:22 +0100
commitdd23a6c84aee249aa5316b48af6956072233bb97 (patch)
treee35eb88062b1dec24dc9d9cfe3f38f51a5fc7086
parent6cc6aacbaccd4b6e876ae9b54d93cd6fe73c0fe4 (diff)
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
-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',
189option('evas-loaders-disabler', 189option('evas-loaders-disabler',
190 type : 'array', 190 type : 'array',
191 description : 'List of modular image/vector loaders to disable in efl', 191 description : 'List of modular image/vector loaders to disable in efl',
192 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'], 192 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'],
193 value : ['json'] 193 value : ['json', 'avif']
194) 194)
195 195
196option('ecore-imf-loaders-disabler', 196option('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
495src/modules/evas/image_loaders/generic/evas_image_load_generic.c 495src/modules/evas/image_loaders/generic/evas_image_load_generic.c
496src/modules/evas/image_loaders/gif/evas_image_load_gif.c 496src/modules/evas/image_loaders/gif/evas_image_load_gif.c
497src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c 497src/modules/evas/image_loaders/tgv/evas_image_load_tgv.c
498src/modules/evas/image_loaders/avif/evas_image_load_avif.c
498src/modules/evas/image_savers/jpeg/evas_image_save_jpeg.c 499src/modules/evas/image_savers/jpeg/evas_image_save_jpeg.c
499src/modules/evas/image_savers/png/evas_image_save_png.c 500src/modules/evas/image_savers/png/evas_image_save_png.c
500src/modules/evas/image_savers/tiff/evas_image_save_tiff.c 501src/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[] =
66 66
67 MATCHING(".dds", "dds"), 67 MATCHING(".dds", "dds"),
68 68
69 MATCHING(".avif", "avif"),
70
69 /* xcf - gefenric */ 71 /* xcf - gefenric */
70 MATCHING(".xcf", "generic"), 72 MATCHING(".xcf", "generic"),
71 MATCHING(".xcf.gz", "generic"), 73 MATCHING(".xcf.gz", "generic"),
@@ -163,7 +165,7 @@ static const struct ext_loader_s loaders[] =
163static const char *loaders_name[] = 165static const char *loaders_name[] =
164{ /* in order of most likely needed */ 166{ /* in order of most likely needed */
165 "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", 167 "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps",
166 "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "generic" 168 "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "generic"
167}; 169};
168 170
169struct evas_image_foreach_loader_data 171struct 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);
196#endif 196#endif
197 197
198#if !EVAS_MODULE_NO_IMAGE_LOADERS 198#if !EVAS_MODULE_NO_IMAGE_LOADERS
199EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, avif);
199EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp); 200EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp);
200EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds); 201EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds);
201EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet); 202EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet);
@@ -287,6 +288,9 @@ static const struct {
287#endif 288#endif
288#endif 289#endif
289#if !EVAS_MODULE_NO_IMAGE_LOADERS 290#if !EVAS_MODULE_NO_IMAGE_LOADERS
291#ifdef EVAS_STATIC_BUILD_AVIF
292 EVAS_EINA_STATIC_MODULE_USE(image_loader, avif),
293#endif
290#ifdef EVAS_STATIC_BUILD_BMP 294#ifdef EVAS_STATIC_BUILD_BMP
291 EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp), 295 EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp),
292#endif 296#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')
10webp = dependency('libwebp', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) 10webp = dependency('libwebp', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false)
11webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) 11webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false)
12libopenjp2 = dependency('libopenjp2', required: get_option('evas-loaders-disabler').contains('jp2k') == false) 12libopenjp2 = dependency('libopenjp2', required: get_option('evas-loaders-disabler').contains('jp2k') == false)
13libavif = dependency('libavif', required: get_option('evas-loaders-disabler').contains('avif') == false)
13 14
14evas_image_loaders_file = [ 15evas_image_loaders_file = [
16 ['avif', 'shared', [libavif]],
15 ['bmp', 'shared', []], 17 ['bmp', 'shared', []],
16 ['eet', 'static', [eet]], 18 ['eet', 'static', [eet]],
17 ['generic', 'shared', [rt]], 19 ['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 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include <avif/avif.h>
8
9#include "Evas_Loader.h"
10
11typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
12struct _Evas_Loader_Internal
13{
14 Eina_File *f;
15 Evas_Image_Load_Opts *opts;
16};
17
18static int _evas_loader_avif_log_dom = -1;
19
20#ifdef ERR
21# undef ERR
22#endif
23#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_avif_log_dom, __VA_ARGS__)
24
25#ifdef WRN
26# undef WRN
27#endif
28#define WRN(...) EINA_LOG_DOM_WARN(_evas_loader_avif_log_dom, __VA_ARGS__)
29
30#ifdef INF
31# undef INF
32#endif
33#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_avif_log_dom, __VA_ARGS__)
34
35static Eina_Bool
36evas_image_load_file_head_avif_internal(unsigned int *w, unsigned int *h,
37 unsigned char *alpha,
38 void *map, size_t length,
39 int *error)
40{
41 avifROData raw;
42 avifDecoder *decoder;
43 avifImage *image;
44 avifResult res;
45
46 raw.size = length;
47 raw.data = (const uint8_t *)map;
48
49 decoder = avifDecoderCreate();
50 if (!decoder)
51 {
52 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
53 return EINA_FALSE;
54 }
55
56 image = avifImageCreateEmpty();
57 if (!image)
58 {
59 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
60 goto destroy_decoder;
61 }
62
63 res = avifDecoderRead(decoder, image, &raw);
64 if (res != AVIF_RESULT_OK)
65 {
66 ERR("avif file format invalid");
67 *error = EVAS_LOAD_ERROR_GENERIC;
68 goto destroy_image;
69 }
70
71 *w = image->width;
72 *h = image->height;
73 *alpha = !!image->alphaPlane;
74 *error = EVAS_LOAD_ERROR_NONE;
75
76 avifImageDestroy(image);
77 avifDecoderDestroy(decoder);
78
79 return EINA_TRUE;
80
81 destroy_image:
82 avifImageDestroy(image);
83 destroy_decoder:
84 avifDecoderDestroy(decoder);
85
86 return EINA_FALSE;
87}
88
89static Eina_Bool
90evas_image_load_file_data_avif_internal(void *pixels,
91 void *map, size_t length,
92 int *error)
93{
94 avifRGBImage rgb;
95 avifROData raw;
96 avifDecoder *decoder;
97 avifImage *image;
98 avifResult res;
99
100 raw.size = length;
101 raw.data = (const uint8_t *)map;
102
103 decoder = avifDecoderCreate();
104 if (!decoder)
105 {
106 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
107 return EINA_FALSE;
108 }
109
110 image = avifImageCreateEmpty();
111 if (!image)
112 {
113 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
114 goto destroy_decoder;
115 }
116
117 res = avifDecoderRead(decoder, image, &raw);
118 if (res != AVIF_RESULT_OK)
119 {
120 ERR("avif file format invalid");
121 *error = EVAS_LOAD_ERROR_GENERIC;
122 goto destroy_image;
123 }
124
125 avifRGBImageSetDefaults(&rgb, image);
126 rgb.format = AVIF_RGB_FORMAT_BGRA;
127 rgb.depth = 8;
128 rgb.pixels = pixels;
129 rgb.rowBytes = 4 * image->width;
130
131 avifImageYUVToRGB(image, &rgb);
132
133 *error = EVAS_LOAD_ERROR_NONE;
134
135 avifImageDestroy(image);
136 avifDecoderDestroy(decoder);
137
138 return EINA_TRUE;
139
140 destroy_image:
141 avifImageDestroy(image);
142 destroy_decoder:
143 avifDecoderDestroy(decoder);
144
145 return EINA_FALSE;
146}
147
148static void *
149evas_image_load_file_open_avif(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
150 Evas_Image_Load_Opts *opts,
151 Evas_Image_Animated *animated EINA_UNUSED,
152 int *error)
153{
154 Evas_Loader_Internal *loader;
155
156 loader = calloc(1, sizeof (Evas_Loader_Internal));
157 if (!loader)
158 {
159 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
160 return NULL;
161 }
162
163 loader->f = f;
164 loader->opts = opts;
165
166 return loader;
167}
168
169static void
170evas_image_load_file_close_avif(void *loader_data)
171{
172 free(loader_data);
173}
174
175static Eina_Bool
176evas_image_load_file_head_avif(void *loader_data,
177 Emile_Image_Property *prop,
178 int *error)
179{
180 Evas_Loader_Internal *loader = loader_data;
181 Eina_File *f;
182 void *map;
183 Eina_Bool val;
184
185 f = loader->f;
186
187 map = eina_file_map_all(f, EINA_FILE_RANDOM);
188 if (!map)
189 {
190 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
191 return EINA_FALSE;
192 }
193
194 val = evas_image_load_file_head_avif_internal(&prop->w, &prop->h,
195 &prop->alpha,
196 map, eina_file_size_get(f),
197 error);
198
199 eina_file_map_free(f, map);
200
201 return val;
202}
203
204static Eina_Bool
205evas_image_load_file_data_avif(void *loader_data,
206 Emile_Image_Property *prop EINA_UNUSED,
207 void *pixels,
208 int *error)
209{
210 Evas_Loader_Internal *loader = loader_data;
211 Eina_File *f;
212 void *map;
213 Eina_Bool val = EINA_FALSE;
214
215 f = loader->f;
216
217 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
218 if (!map)
219 {
220 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
221 goto on_error;
222 }
223
224 val = evas_image_load_file_data_avif_internal(pixels,
225 map, eina_file_size_get(f),
226 error);
227
228 eina_file_map_free(f, map);
229
230 on_error:
231 return val;
232}
233
234static Evas_Image_Load_Func evas_image_load_avif_func =
235{
236 EVAS_IMAGE_LOAD_VERSION,
237 evas_image_load_file_open_avif,
238 evas_image_load_file_close_avif,
239 (void*) evas_image_load_file_head_avif,
240 NULL,
241 (void*) evas_image_load_file_data_avif,
242 NULL,
243 EINA_TRUE,
244 EINA_TRUE
245};
246
247static int
248module_open(Evas_Module *em)
249{
250 if (!em) return 0;
251
252 _evas_loader_avif_log_dom = eina_log_domain_register("evas-avif", EINA_COLOR_BLUE);
253 if (_evas_loader_avif_log_dom < 0)
254 {
255 EINA_LOG_ERR("Can not create a module log domain.");
256 return 0;
257 }
258
259 em->functions = (void *)(&evas_image_load_avif_func);
260
261 return 1;
262}
263
264static void
265module_close(Evas_Module *em EINA_UNUSED)
266{
267 if (_evas_loader_avif_log_dom >= 0)
268 {
269 eina_log_domain_unregister(_evas_loader_avif_log_dom);
270 _evas_loader_avif_log_dom = -1;
271 }
272}
273
274static Evas_Module_Api evas_modapi =
275{
276 EVAS_MODULE_API_VERSION,
277 "avif",
278 "none",
279 {
280 module_open,
281 module_close
282 }
283};
284
285EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, avif);
286
287#ifndef EVAS_STATIC_BUILD_AVIF
288EVAS_EINA_MODULE_DEFINE(image_loader, avif);
289#endif
290