From 179fa413b047bede6e32109e2ce82437c5fb8d34 Mon Sep 17 00:00:00 2001 From: MenTaLguY Date: Mon, 16 Jan 2006 02:36:01 +0000 Subject: moving trunk for module inkscape (bzr r1) --- src/helper/png-write.cpp | 205 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/helper/png-write.cpp (limited to 'src/helper/png-write.cpp') 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 + * 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 +#include +#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; +} + -- cgit v1.2.3