summaryrefslogtreecommitdiff
path: root/src/lib/evas
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2020-07-15 18:51:27 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-07-15 18:51:27 +0100
commitfd24e89144d8808e4e7ee20efe599ff4a6d3d37e (patch)
tree11634a58ed8a143580142b8aa7f52eac8271ee36 /src/lib/evas
parenta8538bacce1457a91e28b39a6417eaadb4744b50 (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.c6
-rw-r--r--src/lib/evas/common/evas_image_save.c2
-rw-r--r--src/lib/evas/file/evas_module.c8
-rw-r--r--src/lib/evas/meson.build3
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[] =
163static const char *loaders_name[] = 167static 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
169struct evas_image_foreach_loader_data 173struct 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
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);
@@ -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
226EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, avif);
225EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet); 227EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet);
226EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg); 228EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, jpeg);
227EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, png); 229EVAS_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')
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]],
@@ -31,6 +33,7 @@ evas_image_loaders_file = [
31] 33]
32 34
33evas_image_savers_file = [ 35evas_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]],