[gthumb] added ability to load WebP images



commit 00d162db01edf5a66bdfc7c3b37a0dc73bd25dd3
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Sat Aug 25 21:02:33 2012 +0200

    added ability to load WebP images
    
    [new feature]

 configure.ac                                       |   24 ++++
 extensions/cairo_io/Makefile.am                    |    8 +-
 extensions/cairo_io/cairo-image-surface-webp.c     |  134 ++++++++++++++++++++
 extensions/cairo_io/cairo-image-surface-webp.h     |   41 ++++++
 extensions/cairo_io/main.c                         |   15 ++-
 .../image_viewer/gth-metadata-provider-image.c     |   31 ++++-
 gthumb/Makefile.am                                 |    1 +
 gthumb/glib-utils.c                                |   19 +++-
 gthumb/glib-utils.h                                |    1 +
 gthumb/gth-file-data.c                             |    4 +-
 gthumb/gth-metadata-provider.c                     |   17 +++
 11 files changed, 280 insertions(+), 15 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c77e1ff..abaadfe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,6 +68,7 @@ GNOME_KEYRING_REQUIRED=3.2.0
 LIBBRASERO_REQUIRED=3.2.0
 LIBCHAMPLAIN_REQUIRED=0.12.0
 LIBRSVG_REQUIRED=2.34.0
+LIBWEBP_REQUIRED=0.2.0
 
 dnl ===========================================================================
 
@@ -418,6 +419,28 @@ AC_SUBST(TIFF_LIBS)
 
 dnl ===========================================================================
 
