support libpng-1.5
libpng-1.5 removes some old API that libvips still used ... update png read/write to support the new API
This commit is contained in:
parent
73839df294
commit
9297a96ecf
14
TODO
14
TODO
|
@ -1,18 +1,4 @@
|
|||
|
||||
- png read/write needs redoing:
|
||||
|
||||
http://www.libpng.org/pub/png/src/libpng-1.4.x-to-1.5.x-summary.txt
|
||||
|
||||
... the ability to directly access
|
||||
the main libpng control structures, png_struct and png_info, deprecated
|
||||
in earlier versions of libpng, has been completely removed from
|
||||
libpng 1.5.
|
||||
|
||||
argh
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- add FITS and MATLAB write
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
* - gtkdoc
|
||||
* 8/1/11
|
||||
* - get png resolution (thanks Zhiyu Wu)
|
||||
* 17/3/11
|
||||
* - update for libpng-1.5 API changes
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -154,7 +156,7 @@ read_new( const char *name, IMAGE *out )
|
|||
|
||||
/* Catch PNG errors from png_create_info_struct().
|
||||
*/
|
||||
if( setjmp( read->pPng->jmpbuf ) ) {
|
||||
if( setjmp( png_jmpbuf( read->pPng ) ) ) {
|
||||
read_destroy( read );
|
||||
return( NULL );
|
||||
}
|
||||
|
@ -174,25 +176,25 @@ static int
|
|||
png2vips_interlace( Read *read )
|
||||
{
|
||||
const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out );
|
||||
const int height = png_get_image_height( read->pPng, read->pInfo );
|
||||
|
||||
int y;
|
||||
|
||||
if( !(read->row_pointer = IM_ARRAY( NULL,
|
||||
read->pInfo->height, png_bytep )) )
|
||||
if( !(read->row_pointer = IM_ARRAY( NULL, height, png_bytep )) )
|
||||
return( -1 );
|
||||
if( !(read->data = (png_bytep) im_malloc( NULL,
|
||||
read->pInfo->height * rowbytes )) )
|
||||
if( !(read->data = (png_bytep) im_malloc( NULL, height * rowbytes )) )
|
||||
return( -1 );
|
||||
|
||||
for( y = 0; y < (int) read->pInfo->height; y++ )
|
||||
for( y = 0; y < (int) height; y++ )
|
||||
read->row_pointer[y] = read->data + y * rowbytes;
|
||||
if( im_outcheck( read->out ) ||
|
||||
im_setupout( read->out ) ||
|
||||
setjmp( read->pPng->jmpbuf ) )
|
||||
setjmp( png_jmpbuf( read->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
png_read_image( read->pPng, read->row_pointer );
|
||||
|
||||
for( y = 0; y < (int) read->pInfo->height; y++ )
|
||||
for( y = 0; y < height; y++ )
|
||||
if( im_writeline( y, read->out, read->row_pointer[y] ) )
|
||||
return( -1 );
|
||||
|
||||
|
@ -206,16 +208,18 @@ static int
|
|||
png2vips_noninterlace( Read *read )
|
||||
{
|
||||
const int rowbytes = IM_IMAGE_SIZEOF_LINE( read->out );
|
||||
const int height = png_get_image_height( read->pPng, read->pInfo );
|
||||
|
||||
int y;
|
||||
|
||||
if( !(read->data = (png_bytep) im_malloc( NULL, rowbytes )) )
|
||||
return( -1 );
|
||||
if( im_outcheck( read->out ) ||
|
||||
im_setupout( read->out ) ||
|
||||
setjmp( read->pPng->jmpbuf ) )
|
||||
setjmp( png_jmpbuf( read->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
for( y = 0; y < (int) read->pInfo->height; y++ ) {
|
||||
for( y = 0; y < height; y++ ) {
|
||||
png_read_row( read->pPng, read->data, NULL );
|
||||
|
||||
if( im_writeline( y, read->out, read->data ) )
|
||||
|
@ -230,36 +234,58 @@ png2vips_noninterlace( Read *read )
|
|||
static int
|
||||
png2vips( Read *read, int header_only )
|
||||
{
|
||||
int bands, bpp, type;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type;
|
||||
int num_trans;
|
||||
png_color_8p sig_bit;
|
||||
|
||||
png_uint_32 res_x, res_y;
|
||||
int unit_type;
|
||||
|
||||
int bands, bpp, type;
|
||||
double Xres, Yres;
|
||||
|
||||
if( setjmp( read->pPng->jmpbuf ) )
|
||||
if( setjmp( png_jmpbuf( read->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
png_init_io( read->pPng, read->fp );
|
||||
png_read_info( read->pPng, read->pInfo );
|
||||
png_get_IHDR( read->pPng, read->pInfo,
|
||||
&width, &height, &bit_depth, &color_type,
|
||||
&interlace_type, NULL, NULL );
|
||||
png_get_tRNS( read->pPng, read->pInfo, NULL, &num_trans, NULL );
|
||||
png_get_sBIT( read->pPng, read->pInfo, &sig_bit );
|
||||
|
||||
/* png_get_channels() gives us 1 band for palette images ... so look
|
||||
* at colour_type for output bands.
|
||||
*/
|
||||
switch( read->pInfo->color_type ) {
|
||||
switch( 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 )
|
||||
if( 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;
|
||||
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" ) );
|
||||
|
@ -268,7 +294,7 @@ png2vips( Read *read, int header_only )
|
|||
|
||||
/* 8 or 16 bit.
|
||||
*/
|
||||
bpp = read->pInfo->bit_depth > 8 ? 2 : 1;
|
||||
bpp = bit_depth > 8 ? 2 : 1;
|
||||
|
||||
if( bpp > 1 ) {
|
||||
if( bands < 3 )
|
||||
|
@ -285,27 +311,29 @@ png2vips( Read *read, int header_only )
|
|||
|
||||
/* Expand palette images.
|
||||
*/
|
||||
if( read->pInfo->color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
if( color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
png_set_expand( read->pPng );
|
||||
|
||||
/* Expand <8 bit images to full bytes.
|
||||
*/
|
||||
if( read->pInfo->bit_depth < 8 ) {
|
||||
if( bit_depth < 8 ) {
|
||||
png_set_packing( read->pPng );
|
||||
png_set_shift( read->pPng, &(read->pInfo->sig_bit) );
|
||||
png_set_shift( read->pPng, 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() )
|
||||
if( bit_depth > 8 && !im_amiMSBfirst() )
|
||||
png_set_swap( read->pPng );
|
||||
|
||||
/* Get resolution. I'm not sure what we should do for UNKNOWN, since
|
||||
* vips is always pixels/mm.
|
||||
*/
|
||||
png_get_pHYs( read->pPng, read->pInfo,
|
||||
&res_x, &res_y, &unit_type );
|
||||
unit_type = PNG_RESOLUTION_METER;
|
||||
res_x = 1000;
|
||||
res_y = 1000;
|
||||
png_get_pHYs( read->pPng, read->pInfo, &res_x, &res_y, &unit_type );
|
||||
switch( unit_type ) {
|
||||
case PNG_RESOLUTION_METER:
|
||||
Xres = res_x / 1000.0;
|
||||
|
@ -320,8 +348,7 @@ png2vips( Read *read, int header_only )
|
|||
|
||||
/* Set VIPS header.
|
||||
*/
|
||||
im_initdesc( read->out,
|
||||
read->pInfo->width, read->pInfo->height, bands,
|
||||
im_initdesc( read->out, width, height, bands,
|
||||
bpp == 1 ? IM_BBITS_BYTE : IM_BBITS_SHORT,
|
||||
bpp == 1 ? IM_BANDFMT_UCHAR : IM_BANDFMT_USHORT,
|
||||
IM_CODING_NONE, type,
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
* - added im_vips2bufpng()
|
||||
* 8/1/11
|
||||
* - set png resolution (thanks Zhiyu Wu)
|
||||
* 17/3/11
|
||||
* - update for libpng-1.5 API changes
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -169,7 +171,7 @@ write_new( IMAGE *in )
|
|||
|
||||
/* Catch PNG errors from png_create_info_struct().
|
||||
*/
|
||||
if( setjmp( write->pPng->jmpbuf ) ) {
|
||||
if( setjmp( png_jmpbuf( write->pPng ) ) ) {
|
||||
write_destroy( write );
|
||||
return( NULL );
|
||||
}
|
||||
|
@ -197,7 +199,7 @@ write_png_block( REGION *region, Rect *area, void *a )
|
|||
|
||||
/* Catch PNG errors. Yuk.
|
||||
*/
|
||||
if( setjmp( write->pPng->jmpbuf ) )
|
||||
if( setjmp( png_jmpbuf( write->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
for( i = 0; i < area->height; i++ )
|
||||
|
@ -216,6 +218,9 @@ write_vips( Write *write, int compress, int interlace )
|
|||
{
|
||||
IMAGE *in = write->in;
|
||||
|
||||
int bit_depth;
|
||||
int color_type;
|
||||
int interlace_type;
|
||||
int i, nb_passes;
|
||||
|
||||
g_assert( in->BandFmt == IM_BANDFMT_UCHAR ||
|
||||
|
@ -225,7 +230,7 @@ write_vips( Write *write, int compress, int interlace )
|
|||
|
||||
/* Catch PNG errors.
|
||||
*/
|
||||
if( setjmp( write->pPng->jmpbuf ) )
|
||||
if( setjmp( png_jmpbuf( write->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
/* Check input image.
|
||||
|
@ -242,21 +247,26 @@ write_vips( Write *write, int compress, int interlace )
|
|||
*/
|
||||
png_set_compression_level( write->pPng, compress );
|
||||
|
||||
write->pInfo->width = in->Xsize;
|
||||
write->pInfo->height = in->Ysize;
|
||||
write->pInfo->bit_depth = (in->BandFmt == IM_BANDFMT_UCHAR ? 8 : 16);
|
||||
write->pInfo->gamma = (float) 1.0;
|
||||
bit_depth = in->BandFmt == IM_BANDFMT_UCHAR ? 8 : 16;
|
||||
|
||||
switch( in->Bands ) {
|
||||
case 1: write->pInfo->color_type = PNG_COLOR_TYPE_GRAY; break;
|
||||
case 2: write->pInfo->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
|
||||
case 3: write->pInfo->color_type = PNG_COLOR_TYPE_RGB; break;
|
||||
case 4: write->pInfo->color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
|
||||
case 1: color_type = PNG_COLOR_TYPE_GRAY; break;
|
||||
case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
|
||||
case 3: color_type = PNG_COLOR_TYPE_RGB; break;
|
||||
case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; break;
|
||||
|
||||
default:
|
||||
g_assert( 0 );
|
||||
}
|
||||
|
||||
interlace_type = interlace ? PNG_INTERLACE_ADAM7 : PNG_INTERLACE_NONE;
|
||||
|
||||
png_set_IHDR( write->pPng, write->pInfo,
|
||||
in->Xsize, in->Ysize, bit_depth, color_type, interlace_type,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
|
||||
|
||||
png_set_gAMA( write->pPng, write->pInfo, (float) 1.0 );
|
||||
|
||||
/* Set resolution. libpnbg uses pixels per meter.
|
||||
*/
|
||||
png_set_pHYs( write->pPng, write->pInfo,
|
||||
|
@ -268,7 +278,7 @@ write_vips( Write *write, int compress, int interlace )
|
|||
/* If we're an intel byte order CPU and this is a 16bit image, we need
|
||||
* to swap bytes.
|
||||
*/
|
||||
if( write->pInfo->bit_depth > 8 && !im_amiMSBfirst() )
|
||||
if( bit_depth > 8 && !im_amiMSBfirst() )
|
||||
png_set_swap( write->pPng );
|
||||
|
||||
if( interlace )
|
||||
|
@ -284,7 +294,7 @@ write_vips( Write *write, int compress, int interlace )
|
|||
|
||||
/* The setjmp() was held by our background writer: reset it.
|
||||
*/
|
||||
if( setjmp( write->pPng->jmpbuf ) )
|
||||
if( setjmp( png_jmpbuf( write->pPng ) ) )
|
||||
return( -1 );
|
||||
|
||||
png_write_end( write->pPng, write->pInfo );
|
||||
|
@ -389,24 +399,24 @@ im_vips2png( IMAGE *in, const char *filename )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
typedef struct _PngWriteBuf {
|
||||
typedef struct _WriteBuf {
|
||||
char *buf;
|
||||
size_t len;
|
||||
size_t alloc;
|
||||
} PngWriteBuf;
|
||||
} WriteBuf;
|
||||
|
||||
static void
|
||||
png_write_buf_free( PngWriteBuf *wbuf )
|
||||
write_buf_free( WriteBuf *wbuf )
|
||||
{
|
||||
IM_FREE( wbuf );
|
||||
}
|
||||
|
||||
static PngWriteBuf *
|
||||
png_write_buf_new( void )
|
||||
static WriteBuf *
|
||||
write_buf_new( void )
|
||||
{
|
||||
PngWriteBuf *wbuf;
|
||||
WriteBuf *wbuf;
|
||||
|
||||
if( !(wbuf = IM_NEW( NULL, PngWriteBuf )) )
|
||||
if( !(wbuf = IM_NEW( NULL, WriteBuf )) )
|
||||
return( NULL );
|
||||
|
||||
wbuf->buf = NULL;
|
||||
|
@ -417,7 +427,7 @@ png_write_buf_new( void )
|
|||
}
|
||||
|
||||
static void
|
||||
png_write_buf_grow( PngWriteBuf *wbuf, size_t grow_len )
|
||||
write_buf_grow( WriteBuf *wbuf, size_t grow_len )
|
||||
{
|
||||
size_t new_len = wbuf->len + grow_len;
|
||||
|
||||
|
@ -434,7 +444,7 @@ png_write_buf_grow( PngWriteBuf *wbuf, size_t grow_len )
|
|||
*/
|
||||
wbuf->buf = g_realloc( wbuf->buf, wbuf->alloc );
|
||||
|
||||
VIPS_DEBUG_MSG( "png_write_buf_grow: grown to %zd bytes\n",
|
||||
VIPS_DEBUG_MSG( "write_buf_grow: grown to %zd bytes\n",
|
||||
wbuf->alloc );
|
||||
}
|
||||
}
|
||||
|
@ -442,13 +452,14 @@ png_write_buf_grow( PngWriteBuf *wbuf, size_t grow_len )
|
|||
static void
|
||||
user_write_data( png_structp png_ptr, png_bytep data, png_size_t length )
|
||||
{
|
||||
PngWriteBuf *wbuf = (PngWriteBuf *) png_ptr->io_ptr;
|
||||
WriteBuf *wbuf = (WriteBuf *) png_get_io_ptr( png_ptr );
|
||||
|
||||
char *write_start;
|
||||
|
||||
png_write_buf_grow( wbuf, length );
|
||||
write_buf_grow( wbuf, length );
|
||||
|
||||
write_start = wbuf->buf + wbuf->len;
|
||||
png_memcpy( write_start, data, length );
|
||||
memcpy( write_start, data, length );
|
||||
|
||||
wbuf->len += length;
|
||||
|
||||
|
@ -479,10 +490,10 @@ int
|
|||
im_vips2bufpng( IMAGE *in, IMAGE *out,
|
||||
int compression, int interlace, char **obuf, size_t *olen )
|
||||
{
|
||||
PngWriteBuf *wbuf;
|
||||
WriteBuf *wbuf;
|
||||
Write *write;
|
||||
|
||||
if( !(wbuf = png_write_buf_new()) ||
|
||||
if( !(wbuf = write_buf_new()) ||
|
||||
!(write = write_new( in )) )
|
||||
return( -1 );
|
||||
|
||||
|
@ -492,7 +503,7 @@ im_vips2bufpng( IMAGE *in, IMAGE *out,
|
|||
*/
|
||||
if( write_vips( write, compression, interlace ) ) {
|
||||
write_destroy( write );
|
||||
png_write_buf_free( wbuf );
|
||||
write_buf_free( wbuf );
|
||||
im_error( "im_vips2bufpng",
|
||||
"%s", _( "unable to write to buffer" ) );
|
||||
|
||||
|
@ -503,7 +514,7 @@ im_vips2bufpng( IMAGE *in, IMAGE *out,
|
|||
*obuf = wbuf->buf;
|
||||
*olen = wbuf->len;
|
||||
|
||||
png_write_buf_free( wbuf );
|
||||
write_buf_free( wbuf );
|
||||
|
||||
if( out && im_add_close_callback( out,
|
||||
(im_callback_fn) im_free, *obuf, NULL ) ) {
|
||||
|
|
|
@ -1207,13 +1207,13 @@ vips_image_class_init( VipsImageClass *class )
|
|||
static void
|
||||
vips_image_init( VipsImage *image )
|
||||
{
|
||||
/* Init to 0 is fine for most header fields.
|
||||
*/
|
||||
|
||||
/* Default to native order.
|
||||
*/
|
||||
image->magic = im_amiMSBfirst() ? VIPS_MAGIC_SPARC : VIPS_MAGIC_INTEL;
|
||||
|
||||
image->Xres = 1.0;
|
||||
image->Yres = 1.0;
|
||||
|
||||
image->fd = -1; /* since 0 is stdout */
|
||||
image->sslock = g_mutex_new();
|
||||
|
||||
|
|
Loading…
Reference in New Issue