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]);
+}

-- 


Reply via email to