00001 /****************************************************************************** 00002 * 00003 * $Id: pngenc.cpp,v 1.0 2000/04/23 14:56:23 root Exp $ 00004 * 00005 * 00006 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00007 * 00008 * Permission to use, copy, modify, and distribute this software and its 00009 * documentation under the terms of the GNU General Public License is hereby 00010 * granted. No representations are made about the suitability of this software 00011 * for any purpose. It is provided "as is" without express or implied warranty. 00012 * See the GNU General Public License for more details. 00013 * 00014 * Documents produced by Doxygen are derivative works derived from the 00015 * input used in their production; they are not affected by this license. 00016 * 00017 * --------------------------------------------------------------------------- 00018 * 00019 * The Portable Network Graphic format is an ISO Standard. 00020 * Most of the code below was donated by Bernhard Ristow. 00021 */ 00022 00023 #ifndef png_jmpbuf 00024 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) 00025 #endif 00026 00027 #define ALL_STATIC 00028 #include <../libpng/png.h> 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <errno.h> 00033 #include "pngenc.h" 00034 #include "message.h" 00035 00036 #undef jmpbuf 00037 00038 static void user_error_fn(png_structp, png_const_charp error_msg) 00039 { 00040 err("%s\n", error_msg); 00041 } 00042 00043 static void user_warning_fn(png_structp, png_const_charp warning_msg) 00044 { 00045 err("%s\n", warning_msg); 00046 } 00047 00048 PngEncoder::PngEncoder(Byte *rawBytes, Color *p, int w, int h, Byte d, int t) : 00049 data(rawBytes), palette(p), width(w), height(h), depth(d), transIndex(t) 00050 { 00051 numPixels = w*h; 00052 dataPtr = data; 00053 } 00054 00055 PngEncoder::~PngEncoder() 00056 { 00057 } 00058 00059 void PngEncoder::write(const char *name) 00060 { 00061 FILE * file = NULL; 00062 unsigned char ** rows = 0; 00063 unsigned char * cmap = 0; 00064 short numOfColors = (1<<depth); 00065 short bit_depth = 4; 00066 long i = 0; 00067 long j = 0; 00068 png_structp png_ptr; 00069 png_infop info_ptr; 00070 char user_error_ptr[] = "PngEncoder"; 00071 png_colorp png_palette; 00072 png_byte ti[1]; 00073 00074 png_ptr = png_create_write_struct 00075 ( PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, 00076 user_error_fn, user_warning_fn); 00077 if (!png_ptr) 00078 { 00079 err("Can not allocate writing structure!\n"); 00080 return; 00081 } 00082 00083 info_ptr = png_create_info_struct(png_ptr); 00084 if (!info_ptr) 00085 { 00086 png_destroy_write_struct(&png_ptr, (png_infopp)NULL); 00087 err("Can not allocate writing structure!\n"); 00088 return; 00089 } 00090 00091 if (setjmp(png_jmpbuf(png_ptr))) 00092 { 00093 png_destroy_write_struct(&png_ptr, &info_ptr); 00094 return; 00095 } 00096 else 00097 { 00098 png_palette = (png_colorp) png_malloc(png_ptr, 00099 PNG_MAX_PALETTE_LENGTH*sizeof(png_color)); 00100 memset(png_palette,0,PNG_MAX_PALETTE_LENGTH*sizeof(png_color)); 00101 for (i=0; i<numOfColors; i++) 00102 { 00103 png_palette[i].red = palette[i].red; 00104 png_palette[i].green = palette[i].green; 00105 png_palette[i].blue = palette[i].blue; 00106 } 00107 png_set_PLTE(png_ptr, info_ptr, png_palette, numOfColors); 00108 png_set_IHDR( png_ptr, info_ptr, width, height, bit_depth, 00109 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, 00110 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE 00111 ); 00112 free(png_palette); 00113 ti[0] = transIndex; 00114 png_set_tRNS(png_ptr,info_ptr,ti,1,NULL); 00115 rows = (unsigned char **) calloc(sizeof(unsigned char*),height); 00116 rows[0] = (unsigned char *) calloc(sizeof(unsigned char),height*width); 00117 for (i=1; i<height; i++) 00118 { 00119 rows[i] = rows[i-1] + width; 00120 } 00121 for (i=0, dataPtr=data; i<height; i++) 00122 { 00123 for (j=0; j<width; j++) 00124 { 00125 if (j%2) 00126 { 00127 rows[i][j/2] = ( rows[i][j/2] | *dataPtr ); 00128 } 00129 else 00130 { 00131 rows[i][j/2] = (*dataPtr) << 4; 00132 } 00133 dataPtr++; 00134 } 00135 } 00136 png_set_rows(png_ptr,info_ptr,rows); 00137 00138 file = fopen(name,"wb"); 00139 if (file==0) 00140 { 00141 err("Error opening png file %s for writing: %s!\n",name,strerror(errno)); 00142 } 00143 else 00144 { 00145 png_init_io(png_ptr,file); 00146 png_write_png(png_ptr,info_ptr,PNG_TRANSFORM_IDENTITY,NULL); 00147 } 00148 } 00149 00150 png_destroy_write_struct(&png_ptr, &info_ptr); 00151 00152 if (file) 00153 { 00154 fclose (file); 00155 } 00156 if (cmap) 00157 { 00158 free(cmap); 00159 } 00160 if (rows) 00161 { 00162 if (rows[0]) 00163 { 00164 free(rows[0]); 00165 } 00166 free(rows); 00167 } 00168 return; 00169 } 00170