static int png2vips_image( Read *read, VipsImage *out ) { int interlace_type = png_get_interlace_type( read->pPng, read->pInfo ); VipsImage **t = (VipsImage **) vips_object_local_array( VIPS_OBJECT( out ), 3 ); if( interlace_type != PNG_INTERLACE_NONE ) { /* Arg awful interlaced image. We have to load to a huge mem * buffer, then copy to out. */ t[0] = vips_image_new_memory(); if( png2vips_header( read, t[0] ) || png2vips_interlace( read, t[0] ) || vips_image_write( t[0], out ) ) return( -1 ); } else { t[0] = vips_image_new(); if( png2vips_header( read, t[0] ) || vips_image_generate( t[0], NULL, png2vips_generate, NULL, read, NULL ) || vips_sequential( t[0], &t[1], "tile_height", 8, "access", read->readbehind ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_SEQUENTIAL_UNBUFFERED, NULL ) || vips_image_write( t[1], out ) ) return( -1 ); } return( 0 ); }
/* Read a PNG file (header) into a VIPS (header). */ static int png2vips( Read *read, int header_only ) { int bands, bpp, type; if( setjmp( read->pPng->jmpbuf ) ) return( -1 ); png_init_io( read->pPng, read->fp ); png_read_info( read->pPng, read->pInfo ); /* png_get_channels() gives us 1 band for palette images ... so look * at colour_type for output bands. */ switch( read->pInfo->color_type ) { case PNG_COLOR_TYPE_PALETTE: bands = 3; /* Don't know if this is really correct. If there are * transparent pixels, assume we're going to output RGBA. */ if( read->pInfo->num_trans ) bands = 4; break; case PNG_COLOR_TYPE_GRAY: bands = 1; break; case PNG_COLOR_TYPE_GRAY_ALPHA: bands = 2; break; case PNG_COLOR_TYPE_RGB: bands = 3; break; case PNG_COLOR_TYPE_RGB_ALPHA: bands = 4; break; default: im_error( "im_png2vips", "%s", _( "unsupported color type" ) ); return( -1 ); } /* 8 or 16 bit. */ bpp = read->pInfo->bit_depth > 8 ? 2 : 1; if( bpp > 1 ) { if( bands < 3 ) type = IM_TYPE_GREY16; else type = IM_TYPE_RGB16; } else { if( bands < 3 ) type = IM_TYPE_B_W; else type = IM_TYPE_sRGB; } /* Expand palette images. */ if( read->pInfo->color_type == PNG_COLOR_TYPE_PALETTE ) png_set_expand( read->pPng ); /* Expand <8 bit images to full bytes. */ if( read->pInfo->bit_depth < 8 ) { png_set_packing( read->pPng ); png_set_shift( read->pPng, &(read->pInfo->sig_bit) ); } /* If we're an INTEL byte order machine and this is 16bits, we need * to swap bytes. */ if( read->pInfo->bit_depth > 8 && !im_amiMSBfirst() ) png_set_swap( read->pPng ); /* Set VIPS header. */ im_initdesc( read->out, read->pInfo->width, read->pInfo->height, bands, bpp == 1 ? IM_BBITS_BYTE : IM_BBITS_SHORT, bpp == 1 ? IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT, IM_CODING_NONE, type, 1.0, 1.0, 0, 0 ); if( !header_only ) { if( png_set_interlace_handling( read->pPng ) > 1 ) { if( png2vips_interlace( read ) ) return( -1 ); } else { if( png2vips_noninterlace( read ) ) return( -1 ); } } return( 0 ); }