1 /* Load/save png image with libpng
2 *
3 * 28/11/03 JC
4 * - better no-overshoot on tile loop
5 * 22/2/05
6 * - read non-interlaced PNG with a line buffer (thanks Michel Brabants)
7 * 11/1/06
8 * - read RGBA palette-ized images more robustly (thanks Tom)
9 * 20/4/06
10 * - auto convert to sRGB/mono (with optional alpha) for save
11 * 1/5/06
12 * - from vips_png.c
13 * 8/5/06
14 * - set RGB16/GREY16 if appropriate
15 * 2/11/07
16 * - use im_wbuffer() API for BG writes
17 * 28/2/09
18 * - small cleanups
19 * 4/2/10
20 * - gtkdoc
21 * - fixed 16-bit save
22 * 12/5/10
23 * - lololo but broke 8-bit save, fixed again
24 * 20/7/10 Tim Elliott
25 * - added im_vips2bufpng()
26 * 8/1/11
27 * - get set png resolution (thanks Zhiyu Wu)
28 * 17/3/11
29 * - update for libpng-1.5 API changes
30 * - better handling of palette and 1-bit images
31 * - ... but we are now png 1.2.9 and later only :-( argh
32 * 28/3/11
33 * - argh gamma was wrong when viewed in firefox
34 * 19/12/11
35 * - rework as a set of fns ready for wrapping as a class
36 * 7/2/12
37 * - mild refactoring
38 * - add support for sequential reads
39 * 23/2/12
40 * - add a longjmp() to our error handler to stop the default one running
41 * 13/3/12
42 * - add ICC profile read/write
43 * 15/3/12
44 * - better alpha handling
45 * - sanity check pixel geometry before allowing read
46 * 17/6/12
47 * - more alpha fixes ... some images have no transparency chunk but
48 * still set color_type to alpha
49 * 16/7/13
50 * - more robust error handling from libpng
51 * 9/8/14
52 * - don't check profiles, helps with libpng >=1.6.11
53 * 27/10/14 Lovell
54 * - add @filter option
55 * 26/2/15
56 * - close the read down early for a header read ... this saves an
57 * fd during file read, handy for large numbers of input images
58 * 31/7/16
59 * - support --strip option
60 * 17/1/17
61 * - invalidate operation on read error
62 * 27/2/17
63 * - use dbuf for buffer output
64 * 30/3/17
65 * - better behaviour for truncated png files, thanks Yury
66 * 26/4/17
67 * - better @fail handling with truncated PNGs
68 * 9/4/18
69 * - set interlaced=1 for interlaced images
70 * 20/6/18 [felixbuenemann]
71 * - support png8 palette write with palette, colours, Q, dither
72 * 25/8/18
73 * - support xmp read/write
74 * 20/4/19
75 * - allow huge xmp metadata
76 * 7/10/19
77 * - restart after minimise
78 * 14/10/19
79 * - revise for connection IO
80 * 11/5/20
81 * - only warn for saving bad profiles, don't fail
82 * 19/2/21 781545872
83 * - read out background, if we can
84 * 29/8/21 joshuamsager
85 * - add "unlimited" flag to png load
86 */
87
88 /*
89
90 This file is part of VIPS.
91
92 VIPS is free software; you can redistribute it and/or modify
93 it under the terms of the GNU Lesser General Public License as published by
94 the Free Software Foundation; either version 2 of the License, or
95 (at your option) any later version.
96
97 This program is distributed in the hope that it will be useful,
98 but WITHOUT ANY WARRANTY; without even the implied warranty of
99 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100 GNU Lesser General Public License for more details.
101
102 You should have received a copy of the GNU Lesser General Public License
103 along with this program; if not, write to the Free Software
104 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
105 02110-1301 USA
106
107 */
108
109 /*
110
111 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
112
113 */
114
115 /*
116 #define DEBUG
117 #define VIPS_DEBUG
118 */
119
120 #ifdef HAVE_CONFIG_H
121 #include <config.h>
122 #endif /*HAVE_CONFIG_H*/
123 #include <vips/intl.h>
124
125 #ifdef HAVE_PNG
126
127 #include <stdio.h>
128 #include <stdlib.h>
129 #include <string.h>
130
131 #include <vips/vips.h>
132 #include <vips/internal.h>
133 #include <vips/debug.h>
134
135 #include "pforeign.h"
136
137 #include <png.h>
138
139 #if PNG_LIBPNG_VER < 10003
140 #error "PNG library too old."
141 #endif
142
143 static void
user_error_function(png_structp png_ptr,png_const_charp error_msg)144 user_error_function( png_structp png_ptr, png_const_charp error_msg )
145 {
146 #ifdef DEBUG
147 printf( "user_error_function: %s\n", error_msg );
148 #endif /*DEBUG*/
149
150 g_warning( "%s", error_msg );
151
152 /* This function must not return or the default error handler will be
153 * invoked.
154 */
155 longjmp( png_jmpbuf( png_ptr ), -1 );
156 }
157
158 static void
user_warning_function(png_structp png_ptr,png_const_charp warning_msg)159 user_warning_function( png_structp png_ptr, png_const_charp warning_msg )
160 {
161 #ifdef DEBUG
162 printf( "user_warning_function: %s\n", warning_msg );
163 #endif /*DEBUG*/
164
165 g_warning( "%s", warning_msg );
166 }
167
168 #ifndef HAVE_SPNG
169
170 #define INPUT_BUFFER_SIZE (4096)
171
172 /* What we track during a PNG read.
173 */
174 typedef struct {
175 char *name;
176 VipsImage *out;
177 VipsFailOn fail_on;
178 gboolean unlimited;
179
180 int y_pos;
181 png_structp pPng;
182 png_infop pInfo;
183 png_bytep *row_pointer;
184
185 VipsSource *source;
186
187 /* read() to this buffer, copy to png as required. libpng does many
188 * very small reads and we want to avoid a syscall for each one.
189 */
190 unsigned char input_buffer[INPUT_BUFFER_SIZE];
191 unsigned char *next_byte;
192 gint64 bytes_in_buffer;
193
194 } Read;
195
196 /* Can be called many times.
197 */
198 static void
read_destroy(Read * read)199 read_destroy( Read *read )
200 {
201 /* We never call png_read_end(), perhaps we should. It can fail on
202 * truncated files, so we'd need a setjmp().
203 */
204
205 if( read->pPng )
206 png_destroy_read_struct( &read->pPng, &read->pInfo, NULL );
207 VIPS_UNREF( read->source );
208 VIPS_FREE( read->row_pointer );
209 }
210
211 static void
read_close_cb(VipsImage * out,Read * read)212 read_close_cb( VipsImage *out, Read *read )
213 {
214 read_destroy( read );
215 }
216
217 static void
read_minimise_cb(VipsImage * image,Read * read)218 read_minimise_cb( VipsImage *image, Read *read )
219 {
220 if( read->source )
221 vips_source_minimise( read->source );
222 }
223
224 static void
vips_png_read_source(png_structp pPng,png_bytep data,png_size_t length)225 vips_png_read_source( png_structp pPng, png_bytep data, png_size_t length )
226 {
227 Read *read = png_get_io_ptr( pPng );
228
229 #ifdef DEBUG
230 printf( "vips_png_read_source: read %zd bytes\n", length );
231 #endif /*DEBUG*/
232
233 /* libpng makes many small reads, which hurts performance if you do a
234 * syscall for each one. Read via our own buffer.
235 */
236 while( length > 0 ) {
237 gint64 bytes_available;
238
239 if( read->bytes_in_buffer <= 0 ) {
240 gint64 bytes_read;
241
242 bytes_read = vips_source_read( read->source,
243 read->input_buffer, INPUT_BUFFER_SIZE );
244 if( bytes_read <= 0 )
245 png_error( pPng, "not enough data" );
246
247 read->next_byte = read->input_buffer;
248 read->bytes_in_buffer = bytes_read;
249 }
250
251 bytes_available = VIPS_MIN( read->bytes_in_buffer, length );
252 memcpy( data, read->next_byte, bytes_available );
253 data += bytes_available;
254 length -= bytes_available;
255 read->next_byte += bytes_available;
256 read->bytes_in_buffer -= bytes_available;
257 }
258 }
259
260 static Read *
read_new(VipsSource * source,VipsImage * out,VipsFailOn fail_on,gboolean unlimited)261 read_new( VipsSource *source, VipsImage *out,
262 VipsFailOn fail_on, gboolean unlimited )
263 {
264 Read *read;
265
266 if( !(read = VIPS_NEW( out, Read )) )
267 return( NULL );
268
269 read->name = NULL;
270 read->fail_on = fail_on;
271 read->out = out;
272 read->y_pos = 0;
273 read->pPng = NULL;
274 read->pInfo = NULL;
275 read->row_pointer = NULL;
276 read->source = source;
277 read->unlimited = unlimited;
278
279 g_object_ref( source );
280
281 g_signal_connect( out, "close",
282 G_CALLBACK( read_close_cb ), read );
283 g_signal_connect( out, "minimise",
284 G_CALLBACK( read_minimise_cb ), read );
285
286 if( !(read->pPng = png_create_read_struct(
287 PNG_LIBPNG_VER_STRING, NULL,
288 user_error_function, user_warning_function )) )
289 return( NULL );
290
291 /* Prevent libpng (>=1.6.11) verifying sRGB profiles. Many PNGs have
292 * broken profiles, but we still want to be able to open them.
293 */
294 #ifdef PNG_SKIP_sRGB_CHECK_PROFILE
295 png_set_option( read->pPng,
296 PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON );
297 #endif /*PNG_SKIP_sRGB_CHECK_PROFILE*/
298
299 /* Disable CRC checking in fuzzing mode. Most fuzzed images will have
300 * bad CRCs so this check would break fuzzing.
301 */
302 #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
303 png_set_crc_action( read->pPng,
304 PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE );
305 #endif /*FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION*/
306
307 if( vips_source_rewind( source ) )
308 return( NULL );
309 png_set_read_fn( read->pPng, read, vips_png_read_source );
310
311 /* Catch PNG errors from png_read_info() etc.
312 */
313 if( setjmp( png_jmpbuf( read->pPng ) ) )
314 return( NULL );
315
316 if( !(read->pInfo = png_create_info_struct( read->pPng )) )
317 return( NULL );
318
319 #ifdef HAVE_PNG_SET_CHUNK_MALLOC_MAX
320
321 /* By default, libpng refuses to open files with a metadata chunk
322 * larger than 8mb. We've seen real files with 20mb, so set 50mb.
323 */
324 png_set_chunk_malloc_max( read->pPng, 50 * 1024 * 1024 );
325
326 /* This limits the number of chunks. The limit from
327 * png_set_chunk_malloc_max() times this value is the maximum
328 * memory use.
329 *
330 * libnpng defaults to 1000, which is rather high.
331 */
332 png_set_chunk_cache_max( read->pPng, 100 );
333
334 #endif /*HAVE_PNG_SET_CHUNK_MALLOC_MAX*/
335
336 png_read_info( read->pPng, read->pInfo );
337
338 return( read );
339 }
340
341 /* Set the png text data as metadata on the vips image. These are always
342 * null-terminated strings.
343 */
344 static int
vips__set_text(VipsImage * out,int i,const char * key,const char * text)345 vips__set_text( VipsImage *out, int i, const char *key, const char *text )
346 {
347 char name[256];
348
349 if( strcmp( key, "XML:com.adobe.xmp" ) == 0 ) {
350 /* Save as an XMP tag. This must be a BLOB, for compatibility
351 * for things like the XMP blob that the tiff loader adds.
352 *
353 * Note that this will remove the null-termination from the
354 * string. We must carefully reattach this.
355 */
356 vips_image_set_blob_copy( out,
357 VIPS_META_XMP_NAME, text, strlen( text ) );
358 }
359 else {
360 /* Save as a string comment. Some PNGs have EXIF data as
361 * text segments, but the correct way to support this is with
362 * png_get_eXIf_1().
363 */
364 vips_snprintf( name, 256, "png-comment-%d-%s", i, key );
365
366 vips_image_set_string( out, name, text );
367 }
368
369 return( 0 );
370 }
371
372 /* Read a png header.
373 */
374 static int
png2vips_header(Read * read,VipsImage * out)375 png2vips_header( Read *read, VipsImage *out )
376 {
377 png_uint_32 width, height;
378 int bitdepth, color_type;
379 int interlace_type;
380 VipsDemandStyle hint;
381
382 png_uint_32 res_x, res_y;
383 int unit_type;
384
385 png_charp name;
386 int compression_type;
387
388 png_textp text_ptr;
389 int num_text;
390
391 /* Well thank you, libpng.
392 */
393 #if PNG_LIBPNG_VER < 10400
394 png_charp profile;
395 #else
396 png_bytep profile;
397 #endif
398
399 png_uint_32 proflen;
400
401 int bands;
402 VipsInterpretation interpretation;
403 double Xres, Yres;
404
405 if( setjmp( png_jmpbuf( read->pPng ) ) )
406 return( -1 );
407
408 png_get_IHDR( read->pPng, read->pInfo,
409 &width, &height, &bitdepth, &color_type,
410 &interlace_type, NULL, NULL );
411
412 /* png_get_channels() gives us 1 band for palette images ... so look
413 * at colour_type for output bands.
414 *
415 * Ignore alpha, we detect that separately below.
416 */
417 switch( color_type ) {
418 case PNG_COLOR_TYPE_PALETTE:
419 bands = 3;
420 break;
421
422 case PNG_COLOR_TYPE_GRAY_ALPHA:
423 case PNG_COLOR_TYPE_GRAY:
424 bands = 1;
425 break;
426
427 case PNG_COLOR_TYPE_RGB:
428 case PNG_COLOR_TYPE_RGB_ALPHA:
429 bands = 3;
430 break;
431
432 default:
433 vips_error( "png2vips", "%s", _( "unsupported color type" ) );
434 return( -1 );
435 }
436
437 if( bitdepth > 8 ) {
438 if( bands < 3 )
439 interpretation = VIPS_INTERPRETATION_GREY16;
440 else
441 interpretation = VIPS_INTERPRETATION_RGB16;
442 }
443 else {
444 if( bands < 3 )
445 interpretation = VIPS_INTERPRETATION_B_W;
446 else
447 interpretation = VIPS_INTERPRETATION_sRGB;
448 }
449
450 /* Expand palette images.
451 */
452 if( color_type == PNG_COLOR_TYPE_PALETTE )
453 png_set_palette_to_rgb( read->pPng );
454
455 /* Expand transparency.
456 */
457 if( png_get_valid( read->pPng, read->pInfo, PNG_INFO_tRNS ) ) {
458 png_set_tRNS_to_alpha( read->pPng );
459 bands += 1;
460 }
461 else if( color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
462 color_type == PNG_COLOR_TYPE_RGB_ALPHA ) {
463 /* Some images have no transparency chunk, but still set
464 * color_type to alpha.
465 */
466 bands += 1;
467 }
468
469 /* Expand <8 bit images to full bytes.
470 */
471 if( color_type == PNG_COLOR_TYPE_GRAY &&
472 bitdepth < 8 )
473 png_set_expand_gray_1_2_4_to_8( read->pPng );
474
475 /* If we're an INTEL byte order machine and this is 16bits, we need
476 * to swap bytes.
477 */
478 if( bitdepth > 8 &&
479 !vips_amiMSBfirst() )
480 png_set_swap( read->pPng );
481
482 /* Get resolution. Default to 72 pixels per inch, the usual png value.
483 */
484 unit_type = PNG_RESOLUTION_METER;
485 res_x = 72.0 / 2.54 * 100.0;
486 res_y = 72.0 / 2.54 * 100.0;
487 png_get_pHYs( read->pPng, read->pInfo, &res_x, &res_y, &unit_type );
488 switch( unit_type ) {
489 case PNG_RESOLUTION_METER:
490 Xres = res_x / 1000.0;
491 Yres = res_y / 1000.0;
492 break;
493
494 default:
495 Xres = res_x;
496 Yres = res_y;
497 break;
498 }
499
500 /* Set VIPS header.
501 */
502 vips_image_init_fields( out,
503 width, height, bands,
504 bitdepth > 8 ? VIPS_FORMAT_USHORT : VIPS_FORMAT_UCHAR,
505 VIPS_CODING_NONE, interpretation,
506 Xres, Yres );
507
508 VIPS_SETSTR( out->filename,
509 vips_connection_filename( VIPS_CONNECTION( read->source ) ) );
510
511 /* Uninterlaced images will be read in seq mode. Interlaced images are
512 * read via a huge memory buffer.
513 */
514 if( interlace_type == PNG_INTERLACE_NONE )
515 /* Sequential mode needs thinstrip to work with things like
516 * vips_shrink().
517 */
518 hint = VIPS_DEMAND_STYLE_THINSTRIP;
519 else
520 hint = VIPS_DEMAND_STYLE_ANY;
521 if( vips_image_pipelinev( out, hint, NULL ) )
522 return( -1 );
523
524 /* Fetch the ICC profile. @name is useless, something like "icc" or
525 * "ICC Profile" etc. Ignore it.
526 *
527 * @profile was png_charpp in libpngs < 1.5, png_bytepp is the
528 * modern one. Ignore the warning, if any.
529 */
530 if( png_get_iCCP( read->pPng, read->pInfo,
531 &name, &compression_type, &profile, &proflen ) ) {
532 #ifdef DEBUG
533 printf( "png2vips_header: attaching %d bytes of ICC profile\n",
534 proflen );
535 printf( "png2vips_header: name = \"%s\"\n", name );
536 #endif /*DEBUG*/
537
538 vips_image_set_blob_copy( out,
539 VIPS_META_ICC_NAME, profile, proflen );
540 }
541
542 /* Some libpng warn you to call png_set_interlace_handling(); here, but
543 * that can actually break interlace on older libpngs.
544 *
545 * Only set this for libpng 1.6+.
546 */
547 #if PNG_LIBPNG_VER > 10600
548 (void) png_set_interlace_handling( read->pPng );
549 #endif
550
551 /* Sanity-check line size.
552 */
553 png_read_update_info( read->pPng, read->pInfo );
554 if( png_get_rowbytes( read->pPng, read->pInfo ) !=
555 VIPS_IMAGE_SIZEOF_LINE( out ) ) {
556 vips_error( "vipspng",
557 "%s", _( "unable to read PNG header" ) );
558 return( -1 );
559 }
560
561 /* Let our caller know. These are very expensive to decode.
562 */
563 if( interlace_type != PNG_INTERLACE_NONE )
564 vips_image_set_int( out, "interlaced", 1 );
565
566 if( png_get_text( read->pPng, read->pInfo,
567 &text_ptr, &num_text ) > 0 ) {
568 int i;
569
570 /* Very large numbers of text chunks are used in DoS
571 * attacks.
572 */
573 if( !read->unlimited &&
574 num_text > MAX_PNG_TEXT_CHUNKS ) {
575 vips_error( "vipspng",
576 _( "%d text chunks, image blocked" ),
577 num_text );
578 return( -1 );
579 }
580
581 for( i = 0; i < num_text; i++ )
582 /* .text is always a null-terminated C string.
583 */
584 if( vips__set_text( out, i,
585 text_ptr[i].key, text_ptr[i].text ) )
586 return( -1 );
587 }
588
589 /* Attach original palette bit depth, if any, as metadata.
590 */
591 if( color_type == PNG_COLOR_TYPE_PALETTE )
592 vips_image_set_int( out, "palette-bit-depth", bitdepth );
593
594 /* Note the PNG background colour, if any.
595 */
596 #ifdef PNG_bKGD_SUPPORTED
597 {
598 png_color_16 *background;
599
600 if( png_get_bKGD( read->pPng, read->pInfo, &background ) ) {
601 const int scale = out->BandFmt == VIPS_FORMAT_UCHAR ? 1 : 256;
602
603 double array[3];
604 int n;
605
606 switch( color_type ) {
607 case PNG_COLOR_TYPE_GRAY:
608 case PNG_COLOR_TYPE_GRAY_ALPHA:
609 array[0] = background->gray / scale;
610 n = 1;
611 break;
612
613 case PNG_COLOR_TYPE_RGB:
614 case PNG_COLOR_TYPE_RGB_ALPHA:
615 array[0] = background->red / scale;
616 array[1] = background->green / scale;
617 array[2] = background->blue / scale;
618 n = 3;
619 break;
620
621 case PNG_COLOR_TYPE_PALETTE:
622 default:
623 /* Not sure what to do here. I suppose we should read
624 * the palette.
625 */
626 n = 0;
627 break;
628 }
629
630 if( n > 0 )
631 vips_image_set_array_double( out, "background",
632 array, n );
633 }
634 }
635 #endif
636
637 return( 0 );
638 }
639
640 /* Out is a huge "t" buffer we decompress to.
641 */
642 static int
png2vips_interlace(Read * read,VipsImage * out)643 png2vips_interlace( Read *read, VipsImage *out )
644 {
645 int y;
646
647 #ifdef DEBUG
648 printf( "png2vips_interlace: reading whole image\n" );
649 #endif /*DEBUG*/
650
651 if( vips_image_write_prepare( out ) )
652 return( -1 );
653
654 if( setjmp( png_jmpbuf( read->pPng ) ) )
655 return( -1 );
656
657 if( !(read->row_pointer = VIPS_ARRAY( NULL, out->Ysize, png_bytep )) )
658 return( -1 );
659 for( y = 0; y < out->Ysize; y++ )
660 read->row_pointer[y] = VIPS_IMAGE_ADDR( out, 0, y );
661
662 png_read_image( read->pPng, read->row_pointer );
663
664 read_destroy( read );
665
666 return( 0 );
667 }
668
669 static int
png2vips_generate(VipsRegion * or,void * seq,void * a,void * b,gboolean * stop)670 png2vips_generate( VipsRegion *or,
671 void *seq, void *a, void *b, gboolean *stop )
672 {
673 VipsRect *r = &or->valid;
674 Read *read = (Read *) a;
675
676 int y;
677
678 #ifdef DEBUG
679 printf( "png2vips_generate: line %d, %d rows\n", r->top, r->height );
680 printf( "png2vips_generate: y_top = %d\n", read->y_pos );
681 #endif /*DEBUG*/
682
683 /* We're inside a tilecache where tiles are the full image width, so
684 * this should always be true.
685 */
686 g_assert( r->left == 0 );
687 g_assert( r->width == or->im->Xsize );
688 g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize );
689
690 /* Tiles should always be a strip in height, unless it's the final
691 * strip.
692 */
693 g_assert( r->height == VIPS_MIN( VIPS__FATSTRIP_HEIGHT,
694 or->im->Ysize - r->top ) );
695
696 /* And check that y_pos is correct. It should be, since we are inside
697 * a vips_sequential().
698 */
699 if( r->top != read->y_pos ) {
700 vips_error( "vipspng",
701 _( "out of order read at line %d" ), read->y_pos );
702 return( -1 );
703 }
704
705 for( y = 0; y < r->height; y++ ) {
706 png_bytep q = (png_bytep) VIPS_REGION_ADDR( or, 0, r->top + y );
707
708 /* We need to catch errors from read_row().
709 */
710 if( !setjmp( png_jmpbuf( read->pPng ) ) )
711 png_read_row( read->pPng, q, NULL );
712 else {
713 /* We've failed to read some pixels. Knock this
714 * operation out of cache.
715 */
716 vips_foreign_load_invalidate( read->out );
717
718 #ifdef DEBUG
719 printf( "png2vips_generate: png_read_row() failed, "
720 "line %d\n", r->top + y );
721 printf( "png2vips_generate: file %s\n", read->name );
722 printf( "png2vips_generate: thread %p\n",
723 g_thread_self() );
724 #endif /*DEBUG*/
725
726 /* And bail if fail is on. We have to add an error
727 * message, since the handler we install just does
728 * g_warning().
729 */
730 if( read->fail_on >= VIPS_FAIL_ON_TRUNCATED ) {
731 vips_error( "vipspng",
732 "%s", _( "libpng read error" ) );
733 return( -1 );
734 }
735 }
736
737 read->y_pos += 1;
738 }
739
740 return( 0 );
741 }
742
743 static int
png2vips_image(Read * read,VipsImage * out)744 png2vips_image( Read *read, VipsImage *out )
745 {
746 int interlace_type = png_get_interlace_type( read->pPng, read->pInfo );
747 VipsImage **t = (VipsImage **)
748 vips_object_local_array( VIPS_OBJECT( out ), 3 );
749
750 if( interlace_type != PNG_INTERLACE_NONE ) {
751 /* Arg awful interlaced image. We have to load to a huge mem
752 * buffer, then copy to out.
753 */
754 t[0] = vips_image_new_memory();
755 if( png2vips_header( read, t[0] ) ||
756 png2vips_interlace( read, t[0] ) ||
757 vips_image_write( t[0], out ) )
758 return( -1 );
759 }
760 else {
761 t[0] = vips_image_new();
762 if( png2vips_header( read, t[0] ) ||
763 vips_image_generate( t[0],
764 NULL, png2vips_generate, NULL,
765 read, NULL ) ||
766 vips_sequential( t[0], &t[1],
767 "tile_height", VIPS__FATSTRIP_HEIGHT,
768 NULL ) ||
769 vips_image_write( t[1], out ) )
770 return( -1 );
771 }
772
773 return( 0 );
774 }
775
776 gboolean
vips__png_ispng_source(VipsSource * source)777 vips__png_ispng_source( VipsSource *source )
778 {
779 const unsigned char *p;
780
781 if( (p = vips_source_sniff( source, 8 )) &&
782 !png_sig_cmp( (png_bytep) p, 0, 8 ) )
783 return( TRUE );
784
785 return( FALSE );
786 }
787
788 int
vips__png_header_source(VipsSource * source,VipsImage * out,gboolean unlimited)789 vips__png_header_source( VipsSource *source, VipsImage *out,
790 gboolean unlimited )
791 {
792 Read *read;
793
794 if( !(read = read_new( source, out, TRUE, unlimited )) ||
795 png2vips_header( read, out ) ) {
796 vips_error( "png2vips", _( "unable to read source %s" ),
797 vips_connection_nick( VIPS_CONNECTION( source ) ) );
798 return( -1 );
799 }
800
801 vips_source_minimise( source );
802
803 return( 0 );
804 }
805
806 int
vips__png_read_source(VipsSource * source,VipsImage * out,VipsFailOn fail_on,gboolean unlimited)807 vips__png_read_source( VipsSource *source, VipsImage *out,
808 VipsFailOn fail_on, gboolean unlimited )
809 {
810 Read *read;
811
812 if( !(read = read_new( source, out, fail_on, unlimited )) ||
813 png2vips_image( read, out ) ||
814 vips_source_decode( source ) ) {
815 vips_error( "png2vips", _( "unable to read source %s" ),
816 vips_connection_nick( VIPS_CONNECTION( source ) ) );
817 return( -1 );
818 }
819
820 return( 0 );
821 }
822
823 /* Interlaced PNGs need to be entirely decompressed into memory then can be
824 * served partially from there. Non-interlaced PNGs may be read sequentially.
825 */
826 gboolean
vips__png_isinterlaced_source(VipsSource * source)827 vips__png_isinterlaced_source( VipsSource *source )
828 {
829 VipsImage *image;
830 Read *read;
831 int interlace_type;
832
833 image = vips_image_new();
834
835 if( !(read = read_new( source, image, TRUE, FALSE )) ) {
836 g_object_unref( image );
837 return( -1 );
838 }
839 interlace_type = png_get_interlace_type( read->pPng, read->pInfo );
840 g_object_unref( image );
841
842 return( interlace_type != PNG_INTERLACE_NONE );
843 }
844
845 #endif /*!defined(HAVE_SPNG)*/
846
847 const char *vips__png_suffs[] = { ".png", NULL };
848
849 /* What we track during a PNG write.
850 */
851 typedef struct {
852 VipsImage *in;
853 VipsImage *memory;
854
855 VipsTarget *target;
856
857 png_structp pPng;
858 png_infop pInfo;
859 png_bytep *row_pointer;
860 } Write;
861
862 static void
write_destroy(Write * write)863 write_destroy( Write *write )
864 {
865 #ifdef DEBUG
866 printf( "write_destroy: %p\n", write );
867 #endif /*DEBUG*/
868
869 VIPS_UNREF( write->memory );
870 if( write->target )
871 vips_target_finish( write->target );
872 if( write->pPng )
873 png_destroy_write_struct( &write->pPng, &write->pInfo );
874 VIPS_FREE( write->row_pointer );
875 VIPS_FREE( write );
876 }
877
878 static void
user_write_data(png_structp pPng,png_bytep data,png_size_t length)879 user_write_data( png_structp pPng, png_bytep data, png_size_t length )
880 {
881 Write *write = (Write *) png_get_io_ptr( pPng );
882
883 if( vips_target_write( write->target, data, length ) )
884 png_error( pPng, "not enough data" );
885 }
886
887 static Write *
write_new(VipsImage * in,VipsTarget * target)888 write_new( VipsImage *in, VipsTarget *target )
889 {
890 Write *write;
891
892 if( !(write = VIPS_NEW( NULL, Write )) )
893 return( NULL );
894 write->in = in;
895 write->target = target;
896
897 #ifdef DEBUG
898 printf( "write_new: %p\n", write );
899 #endif /*DEBUG*/
900
901 if( !(write->row_pointer = VIPS_ARRAY( NULL, in->Ysize, png_bytep )) )
902 return( NULL );
903 if( !(write->pPng = png_create_write_struct(
904 PNG_LIBPNG_VER_STRING, NULL,
905 user_error_function, user_warning_function )) ) {
906 write_destroy( write );
907 return( NULL );
908 }
909
910 /* Prevent libpng (>=1.6.11) verifying sRGB profiles. We are often
911 * asked to copy images containing bad profiles, and this check would
912 * prevent that.
913 */
914 #ifdef PNG_SKIP_sRGB_CHECK_PROFILE
915 png_set_option( write->pPng,
916 PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON );
917 #endif /*PNG_SKIP_sRGB_CHECK_PROFILE*/
918
919 png_set_write_fn( write->pPng, write, user_write_data, NULL );
920
921 /* Catch PNG errors from png_create_info_struct().
922 */
923 if( setjmp( png_jmpbuf( write->pPng ) ) ) {
924 write_destroy( write );
925 return( NULL );
926 }
927
928 if( !(write->pInfo = png_create_info_struct( write->pPng )) ) {
929 write_destroy( write );
930 return( NULL );
931 }
932
933 return( write );
934 }
935
936 static int
write_png_block(VipsRegion * region,VipsRect * area,void * a)937 write_png_block( VipsRegion *region, VipsRect *area, void *a )
938 {
939 Write *write = (Write *) a;
940
941 int i;
942
943 /* The area to write is always a set of complete scanlines.
944 */
945 g_assert( area->left == 0 );
946 g_assert( area->width == region->im->Xsize );
947 g_assert( area->top + area->height <= region->im->Ysize );
948
949 /* Catch PNG errors.
950 */
951 if( setjmp( png_jmpbuf( write->pPng ) ) )
952 return( -1 );
953
954 for( i = 0; i < area->height; i++ )
955 write->row_pointer[i] = (png_bytep)
956 VIPS_REGION_ADDR( region, 0, area->top + i );
957
958 png_write_rows( write->pPng, write->row_pointer, area->height );
959
960 return( 0 );
961 }
962
963 static void
vips__png_set_text(png_structp pPng,png_infop pInfo,const char * key,const char * value)964 vips__png_set_text( png_structp pPng, png_infop pInfo,
965 const char *key, const char *value )
966 {
967 png_text text;
968
969 text.compression = 0;
970 text.key = (char *) key;
971 text.text = (char *) value;
972 text.text_length = strlen( value );
973
974 /* Before 1.4, these fields were only there if explicitly enabled.
975 */
976 #if PNG_LIBPNG_VER > 10400
977 text.itxt_length = 0;
978 text.lang = NULL;
979 #endif
980
981 png_set_text( pPng, pInfo, &text, 1 );
982 }
983
984 static void *
write_png_comment(VipsImage * image,const char * field,GValue * value,void * data)985 write_png_comment( VipsImage *image,
986 const char *field, GValue *value, void *data )
987 {
988 Write *write = (Write *) data;
989
990 if( vips_isprefix( "png-comment-", field ) ) {
991 const char *str;
992 int i;
993 char key[256];
994
995 if( vips_image_get_string( write->in, field, &str ) )
996 return( image );
997
998 if( strlen( field ) > 256 ||
999 sscanf( field, "png-comment-%d-%80s", &i, key ) != 2 ) {
1000 vips_error( "vips2png",
1001 "%s", _( "bad png comment key" ) );
1002 return( image );
1003 }
1004
1005 vips__png_set_text( write->pPng, write->pInfo, key, str );
1006 }
1007
1008 return( NULL );
1009 }
1010
1011 /* Write a VIPS image to PNG.
1012 */
1013 static int
write_vips(Write * write,int compress,int interlace,const char * profile,VipsForeignPngFilter filter,gboolean strip,gboolean palette,int Q,double dither,int bitdepth,int effort)1014 write_vips( Write *write,
1015 int compress, int interlace, const char *profile,
1016 VipsForeignPngFilter filter, gboolean strip,
1017 gboolean palette, int Q, double dither,
1018 int bitdepth, int effort )
1019 {
1020 VipsImage *in = write->in;
1021
1022 int color_type;
1023 int interlace_type;
1024 int i, nb_passes;
1025
1026 g_assert( in->BandFmt == VIPS_FORMAT_UCHAR ||
1027 in->BandFmt == VIPS_FORMAT_USHORT );
1028 g_assert( in->Coding == VIPS_CODING_NONE );
1029 g_assert( in->Bands > 0 && in->Bands < 5 );
1030
1031 /* Catch PNG errors.
1032 */
1033 if( setjmp( png_jmpbuf( write->pPng ) ) )
1034 return( -1 );
1035
1036 /* Check input image. If we are writing interlaced, we need to make 7
1037 * passes over the image. We advertise ourselves as seq, so to ensure
1038 * we only suck once from upstream, switch to WIO.
1039 */
1040 if( interlace ) {
1041 if( !(write->memory = vips_image_copy_memory( in )) )
1042 return( -1 );
1043 in = write->memory;
1044 }
1045 else {
1046 if( vips_image_pio_input( in ) )
1047 return( -1 );
1048 }
1049 if( compress < 0 || compress > 9 ) {
1050 vips_error( "vips2png",
1051 "%s", _( "compress should be in [0,9]" ) );
1052 return( -1 );
1053 }
1054
1055 /* Set compression parameters.
1056 */
1057 png_set_compression_level( write->pPng, compress );
1058
1059 /* Set row filter.
1060 */
1061 png_set_filter( write->pPng, 0, filter );
1062
1063 switch( in->Bands ) {
1064 case 1: color_type = PNG_COLOR_TYPE_GRAY; break;
1065 case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
1066 case 3: color_type = PNG_COLOR_TYPE_RGB; break;
1067 case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
1068
1069 default:
1070 vips_error( "vips2png",
1071 _( "can't save %d band image as png" ), in->Bands );
1072 return( -1 );
1073 }
1074
1075 #ifdef HAVE_IMAGEQUANT
1076 /* Enable image quantisation to paletted 8bpp PNG if colours is set.
1077 */
1078 if( palette )
1079 color_type = PNG_COLOR_TYPE_PALETTE;
1080 #else
1081 if( palette )
1082 g_warning( "%s",
1083 _( "ignoring palette (no quantisation support)" ) );
1084 #endif /*HAVE_IMAGEQUANT*/
1085
1086 interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
1087
1088 png_set_IHDR( write->pPng, write->pInfo,
1089 in->Xsize, in->Ysize, bitdepth, color_type, interlace_type,
1090 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
1091
1092 /* Set resolution. libpng uses pixels per meter.
1093 */
1094 png_set_pHYs( write->pPng, write->pInfo,
1095 VIPS_RINT( in->Xres * 1000 ), VIPS_RINT( in->Yres * 1000 ),
1096 PNG_RESOLUTION_METER );
1097
1098 /* Metadata
1099 */
1100 if( !strip ) {
1101 if( profile ) {
1102 VipsBlob *blob;
1103
1104 if( vips_profile_load( profile, &blob, NULL ) )
1105 return( -1 );
1106 if( blob ) {
1107 size_t length;
1108 const void *data
1109 = vips_blob_get( blob, &length );
1110
1111 #ifdef DEBUG
1112 printf( "write_vips: attaching %zd bytes "
1113 "of ICC profile\n", length );
1114 #endif /*DEBUG*/
1115
1116 png_set_iCCP( write->pPng, write->pInfo,
1117 "icc", PNG_COMPRESSION_TYPE_BASE,
1118 (void *) data, length );
1119
1120 vips_area_unref( (VipsArea *) blob );
1121 }
1122 }
1123 else if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
1124 const void *data;
1125 size_t length;
1126
1127 if( vips_image_get_blob( in, VIPS_META_ICC_NAME,
1128 &data, &length ) )
1129 return( -1 );
1130
1131 #ifdef DEBUG
1132 printf( "write_vips: attaching %zd bytes "
1133 "of ICC profile\n", length );
1134 #endif /*DEBUG*/
1135
1136 /* We need to ignore any errors from png_set_iCCP()
1137 * since we want to drop incompatible profiles rather
1138 * than simply failing.
1139 */
1140 if( setjmp( png_jmpbuf( write->pPng ) ) ) {
1141 /* Silent ignore of error.
1142 */
1143 g_warning( "bad ICC profile not saved" );
1144 }
1145 else {
1146 /* This will jump back to the line above on
1147 * error.
1148 */
1149 png_set_iCCP( write->pPng, write->pInfo, "icc",
1150 PNG_COMPRESSION_TYPE_BASE,
1151 (void *) data, length );
1152 }
1153
1154 /* And restore the setjmp.
1155 */
1156 if( setjmp( png_jmpbuf( write->pPng ) ) )
1157 return( -1 );
1158 }
1159
1160 if( vips_image_get_typeof( in, VIPS_META_XMP_NAME ) ) {
1161 const void *data;
1162 size_t length;
1163 char *str;
1164
1165 /* XMP is attached as a BLOB with no null-termination.
1166 * We must re-add this.
1167 */
1168 if( vips_image_get_blob( in,
1169 VIPS_META_XMP_NAME, &data, &length ) )
1170 return( -1 );
1171
1172 str = g_malloc( length + 1 );
1173 vips_strncpy( str, data, length + 1 );
1174 vips__png_set_text( write->pPng, write->pInfo,
1175 "XML:com.adobe.xmp", str );
1176 g_free( str );
1177 }
1178
1179 if( vips_image_map( in,
1180 write_png_comment, write ) )
1181 return( -1 );
1182 }
1183
1184 #ifdef HAVE_IMAGEQUANT
1185 if( palette ) {
1186 VipsImage *im_index;
1187 VipsImage *im_palette;
1188 int palette_count;
1189 png_color *png_palette;
1190 png_byte *png_trans;
1191 int trans_count;
1192
1193 if( vips__quantise_image( in, &im_index, &im_palette,
1194 1 << bitdepth, Q, dither, effort, FALSE ) )
1195 return( -1 );
1196
1197 palette_count = im_palette->Xsize;
1198
1199 g_assert( palette_count <= PNG_MAX_PALETTE_LENGTH );
1200
1201 png_palette = (png_color *) png_malloc( write->pPng,
1202 palette_count * sizeof( png_color ) );
1203 png_trans = (png_byte *) png_malloc( write->pPng,
1204 palette_count * sizeof( png_byte ) );
1205 trans_count = 0;
1206 for( i = 0; i < palette_count; i++ ) {
1207 VipsPel *p = (VipsPel *)
1208 VIPS_IMAGE_ADDR( im_palette, i, 0 );
1209 png_color *col = &png_palette[i];
1210
1211 col->red = p[0];
1212 col->green = p[1];
1213 col->blue = p[2];
1214 png_trans[i] = p[3];
1215 if( p[3] != 255 )
1216 trans_count = i + 1;
1217 #ifdef DEBUG
1218 printf( "write_vips: palette[%d] %d %d %d %d\n",
1219 i + 1, p[0], p[1], p[2], p[3] );
1220 #endif /*DEBUG*/
1221 }
1222
1223 #ifdef DEBUG
1224 printf( "write_vips: attaching %d color palette\n",
1225 palette_count );
1226 #endif /*DEBUG*/
1227 png_set_PLTE( write->pPng, write->pInfo, png_palette,
1228 palette_count );
1229 if( trans_count ) {
1230 #ifdef DEBUG
1231 printf( "write_vips: attaching %d alpha values\n",
1232 trans_count );
1233 #endif /*DEBUG*/
1234 png_set_tRNS( write->pPng, write->pInfo, png_trans,
1235 trans_count, NULL );
1236 }
1237
1238 png_free( write->pPng, (void *) png_palette );
1239 png_free( write->pPng, (void *) png_trans );
1240
1241 VIPS_UNREF( im_palette );
1242
1243 VIPS_UNREF( write->memory );
1244 write->memory = im_index;
1245 in = write->memory;
1246 }
1247 #endif /*HAVE_IMAGEQUANT*/
1248
1249 png_write_info( write->pPng, write->pInfo );
1250
1251 /* If we're an intel byte order CPU and this is a 16bit image, we need
1252 * to swap bytes.
1253 */
1254 if( bitdepth > 8 &&
1255 !vips_amiMSBfirst() )
1256 png_set_swap( write->pPng );
1257
1258 /* If bitdepth is 1/2/4, pack pixels into bytes.
1259 */
1260 png_set_packing( write->pPng );
1261
1262 if( interlace )
1263 nb_passes = png_set_interlace_handling( write->pPng );
1264 else
1265 nb_passes = 1;
1266
1267 /* Write data.
1268 */
1269 for( i = 0; i < nb_passes; i++ )
1270 if( vips_sink_disc( in, write_png_block, write ) )
1271 return( -1 );
1272
1273 /* The setjmp() was held by our background writer: reset it.
1274 */
1275 if( setjmp( png_jmpbuf( write->pPng ) ) )
1276 return( -1 );
1277
1278 png_write_end( write->pPng, write->pInfo );
1279
1280 return( 0 );
1281 }
1282
1283 int
vips__png_write_target(VipsImage * in,VipsTarget * target,int compression,int interlace,const char * profile,VipsForeignPngFilter filter,gboolean strip,gboolean palette,int Q,double dither,int bitdepth,int effort)1284 vips__png_write_target( VipsImage *in, VipsTarget *target,
1285 int compression, int interlace,
1286 const char *profile, VipsForeignPngFilter filter, gboolean strip,
1287 gboolean palette, int Q, double dither,
1288 int bitdepth, int effort )
1289 {
1290 Write *write;
1291
1292 if( !(write = write_new( in, target )) )
1293 return( -1 );
1294
1295 if( write_vips( write,
1296 compression, interlace, profile, filter, strip, palette,
1297 Q, dither, bitdepth, effort ) ) {
1298 write_destroy( write );
1299 vips_error( "vips2png", _( "unable to write to target %s" ),
1300 vips_connection_nick( VIPS_CONNECTION( target ) ) );
1301 return( -1 );
1302 }
1303
1304 write_destroy( write );
1305
1306 return( 0 );
1307 }
1308
1309 #endif /*HAVE_PNG*/
1310