[gthumb] added a cairo png loader



commit e6ed0a104d5c000801d082fa5de71474e376a052
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Thu Apr 28 14:55:06 2011 +0200

    added a cairo png loader

 extensions/cairo_io/Makefile.am    |    4 +-
 extensions/cairo_io/cairo-io-png.c |  230 ++++++++++++++++++++++++++++++++++++
 extensions/cairo_io/cairo-io-png.h |   40 ++++++
 extensions/cairo_io/main.c         |    5 +
 4 files changed, 278 insertions(+), 1 deletions(-)
---
diff --git a/extensions/cairo_io/Makefile.am b/extensions/cairo_io/Makefile.am
index 283897b..7f4203c 100644
--- a/extensions/cairo_io/Makefile.am
+++ b/extensions/cairo_io/Makefile.am
@@ -7,7 +7,9 @@ libcairo_io_la_SOURCES = 	\
 if ENABLE_JPEG_TOOLS
 libcairo_io_la_SOURCES +=	\
 	cairo-io-jpeg.c		\
-	cairo-io-jpeg.h
+	cairo-io-jpeg.h		\
+	cairo-io-png.c		\
+	cairo-io-png.h
 endif
 
 libcairo_io_la_CFLAGS = $(GTHUMB_CFLAGS) $(JPEG_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
diff --git a/extensions/cairo_io/cairo-io-png.c b/extensions/cairo_io/cairo-io-png.c
new file mode 100644
index 0000000..37dde77
--- /dev/null
+++ b/extensions/cairo_io/cairo-io-png.c
@@ -0,0 +1,230 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 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 <png.h>
+#include <gthumb.h>
+#include "cairo-io-png.h"
+
+
+typedef struct {
+	GFileInputStream  *stream;
+	GCancellable      *cancellable;
+	GError           **error;
+	png_struct        *png_ptr;
+	png_info          *png_info_ptr;
+	cairo_surface_t   *surface;
+} CairoPngData;
+
+
+static void
+_cairo_png_data_destroy (CairoPngData *cairo_png_data)
+{
+	png_destroy_read_struct (&cairo_png_data->png_ptr, &cairo_png_data->png_info_ptr, NULL);
+	g_object_unref (cairo_png_data->stream);
+	g_free (cairo_png_data);
+}
+
+
+static void
+gerror_error_func (png_structp     png_ptr,
+		   png_const_charp message)
+{
+	GError ***error_p = png_get_error_ptr (png_ptr);
+	GError  **error = *error_p;
+
+	if (error != NULL)
+		*error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "%s", message);
+}
+
+
+static void
+gerror_warning_func (png_structp     png_ptr,
+		     png_const_charp message)
+{
+	/* we don't care about warnings */
+}
+
+
+static void
+cairo_png_read_data_func (png_structp png_ptr,
+			  png_bytep   buffer,
+			  png_size_t  size)
+{
+	CairoPngData *cairo_png_data;
+	gssize        n;
+
+	cairo_png_data = png_get_io_ptr (png_ptr);
+	n = g_input_stream_read (G_INPUT_STREAM (cairo_png_data->stream),
+				 buffer,
+				 size,
+				 cairo_png_data->cancellable,
+				 cairo_png_data->error);
+	if (n < 0)
+		png_error (png_ptr, NULL);
+}
+
+
+static void
+transform_to_argb32_format_func (png_structp   png,
+				 png_row_infop row_info,
+				 png_bytep     data)
+{
+	guint   i;
+	guint32 pixel;
+
+	for (i = 0; i < row_info->rowbytes; i += 4) {
+		guchar *p_iter = data + i;
+		guchar  r, g, b, a;
+
+		a = p_iter[3];
+		if (a == 0xff) {
+			pixel = CAIRO_RGBA_TO_UINT32 (p_iter[0], p_iter[1], p_iter[2], 0xff);
+		}
+		else if (a == 0) {
+			pixel = 0;
+		}
+		else {
+			r = _cairo_multiply_alpha (p_iter[0], a);
+			g = _cairo_multiply_alpha (p_iter[1], a);
+			b = _cairo_multiply_alpha (p_iter[2], a);
+			pixel = CAIRO_RGBA_TO_UINT32 (r, g, b, a);
+		}
+		memcpy (p_iter, &pixel, sizeof (guint32));
+	}
+}
+
+
+GthImage *
+_cairo_image_surface_create_from_png (GthFileData   *file_data,
+				      int            requested_size,
+				      int           *original_width,
+				      int           *original_height,
+				      gpointer       user_data,
+				      GCancellable  *cancellable,
+				      GError       **error)
+{
+	GthImage      *image;
+	CairoPngData  *cairo_png_data;
+	png_uint_32    width, height;
+	int            bit_depth, color_type, interlace_type;
+	unsigned char *surface_row;
+	int            rowstride;
+	png_bytep     *row_pointers;
+	int            row;
+
+	image = gth_image_new ();
+
+	cairo_png_data = g_new0 (CairoPngData, 1);
+	cairo_png_data->cancellable = cancellable;
+	cairo_png_data->error = error;
+	cairo_png_data->stream = g_file_read (file_data->file, cancellable, error);
+	if (cairo_png_data->stream == NULL) {
+		_cairo_png_data_destroy (cairo_png_data);
+		return image;
+	}
+
+	cairo_png_data->png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
+							  &cairo_png_data->error,
+							  gerror_error_func,
+							  gerror_warning_func);
+	if (cairo_png_data->png_ptr == NULL) {
+		_cairo_png_data_destroy (cairo_png_data);
+	        return image;
+	}
+
+	cairo_png_data->png_info_ptr = png_create_info_struct (cairo_png_data->png_ptr);
+	if (cairo_png_data->png_info_ptr == NULL) {
+		_cairo_png_data_destroy (cairo_png_data);
+	        return image;
+	}
+
+	if (setjmp (cairo_png_data->png_ptr->jmpbuf)) {
+		_cairo_png_data_destroy (cairo_png_data);
+	        return image;
+	}
+
+	png_set_read_fn (cairo_png_data->png_ptr, cairo_png_data, cairo_png_read_data_func);
+	png_read_info (cairo_png_data->png_ptr, cairo_png_data->png_info_ptr);
+	png_get_IHDR (cairo_png_data->png_ptr,
+		      cairo_png_data->png_info_ptr,
+		      &width,
+		      &height,
+		      &bit_depth,
+		      &color_type,
+		      &interlace_type,
+		      NULL,
+		      NULL);
+
+	cairo_png_data->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+	if (cairo_surface_status (cairo_png_data->surface) != CAIRO_STATUS_SUCCESS) {
+		/* g_warning ("%s", cairo_status_to_string (cairo_surface_status (surface))); */
+		_cairo_png_data_destroy (cairo_png_data);
+	        return image;
+	}
+
+	/* Set the data transformations */
+
+	png_set_strip_16 (cairo_png_data->png_ptr);
+
+	png_set_packing (cairo_png_data->png_ptr);
+
+	if (color_type == PNG_COLOR_TYPE_PALETTE)
+		png_set_palette_to_rgb (cairo_png_data->png_ptr);
+
+	if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
+		png_set_expand_gray_1_2_4_to_8 (cairo_png_data->png_ptr);
+
+	if (png_get_valid (cairo_png_data->png_ptr, cairo_png_data->png_info_ptr, PNG_INFO_tRNS))
+	      png_set_tRNS_to_alpha (cairo_png_data->png_ptr);
+
+	png_set_filler (cairo_png_data->png_ptr, 0xff, PNG_FILLER_AFTER);
+
+	if ((color_type == PNG_COLOR_TYPE_GRAY) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+		png_set_gray_to_rgb (cairo_png_data->png_ptr);
+
+	if (interlace_type != PNG_INTERLACE_NONE)
+		png_set_interlace_handling (cairo_png_data->png_ptr);
+
+	png_set_read_user_transform_fn (cairo_png_data->png_ptr, transform_to_argb32_format_func);
+
+	png_read_update_info (cairo_png_data->png_ptr, cairo_png_data->png_info_ptr);
+
+	/* Read the image */
+
+	cairo_surface_flush (cairo_png_data->surface);
+	surface_row = cairo_image_surface_get_data (cairo_png_data->surface);
+	rowstride = cairo_image_surface_get_stride (cairo_png_data->surface);
+	row_pointers = g_new (png_bytep, height);
+	for (row = 0; row < height; row++) {
+		row_pointers[row] = surface_row;
+		surface_row += rowstride;
+	}
+	png_read_image (cairo_png_data->png_ptr, row_pointers);
+	png_read_end (cairo_png_data->png_ptr, cairo_png_data->png_info_ptr);
+	cairo_surface_mark_dirty (cairo_png_data->surface);
+	if (cairo_surface_status (cairo_png_data->surface) == CAIRO_STATUS_SUCCESS)
+		gth_image_set_cairo_surface (image, cairo_png_data->surface);
+
+	_cairo_png_data_destroy (cairo_png_data);
+
+	return image;
+}
diff --git a/extensions/cairo_io/cairo-io-png.h b/extensions/cairo_io/cairo-io-png.h
new file mode 100644
index 0000000..a5c3ca3
--- /dev/null
+++ b/extensions/cairo_io/cairo-io-png.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ *  GThumb
+ *
+ *  Copyright (C) 2011 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_IO_PNG_H
+#define CAIRO_IO_PNG_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+GthImage *  _cairo_image_surface_create_from_png (GthFileData   *file_data,
+						  int            requested_size,
+						  int           *original_width,
+						  int           *original_height,
+						  gpointer       user_data,
+						  GCancellable  *cancellable,
+						  GError       **error);
+
+G_END_DECLS
+
+#endif /* CAIRO_IO_PNG_H */
diff --git a/extensions/cairo_io/main.c b/extensions/cairo_io/main.c
index 7f74c92..4686146 100644
--- a/extensions/cairo_io/main.c
+++ b/extensions/cairo_io/main.c
@@ -23,6 +23,7 @@
 #include <config.h>
 #include <gthumb.h>
 #include "cairo-io-jpeg.h"
+#include "cairo-io-png.h"
 
 
 G_MODULE_EXPORT void
@@ -34,6 +35,10 @@ gthumb_extension_activate (void)
 					     "image/jpeg",
 					     NULL);
 #endif
+	gth_main_register_image_loader_func (_cairo_image_surface_create_from_png,
+					     GTH_IMAGE_FORMAT_CAIRO_SURFACE,
+					     "image/png",
+					     NULL);
 }
 
 



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