diff options
author | Vincent Torri <vincent.torri@gmail.com> | 2020-07-15 18:51:27 +0100 |
---|---|---|
committer | Carsten Haitzler (Rasterman) <raster@rasterman.com> | 2020-07-15 18:51:27 +0100 |
commit | fd24e89144d8808e4e7ee20efe599ff4a6d3d37e (patch) | |
tree | 11634a58ed8a143580142b8aa7f52eac8271ee36 /src/lib/evas | |
parent | a8538bacce1457a91e28b39a6417eaadb4744b50 (diff) |
Evas: add avif evas loader and saver
Summary:
Add AV1 image file loader and saver to Evas
The loader can be tested with this code :
```
#include <stdlib.h>
#include <stdio.h>
#include <Eina.h>
#include <Ecore.h>
#include <Evas.h>
#include <Ecore_Evas.h>
static int i = 0;
static unsigned char _timer(void *data)
{
Evas_Object *o = (Evas_Object *)data;
if (i < evas_object_image_animated_frame_count_get(o))
{
evas_object_image_animated_frame_set(o, i);
i++;
return ECORE_CALLBACK_RENEW;
}
return ECORE_CALLBACK_DONE;
}
static void _quit(Ecore_Evas *ee)
{
ecore_main_loop_quit();
(void)ee;
}
int main(int argc, char *argv[])
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *o;
int w,h;
Evas_Load_Error err;
if (argc < 2)
{
printf("usage : %s file\n", argv[0]);
return 1;
}
ecore_evas_init();
ee = ecore_evas_new(NULL, 0, 0, 1, 1, NULL);
if (!ee)
{
printf("no ee\n");
return 0;
}
evas = ecore_evas_get(ee);
ecore_evas_title_set(ee, "avif test");
ecore_evas_callback_delete_request_set(ee, _quit);
o = evas_object_image_add(evas);
evas_object_image_file_set(o, argv[1], NULL);
err = evas_object_image_load_error_get(o);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
argv[1], evas_load_error_str(err));
return 1;
}
evas_object_image_size_get(o, &w, &h);
evas_object_image_fill_set(o, 0, 0, w, h);
evas_object_move(o, 0, 0);
evas_object_resize(o, w, h);
evas_object_show(o);
printf("animated : %s\n", evas_object_image_animated_get(o) ? "yes" : "no");
fflush(stdout);
if (evas_object_image_animated_get(o))
{
Ecore_Timer *timer;
printf("frame count : %d\n", evas_object_image_animated_frame_count_get(o));
printf("duration : %f\n", evas_object_image_animated_frame_duration_get(o,1,0));
printf("loop count : %d\n", evas_object_image_animated_loop_count_get(o));
fflush(stdout);
timer = ecore_timer_add(evas_object_image_animated_frame_duration_get(o,1,0), _timer, o);
}
ecore_evas_resize(ee, w, h);
ecore_evas_show(ee);
ecore_main_loop_begin();
ecore_evas_shutdown();
return 0;
}
```
non animated files : https://github.com/AOMediaCodec/libavif/tree/master/tests/data/originals
animated files : https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles/Netflix/avifs
to test the saver :
```
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <Eina.h>
#include <Ecore.h>
#include <Evas.h>
#include <Ecore_Evas.h>
void _quit(Ecore_Evas *ee)
{
ecore_main_loop_quit();
(void)ee;
}
static Evas_Object *
display_data(int w, int h, const char *title, unsigned int *data)
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *o;
unsigned int *d;
ee = ecore_evas_new(NULL, 0, 0, w, h, NULL);
if (!ee)
return NULL;
evas = ecore_evas_get(ee);
ecore_evas_title_set(ee, title);
ecore_evas_callback_delete_request_set(ee, _quit);
o = evas_object_image_add(evas);
evas_object_image_fill_set(o, 0, 0, w, h);
evas_object_image_size_set(o, w, h);
d = evas_object_image_data_get(o, 1);
for (int i = 0; i < w*h; i++)
d[i] = data[i];
evas_object_image_data_set(o, d);
evas_object_image_data_update_add(o, 0, 0, w, h);
evas_object_move(o, 0, 0);
evas_object_resize(o, w, h);
evas_object_show(o);
ecore_evas_show(ee);
return o;
}
static unsigned int *
display_file(const char *title, const char *filename, int *w, int *h)
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *o;
Evas_Load_Error err;
unsigned int *data;
ee = ecore_evas_new(NULL, 0, 0, 1, 1, NULL);
if (!ee)
return NULL;
evas = ecore_evas_get(ee);
ecore_evas_title_set(ee, title);
ecore_evas_callback_delete_request_set(ee, _quit);
o = evas_object_image_add(evas);
evas_object_image_file_set(o, filename, NULL);
err = evas_object_image_load_error_get(o);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
filename, evas_load_error_str(err));
fflush(stderr);
return NULL;
}
evas_object_image_size_get(o, w, h);
evas_object_image_fill_set(o, 0, 0, *w, *h);
evas_object_image_size_set(o, *w, *h);
evas_object_move(o, 0, 0);
evas_object_resize(o, *w, *h);
evas_object_show(o);
ecore_evas_resize(ee, *w, *h);
ecore_evas_show(ee);
data = evas_object_image_data_get(o, 1);
return data;
}
double psnr(int w, int h, unsigned int *data_orig, unsigned int *data)
{
unsigned char *iter_orig;
unsigned char *iter;
double psnr;
psnr = 0.0;
iter_orig = (unsigned char *)data_orig;
iter = (unsigned char *)data;
for (int i = 0; i < 4 * w * h; i++, iter_orig++, iter++)
psnr += (*iter_orig - *iter) * (*iter_orig - *iter);
psnr /= 4 * w * h;
psnr = 10 * log10(255.0 * 255.0 / psnr);
return psnr;
}
void compare(int quality, int w, int h, unsigned int *data_orig)
{
char title[1024];
char filename[1024];
unsigned char *data;
unsigned int *data_jpeg;
unsigned int *data_avif;
unsigned char *iter_orig;
unsigned char *iter_jpeg;
unsigned char *iter_avif;
double psnr_jpeg;
double psnr_avif;
Eina_File *f_jpeg;
Eina_File *f_avif;
size_t size_jpeg;
size_t size_avif;
/* jpeg */
snprintf(title, sizeof(title), "jpeg test quality %d", quality);
snprintf(filename, sizeof(filename), "test_%d.jpg", quality);
data_jpeg = display_file(title, filename, &w, &h);
if (!data_jpeg)
return;
f_jpeg = eina_file_open(filename, EINA_FALSE);
size_jpeg = eina_file_size_get(f_jpeg);
eina_file_close(f_jpeg);
fprintf(stderr, "size : %u\n", (unsigned int)size_jpeg);
fflush(stderr);
/* avif */
snprintf(title, sizeof(title), "avif test quality %d", quality);
snprintf(filename, sizeof(filename), "test_%d.avif", quality);
data_avif = display_file(title, filename, &w, &h);
if (!data_avif)
return;
f_avif = eina_file_open(filename, EINA_FALSE);
size_avif = eina_file_size_get(f_avif);
eina_file_close(f_avif);
fprintf(stderr, "size : %u\n", (unsigned int)size_avif);
fflush(stderr);
psnr_jpeg = psnr(w, h, data_orig, data_jpeg);
fprintf(stderr, "psnr jpeg : %f\n", psnr_jpeg);
fflush(stderr);
snprintf(title, sizeof(title), "jpeg vs orig (psnr: %.2f, size: %u b)", psnr_jpeg, (unsigned int)size_jpeg);
iter_orig = (unsigned char *)data_orig;
iter_jpeg = (unsigned char *)data_jpeg;
data = malloc(4*w*h);
for (int i = 0; i < 4*w*h; i++, iter_orig++, iter_jpeg++)
data[i] = abs(*iter_jpeg - *iter_orig);
display_data(w, h, title, (unsigned int *)data);
psnr_avif = psnr(w, h, data_orig, data_avif);
fprintf(stderr, "psnr avif : %f\n", psnr_avif);
fflush(stderr);
snprintf(title, sizeof(title), "avif vs orig (psnr: %.2f, size: %u b)", psnr_avif, (unsigned int)size_avif);
iter_orig = (unsigned char *)data_orig;
iter_avif = (unsigned char *)data_avif;
data = malloc(4*w*h);
for (int i = 0; i < 4*w*h; i++, iter_orig++, iter_avif++)
data[i] = abs(*iter_avif - *iter_orig);
display_data(w, h, title, (unsigned int *)data);
}
int main()
{
Ecore_Evas *ee;
Evas *evas;
Evas_Object *o;
Evas_Load_Error err;
unsigned int *data;
int w,h;
ecore_evas_init();
ee = ecore_evas_new(NULL, 0, 0, 1, 1, NULL);
if (!ee)
return 1;
evas = ecore_evas_get(ee);
ecore_evas_title_set(ee, "original");
ecore_evas_callback_delete_request_set(ee, _quit);
o = evas_object_image_add(evas);
evas_object_image_file_set(o, "x1d-II-sample-02.fff", NULL);
err = evas_object_image_load_error_get(o);
if (err != EVAS_LOAD_ERROR_NONE)
{
fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
"x1d-II-sample-02.fff", evas_load_error_str(err));
fflush(stderr);
return 1;
}
evas_object_image_size_get(o, &w, &h);
evas_object_image_fill_set(o, 0, 0, w, h);
evas_object_image_size_set(o, w, h);
evas_object_move(o, 0, 0);
evas_object_resize(o, w, h);
evas_object_show(o);
data = evas_object_image_data_get(o, 1);
ecore_evas_resize(ee, w, h);
ecore_evas_show(ee);
/* evas_object_image_save(o, "test_100.jpg", NULL, "quality=100"); */
evas_object_image_save(o, "test_90.jpg", NULL, "quality=90");
/* evas_object_image_save(o, "test_70.jpg", NULL, "quality=70"); */
/* evas_object_image_save(o, "test_50.jpg", NULL, "quality=50"); */
/* evas_object_image_save(o, "test_100.avif", NULL, "quality=100"); */
evas_object_image_save(o, "test_90.avif", NULL, "quality=90");
/* evas_object_image_save(o, "test_70.avif", NULL, "quality=70"); */
/* evas_object_image_save(o, "test_50.avif", NULL, "quality=50"); */
compare(90, w, h, data);
ecore_main_loop_begin();
ecore_evas_shutdown();
return 0;
}
```
the raw file canbe found here : https://www.hasselblad.com/learn/sample-images/
Test Plan: test executable with avif files found in libavif project
Reviewers: raster, q66
Reviewed By: q66
Subscribers: q66, cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D12051
Diffstat (limited to 'src/lib/evas')
-rw-r--r-- | src/lib/evas/common/evas_image_load.c | 6 | ||||
-rw-r--r-- | src/lib/evas/common/evas_image_save.c | 2 | ||||
-rw-r--r-- | src/lib/evas/file/evas_module.c | 8 | ||||
-rw-r--r-- | src/lib/evas/meson.build | 3 |
4 files changed, 18 insertions, 1 deletions
diff --git a/src/lib/evas/common/evas_image_load.c b/src/lib/evas/common/evas_image_load.c index 1d28253c7e..96caa1627e 100644 --- a/src/lib/evas/common/evas_image_load.c +++ b/src/lib/evas/common/evas_image_load.c | |||
@@ -66,6 +66,9 @@ static const struct ext_loader_s loaders[] = | |||
66 | 66 | ||
67 | MATCHING(".dds", "dds"), | 67 | MATCHING(".dds", "dds"), |
68 | 68 | ||
69 | MATCHING(".avif", "avif"), | ||
70 | MATCHING(".avifs", "avif"), | ||
71 | |||
69 | /* xcf - gefenric */ | 72 | /* xcf - gefenric */ |
70 | MATCHING(".xcf", "generic"), | 73 | MATCHING(".xcf", "generic"), |
71 | MATCHING(".xcf.gz", "generic"), | 74 | MATCHING(".xcf.gz", "generic"), |
@@ -93,6 +96,7 @@ static const struct ext_loader_s loaders[] = | |||
93 | MATCHING(".dcr", "generic"), | 96 | MATCHING(".dcr", "generic"), |
94 | MATCHING(".dng", "generic"), | 97 | MATCHING(".dng", "generic"), |
95 | MATCHING(".erf", "generic"), | 98 | MATCHING(".erf", "generic"), |
99 | MATCHING(".fff", "generic"), | ||
96 | MATCHING(".k25", "generic"), | 100 | MATCHING(".k25", "generic"), |
97 | MATCHING(".kdc", "generic"), | 101 | MATCHING(".kdc", "generic"), |
98 | MATCHING(".mrw", "generic"), | 102 | MATCHING(".mrw", "generic"), |
@@ -163,7 +167,7 @@ static const struct ext_loader_s loaders[] = | |||
163 | static const char *loaders_name[] = | 167 | static const char *loaders_name[] = |
164 | { /* in order of most likely needed */ | 168 | { /* in order of most likely needed */ |
165 | "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", | 169 | "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", |
166 | "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "generic" | 170 | "bmp", "tga", "wbmp", "ico", "psd", "jp2k", "dds", "avif", "generic" |
167 | }; | 171 | }; |
168 | 172 | ||
169 | struct evas_image_foreach_loader_data | 173 | struct evas_image_foreach_loader_data |
diff --git a/src/lib/evas/common/evas_image_save.c b/src/lib/evas/common/evas_image_save.c index 9a6a7621c1..45718c5b9f 100644 --- a/src/lib/evas/common/evas_image_save.c +++ b/src/lib/evas/common/evas_image_save.c | |||
@@ -33,6 +33,8 @@ evas_common_save_image_to_file(RGBA_Image *im, const char *file, const char *key | |||
33 | saver = "webp"; | 33 | saver = "webp"; |
34 | if (!strcasecmp(p, "tgv")) | 34 | if (!strcasecmp(p, "tgv")) |
35 | saver = "tgv"; | 35 | saver = "tgv"; |
36 | if (!strcasecmp(p, "avif")) | ||
37 | saver = "avif"; | ||
36 | } | 38 | } |
37 | 39 | ||
38 | if (saver) | 40 | if (saver) |
diff --git a/src/lib/evas/file/evas_module.c b/src/lib/evas/file/evas_module.c index a1e8b623af..83f1d804df 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 |
199 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, avif); | ||
199 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp); | 200 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, bmp); |
200 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds); | 201 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, dds); |
201 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet); | 202 | EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, eet); |
@@ -222,6 +223,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(vg_saver, svg); | |||
222 | #endif | 223 | #endif |
223 | 224 | ||
224 | #if !EVAS_MODULE_NO_IMAGE_SAVERS | 225 | #if !EVAS_MODULE_NO_IMAGE_SAVERS |
226 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, avif); | ||
225 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet); | 227 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet); |
226 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg); | 228 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg); |
227 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png); | 229 | EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png); |
@@ -287,6 +289,9 @@ static const struct { | |||
287 | #endif | 289 | #endif |
288 | #endif | 290 | #endif |
289 | #if !EVAS_MODULE_NO_IMAGE_LOADERS | 291 | #if !EVAS_MODULE_NO_IMAGE_LOADERS |
292 | #ifdef EVAS_STATIC_BUILD_AVIF | ||
293 | EVAS_EINA_STATIC_MODULE_USE(image_loader, avif), | ||
294 | #endif | ||
290 | #ifdef EVAS_STATIC_BUILD_BMP | 295 | #ifdef EVAS_STATIC_BUILD_BMP |
291 | EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp), | 296 | EVAS_EINA_STATIC_MODULE_USE(image_loader, bmp), |
292 | #endif | 297 | #endif |
@@ -351,6 +356,9 @@ static const struct { | |||
351 | #endif | 356 | #endif |
352 | #endif | 357 | #endif |
353 | #if !EVAS_MODULE_NO_IMAGE_SAVERS | 358 | #if !EVAS_MODULE_NO_IMAGE_SAVERS |
359 | #ifdef EVAS_STATIC_BUILD_AVIF | ||
360 | EVAS_EINA_STATIC_MODULE_USE(image_saver, avif), | ||
361 | #endif | ||
354 | #ifdef EVAS_STATIC_BUILD_EET | 362 | #ifdef EVAS_STATIC_BUILD_EET |
355 | EVAS_EINA_STATIC_MODULE_USE(image_saver, eet), | 363 | EVAS_EINA_STATIC_MODULE_USE(image_saver, eet), |
356 | #endif | 364 | #endif |
diff --git a/src/lib/evas/meson.build b/src/lib/evas/meson.build index fca88309ad..56dabb9eb4 100644 --- a/src/lib/evas/meson.build +++ b/src/lib/evas/meson.build | |||
@@ -10,8 +10,10 @@ giflib = cc.find_library('gif') | |||
10 | webp = dependency('libwebp', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) | 10 | webp = dependency('libwebp', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) |
11 | webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) | 11 | webpdemux = dependency('libwebpdemux', version: ['>=0.5.0'], required: get_option('evas-loaders-disabler').contains('webp') == false) |
12 | libopenjp2 = dependency('libopenjp2', required: get_option('evas-loaders-disabler').contains('jp2k') == false) | 12 | libopenjp2 = dependency('libopenjp2', required: get_option('evas-loaders-disabler').contains('jp2k') == false) |
13 | libavif = dependency('libavif', required: get_option('evas-loaders-disabler').contains('avif') == false) | ||
13 | 14 | ||
14 | evas_image_loaders_file = [ | 15 | evas_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]], |
@@ -31,6 +33,7 @@ evas_image_loaders_file = [ | |||
31 | ] | 33 | ] |
32 | 34 | ||
33 | evas_image_savers_file = [ | 35 | evas_image_savers_file = [ |
36 | ['avif', 'shared', [libavif]], | ||
34 | ['eet', 'static', [eet]], | 37 | ['eet', 'static', [eet]], |
35 | ['jpeg', 'static', [jpeg]], | 38 | ['jpeg', 'static', [jpeg]], |
36 | ['png', 'static', [png]], | 39 | ['png', 'static', [png]], |