From e42648154ff65e676ce1dec02ea00d5bc8308d46 Mon Sep 17 00:00:00 2001 From: Igor Murzov Date: Mon, 3 Sep 2012 06:22:59 +0000 Subject: [PATCH] From: Igor Murzov Subject: [E-devel] [PATCH][RESEND][Evas] WebP image loader This patch adds a WebP image loader to Evas. No saver, no animation support for now, just loader. Tested with the libwebp-0.2.0 only, but should work fine with older versions. SVN revision: 75951 --- legacy/evas/AUTHORS | 1 + legacy/evas/ChangeLog | 4 + legacy/evas/NEWS | 4 + legacy/evas/README | 3 + legacy/evas/configure.ac | 6 + legacy/evas/m4/evas_check_loader.m4 | 32 ++++ legacy/evas/src/bin/evas_cserve2_slave.c | 3 +- legacy/evas/src/bin/loaders/Makefile.am | 4 + legacy/evas/src/bin/loaders/webp/Makefile.am | 33 ++++ .../bin/loaders/webp/evas_image_load_webp.c | 135 ++++++++++++++ .../src/lib/engines/common/evas_image_load.c | 3 +- legacy/evas/src/lib/file/evas_module.c | 4 + legacy/evas/src/modules/loaders/Makefile.am | 6 + .../evas/src/modules/loaders/webp/Makefile.am | 35 ++++ .../loaders/webp/evas_image_load_webp.c | 165 ++++++++++++++++++ 15 files changed, 436 insertions(+), 2 deletions(-) create mode 100644 legacy/evas/src/bin/loaders/webp/Makefile.am create mode 100644 legacy/evas/src/bin/loaders/webp/evas_image_load_webp.c create mode 100644 legacy/evas/src/modules/loaders/webp/Makefile.am create mode 100644 legacy/evas/src/modules/loaders/webp/evas_image_load_webp.c diff --git a/legacy/evas/AUTHORS b/legacy/evas/AUTHORS index ae614e5898..f8c2a51874 100644 --- a/legacy/evas/AUTHORS +++ b/legacy/evas/AUTHORS @@ -37,3 +37,4 @@ Jérôme Pinot Rafael Antognolli Daniel Zaoui Christophe Sadoine +Igor Murzov diff --git a/legacy/evas/ChangeLog b/legacy/evas/ChangeLog index 2e9c5c9c09..dfce0a1f1a 100644 --- a/legacy/evas/ChangeLog +++ b/legacy/evas/ChangeLog @@ -1008,3 +1008,7 @@ * Fix seg fault in the esvg loader, latest code is required, and enable it on Windows. + +2012-09-03 Igor Murzov + + * Add WEBP loader module and cserve2 binary loader patch. diff --git a/legacy/evas/NEWS b/legacy/evas/NEWS index 27c0875928..6b9664892d 100644 --- a/legacy/evas/NEWS +++ b/legacy/evas/NEWS @@ -3,6 +3,10 @@ Evas 1.8.0 Changes since Evas 1.7.0: ------------------------- +Additions: + + * WEBP image loader support. + Improvements: * Function to rotate an evas map with a quaternion: evas_map_util_quat_rotate(). diff --git a/legacy/evas/README b/legacy/evas/README index 5e0b0bc674..7660890081 100644 --- a/legacy/evas/README +++ b/legacy/evas/README @@ -527,6 +527,9 @@ egueb this loader uses libtiff to load tiff image files +--enable-image-loader-webp[=static] + +this loader uses libwebp to load webp image files --enable-image-loader-xpm[=static] diff --git a/legacy/evas/configure.ac b/legacy/evas/configure.ac index 30f5785b3f..8dfd9bbee1 100644 --- a/legacy/evas/configure.ac +++ b/legacy/evas/configure.ac @@ -126,6 +126,7 @@ want_evas_image_loader_xpm="yes" want_evas_image_loader_bmp="yes" want_evas_image_loader_tga="yes" want_evas_image_loader_wbmp="yes" +want_evas_image_loader_webp="yes" want_evas_image_loader_ico="yes" want_evas_image_loader_psd="yes" want_evas_image_loader_generic="yes" @@ -1058,6 +1059,8 @@ EVAS_CHECK_IMAGE_LOADER([TGA], [${want_evas_image_loader_tga}]) EVAS_CHECK_IMAGE_LOADER([WBMP], [${want_evas_image_loader_wbmp}]) +EVAS_CHECK_IMAGE_LOADER([WEBP], [${want_evas_image_loader_webp}]) + EVAS_CHECK_IMAGE_LOADER([ICO], [${want_evas_image_loader_ico}]) EVAS_CHECK_IMAGE_LOADER([PSD], [${want_evas_image_loader_psd}]) @@ -1845,6 +1848,7 @@ src/bin/loaders/ico/Makefile src/bin/loaders/tga/Makefile src/bin/loaders/pmaps/Makefile src/bin/loaders/wbmp/Makefile +src/bin/loaders/webp/Makefile src/bin/loaders/psd/Makefile src/lib/Makefile src/lib/canvas/Makefile @@ -1900,6 +1904,7 @@ src/modules/loaders/tga/Makefile src/modules/loaders/svg/Makefile src/modules/loaders/pmaps/Makefile src/modules/loaders/wbmp/Makefile +src/modules/loaders/webp/Makefile src/modules/loaders/psd/Makefile src/modules/loaders/generic/Makefile src/modules/savers/Makefile @@ -1994,6 +1999,7 @@ echo " SVG.....................: $have_evas_image_loader_svg" echo " TGA.....................: $have_evas_image_loader_tga" echo " TIFF....................: $have_evas_image_loader_tiff" echo " WBMP....................: $have_evas_image_loader_wbmp" +echo " WEBP....................: $have_evas_image_loader_webp" echo " XPM.....................: $have_evas_image_loader_xpm" echo echo "Font Sourcing Systems:" diff --git a/legacy/evas/m4/evas_check_loader.m4 b/legacy/evas/m4/evas_check_loader.m4 index cf4924ecc9..01304847e2 100644 --- a/legacy/evas/m4/evas_check_loader.m4 +++ b/legacy/evas/m4/evas_check_loader.m4 @@ -429,6 +429,38 @@ fi ]) +dnl use: EVAS_CHECK_LOADER_DEP_WEBP(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) + +AC_DEFUN([EVAS_CHECK_LOADER_DEP_WEBP], +[ + +have_dep="no" +evas_image_loader_[]$1[]_cflags="" +evas_image_loader_[]$1[]_libs="" + +AC_CHECK_HEADER([webp/decode.h], [have_dep="yes"]) + +if test "x${have_dep}" = "xyes" ; then + AC_CHECK_LIB([webp], + [WebPDecodeRGBA], + [ + evas_image_loader_[]$1[]_libs="-lwebp" + ], + [have_dep="no"] + ) +fi + +AC_SUBST([evas_image_loader_$1_cflags]) +AC_SUBST([evas_image_loader_$1_libs]) + +if test "x${have_dep}" = "xyes" ; then + m4_default([$3], [:]) +else + m4_default([$4], [:]) +fi + +]) + dnl use: EVAS_CHECK_LOADER_DEP_GENERIC(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) AC_DEFUN([EVAS_CHECK_LOADER_DEP_GENERIC], diff --git a/legacy/evas/src/bin/evas_cserve2_slave.c b/legacy/evas/src/bin/evas_cserve2_slave.c index a11c6351ec..9a1e01b5b9 100644 --- a/legacy/evas/src/bin/evas_cserve2_slave.c +++ b/legacy/evas/src/bin/evas_cserve2_slave.c @@ -50,6 +50,7 @@ static const struct ext_loader_s map_loaders[] = MATCHING(".bmp", "bmp"), MATCHING(".tga", "tga"), MATCHING(".wbmp", "wbmp"), + MATCHING(".webp", "webp"), MATCHING(".ico", "ico"), MATCHING(".cur", "ico"), MATCHING(".psd", "psd") @@ -57,7 +58,7 @@ static const struct ext_loader_s map_loaders[] = static const char *loaders_name[] = { /* in order of most likely needed */ - "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "edb" + "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "edb" }; Eina_Bool diff --git a/legacy/evas/src/bin/loaders/Makefile.am b/legacy/evas/src/bin/loaders/Makefile.am index 46222c843c..96d0c5eac6 100644 --- a/legacy/evas/src/bin/loaders/Makefile.am +++ b/legacy/evas/src/bin/loaders/Makefile.am @@ -42,6 +42,10 @@ if BUILD_LOADER_WBMP SUBDIRS += wbmp endif +if BUILD_LOADER_WEBP +SUBDIRS += webp +endif + if BUILD_LOADER_XPM SUBDIRS += xpm endif diff --git a/legacy/evas/src/bin/loaders/webp/Makefile.am b/legacy/evas/src/bin/loaders/webp/Makefile.am new file mode 100644 index 0000000000..9f186ff548 --- /dev/null +++ b/legacy/evas/src/bin/loaders/webp/Makefile.am @@ -0,0 +1,33 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/lib/include \ +-I$(top_srcdir)/src/lib/cserve2 \ +-I$(top_srcdir)/src/bin \ +@EINA_CFLAGS@ \ +@evas_image_loader_webp_cflags@ \ +@EVIL_CFLAGS@ + +if BUILD_LOADER_WEBP +#if !EVAS_STATIC_BUILD_WEBP + +pkgdir = $(libdir)/evas/cserve2/loaders/webp/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = evas_image_load_webp.c + +module_la_LIBADD = @EINA_LIBS@ @evas_image_loader_webp_libs@ @EVIL_LIBS@ +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static + +#else + +#noinst_LTLIBRARIES = libevas_loader_webp.la +#libevas_loader_webp_la_SOURCES = evas_image_load_webp.c +#libevas_loader_webp_la_LIBADD = @evas_image_loader_webp_libs@ + +#endif +endif diff --git a/legacy/evas/src/bin/loaders/webp/evas_image_load_webp.c b/legacy/evas/src/bin/loaders/webp/evas_image_load_webp.c new file mode 100644 index 0000000000..6adf0ea9a3 --- /dev/null +++ b/legacy/evas/src/bin/loaders/webp/evas_image_load_webp.c @@ -0,0 +1,135 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "evas_macros.h" + +#include "evas_cserve2.h" +#include "evas_cserve2_slave.h" + + +static Eina_Bool +evas_image_load_file_head_webp(Evas_Img_Load_Params *ilp, const char *file, const char *key __UNUSED__, int *error) +{ + WebPDecoderConfig config; + FILE *f; + size_t header_size = 30; + uint8_t header[30]; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + if (fread(header, header_size, 1, f) != 1) + { + fclose(f); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; + } + fclose(f); + + if (!WebPInitDecoderConfig(&config)) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; + } + if (WebPGetFeatures(header, header_size, &config.input) != VP8_STATUS_OK) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; + } + + ilp->w = config.input.width; + ilp->h = config.input.height; + ilp->alpha = config.input.has_alpha; + + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; +} + +static Eina_Bool +evas_image_load_file_data_webp(Evas_Img_Load_Params *ilp, const char *file, const char *key __UNUSED__, int *error) +{ + FILE *f; + size_t file_size; + uint8_t *data, *decoded; + int width, height; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + if (fseek(f, 0, SEEK_END) != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + file_size = ftell(f); + if (fseek(f, 0, SEEK_SET) != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + + data = malloc(file_size); + if (!data) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + if (fread(data, file_size, 1, f) != 1) + { + free(data); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + fclose(f); + + decoded = WebPDecodeBGRA(data, file_size, &width, &height); + memcpy(ilp->buffer, decoded, width * height * 4); + evas_cserve2_image_premul(ilp); + + free(decoded); + free(data); + + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; + +close_file: + fclose(f); + return EINA_FALSE; +} + +static Evas_Loader_Module_Api modapi = +{ + EVAS_CSERVE2_MODULE_API_VERSION, + "webp", + evas_image_load_file_head_webp, + evas_image_load_file_data_webp +}; + +static Eina_Bool +module_init(void) +{ + return evas_cserve2_loader_register(&modapi); +} + +static void +module_shutdown(void) +{ +} + +EINA_MODULE_INIT(module_init); +EINA_MODULE_SHUTDOWN(module_shutdown); diff --git a/legacy/evas/src/lib/engines/common/evas_image_load.c b/legacy/evas/src/lib/engines/common/evas_image_load.c index 386bb766c5..d88cbecd99 100644 --- a/legacy/evas/src/lib/engines/common/evas_image_load.c +++ b/legacy/evas/src/lib/engines/common/evas_image_load.c @@ -47,6 +47,7 @@ static const struct ext_loader_s loaders[] = MATCHING(".bmp", "bmp"), MATCHING(".tga", "tga"), MATCHING(".wbmp", "wbmp"), + MATCHING(".webp", "webp"), MATCHING(".ico", "ico"), MATCHING(".cur", "ico"), MATCHING(".psd", "psd"), @@ -127,7 +128,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", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "edb", "generic" + "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "webp", "pmaps", "bmp", "tga", "wbmp", "ico", "psd", "edb", "generic" }; struct evas_image_foreach_loader_data diff --git a/legacy/evas/src/lib/file/evas_module.c b/legacy/evas/src/lib/file/evas_module.c index 3c9378dd6a..7bc52bcaec 100644 --- a/legacy/evas/src/lib/file/evas_module.c +++ b/legacy/evas/src/lib/file/evas_module.c @@ -123,6 +123,7 @@ EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, svg); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tga); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, tiff); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, wbmp); +EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, webp); EVAS_EINA_STATIC_MODULE_DEFINE(image_loader, xpm); EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, edb); EVAS_EINA_STATIC_MODULE_DEFINE(image_saver, eet); @@ -233,6 +234,9 @@ static const struct { #ifdef EVAS_STATIC_BUILD_WBMP EVAS_EINA_STATIC_MODULE_USE(image_loader, wbmp), #endif +#ifdef EVAS_STATIC_BUILD_WEBP + EVAS_EINA_STATIC_MODULE_USE(image_loader, webp), +#endif #ifdef EVAS_STATIC_BUILD_XPM EVAS_EINA_STATIC_MODULE_USE(image_loader, xpm), #endif diff --git a/legacy/evas/src/modules/loaders/Makefile.am b/legacy/evas/src/modules/loaders/Makefile.am index b7ed9a5324..8122e56477 100644 --- a/legacy/evas/src/modules/loaders/Makefile.am +++ b/legacy/evas/src/modules/loaders/Makefile.am @@ -86,6 +86,12 @@ SUBDIRS += wbmp endif endif +if BUILD_LOADER_WEBP +if !EVAS_STATIC_BUILD_WEBP +SUBDIRS += webp +endif +endif + if BUILD_LOADER_XPM if !EVAS_STATIC_BUILD_XPM SUBDIRS += xpm diff --git a/legacy/evas/src/modules/loaders/webp/Makefile.am b/legacy/evas/src/modules/loaders/webp/Makefile.am new file mode 100644 index 0000000000..c10b5b91aa --- /dev/null +++ b/legacy/evas/src/modules/loaders/webp/Makefile.am @@ -0,0 +1,35 @@ + +MAINTAINERCLEANFILES = Makefile.in + +AM_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/src/lib \ +-I$(top_srcdir)/src/lib/include \ +@FREETYPE_CFLAGS@ \ +@PIXMAN_CFLAGS@ \ +@EINA_CFLAGS@ \ +@FRIBIDI_CFLAGS@ \ +@evas_image_loader_webp_cflags@ \ +@EVIL_CFLAGS@ + +if BUILD_LOADER_WEBP +if !EVAS_STATIC_BUILD_WEBP + +pkgdir = $(libdir)/evas/modules/loaders/webp/$(MODULE_ARCH) +pkg_LTLIBRARIES = module.la + +module_la_SOURCES = evas_image_load_webp.c + +module_la_LIBADD = @EINA_LIBS@ @EVIL_LIBS@ @evas_image_loader_webp_libs@ $(top_builddir)/src/lib/libevas.la +module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version +module_la_LIBTOOLFLAGS = --tag=disable-static + +else + +noinst_LTLIBRARIES = libevas_loader_webp.la + +libevas_loader_webp_la_SOURCES = evas_image_load_webp.c +libevas_loader_webp_la_LIBADD = @evas_image_loader_webp_libs@ + +endif +endif diff --git a/legacy/evas/src/modules/loaders/webp/evas_image_load_webp.c b/legacy/evas/src/modules/loaders/webp/evas_image_load_webp.c new file mode 100644 index 0000000000..5b2391001c --- /dev/null +++ b/legacy/evas/src/modules/loaders/webp/evas_image_load_webp.c @@ -0,0 +1,165 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#ifdef HAVE_EVIL +# include +#endif + +#include "evas_common.h" +#include "evas_private.h" + +static Eina_Bool evas_image_load_file_head_webp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); +static Eina_Bool evas_image_load_file_data_webp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4); + +static Evas_Image_Load_Func evas_image_load_webp_func = +{ + EINA_TRUE, + evas_image_load_file_head_webp, + evas_image_load_file_data_webp, + NULL, + EINA_FALSE +}; + + +static Eina_Bool +evas_image_load_file_head_webp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) +{ + WebPDecoderConfig config; + FILE *f; + size_t header_size = 30; + uint8_t header[30]; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + if (fread(header, header_size, 1, f) != 1) + { + fclose(f); + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + return EINA_FALSE; + } + fclose(f); + + if (!WebPInitDecoderConfig(&config)) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; + } + if (WebPGetFeatures(header, header_size, &config.input) != VP8_STATUS_OK) + { + *error = EVAS_LOAD_ERROR_CORRUPT_FILE; + return EINA_FALSE; + } + + ie->w = config.input.width; + ie->h = config.input.height; + ie->flags.alpha = config.input.has_alpha; + + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; +} + +static Eina_Bool +evas_image_load_file_data_webp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error) +{ + FILE *f; + size_t file_size; + uint8_t *data, *decoded, *surface; + int width, height; + + f = fopen(file, "rb"); + if (!f) + { + *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST; + return EINA_FALSE; + } + + if (fseek(f, 0, SEEK_END) != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + file_size = ftell(f); + + if (fseek(f, 0, SEEK_SET) != 0) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto close_file; + } + + data = malloc(file_size); + if (!data) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto close_file; + } + if (fread(data, file_size, 1, f) != 1) + { + *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT; + goto free_data; + } + + evas_cache_image_surface_alloc(ie, ie->w, ie->h); + surface = evas_cache_image_pixels(ie); + if (!surface) + { + *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; + goto free_data; + } + + decoded = WebPDecodeBGRA(data, file_size, &width, &height); + memcpy(surface, decoded, width * height * 4); + evas_common_image_premul(ie); + + free(decoded); + free(data); + fclose(f); + + *error = EVAS_LOAD_ERROR_NONE; + return EINA_TRUE; + +free_data: + free(data); + +close_file: + fclose(f); + return EINA_FALSE; +} + +static int +module_open(Evas_Module *em) +{ + if (!em) return 0; + em->functions = (void *)(&evas_image_load_webp_func); + return 1; +} + +static void +module_close(Evas_Module *em __UNUSED__) +{ +} + +static Evas_Module_Api evas_modapi = +{ + EVAS_MODULE_API_VERSION, + "webp", + "none", + { + module_open, + module_close + } +}; + +EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, webp); + +#ifndef EVAS_STATIC_BUILD_WEBP +EVAS_EINA_MODULE_DEFINE(image_loader, webp); +#endif