diff --git a/ChangeLog b/ChangeLog index 1ffb1872..ead3bdb8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,7 @@ - im_iterate() -> vips_sink() - better number-of-bands detection for im_magick2vips() - added im_get_argv0() +- added PFM read / write 16/1/10 started 7.21.2 - "invalidate" is careful to keep images alive, so invalidate callbacks can do diff --git a/TODO b/TODO index 781a00e1..9c7bcdd6 100644 --- a/TODO +++ b/TODO @@ -1,8 +1,9 @@ -- add support for PFM files, portable float maps +- convert_saveable for other writers: tiff, ppm, csv, rad etc. - used in HDR imaging, apparently + the tiff writer could use more im_check_ things + test pfm write - expose more of the tone funcs in nip2 diff --git a/libvips/conversion/im_copy.c b/libvips/conversion/im_copy.c index e585ef28..379658a2 100644 --- a/libvips/conversion/im_copy.c +++ b/libvips/conversion/im_copy.c @@ -389,16 +389,16 @@ im_copy_native( IMAGE *in, IMAGE *out, gboolean is_msb_first ) /* Convert to a saveable format. * * im__saveable_t gives the general type of image - * we make: vanilla 1/3 bands (PPM), with an optional alpha (like PNG), or - * with CMYK as an option (like JPEG). + * we make: vanilla 1/3 bands (eg. PPM), with an optional alpha (eg. PNG), or + * with CMYK as an option (eg. JPEG). * - * sixteen TRUE means 16 bit uchar is OK as well (eg. PNG), otherwise we - * always cast down to u8. + * format_table[] says how to convert each input format. * * Need to im_close() the result IMAGE. */ IMAGE * -im__convert_saveable( IMAGE *in, im__saveable_t saveable, gboolean sixteen ) +im__convert_saveable( IMAGE *in, + im__saveable_t saveable, int format_table[10] ) { IMAGE *out; @@ -476,6 +476,9 @@ im__convert_saveable( IMAGE *in, im__saveable_t saveable, gboolean sixteen ) in = t; } + + /* Else we have saveable IM__ANY and we don't chop bands down. + */ } /* Interpret the Type field for colorimetric images. @@ -573,18 +576,12 @@ im__convert_saveable( IMAGE *in, im__saveable_t saveable, gboolean sixteen ) in = t[1]; } - /* Clip to uchar/ushort if not there already. + /* Cast to the output format. */ - if( (sixteen && - in->BandFmt != IM_BANDFMT_UCHAR && - in->BandFmt != IM_BANDFMT_USHORT) || - (!sixteen && - in->BandFmt != IM_BANDFMT_UCHAR) ) { + { IMAGE *t = im_open_local( out, "conv:1", "p" ); - VipsBandFmt fmt = sixteen && IM_IMAGE_SIZEOF_ELEMENT( in ) > 1 ? - IM_BANDFMT_USHORT : IM_BANDFMT_UCHAR; - if( !t || im_clip2fmt( in, t, fmt ) ) { + if( !t || im_clip2fmt( in, t, format_table[in->BandFmt] ) ) { im_close( out ); return( NULL ); } @@ -599,4 +596,3 @@ im__convert_saveable( IMAGE *in, im__saveable_t saveable, gboolean sixteen ) return( out ); } - diff --git a/libvips/format/im_magick2vips.c b/libvips/format/im_magick2vips.c index c289f4db..8d386163 100644 --- a/libvips/format/im_magick2vips.c +++ b/libvips/format/im_magick2vips.c @@ -367,9 +367,8 @@ parse_header( Read *read ) ResetImagePropertyIterator( image ); while( (key = GetNextImageProperty( image )) ) { char name_text[256]; - VipsBuf name; + VipsBuf name = VIPS_BUF_STATIC( name_text ); - vips_buf_init_static( &name, name_text, 256 ); vips_buf_appendf( &name, "magick-%s", key ); im_meta_set_string( im, vips_buf_all( &name ), GetImageProperty( image, key ) ); @@ -384,9 +383,8 @@ parse_header( Read *read ) ResetImageAttributeIterator( image ); while( (attr = GetNextImageAttribute( image )) ) { char name_text[256]; - VipsBuf name; + VipsBuf name = VIPS_BUF_STATIC( name_text ); - vips_buf_init_static( &name, name_text, 256 ); vips_buf_appendf( &name, "magick-%s", attr->key ); im_meta_set_string( im, vips_buf_all( &name ), attr->value ); } @@ -401,9 +399,8 @@ parse_header( Read *read ) */ for( attr = image->attributes; attr; attr = attr->next ) { char name_text[256]; - VipsBuf name; + VipsBuf name = VIPS_BUF_STATIC( name_text ); - vips_buf_init_static( &name, name_text, 256 ); vips_buf_appendf( &name, "magick-%s", attr->key ); im_meta_set_string( im, vips_buf_all( &name ), attr->value ); } diff --git a/libvips/format/im_ppm2vips.c b/libvips/format/im_ppm2vips.c index ba59a564..ae61e985 100644 --- a/libvips/format/im_ppm2vips.c +++ b/libvips/format/im_ppm2vips.c @@ -21,6 +21,8 @@ * - tiny cleanups * 4/2/10 * - gtkdoc + * 1/5/10 + * - add PFM (portable float map) support */ /* @@ -56,9 +58,9 @@ #include #include -#include #include #include +#include #include #include @@ -96,39 +98,35 @@ skip_white_space( FILE *fp ) } static int -read_uint( FILE *fp ) +read_int( FILE *fp, int *i ) { - int i; - char buf[IM_MAX_THING]; - int ch; - skip_white_space( fp ); - - /* Stop complaints about used-before-set on ch. - */ - ch = -1; - - for( i = 0; i < IM_MAX_THING - 1 && isdigit( ch = fgetc( fp ) ); i++ ) - buf[i] = ch; - buf[i] = '\0'; - - if( i == 0 ) { - im_error( "im_ppm2vips", "%s", _( "bad unsigned int" ) ); + if( fscanf( fp, "%d", i ) != 1 ) { + im_error( "im_ppm2vips", "%s", _( "bad int" ) ); return( -1 ); } - ungetc( ch, fp ); - - return( atoi( buf ) ); + return( 0 ); } static int -read_header( FILE *fp, IMAGE *out, int *bits, int *ascii ) +read_float( FILE *fp, float *f ) +{ + skip_white_space( fp ); + if( fscanf( fp, "%f", f ) != 1 ) { + im_error( "im_ppm2vips", "%s", _( "bad float" ) ); + return( -1 ); + } + + return( 0 ); +} + +static int +read_header( FILE *fp, IMAGE *out, int *bits, int *ascii, int *msb_first ) { int width, height, bands, fmt, type; - int i; + int index; char buf[IM_MAX_THING]; - int max_value; /* ppm types. */ @@ -138,19 +136,21 @@ read_header( FILE *fp, IMAGE *out, int *bits, int *ascii ) "P3", /* ppm ... 3 band many bit, ascii */ "P4", /* pbm ... 1 band 1 bit, binary */ "P5", /* pgm ... 1 band 8 bit, binary */ - "P6" /* ppm ... 3 band 8 bit, binary */ + "P6", /* ppm ... 3 band 8 bit, binary */ + "PF", /* pfm ... 3 band 32 bit, binary */ + "Pf" /* pfm ... 1 band 32 bit, binary */ }; /* Characteristics, indexed by ppm type. */ static int lookup_bits[] = { - 1, 8, 8, 1, 8, 8 + 1, 8, 8, 1, 8, 8, 32, 32 }; static int lookup_bands[] = { - 1, 1, 3, 1, 1, 3 + 1, 1, 3, 1, 1, 3, 3, 1 }; static int lookup_ascii[] = { - 1, 1, 1, 0, 0, 0 + 1, 1, 1, 0, 0, 0, 0, 0 }; /* Read in the magic number. @@ -159,33 +159,52 @@ read_header( FILE *fp, IMAGE *out, int *bits, int *ascii ) buf[1] = fgetc( fp ); buf[2] = '\0'; - for( i = 0; i < IM_NUMBER( magic_names ); i++ ) - if( strcmp( magic_names[i], buf ) == 0 ) + for( index = 0; index < IM_NUMBER( magic_names ); index++ ) + if( strcmp( magic_names[index], buf ) == 0 ) break; - if( i == IM_NUMBER( magic_names ) ) { + if( index == IM_NUMBER( magic_names ) ) { im_error( "im_ppm2vips", "%s", _( "bad magic number" ) ); return( -1 ); } - *bits = lookup_bits[i]; - bands = lookup_bands[i]; - *ascii = lookup_ascii[i]; + *bits = lookup_bits[index]; + bands = lookup_bands[index]; + *ascii = lookup_ascii[index]; + + /* Default ... can be changed below for PFM images. + */ + *msb_first = 0; /* Read in size. */ - if( (width = read_uint( fp )) < 0 || - (height = read_uint( fp )) < 0 ) + if( read_int( fp, &width ) || + read_int( fp, &height ) ) return( -1 ); - /* Read in max value for >1 bit images. + /* Read in max value / scale for >1 bit images. */ if( *bits > 1 ) { - if( (max_value = read_uint( fp )) < 0 ) - return( -1 ); + if( index == 6 || index == 7 ) { + float scale; - if( max_value > 255 ) - *bits = 16; - if( max_value > 65535 ) - *bits = 32; + if( read_float( fp, &scale ) ) + return( -1 ); + + /* Scale > 0 means big-endian. + */ + *msb_first = scale > 0; + im_meta_set_double( out, "pfm-scale", fabs( scale ) ); + } + else { + int max_value; + + if( read_int( fp, &max_value ) ) + return( -1 ); + + if( max_value > 255 ) + *bits = 16; + if( max_value > 65535 ) + *bits = 32; + } } /* For binary images, there is always exactly 1 more whitespace @@ -210,11 +229,14 @@ read_header( FILE *fp, IMAGE *out, int *bits, int *ascii ) break; case 32: - fmt = IM_BANDFMT_UINT; + if( index == 6 || index == 7 ) + fmt = IM_BANDFMT_FLOAT; + else + fmt = IM_BANDFMT_UINT; break; default: - assert( 0 ); + g_assert( 0 ); } if( bands == 1 ) { @@ -244,7 +266,7 @@ read_header( FILE *fp, IMAGE *out, int *bits, int *ascii ) /* Read a ppm/pgm file using mmap(). */ static int -read_mmap( FILE *fp, const char *filename, IMAGE *out ) +read_mmap( FILE *fp, const char *filename, int msb_first, IMAGE *out ) { const int header_offset = ftell( fp ); IMAGE *t[2]; @@ -255,7 +277,7 @@ read_mmap( FILE *fp, const char *filename, IMAGE *out ) IM_IMAGE_SIZEOF_PEL( out ), header_offset ) || im_copy_morph( t[0], t[1], out->Bands, out->BandFmt, out->Coding ) || - im_copy_native( t[1], out, TRUE ) ) + im_copy_native( t[1], out, msb_first ) ) return( -1 ); return( 0 ); @@ -277,7 +299,7 @@ read_ascii( FILE *fp, IMAGE *out ) for( x = 0; x < out->Xsize * out->Bands; x++ ) { int val; - if( (val = read_uint( fp )) < 0 ) + if( read_int( fp, &val ) ) return( -1 ); switch( out->BandFmt ) { @@ -295,7 +317,7 @@ read_ascii( FILE *fp, IMAGE *out ) break; default: - assert( 0 ); + g_assert( 0 ); } } @@ -322,7 +344,7 @@ read_1bit_ascii( FILE *fp, IMAGE *out ) for( x = 0; x < out->Xsize * out->Bands; x++ ) { int val; - if( (val = read_uint( fp )) < 0 ) + if( read_int( fp, &val ) ) return( -1 ); if( val == 1 ) @@ -372,14 +394,15 @@ parse_ppm( FILE *fp, const char *filename, IMAGE *out ) { int bits; int ascii; + int msb_first; - if( read_header( fp, out, &bits, &ascii ) ) + if( read_header( fp, out, &bits, &ascii, &msb_first ) ) return( -1 ); /* What sort of read are we doing? */ if( !ascii && bits >= 8 ) - return( read_mmap( fp, filename, out ) ); + return( read_mmap( fp, filename, msb_first, out ) ); else if( !ascii && bits == 1 ) return( read_1bit_binary( fp, out ) ); else if( ascii && bits == 1 ) @@ -394,10 +417,11 @@ ppm2vips_header( const char *filename, IMAGE *out ) FILE *fp; int bits; int ascii; + int msb_first; if( !(fp = im__file_open_read( filename, NULL )) ) return( -1 ); - if( read_header( fp, out, &bits, &ascii ) ) { + if( read_header( fp, out, &bits, &ascii, &msb_first ) ) { fclose( fp ); return( -1 ); } @@ -416,6 +440,7 @@ isppmmmap( const char *filename ) FILE *fp; int bits; int ascii; + int msb_first; if( !(fp = im__file_open_read( filename, NULL )) ) return( -1 ); @@ -424,7 +449,7 @@ isppmmmap( const char *filename ) fclose( fp ); return( 0 ); } - if( read_header( fp, im, &bits, &ascii ) ) { + if( read_header( fp, im, &bits, &ascii, &msb_first ) ) { im_close( im ); fclose( fp ); return( 0 ); @@ -440,12 +465,14 @@ isppmmmap( const char *filename ) * @filename: file to load * @out: image to write to * - * Read a PPM/PBM/PGM file into a VIPS image. + * Read a PPM/PBM/PGM/PFM file into a VIPS image. * It can read 1, 8, 16 and 32 bit images, colour or monochrome, * stored in binary or in ASCII. One bit images become 8 bit VIPS images, * with 0 and 255 for 0 and 1. * - * See also: #VipsFormat, im_vips2ppm(). + * PFM images have the scale factor attached as "pfm-scale". + * + * See also: #VipsFormat, im_vips2ppm(), im_meta_get_double() * * Returns: 0 on success, -1 on error. */ @@ -491,7 +518,7 @@ ppm_flags( const char *filename ) return( flags ); } -static const char *ppm_suffs[] = { ".ppm", ".pgm", ".pbm", NULL }; +static const char *ppm_suffs[] = { ".ppm", ".pgm", ".pbm", ".pfm", NULL }; /* ppm format adds no new members. */ @@ -505,7 +532,7 @@ vips_format_ppm_class_init( VipsFormatPpmClass *class ) VipsFormatClass *format_class = (VipsFormatClass *) class; object_class->nickname = "ppm"; - object_class->description = _( "PPM/PBM/PNM" ); + object_class->description = _( "PPM/PBM/PNM/PFM" ); format_class->is_a = isppm; format_class->header = ppm2vips_header; diff --git a/libvips/format/im_vips2jpeg.c b/libvips/format/im_vips2jpeg.c index 5236ba58..9c8f58b7 100644 --- a/libvips/format/im_vips2jpeg.c +++ b/libvips/format/im_vips2jpeg.c @@ -219,6 +219,15 @@ write_destroy( Write *write ) im_free( write ); } +#define UC IM_BANDFMT_UCHAR + +/* Type promotion for save ... just always go to uchar. + */ +static int bandfmt_jpeg[10] = { +/* UC C US S UI I F X D DX */ + UC, UC, UC, UC, UC, UC, UC, UC, UC, UC +}; + static Write * write_new( IMAGE *in ) { @@ -228,13 +237,13 @@ write_new( IMAGE *in ) return( NULL ); memset( write, 0, sizeof( Write ) ); - if( !(write->in = im__convert_saveable( in, IM__RGB_CMYK, FALSE )) ) { + if( !(write->in = im__convert_saveable( in, + IM__RGB_CMYK, bandfmt_jpeg )) ) { im_error( "im_vips2jpeg", "%s", _( "unable to convert to saveable format" ) ); write_destroy( write ); return( NULL ); - } - + } write->row_pointer = NULL; write->cinfo.err = jpeg_std_error( &write->eman.pub ); write->eman.pub.error_exit = new_error_exit; diff --git a/libvips/format/im_vips2png.c b/libvips/format/im_vips2png.c index 8e0b2fc8..7fb83431 100644 --- a/libvips/format/im_vips2png.c +++ b/libvips/format/im_vips2png.c @@ -117,6 +117,16 @@ write_destroy( Write *write ) im_free( write ); } +#define UC IM_BANDFMT_UCHAR +#define US IM_BANDFMT_USHORT + +/* Type promotion for save ... uchar or ushort. + */ +static int bandfmt_png[10] = { +/* UC C US S UI I F X D DX */ + US, UC, US, US, US, US, UC, UC, UC, UC +}; + static Write * write_new( IMAGE *in ) { @@ -126,7 +136,7 @@ write_new( IMAGE *in ) return( NULL ); memset( write, 0, sizeof( Write ) ); - if( !(write->in = im__convert_saveable( in, IM__RGBA, TRUE )) ) { + if( !(write->in = im__convert_saveable( in, IM__RGBA, bandfmt_png )) ) { im_error( "im_vips2png", "%s", _( "unable to convert to saveable format" ) ); write_destroy( write ); diff --git a/libvips/format/im_vips2ppm.c b/libvips/format/im_vips2ppm.c index 3436eb30..f869ab62 100644 --- a/libvips/format/im_vips2ppm.c +++ b/libvips/format/im_vips2ppm.c @@ -9,6 +9,8 @@ * 4/2/10 * - gtkdoc * - cleanups + * 1/5/10 + * - add PFM (portable float map) support */ /* @@ -44,7 +46,6 @@ #include #include -#include #include #include #include @@ -100,14 +101,10 @@ static int write_ppm_line_ascii( IMAGE *in, FILE *fp, PEL *p ) { const int sk = IM_IMAGE_SIZEOF_PEL( in ); - const int nb = IM_MIN( 3, in->Bands ); int x, k; - /* If IM_CODING_LABQ, write 3 bands. - */ - for( x = 0; x < in->Xsize; x++ ) { - for( k = 0; k < nb; k++ ) { + for( k = 0; k < in->Bands; k++ ) { switch( in->BandFmt ) { case IM_BANDFMT_UCHAR: fprintf( fp, "%d ", p[k] ); @@ -122,7 +119,7 @@ write_ppm_line_ascii( IMAGE *in, FILE *fp, PEL *p ) break; default: - assert( 0 ); + g_assert( 0 ); } } @@ -143,18 +140,10 @@ write_ppm_line_ascii( IMAGE *in, FILE *fp, PEL *p ) static int write_ppm_line_binary( IMAGE *in, FILE *fp, PEL *p ) { - const int sk = IM_IMAGE_SIZEOF_PEL( in ); - const int nb = IM_MIN( 3, in->Bands ); - int x; - - for( x = 0; x < in->Xsize; x++ ) { - if( !fwrite( p, 1, nb, fp ) ) { - im_error( "im_vips2ppm", - "%s", _( "write error ... disc full?" ) ); - return( -1 ); - } - - p += sk; + if( !fwrite( p, IM_IMAGE_SIZEOF_LINE( in ), 1, fp ) ) { + im_error( "im_vips2ppm", + "%s", _( "write error ... disc full?" ) ); + return( -1 ); } return( 0 ); @@ -181,28 +170,14 @@ write_ppm( Write *write, int ascii ) { IMAGE *in = write->in; - int max_value; char *magic; time_t timebuf; - switch( in->BandFmt ) { - case IM_BANDFMT_UCHAR: - max_value = UCHAR_MAX; - break; - - case IM_BANDFMT_USHORT: - max_value = USHRT_MAX; - break; - - case IM_BANDFMT_UINT: - max_value = UINT_MAX; - break; - - default: - assert( 0 ); - } - - if( in->Bands == 1 && ascii ) + if( in->BandFmt == IM_BANDFMT_FLOAT && in->Bands == 3 ) + magic = "PF"; + else if( in->BandFmt == IM_BANDFMT_FLOAT && in->Bands == 1 ) + magic = "Pf"; + else if( in->Bands == 1 && ascii ) magic = "P2"; else if( in->Bands == 1 && !ascii ) magic = "P5"; @@ -211,13 +186,41 @@ write_ppm( Write *write, int ascii ) else if( in->Bands == 3 && !ascii ) magic = "P6"; else - assert( 0 ); + g_assert( 0 ); fprintf( write->fp, "%s\n", magic ); time( &timebuf ); fprintf( write->fp, "#im_vips2ppm - %s\n", ctime( &timebuf ) ); fprintf( write->fp, "%d %d\n", in->Xsize, in->Ysize ); - fprintf( write->fp, "%d\n", max_value ); + + switch( in->BandFmt ) { + case IM_BANDFMT_UCHAR: + fprintf( write->fp, "%d\n", UCHAR_MAX ); + break; + + case IM_BANDFMT_USHORT: + fprintf( write->fp, "%d\n", USHRT_MAX ); + break; + + case IM_BANDFMT_UINT: + fprintf( write->fp, "%d\n", UINT_MAX ); + break; + + case IM_BANDFMT_FLOAT: +{ + double scale; + + if( im_meta_get_double( in, "pfm-scale", &scale ) ) + scale = 1; + if( !im_amiMSBfirst() ) + scale *= -1; + fprintf( write->fp, "%g\n", scale ); +} + break; + + default: + g_assert( 0 ); + } write->fn = ascii ? write_ppm_line_ascii : write_ppm_line_binary; @@ -233,9 +236,12 @@ write_ppm( Write *write, int ascii ) * @filename: file to write to * * Write a VIPS image to a file as PPM. It can write 8, 16 or - * 32 bit unsigned integer images, colour or monochrome, stored as binary or - * ASCII. - * Images of more than 8 bits can only be stored in ASCII. + * 32 bit unsigned integer images, float images, colour or monochrome, + * stored as binary or ASCII. + * Integer images of more than 8 bits can only be stored in ASCII. + * + * When writing float (PFM) images the scale factor is set from the + * "pfm-scale" metadata. * * The storage format is indicated by a filename extension, for example: * @@ -245,7 +251,7 @@ write_ppm( Write *write, int ascii ) * * will write to "fred.ppm" in ascii format. The default is binary. * - * See also: #VipsFormat, im_ppm2vips(). + * See also: #VipsFormat, im_ppm2vips(), im_meta_set_double(). * * Returns: 0 on success, -1 on error. */ @@ -277,17 +283,22 @@ im_vips2ppm( IMAGE *in, const char *filename ) } } - if( im_bits_of_fmt( in->BandFmt ) > 8 && !ascii ) { - im_error( "im_vips2ppm", - "%s", _( "can't write binary >8 bit images" ) ); - return( -1 ); - } - if( im_check_uint( "im_vips2ppm", in ) || + if( im_check_uintorf( "im_vips2ppm", in ) || im_check_bands_1or3( "im_vips2ppm", in ) || im_check_uncoded( "im_vips2ppm", in ) || im_pincheck( in ) ) return( -1 ); + /* We can only write >8 bit binary images in float. + */ + if( im_bits_of_fmt( in->BandFmt ) > 8 && + !ascii && + in->BandFmt != IM_BANDFMT_FLOAT ) { + im_error( "im_vips2ppm", + "%s", _( "binary >8 bit images must be float" ) ); + return( -1 ); + } + if( !(write = write_new( in, name )) ) return( -1 ); diff --git a/libvips/format/im_vips2tiff.c b/libvips/format/im_vips2tiff.c index 0464f7ff..bb8f695f 100644 --- a/libvips/format/im_vips2tiff.c +++ b/libvips/format/im_vips2tiff.c @@ -1690,12 +1690,9 @@ im_vips2tiff( IMAGE *in, const char *filename ) /* Check input image. */ - if( im_pincheck( in ) ) + if( im_pincheck( in ) || + im_check_coding_known( "im_vips2tiff", in ) ) return( -1 ); - if( in->Coding != IM_CODING_LABQ && in->Coding != IM_CODING_NONE ) { - im_error( "im_vips2tiff", "%s", _( "unknown coding type" ) ); - return( -1 ); - } if( in->BandFmt != IM_BANDFMT_UCHAR && !(in->BandFmt == IM_BANDFMT_SHORT && in->Type == IM_TYPE_LABS) && diff --git a/libvips/include/vips/check.h b/libvips/include/vips/check.h index f57130bd..000ba2bc 100644 --- a/libvips/include/vips/check.h +++ b/libvips/include/vips/check.h @@ -57,6 +57,7 @@ int im_check_bands_same( const char *domain, IMAGE *im1, IMAGE *im2 ); int im_check_bandno( const char *domain, IMAGE *im, int bandno ); int im_check_int( const char *domain, IMAGE *im ); int im_check_uint( const char *domain, IMAGE *im ); +int im_check_uintorf( const char *domain, IMAGE *im ); int im_check_noncomplex( const char *domain, IMAGE *im ); int im_check_complex( const char *domain, IMAGE *im ); int im_check_format( const char *domain, IMAGE *im, VipsBandFmt fmt ); diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 345579c1..8278eef0 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -126,13 +126,14 @@ extern int im__read_test; extern GMutex *im__global_lock; typedef enum { - IM__RGB, /* 1 or 3 bands (like PPM) */ - IM__RGBA, /* 1, 2, 3 or 4 bands (like PNG) */ - IM__RGB_CMYK /* 1, 3 or 4 bands (like JPEG) */ + IM__RGB, /* 1 or 3 bands (eg. PPM) */ + IM__RGBA, /* 1, 2, 3 or 4 bands (eg. PNG) */ + IM__RGB_CMYK, /* 1, 3 or 4 bands (eg. JPEG) */ + IM__ANY /* any number of bands (eg. TIFF) */ } im__saveable_t; IMAGE *im__convert_saveable( IMAGE *in, - im__saveable_t saveable, gboolean sixteen ); + im__saveable_t saveable, int format_table[10] ); void im__link_break_all( IMAGE *im ); void *im__link_map( IMAGE *im, VSListMap2Fn fn, void *a, void *b ); diff --git a/libvips/iofuncs/check.c b/libvips/iofuncs/check.c index 38712351..87df0d9b 100644 --- a/libvips/iofuncs/check.c +++ b/libvips/iofuncs/check.c @@ -947,6 +947,33 @@ im_check_u8or16orf( const char *domain, IMAGE *im ) return( 0 ); } +/** + * im_check_uintorf: + * @domain: the originating domain for the error message + * @im: image to check + * + * Check that the image is unsigned int or float. + * Otherwise set an error message and return non-zero. + * + * See also: im_error(). + * + * Returns: 0 if OK, -1 otherwise. + */ +int +im_check_uintorf( const char *domain, IMAGE *im ) +{ + if( im->BandFmt != IM_BANDFMT_UCHAR && + im->BandFmt != IM_BANDFMT_USHORT && + im->BandFmt != IM_BANDFMT_UINT && + im->BandFmt != IM_BANDFMT_FLOAT ) { + im_error( domain, "%s", + _( "image must be unsigned int or float" ) ); + return( -1 ); + } + + return( 0 ); +} + /** * im_check_size_same: * @domain: the originating domain for the error message