+AC_ARG_ENABLE([libwebp],
+	      [AS_HELP_STRING([--enable-libwebp],[compile code that uses the libwebp library])],,
+	      [enable_libwebp=yes])
+
+if test x$enable_libwebp = xyes ; then
+	PKG_CHECK_MODULES(LIBWEBP,
+			  [libwebp >= $LIBWEBP_REQUIRED],
+			  [enable_libwebp=yes],
+			  [enable_libwebp=no])
+fi
+if test x$enable_libwebp = xyes ; then
+	AC_DEFINE(HAVE_LIBWEBP, 1, [Define to 1 if libwebp support is included])
+fi
+
+AC_SUBST(LIBWEBP_LIBS)
+AC_SUBST(LIBWEBP_CFLAGS)
+AM_CONDITIONAL(ENABLE_LIBWEBP, test "x$enable_libwebp" = xyes)
+
+AC_DEFINE(WEBP_IS_UNKNOWN_TO_GLIB, 1, [Define to 1 if webp images area not recognized by the glib functions])
+
+dnl ===========================================================================
+
 AC_MSG_CHECKING(liboperaw)
 AC_ARG_ENABLE([libopenraw],
 	      [AS_HELP_STRING([--enable-libopenraw],[use the libopenraw library to read raw files [default=no]])],,
@@ -739,4 +762,5 @@ Configuration:
 	SM client support    : ${with_smclient}
 	Map support          : ${enable_libchamplain}
 	SVG support          : ${enable_librsvg}
+	WebP support         : ${enable_libwebp}
 "
diff --git a/extensions/cairo_io/Makefile.am b/extensions/cairo_io/Makefile.am
index 4278ed0..9e822d1 100644
--- a/extensions/cairo_io/Makefile.am
+++ b/extensions/cairo_io/Makefile.am
@@ -55,9 +55,15 @@ libcairo_io_la_SOURCES +=		\
 	cairo-image-surface-svg.h
 endif
 
+if ENABLE_LIBWEBP
+libcairo_io_la_SOURCES +=		\
+	cairo-image-surface-webp.c	\
+	cairo-image-surface-webp.h
+endif
+
 libcairo_io_la_CFLAGS = $(GTHUMB_CFLAGS) $(JPEG_CFLAGS) $(LIBRSVG_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
 libcairo_io_la_LDFLAGS = $(EXTENSION_LIBTOOL_FLAGS)
-libcairo_io_la_LIBADD = $(GTHUMB_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LIBRSVG_LIBS)
+libcairo_io_la_LIBADD = $(GTHUMB_LIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LIBRSVG_LIBS) $(LIBWEBP_LIBS)
 if ENABLE_JPEG_TOOLS
 libcairo_io_la_LIBADD += ../jpeg_utils/libjpeg_utils.la
 endif
diff --git a/extensions/cairo_io/cairo-image-surface-webp.c b/extensions/cairo_io/cairo-image-surface-webp.c
new file mode 100644
index 0000000..965d0d3
--- /dev/null
+++ b/extensions/cairo_io/cairo-image-surface-webp.c
@@ -0,0 +1,134 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <webp/decode.h>
+#include <gthumb.h>
+#include "cairo-image-surface-webp.h"
+
+
+#define BUFFER_SIZE (16*1024)
+
+
+GthImage *
+_cairo_image_surface_create_from_webp (GInputStream  *istream,
+		       	       	       GthFileData   *file_data,
+				       int            requested_size,
+				       int           *original_width,
+				       int           *original_height,
+				       gpointer       user_data,
+				       GCancellable  *cancellable,
+				       GError       **error)
+{
+	GthImage                  *image;
+	WebPDecoderConfig          config;
+	guchar                    *buffer;
+	gssize                     bytes_read;
+	int                        width, height;
+	cairo_surface_t           *surface;
+	cairo_surface_metadata_t  *metadata;
+	WebPIDecoder              *idec;
+
+	image = gth_image_new ();
+
+	if (! WebPInitDecoderConfig (&config))
+		return image;
+
+	buffer = g_new (guchar, BUFFER_SIZE);
+	bytes_read = g_input_stream_read (istream,
+					  buffer,
+					  BUFFER_SIZE,
+					  cancellable,
+					  error);
+
+	if (WebPGetFeatures (buffer, bytes_read, &config.input) != VP8_STATUS_OK) {
+		g_free (buffer);
+		return image;
+	}
+
+	width = config.input.width;
+	height = config.input.height;
+
+	if (original_width != NULL)
+		*original_width = width;
+	if (original_height != NULL)
+		*original_height = height;
+
+#if SCALING_WORKS
+	if (requested_size > 0)
+		scale_keeping_ratio (&width, &height, requested_size, requested_size, FALSE);
+#endif
+
+	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+	metadata = _cairo_image_surface_get_metadata (surface);
+	metadata->has_alpha = (config.input.has_alpha);
+
+	cairo_surface_flush (surface);
+
+	config.options.no_fancy_upsampling = 1;
+
+#if SCALING_WORKS
+	if (requested_size > 0) {
+		config.options.use_scaling = 1;
+		config.options.scaled_width = width;
+		config.options.scaled_height = height;
+	}
+#endif
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+	config.output.colorspace = MODE_BGRA;
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+	config.output.colorspace = MODE_ARGB
+#endif
+	config.output.u.RGBA.rgba = (uint8_t *) cairo_image_surface_get_data (surface);
+	config.output.u.RGBA.stride = cairo_image_surface_get_stride (surface);
+	config.output.u.RGBA.size = cairo_image_surface_get_stride (surface) * height;
+	config.output.is_external_memory = 1;
+
+	idec = WebPINewDecoder (&config.output);
+	if (idec == NULL) {
+		g_free (buffer);
+		return image;
+	}
+
+	do {
+		VP8StatusCode status = WebPIAppend (idec, buffer, bytes_read);
+		if ((status != VP8_STATUS_OK) && (status != VP8_STATUS_SUSPENDED))
+			break;
+	}
+	while ((bytes_read = g_input_stream_read (istream,
+						  buffer,
+						  BUFFER_SIZE,
+						  cancellable,
+						  error)) > 0);
+
+	cairo_surface_mark_dirty (surface);
+	if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
+		gth_image_set_cairo_surface (image, surface);
+
+	WebPIDelete (idec);
+	WebPFreeDecBuffer (&config.output);
+
+	g_free (buffer);
+
+	return image;
+}
diff --git a/extensions/cairo_io/cairo-image-surface-webp.h b/extensions/cairo_io/cairo-image-surface-webp.h
new file mode 100644
index 0000000..d9c952b
--- /dev/null
+++ b/extensions/cairo_io/cairo-image-surface-webp.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAIRO_IMAGE_SURFACE_WEBP_H
+#define CAIRO_IMAGE_SURFACE_WEBP_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+GthImage *  _cairo_image_surface_create_from_webp (GInputStream  *istream,
+		  	  	  	  	   GthFileData   *file_data,
+		  	  	  	  	   int            requested_size,
+		  	  	  	  	   int           *original_width,
+		  	  	  	  	   int           *original_height,
+		  	  	  	  	   gpointer       user_data,
+		  	  	  	  	   GCancellable  *cancellable,
+		  	  	  	  	   GError       **error);
+
+G_END_DECLS
+
+#endif /* CAIRO_IMAGE_SURFACE_WEBP_H */
diff --git a/extensions/cairo_io/main.c b/extensions/cairo_io/main.c
index 249fb22..a685ecc 100644
--- a/extensions/cairo_io/main.c
+++ b/extensions/cairo_io/main.c
@@ -25,10 +25,12 @@
 #include "cairo-image-surface-jpeg.h"
 #include "cairo-image-surface-png.h"
 #include "cairo-image-surface-svg.h"
+#include "cairo-image-surface-webp.h"
 #include "gth-image-saver-jpeg.h"
 #include "gth-image-saver-png.h"
 #include "gth-image-saver-tga.h"
 #include "gth-image-saver-tiff.h"
+/*#include "gth-image-saver-webp.h"*/
 #include "preferences.h"
 
 
@@ -36,13 +38,11 @@ G_MODULE_EXPORT void
 gthumb_extension_activate (void)
 {
 #ifdef HAVE_LIBJPEG
-
 	gth_main_register_image_loader_func (_cairo_image_surface_create_from_jpeg,
 					     GTH_IMAGE_FORMAT_CAIRO_SURFACE,
 					     "image/jpeg",
 					     NULL);
 	gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_JPEG);
-
 #endif
 
 	gth_main_register_image_loader_func (_cairo_image_surface_create_from_png,
@@ -51,17 +51,24 @@ gthumb_extension_activate (void)
 					     NULL);
 
 #ifdef HAVE_LIBRSVG
-
 	gth_main_register_image_loader_func (_cairo_image_surface_create_from_svg,
 					     GTH_IMAGE_FORMAT_CAIRO_SURFACE,
 					     "image/svg+xml",
 					     NULL);
-
 #endif
 
 	gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_PNG);
 	gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_TGA);
 	gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_TIFF);
