src/lib/pngwrite.c 1.4
1.4 2010/06/05 19:29:53 braney
add support for 32-bit color (make USE_PNG have global consequence)
Index: src/lib/pngwrite.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/pngwrite.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -b -B -U 1000000 -r1.3 -r1.4
--- src/lib/pngwrite.c 1 Nov 2009 01:11:13 -0000 1.3
+++ src/lib/pngwrite.c 5 Jun 2010 19:29:53 -0000 1.4
@@ -1,110 +1,117 @@
/* pngwrite.c - write out a memGfx to a PNG file, using the reference library libpng */
/* (libpng is available from sourceforge and included in many open source distros,
* has a wide-open license intended to encourage usage of the PNG format, and the lib
* has been under development and testing for 14 years -- http://libpng.org/) */
#ifdef USE_PNG
#include "png.h" // MUST come before common.h, due to setjmp checking in pngconf.h
#include "common.h"
#include "memgfx.h"
static char const rcsid[] = "$Id$";
static void pngAbort(png_structp png, png_const_charp errorMessage)
/* type png_error wrapper around errAbort */
{
errAbort("%s", (char *)errorMessage);
}
static void pngWarn(png_structp png, png_const_charp warningMessage)
/* type png_error wrapper around warn */
{
warn("%s", (char *)warningMessage);
}
boolean mgSaveToPng(FILE *png_file, struct memGfx *mg, boolean useTransparency)
/* Save PNG to an already open file.
* If useTransparency, then the first color in memgfx's colormap/palette is
* assumed to be the image background color, and pixels of that color
* are made transparent. */
/* Reference: http://libpng.org/pub/png/libpng-1.2.5-manual.html */
{
if (!png_file || !mg)
errAbort("mgSaveToPng: called with a NULL");
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, // don't need pointer to data for err/warn handlers
pngAbort, pngWarn);
if (!png)
{
errAbort("png_write_struct failed");
return FALSE;
}
png_infop info = png_create_info_struct(png);
if (!info)
{
errAbort("png create_info_struct failed");
png_destroy_write_struct(&png, NULL);
return FALSE;
}
// If setjmp returns nonzero, it means png_error is returning control here.
// But that should not happen because png_error should call pngAbort which calls errAbort.
if (setjmp(png_jmpbuf(png)))
{
png_destroy_write_struct(&png, &info);
fclose(png_file);
errAbort("pngwrite: setjmp nonzero. "
"why didn't png_error..pngAbort..errAbort stop execution before this errAbort?");
return FALSE;
}
// Configure PNG output params:
png_init_io(png, png_file);
+#ifdef COLOR32
+png_set_IHDR(png, info, mg->width, mg->height, 8, // 8=bit_depth
+ PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+#else
png_set_IHDR(png, info, mg->width, mg->height, 8, // 8=bit_depth
PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
png_set_PLTE(png, info,
(png_color *)(mg->colorMap), // png_color is same as struct rgbColor!
mg->colorsUsed);
+#endif
if (useTransparency)
{
// First palette color is assumed to be background/transparent, so
// that's the only one we need in the parallel array opacities[].
png_byte opacities[] = {0};
int num_opacities = ArraySize(opacities);
png_color_16p nonPalette_opacities_values = NULL; // n/a for us, we're using palette
png_set_tRNS(png, info, opacities, num_opacities, nonPalette_opacities_values);
}
// Write header/params, write pixels, close and clean up.
// PNG wants a 2D array of pointers to byte offsets into palette/colorMap.
// mg has a 1D array of byte offsets. Make row pointers for PNG:
+
png_byte **row_pointers = needMem(mg->height * sizeof(png_byte *));
int i;
for (i = 0; i < mg->height; i++)
- row_pointers[i] = &(mg->pixels[i*mg->width]);
+ row_pointers[i] = (unsigned char *)&(mg->pixels[i*mg->width]);
png_set_rows(png, info, row_pointers);
png_write_png(png, info, PNG_TRANSFORM_IDENTITY, // no transform
NULL); // unused as of PNG 1.2
png_destroy_write_struct(&png, &info);
return TRUE;
}
void mgSavePng(struct memGfx *mg, char *filename, boolean useTransparency)
/* Save memory bitmap to filename as a PNG.
* If useTransparency, then the first color in memgfx's colormap/palette is
* assumed to be the image background color, and pixels of that color
* are made transparent. */
{
FILE *pngFile = mustOpen(filename, "wb");
if (!mgSaveToPng(pngFile, mg, useTransparency))
{
remove(filename);
errAbort("Couldn't save %s", filename);
}
if (fclose(pngFile) != 0)
errnoAbort("fclose failed");
}
#endif//def USE_PNG