summaryrefslogtreecommitdiffstats
path: root/src/pngenc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pngenc.cpp')
-rw-r--r--src/pngenc.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/pngenc.cpp b/src/pngenc.cpp
new file mode 100644
index 0000000..438b4b5
--- /dev/null
+++ b/src/pngenc.cpp
@@ -0,0 +1,157 @@
+/******************************************************************************
+ *
+ *
+ *
+ *
+ * Copyright (C) 1997-2001 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * Documents produced by Doxygen are derivative works derived from the
+ * input used in their production; they are not affected by this license.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The Portable Network Graphic format is an ISO Standard.
+ * Most of the code below was donated by Bernhard Ristow.
+ */
+
+#ifndef png_jmpbuf
+# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+#include <png.h>
+#include <stdio.h>
+#include <malloc.h>
+#include "pngenc.h"
+#include "message.h"
+
+static void user_error_fn(png_structp, png_const_charp error_msg)
+{
+ err("%s\n", error_msg);
+}
+
+static void user_warning_fn(png_structp, png_const_charp warning_msg)
+{
+ err("%s\n", warning_msg);
+}
+
+PngEncoder::PngEncoder(Byte *rawBytes, Color *p, int w, int h, Byte d, int t) :
+ data(rawBytes), palette(p), width(w), height(h), depth(d), transIndex(t)
+{
+ numPixels = w*h;
+ dataPtr = data;
+}
+
+PngEncoder::~PngEncoder()
+{
+}
+
+void PngEncoder::write(const char *name)
+{
+ FILE * file = NULL;
+ unsigned char ** rows = 0;
+ unsigned char * cmap = 0;
+ short numOfColors = (1<<depth);
+ short bit_depth = 4;
+ long i = 0;
+ long j = 0;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ char user_error_ptr[] = "PngEncoder";
+ png_colorp png_palette;
+ png_byte ti[1];
+
+ png_ptr = png_create_write_struct
+ ( PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ {
+ err("Can not allocate writing structure!\n");
+ return;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ err("Can not allocate writing structure!\n");
+ return;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ return;
+ }
+ else
+ {
+ png_palette = (png_colorp) png_malloc(png_ptr,
+ PNG_MAX_PALETTE_LENGTH*sizeof(png_color));
+ memset(png_palette,0,PNG_MAX_PALETTE_LENGTH*sizeof(png_color));
+ for (i=0; i<numOfColors; i++)
+ {
+ png_palette[i].red = palette[i].red;
+ png_palette[i].green = palette[i].green;
+ png_palette[i].blue = palette[i].blue;
+ }
+ png_set_PLTE(png_ptr, info_ptr, png_palette, PNG_MAX_PALETTE_LENGTH);
+ png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth,
+ PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
+ );
+ ti[0] = transIndex;
+ png_set_tRNS(png_ptr,info_ptr,ti,1,NULL);
+ rows = (unsigned char **) calloc(sizeof(unsigned char*),height);
+ rows[0] = (unsigned char *) calloc(sizeof(unsigned char),height*width);
+ for (i=1; i<height; i++)
+ {
+ rows[i] = rows[i-1] + width;
+ }
+ for (i=0, dataPtr=data; i<height; i++)
+ {
+ for (j=0; j<width; j++)
+ {
+ if (j%2)
+ {
+ rows[i][j/2] = ( rows[i][j/2] | *dataPtr );
+ }
+ else
+ {
+ rows[i][j/2] = (*dataPtr) << 4;
+ }
+ dataPtr++;
+ }
+ }
+ png_set_rows(png_ptr,info_ptr,rows);
+
+ file = fopen(name,"wb");
+ png_init_io(png_ptr,file);
+ png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL);
+ }
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ if (file)
+ {
+ fclose (file);
+ }
+ if (cmap)
+ {
+ free(cmap);
+ }
+ if (rows)
+ {
+ if (rows[0])
+ {
+ free(rows[0]);
+ }
+ free(rows);
+ }
+ return;
+}
+