+
+#ifdef HAVE_LIBWEBP
+	gth_main_register_image_loader_func (_cairo_image_surface_create_from_webp,
+					     GTH_IMAGE_FORMAT_CAIRO_SURFACE,
+					     "image/webp",
+					     NULL);
+	/*gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_WEBP);*/
+#endif
+
 	gth_hook_add_callback ("dlg-preferences-construct", 30, G_CALLBACK (ci__dlg_preferences_construct_cb), NULL);
 	gth_hook_add_callback ("dlg-preferences-apply", 10, G_CALLBACK (ci__dlg_preferences_apply_cb), NULL);
 }
diff --git a/extensions/image_viewer/gth-metadata-provider-image.c b/extensions/image_viewer/gth-metadata-provider-image.c
index b03217c..411443e 100644
--- a/extensions/image_viewer/gth-metadata-provider-image.c
+++ b/extensions/image_viewer/gth-metadata-provider-image.c
@@ -27,10 +27,13 @@
 #if HAVE_LIBJPEG
 #include <extensions/jpeg_utils/jpeg-info.h>
 #endif /* HAVE_LIBJPEG */
+#if HAVE_LIBWEBP
+#include <webp/decode.h>
+#endif /* HAVE_LIBWEBP */
 #include "gth-metadata-provider-image.h"
 
 
-#define BUFFER_SIZE 32
+#define BUFFER_SIZE 1024
 
 
 G_DEFINE_TYPE (GthMetadataProviderImage, gth_metadata_provider_image, GTH_TYPE_METADATA_PROVIDER)
@@ -104,10 +107,9 @@ gth_metadata_provider_image_read (GthMetadataProvider *self,
 
 				width  = (buffer[16] << 24) + (buffer[17] << 16) + (buffer[18] << 8) + buffer[19];
 				height = (buffer[20] << 24) + (buffer[21] << 16) + (buffer[22] << 8) + buffer[23];
-
-				format_recognized = TRUE;
-				description = "PNG";
+				description = _("PNG");
 				mime_type = "image/png";
+				format_recognized = TRUE;
 			}
 
 #if HAVE_LIBJPEG
@@ -135,9 +137,9 @@ gth_metadata_provider_image_read (GthMetadataProvider *self,
 							  cancellable,
 							  NULL))
 				{
-					format_recognized = TRUE;
-					description = "JPEG";
+					description = _("JPEG");
 					mime_type = "image/jpeg";
+					format_recognized = TRUE;
 
 					if ((orientation == GTH_TRANSFORM_ROTATE_90)
 					     ||	(orientation == GTH_TRANSFORM_ROTATE_270)
@@ -151,6 +153,23 @@ gth_metadata_provider_image_read (GthMetadataProvider *self,
 				}
 			}
 #endif /* HAVE_LIBJPEG */
+
+#if HAVE_LIBWEBP
+			else if ((size > 15) && (memcmp (buffer + 8, "WEBPVP8", 7) == 0)) {
+				WebPDecoderConfig config;
+
+				if (WebPInitDecoderConfig (&config)) {
+					if (WebPGetFeatures (buffer, buffer_size, &config.input) == VP8_STATUS_OK) {
+						width = config.input.width;
+						height = config.input.height;
+						description = _("WebP");
+						mime_type = "image/webp";
+						format_recognized = TRUE;
+					}
+					WebPFreeDecBuffer (&config.output);
+				}
+			}
+#endif /* HAVE_LIBWEBP */
 		}
 
 		g_free (buffer);
