10
#include "png.h" /* includes zlib.h and setjmp.h */
15
/*---------------------------------------------------------------------------
17
gd_png.c Copyright 1999 Greg Roelofs and Thomas Boutell
19
The routines in this file, gdImagePng*() and gdImageCreateFromPng*(),
20
are drop-in replacements for gdImageGif*() and gdImageCreateFromGif*(),
21
except that these functions are noisier in the case of errors (comment
22
out all fprintf() statements to disable that).
24
GD 2.0 supports RGBA truecolor and will read and write truecolor PNGs.
25
GD 2.0 supports 8 bits of color resolution per channel and
26
7 bits of alpha channel resolution. Images with more than 8 bits
27
per channel are reduced to 8 bits. Images with an alpha channel are
28
only able to resolve down to '1/128th opaque' instead of '1/256th',
29
and this conversion is also automatic. I very much doubt you can see it.
30
Both tRNS and true alpha are supported.
32
Gamma is ignored, and there is no support for text annotations.
34
Last updated: 9 February 2001
36
---------------------------------------------------------------------------*/
38
#ifndef PNG_SETJMP_NOT_SUPPORTED
39
typedef struct _jmpbuf_wrapper
45
static jmpbuf_wrapper gdPngJmpbufStruct;
48
gdPngErrorHandler (png_structp png_ptr, png_const_charp msg)
50
jmpbuf_wrapper *jmpbuf_ptr;
52
/* This function, aside from the extra step of retrieving the "error
53
* pointer" (below) and the fact that it exists within the application
54
* rather than within libpng, is essentially identical to libpng's
55
* default error handler. The second point is critical: since both
56
* setjmp() and longjmp() are called from the same code, they are
57
* guaranteed to have compatible notions of how big a jmp_buf is,
58
* regardless of whether _BSD_SOURCE or anything else has (or has not)
61
fprintf (stderr, "gd-png: fatal libpng error: %s\n", msg);
64
jmpbuf_ptr = png_get_error_ptr (png_ptr);
65
if (jmpbuf_ptr == NULL)
66
{ /* we are completely hosed now */
68
"gd-png: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
73
longjmp (jmpbuf_ptr->jmpbuf, 1);
78
gdPngReadData (png_structp png_ptr,
79
png_bytep data, png_size_t length)
81
gdGetBuf (data, length, (gdIOCtx *)
82
png_get_io_ptr (png_ptr));
86
gdPngWriteData (png_structp png_ptr,
87
png_bytep data, png_size_t length)
89
gdPutBuf (data, length, (gdIOCtx *)
90
png_get_io_ptr (png_ptr));
94
gdPngFlushData (png_structp png_ptr)
99
gdImageCreateFromPng (FILE * inFile)
102
gdIOCtx *in = gdNewFileCtx (inFile);
103
im = gdImageCreateFromPngCtx (in);
109
/* This routine is based in part on the Chapter 13 demo code in "PNG: The
110
* Definitive Guide" (http://www.cdrom.com/pub/png/pngbook.html).
113
gdImageCreateFromPngCtx (gdIOCtx * infile)
118
png_uint_32 width, height, rowbytes;
119
int bit_depth, color_type, interlace_type;
120
int num_palette, num_trans;
122
png_color_16p trans_gray_rgb;
123
png_color_16p trans_color_rgb;
125
png_bytep image_data = NULL;
126
png_bytepp row_pointers = NULL;
127
gdImagePtr im = NULL;
129
volatile int transparent = -1;
130
volatile int palette_allocated = FALSE;
132
/* Make sure the signature can't match by dumb luck -- TBB */
133
/* GRR: isn't sizeof(infile) equal to the size of the pointer? */
134
memset (infile, 0, sizeof (infile));
136
/* first do a quick check that the file really is a PNG image; could
137
* have used slightly more general png_sig_cmp() function instead */
138
gdGetBuf (sig, 8, infile);
139
if (!png_check_sig (sig, 8))
140
return NULL; /* bad signature */
142
#ifndef PNG_SETJMP_NOT_SUPPORTED
143
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &gdPngJmpbufStruct,
144
gdPngErrorHandler, NULL);
146
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
150
fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
154
info_ptr = png_create_info_struct (png_ptr);
155
if (info_ptr == NULL)
157
fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
158
png_destroy_read_struct (&png_ptr, NULL, NULL);
162
/* we could create a second info struct here (end_info), but it's only
163
* useful if we want to keep pre- and post-IDAT chunk info separated
164
* (mainly for PNG-aware image editors and converters) */
166
/* setjmp() must be called in every non-callback function that calls a
167
* PNG-reading libpng function */
168
#ifndef PNG_SETJMP_NOT_SUPPORTED
169
if (setjmp (gdPngJmpbufStruct.jmpbuf))
171
fprintf (stderr, "gd-png error: setjmp returns error condition\n");
172
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
177
png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */
179
png_set_read_fn (png_ptr, (void *) infile, gdPngReadData);
180
png_read_info (png_ptr, info_ptr); /* read all PNG info up to image data */
182
png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
183
&interlace_type, NULL, NULL);
184
if ((color_type == PNG_COLOR_TYPE_RGB) ||
185
(color_type == PNG_COLOR_TYPE_RGB_ALPHA))
187
im = gdImageCreateTrueColor ((int) width, (int) height);
191
im = gdImageCreate ((int) width, (int) height);
195
fprintf (stderr, "gd-png error: cannot allocate gdImage struct\n");
196
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
198
gdFree (row_pointers);
203
png_set_strip_16 (png_ptr);
204
else if (bit_depth < 8)
205
png_set_packing (png_ptr); /* expand to 1 byte per pixel */
208
case PNG_COLOR_TYPE_PALETTE:
209
png_get_PLTE (png_ptr, info_ptr, &palette, &num_palette);
211
fprintf (stderr, "gd-png color_type is palette, colors: %d\n",
214
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
216
/* gd 2.0: we support this rather thoroughly now. Grab the
217
first fully transparent entry, if any, as the value of
218
the simple-transparency index, mostly for backwards
219
binary compatibility. The alpha channel is where it's
220
really at these days. */
222
png_get_tRNS (png_ptr, info_ptr, &trans, &num_trans, NULL);
223
for (i = 0; i < num_trans; ++i)
225
im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
226
if ((trans[i] == 0) && (firstZero))
235
case PNG_COLOR_TYPE_GRAY:
236
case PNG_COLOR_TYPE_GRAY_ALPHA:
237
/* create a fake palette and check for single-shade transparency */
238
if ((palette = (png_colorp) gdMalloc (256 * sizeof (png_color))) == NULL)
240
fprintf (stderr, "gd-png error: cannot allocate gray palette\n");
241
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
244
palette_allocated = TRUE;
247
num_palette = 1 << bit_depth;
248
for (i = 0; i < 256; ++i)
250
j = (255 * i) / (num_palette - 1);
251
palette[i].red = palette[i].green = palette[i].blue = j;
257
for (i = 0; i < 256; ++i)
259
palette[i].red = palette[i].green = palette[i].blue = i;
262
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
264
png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_gray_rgb);
265
if (bit_depth == 16) /* png_set_strip_16() not yet in effect */
266
transparent = trans_gray_rgb->gray >> 8;
268
transparent = trans_gray_rgb->gray;
269
/* Note slight error in 16-bit case: up to 256 16-bit shades
270
* may get mapped to a single 8-bit shade, and only one of them
271
* is supposed to be transparent. IOW, both opaque pixels and
272
* transparent pixels will be mapped into the transparent entry.
273
* There is no particularly good way around this in the case
274
* that all 256 8-bit shades are used, but one could write some
275
* custom 16-bit code to handle the case where there are gdFree
276
* palette entries. This error will be extremely rare in
277
* general, though. (Quite possibly there is only one such
278
* image in existence.) */
282
case PNG_COLOR_TYPE_RGB:
283
case PNG_COLOR_TYPE_RGB_ALPHA:
284
/* gd 2.0: we now support truecolor. See the comment above
285
for a rare situation in which the transparent pixel may not
286
work properly with 16-bit channels. */
287
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
289
png_get_tRNS (png_ptr, info_ptr, NULL, NULL, &trans_color_rgb);
290
if (bit_depth == 16) /* png_set_strip_16() not yet in effect */
291
transparent = gdTrueColor (trans_color_rgb->red >> 8,
292
trans_color_rgb->green >> 8,
293
trans_color_rgb->blue >> 8);
295
transparent = gdTrueColor (trans_color_rgb->red,
296
trans_color_rgb->green,
297
trans_color_rgb->blue);
302
png_read_update_info (png_ptr, info_ptr);
304
/* allocate space for the PNG image data */
305
rowbytes = png_get_rowbytes (png_ptr, info_ptr);
306
if ((image_data = (png_bytep) gdMalloc (rowbytes * height)) == NULL)
308
fprintf (stderr, "gd-png error: cannot allocate image data\n");
309
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
312
if ((row_pointers = (png_bytepp) gdMalloc (height * sizeof (png_bytep))) == NULL)
314
fprintf (stderr, "gd-png error: cannot allocate row pointers\n");
315
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
320
/* set the individual row_pointers to point at the correct offsets */
321
for (j = 0; j < height; ++j)
323
row_pointers[j] = image_data + j * rowbytes;
326
png_read_image (png_ptr, row_pointers); /* read whole image... */
327
png_read_end (png_ptr, NULL); /* ...done! */
331
im->colorsTotal = num_palette;
332
im->transparent = transparent;
333
/* load the palette and mark all entries "open" (unused) for now */
335
for (i = 0; i < num_palette; ++i)
337
im->red[i] = palette[i].red;
338
im->green[i] = palette[i].green;
339
im->blue[i] = palette[i].blue;
342
for (i = num_palette; i < gdMaxColors; ++i)
347
im->interlace = (interlace_type == PNG_INTERLACE_ADAM7);
349
/* can't nuke structs until done with palette */
350
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
353
case PNG_COLOR_TYPE_RGB:
354
for (j = 0; j < height; j++)
357
for (i = 0; i < width; i++)
359
register png_byte r = row_pointers[j][boffset++];
360
register png_byte g = row_pointers[j][boffset++];
361
register png_byte b = row_pointers[j][boffset++];
362
im->tpixels[j][i] = gdTrueColor (r, g, b);
366
case PNG_COLOR_TYPE_RGB_ALPHA:
367
for (j = 0; j < height; j++)
370
for (i = 0; i < width; i++)
372
register png_byte r = row_pointers[j][boffset++];
373
register png_byte g = row_pointers[j][boffset++];
374
register png_byte b = row_pointers[j][boffset++];
375
/* gd has only 7 bits of alpha channel resolution, and
376
127 is transparent, 0 opaque. A moment of convenience,
377
a lifetime of compatibility. */
378
register png_byte a = gdAlphaMax -
379
(row_pointers[j][boffset++] >> 1);
380
im->tpixels[j][i] = gdTrueColorAlpha (r, g, b, a);
385
/* Palette image, or something coerced to be one */
386
for (j = 0; j < height; ++j)
388
for (i = 0; i < width; ++i)
390
register png_byte idx = row_pointers[j][i];
391
im->pixels[j][i] = idx;
399
for (i = num_palette; i < gdMaxColors; ++i)
403
fprintf (stderr, "gd-png warning: image data references out-of-range"
404
" color index (%d)\n", i);
410
if (palette_allocated)
413
gdFree (row_pointers);
420
gdImagePng (gdImagePtr im, FILE * outFile)
422
gdIOCtx *out = gdNewFileCtx (outFile);
423
gdImagePngCtx (im, out);
428
gdImagePngPtr (gdImagePtr im, int *size)
431
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
432
gdImagePngCtx (im, out);
433
rv = gdDPExtractData (out, size);
438
/* This routine is based in part on code from Dale Lutz (Safe Software Inc.)
439
* and in part on demo code from Chapter 15 of "PNG: The Definitive Guide"
440
* (http://www.cdrom.com/pub/png/pngbook.html).
443
gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile)
445
int i, j, bit_depth, interlace_type;
448
int colors = im->colorsTotal;
449
int *open = im->open;
450
int mapping[gdMaxColors]; /* mapping[gd_index] == png_index */
451
png_byte trans_values[256];
452
png_color_16 trans_rgb_value;
453
png_color palette[gdMaxColors];
456
volatile int transparent = im->transparent;
457
volatile int remap = FALSE;
460
#ifndef PNG_SETJMP_NOT_SUPPORTED
461
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
462
&gdPngJmpbufStruct, gdPngErrorHandler, NULL);
464
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
468
fprintf (stderr, "gd-png error: cannot allocate libpng main struct\n");
472
info_ptr = png_create_info_struct (png_ptr);
473
if (info_ptr == NULL)
475
fprintf (stderr, "gd-png error: cannot allocate libpng info struct\n");
476
png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
480
#ifndef PNG_SETJMP_NOT_SUPPORTED
481
if (setjmp (gdPngJmpbufStruct.jmpbuf))
483
fprintf (stderr, "gd-png error: setjmp returns error condition\n");
484
png_destroy_write_struct (&png_ptr, &info_ptr);
489
png_set_write_fn (png_ptr, (void *) outfile, gdPngWriteData, gdPngFlushData);
491
/* This is best for palette images, and libpng defaults to it for
492
palette images anyway, so we don't need to do it explicitly.
493
What to ideally do for truecolor images depends, alas, on the image.
494
gd is intentionally imperfect and doesn't spend a lot of time
495
fussing with such things. */
496
/* png_set_filter(png_ptr, 0, PNG_FILTER_NONE); */
498
/* may want to force maximum compression, but time penalty is large */
499
/* png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); */
501
/* can set this to a smaller value without compromising compression if all
502
* image data is 16K or less; will save some decoder memory [min == 8] */
503
/* png_set_compression_window_bits(png_ptr, 15); */
507
if (transparent >= im->colorsTotal ||
508
(transparent >= 0 && open[transparent]))
513
for (i = 0; i < gdMaxColors; ++i)
518
/* count actual number of colors used (colorsTotal == high-water mark) */
520
for (i = 0; i < im->colorsTotal; ++i)
528
if (colors < im->colorsTotal)
534
else if (colors <= 4)
536
else if (colors <= 16)
541
interlace_type = im->interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
545
if (im->saveAlphaFlag)
547
png_set_IHDR (png_ptr, info_ptr, width, height, 8,
548
PNG_COLOR_TYPE_RGB_ALPHA, interlace_type,
549
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
553
png_set_IHDR (png_ptr, info_ptr, width, height, 8,
554
PNG_COLOR_TYPE_RGB, interlace_type,
555
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
560
png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth,
561
PNG_COLOR_TYPE_PALETTE, interlace_type,
562
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
564
if (im->trueColor && (!im->saveAlphaFlag) && (transparent >= 0))
566
trans_rgb_value.red = gdTrueColorGetRed (im->trueColor);
567
trans_rgb_value.green = gdTrueColorGetGreen (im->trueColor);
568
trans_rgb_value.blue = gdTrueColorGetBlue (im->trueColor);
569
png_set_tRNS (png_ptr, info_ptr, 0, 0, &trans_rgb_value);
573
/* Oy veh. Remap the PNG palette to put the
574
entries with interesting alpha channel
575
values first. This minimizes the size
576
of the tRNS chunk and thus the size
577
of the PNG file as a whole. */
583
for (i = 0; (i < im->colorsTotal); i++)
585
if ((!im->open[i]) &&
586
(im->alpha[i] != gdAlphaOpaque))
594
for (i = 0; (i < im->colorsTotal); i++)
596
trans_values[i] = 255 -
597
((im->alpha[i] << 1) +
598
(im->alpha[i] >> 7));
600
png_set_tRNS (png_ptr, info_ptr, trans_values, 256, NULL);
606
/* (Semi-)transparent indexes come up from the bottom
607
of the list of real colors; opaque
608
indexes come down from the top */
611
for (i = 0; (i < im->colorsTotal); i++)
615
if (im->alpha[i] != gdAlphaOpaque)
617
trans_values[j] = 255 -
618
((im->alpha[i] << 1) +
619
(im->alpha[i] >> 7));
628
png_set_tRNS (png_ptr, info_ptr, trans_values, tc, NULL);
632
/* convert palette to libpng layout */
636
for (i = 0; i < im->colorsTotal; ++i)
640
palette[mapping[i]].red = im->red[i];
641
palette[mapping[i]].green = im->green[i];
642
palette[mapping[i]].blue = im->blue[i];
645
for (i = 0; i < colors; ++i)
647
palette[i].red = im->red[i];
648
palette[i].green = im->green[i];
649
palette[i].blue = im->blue[i];
651
png_set_PLTE (png_ptr, info_ptr, palette, colors);
654
/* write out the PNG header info (everything up to first IDAT) */
655
png_write_info (png_ptr, info_ptr);
657
/* make sure < 8-bit images are packed into pixels as tightly as possible */
658
png_set_packing (png_ptr);
660
/* This code allocates a set of row buffers and copies the gd image data
661
* into them only in the case that remapping is necessary; in gd 1.3 and
662
* later, the im->pixels array is laid out identically to libpng's row
663
* pointers and can be passed to png_write_image() function directly.
664
* The remapping case could be accomplished with less memory for non-
665
* interlaced images, but interlacing causes some serious complications. */
668
int channels = im->saveAlphaFlag ? 4 : 3;
669
/* Our little 7-bit alpha channel trick costs us a bit here. */
670
png_bytep *row_pointers;
671
row_pointers = gdMalloc (sizeof (png_bytep) * height);
672
if (row_pointers == NULL)
674
fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
676
for (j = 0; j < height; ++j)
679
if ((row_pointers[j] = (png_bytep) gdMalloc (width * channels)) == NULL)
681
fprintf (stderr, "gd-png error: unable to allocate rows\n");
682
for (i = 0; i < j; ++i)
683
gdFree (row_pointers[i]);
686
for (i = 0; i < width; ++i)
689
row_pointers[j][bo++] = gdTrueColorGetRed (im->tpixels[j][i]);
690
row_pointers[j][bo++] = gdTrueColorGetGreen (im->tpixels[j][i]);
691
row_pointers[j][bo++] = gdTrueColorGetBlue (im->tpixels[j][i]);
692
if (im->saveAlphaFlag)
694
/* convert the 7-bit alpha channel to an 8-bit alpha channel.
695
We do a little bit-flipping magic, repeating the MSB
696
as the LSB, to ensure that 0 maps to 0 and
697
127 maps to 255. We also have to invert to match
698
PNG's convention in which 255 is opaque. */
699
a = gdTrueColorGetAlpha (im->tpixels[j][i]);
700
row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 7));
705
png_write_image (png_ptr, row_pointers);
706
png_write_end (png_ptr, info_ptr);
708
for (j = 0; j < height; ++j)
709
gdFree (row_pointers[j]);
710
gdFree (row_pointers);
716
png_bytep *row_pointers;
717
row_pointers = gdMalloc (sizeof (png_bytep) * height);
718
if (row_pointers == NULL)
720
fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
722
for (j = 0; j < height; ++j)
724
if ((row_pointers[j] = (png_bytep) gdMalloc (width)) == NULL)
726
fprintf (stderr, "gd-png error: unable to allocate rows\n");
727
for (i = 0; i < j; ++i)
728
gdFree (row_pointers[i]);
731
for (i = 0; i < width; ++i)
732
row_pointers[j][i] = mapping[im->pixels[j][i]];
735
png_write_image (png_ptr, row_pointers);
736
png_write_end (png_ptr, info_ptr);
738
for (j = 0; j < height; ++j)
739
gdFree (row_pointers[j]);
740
gdFree (row_pointers);
744
png_write_image (png_ptr, im->pixels);
745
png_write_end (png_ptr, info_ptr);
748
/* 1.6.3: maybe we should give that memory BACK! TBB */
749
png_destroy_write_struct (&png_ptr, &info_ptr);
753
#endif /* HAVE_LIBPNG */