[libgxps] tools: Add xpstopng tool



commit 4127140589b7c25b13f049ddab4b4e0c11532e83
Author: Carlos Garcia Campos <carlosgc gnome org>
Date:   Sat Oct 29 12:22:46 2011 +0200

    tools: Add xpstopng tool

 configure.ac                |   10 ++
 tools/Makefile.am           |   35 +++++++
 tools/gxps-converter-main.c |   43 +++++++++
 tools/gxps-png-converter.c  |  133 ++++++++++++++++++++++++++
 tools/gxps-png-converter.h  |   41 ++++++++
 tools/gxps-png-writer.c     |  215 +++++++++++++++++++++++++++++++++++++++++++
 tools/gxps-png-writer.h     |   49 ++++++++++
 7 files changed, 526 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c3e73d6..05c659c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -157,6 +157,16 @@ fi
 
 AM_CONDITIONAL(ENABLE_TEST, test x$enable_test = xyes)
 
+dnl Tools
+
+dnl libpng
+PKG_CHECK_MODULES(LIBPNG, libpng, [have_libpng="yes"], [have_libpng="no"])
+
+AM_CONDITIONAL(HAVE_LIBPNG, test x$have_libpng = xyes)
+
+AC_SUBST(LIBPNG_CFLAGS)
+AC_SUBST(LIBPNG_LIBS)
+
 dnl gtk-doc
 GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
 
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9656fab..c4c93dc 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -19,3 +19,38 @@ libgxpstools_la_CFLAGS = \
 
 libgxpstools_la_LIBADD = \
 	$(top_builddir)/libgxps/libgxps.la
