kwo pushed a commit to branch master. http://git.enlightenment.org/legacy/imlib2.git/commit/?id=3f4d80dc82760eff81fb4e5348d04d48b9de3740
commit 3f4d80dc82760eff81fb4e5348d04d48b9de3740 Author: Kim Woelders <[email protected]> Date: Sun Aug 11 17:38:54 2019 +0200 Add new WebP loader Contributed by Jason Andresen <[email protected]>. --- configure.ac | 22 +++++ src/modules/loaders/Makefile.am | 10 ++ src/modules/loaders/loader_webp.c | 188 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) diff --git a/configure.ac b/configure.ac index f414810..f00c750 100644 --- a/configure.ac +++ b/configure.ac @@ -192,6 +192,27 @@ else fi AM_CONDITIONAL(BUILD_PNG_LOADER, test "$png_ok" = yes) +AC_MSG_CHECKING(whether to enable webp support) +AC_ARG_WITH([webp], + [AS_HELP_STRING([--without-webp], [Disable WEBP image loader])], + [ + if test "$withval" = no ; then + webp_loader=no + else + webp_loader=yes + fi + ], + [ webp_loader=auto ] +) +AC_MSG_RESULT($webp_loader) + +if test "$webp_loader" != no ; then + PKG_CHECK_MODULES(WEBP, libwebp, [ webp_ok="yes" ], [ webp_ok="no" ]) +else + webp_ok="no" +fi +AM_CONDITIONAL(BUILD_WEBP_LOADER, test "$webp_ok" = yes) + AC_MSG_CHECKING(whether to enable tiff support) AC_ARG_WITH([tiff], @@ -453,6 +474,7 @@ echo " JPEG....................: $jpeg_ok" echo " PNG.....................: $png_ok" echo " TIFF....................: $tiff_ok" echo " GIF.....................: $gif_ok" +echo " WEBP....................: $webp_ok" echo " ZLIB....................: $zlib_ok" echo " BZIP2...................: $bz2_ok" echo " ID3.....................: $id3_ok" diff --git a/src/modules/loaders/Makefile.am b/src/modules/loaders/Makefile.am index 2292c00..f498a74 100644 --- a/src/modules/loaders/Makefile.am +++ b/src/modules/loaders/Makefile.am @@ -23,6 +23,9 @@ endif if BUILD_TIFF_LOADER TIFF_L = tiff.la endif +if BUILD_WEBP_LOADER +WEBP_L = webp.la +endif if BUILD_ZLIB_LOADER ZLIB_L = zlib.la endif @@ -41,6 +44,7 @@ $(PNG_L) \ pnm.la \ tga.la \ $(TIFF_L) \ +$(WEBP_L) \ xpm.la \ $(ZLIB_L) @@ -112,6 +116,12 @@ tiff_la_LDFLAGS = -module -avoid-version tiff_la_LIBADD = @TIFFLIBS@ $(top_builddir)/src/lib/libImlib2.la tiff_la_LIBTOOLFLAGS = --tag=disable-static +webp_la_SOURCES = loader_webp.c +webp_la_CPPFLAGS = @WEBP_CFLAGS@ $(AM_CPPFLAGS) +webp_la_LDFLAGS = -module -avoid-version +webp_la_LIBADD = @WEBP_LIBS@ $(top_builddir)/src/lib/libImlib2.la +webp_la_LIBTOOLFLAGS = --tag=disable-static + xpm_la_SOURCES = loader_xpm.c xpm_la_LDFLAGS = -module -avoid-version xpm_la_LIBADD = $(top_builddir)/src/lib/libImlib2.la diff --git a/src/modules/loaders/loader_webp.c b/src/modules/loaders/loader_webp.c new file mode 100644 index 0000000..8f04cce --- /dev/null +++ b/src/modules/loaders/loader_webp.c @@ -0,0 +1,188 @@ +#include "loader_common.h" + +#include <fcntl.h> +#include <sys/stat.h> +#include <webp/decode.h> +#include <webp/encode.h> + +static const char * +webp_strerror(VP8StatusCode code) +{ + switch (code) + { + case VP8_STATUS_OK: + return "No Error"; + case VP8_STATUS_OUT_OF_MEMORY: + return "Out of memory"; + case VP8_STATUS_INVALID_PARAM: + return "Invalid API parameter"; + case VP8_STATUS_BITSTREAM_ERROR: + return "Bitstream Error"; + case VP8_STATUS_UNSUPPORTED_FEATURE: + return "Unsupported Feature"; + case VP8_STATUS_SUSPENDED: + return "Suspended"; + case VP8_STATUS_USER_ABORT: + return "User abort"; + case VP8_STATUS_NOT_ENOUGH_DATA: + return "Not enough data/truncated file"; + default: + return "Unknown error"; + } +} + +char +load(ImlibImage * im, ImlibProgressFunction progress, + char progress_granularity, char immediate_load) +{ + uint8_t *encoded_data; + struct stat stats; + int encoded_fd; + WebPBitstreamFeatures features; + VP8StatusCode vp8return; + + if (stat(im->real_file, &stats) < 0) + { + return 0; + } + + encoded_fd = open(im->real_file, O_RDONLY); + if (encoded_fd < 0) + { + return 0; + } + + encoded_data = malloc(stats.st_size); + + if (encoded_data == NULL) + { + close(encoded_fd); + return 0; + } + + if (read(encoded_fd, encoded_data, stats.st_size) < stats.st_size) + { + free(encoded_data); + close(encoded_fd); + return 0; + } + close(encoded_fd); + + if (WebPGetInfo(encoded_data, stats.st_size, &im->w, &im->h) == 0) + { + free(encoded_data); + return 0; + } + + if (!IMAGE_DIMENSIONS_OK(im->w, im->h)) + { + free(encoded_data); + return 0; + } + + vp8return = WebPGetFeatures(encoded_data, stats.st_size, &features); + if (vp8return != VP8_STATUS_OK) + { + fprintf(stderr, "%s: Error reading file header: %s\n", + im->real_file, webp_strerror(vp8return)); + free(encoded_data); + return 0; + } + + if (features.has_alpha == 0) + UNSET_FLAG(im->flags, F_HAS_ALPHA); + else + SET_FLAG(im->flags, F_HAS_ALPHA); + + if (im->loader || immediate_load || progress) + { + size_t webp_buffer_size = sizeof(DATA32) * im->w * im->h; + + im->data = malloc(webp_buffer_size); + if (WebPDecodeBGRAInto(encoded_data, stats.st_size, + (uint8_t *) im->data, webp_buffer_size, + im->w * 4) == NULL) + { + free(encoded_data); + return 0; + } + + if (progress) + progress(im, 100, 0, 0, im->w, im->h); + } + + free(encoded_data); + return 1; /* Success */ +} + +char +save(ImlibImage * im, ImlibProgressFunction progress, char progress_granularity) +{ + int encoded_fd; + ImlibImageTag *quality_tag; + float quality; + uint8_t *encoded_data; + ssize_t encoded_size; + + if (!im->data) + return 0; + + encoded_fd = open(im->real_file, + O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + + if (encoded_fd < 0) + { + perror(im->real_file); + return 0; + } + + quality = 75; + quality_tag = __imlib_GetTag(im, "quality"); + if (quality_tag) + { + quality = quality_tag->val; + if (quality < 0) + { + fprintf(stderr, + "Warning: 'quality' setting %f too low for WebP, using 0\n", + quality); + quality = 0; + } + + if (quality > 100) + { + fprintf(stderr, + "Warning, 'quality' setting %f too high for WebP, using 100\n", + quality); + quality = 100; + } + } + + encoded_size = WebPEncodeBGRA((uint8_t *) im->data, im->w, im->h, + im->w * 4, quality, &encoded_data); + + if (write(encoded_fd, encoded_data, encoded_size) < encoded_size) + { + close(encoded_fd); + WebPFree(encoded_data); + perror(im->real_file); + return 0; + } + + close(encoded_fd); + WebPFree(encoded_data); + return 1; +} + +void +formats(ImlibLoader * l) +{ + static const char *const list_formats[] = { "webp" }; + int i; + + l->num_formats = sizeof(list_formats) / sizeof(char *); + l->formats = malloc(sizeof(char *) * l->num_formats); + + for (i = 0; i < l->num_formats; i++) + l->formats[i] = strdup(list_formats[i]); +} --
