summaryrefslogtreecommitdiffstats
path: root/src/helper/png-write.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/helper/png-write.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/helper/png-write.cpp')
-rw-r--r--src/helper/png-write.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
new file mode 100644
index 000000000..21eca1efa
--- /dev/null
+++ b/src/helper/png-write.cpp
@@ -0,0 +1,205 @@
+#define __SP_PNG_WRITE_C__
+
+/*
+ * PNG file format utilities
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Whoever wrote this example in libpng documentation
+ *
+ * Copyright (C) 1999-2002 authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib/gmessages.h>
+#include <png.h>
+#include "png-write.h"
+#include "io/sys.h"
+
+/* This is an example of how to use libpng to read and write PNG files.
+ * The file libpng.txt is much more verbose then this. If you have not
+ * read it, do so first. This was designed to be a starting point of an
+ * implementation. This is not officially part of libpng, and therefore
+ * does not require a copyright notice.
+ *
+ * This file does not currently compile, because it is missing certain
+ * parts, like allocating memory to hold an image. You will have to
+ * supply these parts to get it to compile. For an example of a minimal
+ * working PNG reader/writer, see pngtest.c, included in this distribution.
+ */
+
+/* write a png file */
+
+typedef struct SPPNGBD {
+ const guchar *px;
+ int rowstride;
+} SPPNGBD;
+
+static int
+sp_png_get_block_stripe (const guchar **rows, int row, int num_rows, void *data)
+{
+ SPPNGBD *bd = (SPPNGBD *) data;
+
+ for (int r = 0; r < num_rows; r++) {
+ rows[r] = bd->px + (row + r) * bd->rowstride;
+ }
+
+ return num_rows;
+}
+
+int
+sp_png_write_rgba (const gchar *filename, const guchar *px, int width, int height, int rowstride)
+{
+ SPPNGBD bd;
+
+ bd.px = px;
+ bd.rowstride = rowstride;
+
+ return sp_png_write_rgba_striped (filename, width, height, sp_png_get_block_stripe, &bd);
+}
+
+int
+sp_png_write_rgba_striped (const gchar *filename, int width, int height,
+ int (* get_rows) (const guchar **rows, int row, int num_rows, void *data),
+ void *data)
+{
+ FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_color_8 sig_bit;
+ png_text text_ptr[3];
+ png_uint_32 r;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ /* open the file */
+
+ Inkscape::IO::dump_fopen_call(filename, "M");
+ fp = Inkscape::IO::fopen_utf8name(filename, "wb");
+ g_return_val_if_fail (fp != NULL, FALSE);
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+ */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+
+ if (png_ptr == NULL) {
+ fclose(fp);
+ return FALSE;
+ }
+
+ /* Allocate/initialize the image information data. REQUIRED */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL) {
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, NULL);
+ return FALSE;
+ }
+
+ /* Set error handling. REQUIRED if you aren't supplying your own
+ * error hadnling functions in the png_create_write_struct() call.
+ */
+ if (setjmp(png_ptr->jmpbuf)) {
+ /* If we get here, we had a problem reading the file */
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ return FALSE;
+ }
+
+ /* set up the output control if you are using standard C streams */
+ png_init_io(png_ptr, fp);
+
+ /* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+ */
+ png_set_IHDR(png_ptr, info_ptr,
+ width,
+ height,
+ 8, /* bit_depth */
+ PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
+
+ /* otherwise, if we are dealing with a color image then */
+ sig_bit.red = 8;
+ sig_bit.green = 8;
+ sig_bit.blue = 8;
+ /* if the image has an alpha channel then */
+ sig_bit.alpha = 8;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+ /* Made by Inkscape comment */
+ text_ptr[0].key = "Software";
+ text_ptr[0].text = "www.inkscape.org";
+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ png_set_text(png_ptr, info_ptr, text_ptr, 1);
+
+ /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
+ /* note that if sRGB is present the cHRM chunk must be ignored
+ * on read and must be written in accordance with the sRGB profile */
+
+ /* Write the file header information. REQUIRED */
+ png_write_info(png_ptr, info_ptr);
+
+ /* Once we write out the header, the compression type on the text
+ * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+ * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+ * at the end.
+ */
+
+ /* set up the transformations you want. Note that these are
+ * all optional. Only call them if you want them.
+ */
+
+ /* --- CUT --- */
+
+ /* The easiest way to write the image (you may have a different memory
+ * layout, however, so choose what fits your needs best). You need to
+ * use the first method if you aren't handling interlacing yourself.
+ */
+
+ r = 0;
+ while (r < static_cast< png_uint_32 > (height) ) {
+ png_bytep row_pointers[64];
+ int h, n;
+
+ h = MIN (height - r, 64);
+ n = get_rows ((const unsigned char **) row_pointers, r, h, data);
+ if (!n) break;
+ png_write_rows (png_ptr, row_pointers, n);
+ r += n;
+ }
+
+ /* You can write optional chunks like tEXt, zTXt, and tIME at the end
+ * as well.
+ */
+
+ /* It is REQUIRED to call this to finish writing the rest of the file */
+ png_write_end(png_ptr, info_ptr);
+
+ /* if you allocated any text comments, free them here */
+
+ /* clean up after the write, and free any memory allocated */
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ /* close the file */
+ fclose(fp);
+
+ /* that's it */
+ return TRUE;
+}
+