From aee98e47696b6a5336bae22ac737834d763f35cc Mon Sep 17 00:00:00 2001 From: slevy <slevy> Date: Wed, 26 Oct 2011 16:46:23 +0000 Subject: [PATCH] Use libpng for snapshotting if available. Change default snapshot parameters: - four digits by default - use .png suffix if libpng available, or if unix (assumes "convert" available) - use .ppm suffix if WIN32 and no libpng --- src/partiviewc.cc | 146 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 27 deletions(-) diff --git a/src/partiviewc.cc b/src/partiviewc.cc index 2ab1790..23ce532 100644 --- a/src/partiviewc.cc +++ b/src/partiviewc.cc @@ -6,6 +6,7 @@ * This file is part of partiview, released under the * Illinois Open Source License; see the file LICENSE.partiview for details. */ +#include "config.h" #include <stdio.h> #include <stdlib.h> @@ -26,6 +27,7 @@ #include <math.h> #include <errno.h> #include <signal.h> +#include <png.h> #include "specks.h" #include "partiview.H" @@ -546,10 +548,12 @@ static int endswith(char *str, char *suf) { int parti_snapset( char *fname, char *frameno, char *imgsize ) { int len; -#if unix - static char suf[] = ".%03d.ppm.gz"; -#else - static char suf[] = ".%03d.ppm"; +#ifdef HAVE_PNG_H + static char suf[] = ".%04d.png"; +#elif unix + static char suf[] = ".%04d.ppm.gz"; +#else /* WIN32 */ + static char suf[] = ".%04d.ppm"; #endif int needsuf; @@ -570,16 +574,84 @@ int parti_snapset( char *fname, char *frameno, char *imgsize ) return ppui.snapfno; } + +#ifdef HAVE_PNG_H + +/* png image snapshotting */ +static png_structp png_ptr = NULL; +static png_infop info_ptr = NULL; + +static void failpng() { + png_destroy_write_struct(&png_ptr, &info_ptr); + msg("snapshot: error writing png header"); +} + +/* returns 0 on success, nonzero on failure */ +static int snappng( char *outfname, int xsize, int ysize, char *rgbbuf ) +{ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr) + info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) { + msg("snapshot: can't init png library"); + return 1; + } + + if(setjmp(png_jmpbuf(png_ptr))) { + failpng(); + return 1; + } + + FILE *outf = fopen( outfname, "wb" ); + if(outf == 0) { + return 1; + } + + png_init_io( png_ptr, outf ); + + png_set_IHDR( png_ptr, info_ptr, + xsize, ysize, 8,/*bit depth*/ + PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + /* Don't really know that we're in sRGB color space, but let's say so anyway. */ + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, PNG_INFO_sRGB); + + png_write_info( png_ptr, info_ptr ); + + png_bytep *rowps = new png_bytep[ysize]; + for(int k = 0; k < ysize; k++) + rowps[k] = (png_bytep) &rgbbuf[k*xsize*3]; + png_write_image( png_ptr, rowps ); + delete rowps; + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(outf); + return 0; +} + +#endif /* HAVE_PNG_H */ + + int parti_snapshot( char *snapinfo ) { char tfcmd[10240], *tftail; int fail; + int as_png = 0; + +#if defined(HAVE_PNG_H) || !WIN32 + static char defsnap[] = "snap.%04d.png"; +#else + static char defsnap[] = "snap.%04d.ppm"; +#endif + #if !WIN32 /* if unix */ - static char defsnap[] = "snap.%03d.sgi"; static char prefix[] = "|convert ppm:- "; static char gzprefix[] = "|gzip >"; #else - static char defsnap[] = "snap.%03d.ppm"; static char prefix[] = ""; #endif @@ -591,6 +663,14 @@ int parti_snapshot( char *snapinfo ) if(ppui.snapfmt[0] == '|' || endswith(ppui.snapfmt, ".ppm")) { tfcmd[0] = '\0'; + +#ifdef HAVE_PNG_H + } else if(endswith(ppui.snapfmt, ".png")) { + /* use built-in libpng writer if available */ + as_png = 1; + tfcmd[0] = '\0'; +#endif + #if unix } else if(endswith(ppui.snapfmt, ".ppm.gz")) { strcpy(tfcmd, gzprefix); @@ -619,35 +699,47 @@ int parti_snapshot( char *snapinfo ) return -2; } - FILE *p; + if(as_png) { +#ifdef HAVE_PNG_H + fail = snappng( tfcmd, w, h, buf ); +#else + msg("Recompile with --with-libpng=... to write png images"); + fail = 1; +#endif + + } else { + /* write ppm stream/file */ + FILE *p; #if unix - void (*oldpipe)(int) = 0; - int popened = tfcmd[0] == '|'; - if(popened) { - oldpipe = signal(SIGPIPE, SIG_IGN); - p = popen(tfcmd+1, "w"); - } else + void (*oldpipe)(int) = 0; + int popened = tfcmd[0] == '|'; + if(popened) { + oldpipe = signal(SIGPIPE, SIG_IGN); + p = popen(tfcmd+1, "w"); + } else #endif - p = fopen(tfcmd, "wb"); + p = fopen(tfcmd, "wb"); - fprintf(p, "P6\n%d %d\n255\n", w, h); - for(y = h; --y >= 0 && fwrite(&buf[w*3*y], w*3, 1, p) > 0; ) - ; - free(buf); - fflush(p); - fail = ferror(p); + fprintf(p, "P6\n%d %d\n255\n", w, h); + for(y = h; --y >= 0 && fwrite(&buf[w*3*y], w*3, 1, p) > 0; ) + ; + free(buf); + fflush(p); + fail = ferror(p) || y >= 0; #if unix - if(popened) { - pclose(p); - signal(SIGPIPE, oldpipe); - } - else + if(popened) { + pclose(p); + signal(SIGPIPE, oldpipe); + } + else #endif - fclose(p); /* win32 */ + fclose(p); /* win32 */ + /* end of "write ppm" case */ + } - if(y >= 0 || fail) { + if(fail) { msg("snapshot: Error writing to %s", tfcmd); return -1; } -- GitLab