diff --git a/gthumb/Makefile.am b/gthumb/Makefile.am
index 224a587..79aa888 100644
--- a/gthumb/Makefile.am
+++ b/gthumb/Makefile.am
@@ -274,6 +274,7 @@ gthumb_LDADD =						\
 	$(LIBSOUP_LIBS)					\
 	$(LIBCHAMPLAIN_LIBS)				\
 	$(LIBRSVG_LIBS)					\
+	$(LIBWEBP_LIBS)					\
 	$(NULL)
 
 if RUN_IN_PLACE
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index a25a3a7..c25df62 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -2799,6 +2799,20 @@ _g_file_info_swap_attributes (GFileInfo  *info,
 }
 
 
+const char *
+_g_content_type_guess_from_name (const char *filename)
+{
+#if WEBP_IS_UNKNOWN_TO_GLIB
+	const char *ext;
+
+	ext = _g_uri_get_file_extension (filename);
+	if (g_strcmp0 (ext, ".webp") == 0)
+		return "image/webp";
+#endif
+	return g_content_type_guess (filename, NULL, 0, NULL);
+}
+
+
 gboolean
 _g_content_type_is_a (const char *type,
 		      const char *supertype)
@@ -2848,12 +2862,13 @@ get_mime_type_from_magic_numbers (void  *buffer,
 		const char * const mime_type;
 	}
 	magic_ids [] = {
-		/* magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
+		/* some magic ids taken from magic/Magdir/archive from the file-4.21 tarball */
 		{ 0,  8, "\x89PNG\x0d\x0a\x1a\x0a",		"image/png" },
 		{ 0,  4, "MM\x00\x2a",				"image/tiff" },
 		{ 0,  4, "II\x2a\x00",				"image/tiff" },
 		{ 0,  4, "GIF8",				"image/gif" },
-		{ 0,  2, "\xff\xd8",				"image/jpeg" },
+		{ 0,  3, "\xff\xd8\xff",			"image/jpeg" },
+		{ 8,  7, "WEBPVP8",				"image/webp" }
 	};
 
 	int  i;
diff --git a/gthumb/glib-utils.h b/gthumb/glib-utils.h
index c647d0f..f870863 100644
--- a/gthumb/glib-utils.h
+++ b/gthumb/glib-utils.h
@@ -307,6 +307,7 @@ gboolean        _g_file_attributes_matches_any_v (const char *attributes,
 void            _g_file_info_swap_attributes     (GFileInfo  *info,
 						  const char *attr1,
 						  const char *attr2);
+const char *    _g_content_type_guess_from_name  (const char *filename);
 gboolean        _g_content_type_is_a             (const char *type,
 						  const char *supertype);
 const char *    _g_content_type_get_from_stream  (GInputStream  *istream,
diff --git a/gthumb/gth-file-data.c b/gthumb/gth-file-data.c
index 1f8b782..78704bd 100644
--- a/gthumb/gth-file-data.c
+++ b/gthumb/gth-file-data.c
@@ -223,7 +223,7 @@ gth_file_data_get_mime_type (GthFileData *self)
 		if (filename == NULL)
 			return NULL;
 
-		content_type = g_content_type_guess (filename, NULL, 0, NULL);
+		content_type = _g_content_type_guess_from_name (filename);
 		g_file_info_set_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, content_type);
 
 		g_free (filename);
@@ -267,7 +267,7 @@ gth_file_data_get_mime_type_from_content (GthFileData  *self,
 
 		content_type = _g_content_type_get_from_stream (istream, cancellable, &error);
 		if ((content_type == NULL) || (strcmp (content_type, "application/xml") == 0))
-			content_type = g_content_type_guess (filename, NULL, 0, NULL);
+			content_type = _g_content_type_guess_from_name (filename);
 
 		g_file_info_set_attribute_string (self->info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, content_type);
 
diff --git a/gthumb/gth-metadata-provider.c b/gthumb/gth-metadata-provider.c
index 5c06085..833c8cf 100644
--- a/gthumb/gth-metadata-provider.c
+++ b/gthumb/gth-metadata-provider.c
@@ -177,6 +177,23 @@ _g_query_metadata_async_thread (GSimpleAsyncResult *result,
 			break;
 		}
 
+#if WEBP_IS_UNKNOWN_TO_GLIB
+		if (_g_file_attributes_matches_any_v (G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+						      G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE,
+						      qmd->attributes_v))
+		{
+			char       *uri;
+			const char *ext;
+
+			uri = g_file_get_uri (file_data->file);
+			ext = _g_uri_get_file_extension (uri);
+			if (g_strcmp0 (ext, ".webp") == 0)
+				gth_file_data_set_mime_type (file_data, "image/webp");
+
+			g_free (uri);
+		}
+#endif
+
 		for (scan_providers = providers; scan_providers; scan_providers = scan_providers->next) {
 			GthMetadataProvider *metadata_provider = scan_providers->data;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]