+
+bin_PROGRAMS =
+
+tools_cppflags = \
+	-I$(top_srcdir)	\
+	$(AM_CPPFLAGS)
+
+tools_cflags = \
+	$(GXPS_CFLAGS)	\
+	$(WARN_CFLAGS)
+	$(AM_CFLAGS)
+
+if HAVE_LIBPNG
+bin_PROGRAMS += xpstopng
+
+xpstopng_SOURCES = \
+	gxps-converter-main.c	\
+	gxps-png-converter.c	\
+	gxps-png-converter.h	\
+	gxps-png-writer.c	\
+	gxps-png-writer.h
+
+xpstopng_CPPFLAGS = \
+	$(tools_cppflags)				\
+	-DCONVERTER_TYPE=GXPS_TYPE_PNG_CONVERTER	\
+	-DCONVERTER_HEADER=gxps-png-converter.h
+
+xpstopng_CFLAGS = \
+	$(tools_cflags) 	\
+	$(LIBPNG_CFLAGS)
+
+xpstopng_LDADD = \
+	libgxpstools.la		\
+	$(LIBPNG_LIBS)
+endif # HAVE_LIBPNG
\ No newline at end of file
diff --git a/tools/gxps-converter-main.c b/tools/gxps-converter-main.c
new file mode 100644
index 0000000..20b7fda
--- /dev/null
+++ b/tools/gxps-converter-main.c
@@ -0,0 +1,43 @@
+/* Main for GXPS converters
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include G_STRINGIFY(CONVERTER_HEADER)
+
+gint main (gint argc, gchar **argv)
+{
+        GXPSConverter *converter;
+
+        g_type_init ();
+
+        converter = GXPS_CONVERTER (g_object_new (CONVERTER_TYPE, NULL));
+
+        if (!gxps_converter_init_with_args (converter, &argc, &argv)) {
+                g_object_unref (converter);
+
+                return 1;
+        }
+
+        gxps_converter_run (converter);
+        g_object_unref (converter);
+
+        return 0;
+}
diff --git a/tools/gxps-png-converter.c b/tools/gxps-png-converter.c
new file mode 100644
index 0000000..58d0e7f
--- /dev/null
+++ b/tools/gxps-png-converter.c
@@ -0,0 +1,133 @@
+/* GXPSPngConverter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <config.h>
+
+#include "gxps-png-converter.h"
+#include "gxps-png-writer.h"
+#include <math.h>
+#include <libgxps/gxps.h>
+
+struct _GXPSPngConverter {
+	GXPSImageConverter parent;
+
+        guint bg_transparent : 1;
+};
+
+struct _GXPSPngConverterClass {
+	GXPSImageConverterClass parent_class;
+};
+
+G_DEFINE_TYPE (GXPSPngConverter, gxps_png_converter, GXPS_TYPE_IMAGE_CONVERTER)
+
+static gboolean bg_transparent = FALSE;
+
+static const GOptionEntry options[] =
+{
+        { "transparent-bg", 't', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &bg_transparent, "use a transparent background instead of white", NULL },
+        { NULL }
+};
+
+static gboolean
+gxps_png_converter_init_with_args (GXPSConverter *converter,
+                                   gint          *argc,
+                                   gchar       ***argv,
+                                   GList        **option_groups)
+{
+        GXPSPngConverter *png_converter = GXPS_PNG_CONVERTER (converter);
+        GOptionContext   *context;
+        GOptionGroup     *option_group;
+        GError           *error = NULL;
+
+        option_group = g_option_group_new ("png", "PNG Options", "Show PNG Options", NULL, NULL);
+        g_option_group_add_entries (option_group, options);
+
+        *option_groups = g_list_prepend (*option_groups, option_group);
+
+        if (GXPS_CONVERTER_CLASS (gxps_png_converter_parent_class)->init_with_args) {
+                if (!GXPS_CONVERTER_CLASS (gxps_png_converter_parent_class)->init_with_args (converter, argc, argv, option_groups))
+                        return FALSE;
+        }
+
+        context = g_option_context_new (NULL);
+        g_option_context_set_ignore_unknown_options (context, TRUE);
+        g_option_context_set_help_enabled (context, FALSE);
+        g_option_context_add_main_entries (context, options, NULL);
+        if (!g_option_context_parse (context, argc, argv, &error)) {
+                g_printerr ("Error parsing arguments: %s\n", error->message);
+                g_error_free (error);
+                g_option_context_free (context);
+
+                return FALSE;
+        }
+        g_option_context_free (context);
+
+        png_converter->bg_transparent = bg_transparent;
+
+        return TRUE;
+}
+
+static const gchar *
+gxps_png_converter_get_extension (GXPSConverter *converter)
+{
+        return "png";
+}
+
+static void
+gxps_png_converter_begin_document (GXPSConverter *converter,
+                                   const gchar   *output_filename,
+                                   GXPSPage      *first_page)
+{
+        GXPSPngConverter   *png_converter = GXPS_PNG_CONVERTER (converter);
+        GXPSImageConverter *image_converter = GXPS_IMAGE_CONVERTER (converter);
+
+        image_converter->fill_background = !png_converter->bg_transparent;
+        GXPS_CONVERTER_CLASS (gxps_png_converter_parent_class)->begin_document (converter, output_filename, first_page);
+}
+
+static void
+gxps_png_converter_end_page (GXPSConverter *converter)
+{
+        GXPSImageConverter *image_converter = GXPS_IMAGE_CONVERTER (converter);
+        GXPSPngConverter   *png_converter = GXPS_PNG_CONVERTER (converter);
+
+        if (!image_converter->writer) {
+                GXPSPngFormat format = png_converter->bg_transparent ? GXPS_PNG_FORMAT_RGBA : GXPS_PNG_FORMAT_RGB;
+
+                image_converter->writer = gxps_png_writer_new (format);
+        }
+
+        GXPS_CONVERTER_CLASS (gxps_png_converter_parent_class)->end_page (converter);
+}
+
+static void
+gxps_png_converter_init (GXPSPngConverter *converter)
+{
+}
+
+static void
+gxps_png_converter_class_init (GXPSPngConverterClass *klass)
+{
+        GXPSConverterClass *converter_class = GXPS_CONVERTER_CLASS (klass);
+
+        converter_class->init_with_args = gxps_png_converter_init_with_args;
+        converter_class->get_extension = gxps_png_converter_get_extension;
+        converter_class->begin_document = gxps_png_converter_begin_document;
+        converter_class->end_page = gxps_png_converter_end_page;
+}
diff --git a/tools/gxps-png-converter.h b/tools/gxps-png-converter.h
new file mode 100644
index 0000000..3001480
--- /dev/null
+++ b/tools/gxps-png-converter.h
@@ -0,0 +1,41 @@
+/* GXPSPngConverter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GXPS_PNG_CONVERTER_H__
+#define __GXPS_PNG_CONVERTER_H__
+
+#include "gxps-image-converter.h"
+
+G_BEGIN_DECLS
+
+#define GXPS_TYPE_PNG_CONVERTER           (gxps_png_converter_get_type ())
+#define GXPS_PNG_CONVERTER(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GXPS_TYPE_PNG_CONVERTER, GXPSPngConverter))
+#define GXPS_PNG_CONVERTER_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GXPS_TYPE_PNG_CONVERTER, GXPSPngConverterClass))
+#define GXPS_IS_PNG_CONVERTER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GXPS_TYPE_PNG_CONVERTER))
+#define GXPS_IS_PNG_CONVERTER_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GXPS_TYPE_PNG_CONVERTER))
+#define GXPS_PNG_CONVERTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GXPS_TYPE_PNG_CONVERTER, GXPSPngConverterClass))
+
+typedef struct _GXPSPngConverter        GXPSPngConverter;
+typedef struct _GXPSPngConverterClass   GXPSPngConverterClass;
+
+GType gxps_png_converter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GXPS_PNG_CONVERTER_H__ */
diff --git a/tools/gxps-png-writer.c b/tools/gxps-png-writer.c
new file mode 100644
index 0000000..7d78ec9
--- /dev/null
+++ b/tools/gxps-png-writer.c
@@ -0,0 +1,215 @@
+/* GXPSPngWriter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <config.h>
+
+#include "gxps-png-writer.h"
+#include <png.h>
+#include <stdint.h>
+
+struct _GXPSPngWriter {
+	GObject parent;
+
+        GXPSPngFormat format;
+
+        png_structp   png_ptr;
+        png_infop     info_ptr;
+};
+
+struct _GXPSPngWriterClass {
+	GObjectClass parent_class;
+};
+
+static void gxps_png_writer_image_writer_iface_init (GXPSImageWriterInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GXPSPngWriter, gxps_png_writer, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GXPS_TYPE_IMAGE_WRITER,
+                                                gxps_png_writer_image_writer_iface_init))
+
+static void
+gxps_png_writer_init (GXPSPngWriter *png_writer)
+{
+}
+
+static void
+gxps_png_writer_class_init (GXPSPngWriterClass *klass)
+{
+}
+
+GXPSImageWriter *
+gxps_png_writer_new (GXPSPngFormat format)
+{
+        GXPSPngWriter *png_writer = GXPS_PNG_WRITER (g_object_new (GXPS_TYPE_PNG_WRITER, NULL));
+
+        png_writer->format = format;
+
+        return GXPS_IMAGE_WRITER (png_writer);
+}
+
+/* Unpremultiplies data and converts native endian ARGB => RGBA bytes */
+static void
+unpremultiply_data (png_structp png, png_row_infop row_info, png_bytep data)
+{
+        unsigned int i;
+
+        for (i = 0; i < row_info->rowbytes; i += 4) {
+                uint8_t *b = &data[i];
+                uint32_t pixel;
+                uint8_t  alpha;
+
+                memcpy (&pixel, b, sizeof (uint32_t));
+                alpha = (pixel & 0xff000000) >> 24;
+                if (alpha == 0) {
+                        b[0] = b[1] = b[2] = b[3] = 0;
+                } else {
+                        b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+                        b[1] = (((pixel & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+                        b[2] = (((pixel & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+                        b[3] = alpha;
+                }
+        }
+}
+
+/* Converts native endian xRGB => RGBx bytes */
+static void
+convert_data_to_bytes (png_structp png, png_row_infop row_info, png_bytep data)
+{
+        unsigned int i;
+
+        for (i = 0; i < row_info->rowbytes; i += 4) {
+                uint8_t *b = &data[i];
+                uint32_t pixel;
+
+                memcpy (&pixel, b, sizeof (uint32_t));
+
+                b[0] = (pixel & 0xff0000) >> 16;
+                b[1] = (pixel & 0x00ff00) >>  8;
+                b[2] = (pixel & 0x0000ff) >>  0;
+                b[3] = 0;
+        }
+}
+
+static gboolean
+gxps_png_writer_image_writer_init (GXPSImageWriter *image_writer,
+                                   FILE            *fd,
+                                   guint            width,
+                                   guint            height,
+                                   guint            x_resolution,
+                                   guint            y_resolution)
+{
+        GXPSPngWriter *png_writer = GXPS_PNG_WRITER (image_writer);
+
+        png_writer->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+        if (!png_writer->png_ptr) {
+                g_printerr ("Error initializing png writer: png_create_write_struct failed\n");
+                return FALSE;
+        }
+
+        png_writer->info_ptr = png_create_info_struct (png_writer->png_ptr);
+        if (!png_writer->info_ptr) {
+                g_printerr ("Error initializing png writer: png_create_info_struct failed\n");
+                return FALSE;
+        }
+
+        if (setjmp (png_jmpbuf (png_writer->png_ptr))) {
+                g_printerr ("Error initializing png writer: png_jmpbuf failed\n");
+                return FALSE;
+        }
+
+        /* write header */
+        png_init_io (png_writer->png_ptr, fd);
+        if (setjmp (png_jmpbuf (png_writer->png_ptr))) {
+                g_printerr ("Error initializing png writer: error writing PNG header\n");
+                return FALSE;
+        }
+
+        png_set_compression_level (png_writer->png_ptr, Z_BEST_COMPRESSION);
+
+        png_set_IHDR (png_writer->png_ptr, png_writer->info_ptr,
+                      width, height, 8,
+                      png_writer->format == GXPS_PNG_FORMAT_RGB ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA,
+                      PNG_INTERLACE_NONE,
+                      PNG_COMPRESSION_TYPE_DEFAULT,
+                      PNG_FILTER_TYPE_DEFAULT);
+
+        png_set_pHYs (png_writer->png_ptr, png_writer->info_ptr,
+                      x_resolution / 0.0254, y_resolution / 0.0254,
+                      PNG_RESOLUTION_METER);
+
+        png_write_info (png_writer->png_ptr, png_writer->info_ptr);
+        if (setjmp (png_jmpbuf (png_writer->png_ptr))) {
+                g_printerr ("Error initializing png writer: error writing png info bytes\n");
+                return FALSE;
+        }
+
+        switch (png_writer->format) {
+        case GXPS_PNG_FORMAT_RGB:
+                png_set_write_user_transform_fn (png_writer->png_ptr, convert_data_to_bytes);
+                png_set_filler (png_writer->png_ptr, 0, PNG_FILLER_AFTER);
+
+                break;
+        case GXPS_PNG_FORMAT_RGBA:
+                png_set_write_user_transform_fn (png_writer->png_ptr, unpremultiply_data);
+
+                break;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+gxps_png_writer_image_writer_write (GXPSImageWriter *image_writer,
+                                    guchar          *row)
+{
+        GXPSPngWriter *png_writer = GXPS_PNG_WRITER (image_writer);
+
+        png_write_rows (png_writer->png_ptr, &row, 1);
+        if (setjmp (png_jmpbuf (png_writer->png_ptr))) {
+                g_printerr ("Error writing png: error during png row write\n");
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+gxps_png_writer_image_writer_finish (GXPSImageWriter *image_writer)
+{
+        GXPSPngWriter *png_writer = GXPS_PNG_WRITER (image_writer);
+
+        png_write_end (png_writer->png_ptr, png_writer->info_ptr);
+        if (setjmp (png_jmpbuf (png_writer->png_ptr))) {
+                g_printerr ("Error finishing png: error during end of write\n");
+                return FALSE;
+        }
+
+        png_destroy_write_struct (&png_writer->png_ptr, &png_writer->info_ptr);
+
+        return TRUE;
+}
+
+static void
+gxps_png_writer_image_writer_iface_init (GXPSImageWriterInterface *iface)
+{
+        iface->init = gxps_png_writer_image_writer_init;
+        iface->write = gxps_png_writer_image_writer_write;
+        iface->finish = gxps_png_writer_image_writer_finish;
+}
+
+
diff --git a/tools/gxps-png-writer.h b/tools/gxps-png-writer.h
new file mode 100644
index 0000000..39044e2
--- /dev/null
+++ b/tools/gxps-png-writer.h
@@ -0,0 +1,49 @@
+/* GXPSPngWriter
+ *
+ * Copyright (C) 2011  Carlos Garcia Campos <carlosgc gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __GXPS_PNG_WRITER_H__
+#define __GXPS_PNG_WRITER_H__
+
+#include <glib-object.h>
+#include "gxps-image-writer.h"
+
+G_BEGIN_DECLS
+
+#define GXPS_TYPE_PNG_WRITER           (gxps_png_writer_get_type ())
+#define GXPS_PNG_WRITER(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GXPS_TYPE_PNG_WRITER, GXPSPngWriter))
+#define GXPS_PNG_WRITER_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GXPS_TYPE_PNG_WRITER, GXPSPngWriterClass))
+#define GXPS_IS_PNG_WRITER(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GXPS_TYPE_PNG_WRITER))
+#define GXPS_IS_PNG_WRITER_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GXPS_TYPE_PNG_WRITER))
+#define GXPS_PNG_WRITER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GXPS_TYPE_PNG_WRITER, GXPSPngWriterClass))
+
+typedef enum {
+        GXPS_PNG_FORMAT_RGB,
+        GXPS_PNG_FORMAT_RGBA
+} GXPSPngFormat;
+
+typedef struct _GXPSPngWriter        GXPSPngWriter;
+typedef struct _GXPSPngWriterClass   GXPSPngWriterClass;
+
+GType            gxps_png_writer_get_type (void);
+GXPSImageWriter *gxps_png_writer_new      (GXPSPngFormat format);
+
+
+G_END_DECLS
+
+#endif /* __GXPS_PNG_WRITER_H__ */



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