better colourspace sniffing

This commit is contained in:
John Cupitt 2012-11-01 13:16:54 +00:00
parent f5790be152
commit 8e72d25c9a
4 changed files with 130 additions and 12 deletions

9
TODO
View File

@ -3,15 +3,6 @@
- add mono as a colourspace? also rad? - add mono as a colourspace? also rad?
- something to test if an image is in a supported colourspace?
at the moment we only look at interpretation, but for things like labq
we should check coding too
labs needs more checks than that
_RGB and _sRGB as well
move colour_convert into a separate file move colour_convert into a separate file
- im_icc_ac2rc needs doing once we have a general 'convert' operator - im_icc_ac2rc needs doing once we have a general 'convert' operator

View File

@ -709,6 +709,8 @@ vips_colour_convert_build( VipsObject *object )
VipsImage *x; VipsImage *x;
VipsImage **t; VipsImage **t;
VipsInterpretation interpretation;
t = (VipsImage **) vips_object_local_array( object, MAX_STEPS ); t = (VipsImage **) vips_object_local_array( object, MAX_STEPS );
/* Verify that all input args have been set. /* Verify that all input args have been set.
@ -717,9 +719,11 @@ vips_colour_convert_build( VipsObject *object )
build( object ) ) build( object ) )
return( -1 ); return( -1 );
interpretation = vips_image_guess_interpretation( convert->in );
/* No conversion necessary. /* No conversion necessary.
*/ */
if( convert->in->Type == convert->space ) { if( interpretation == convert->space ) {
g_object_set( convert, "out", vips_image_new(), NULL ); g_object_set( convert, "out", vips_image_new(), NULL );
return( vips_image_write( convert->in, convert->out ) ); return( vips_image_write( convert->in, convert->out ) );
@ -728,13 +732,14 @@ vips_colour_convert_build( VipsObject *object )
x = convert->in; x = convert->in;
for( i = 0; i < VIPS_NUMBER( vips_colour_routes ); i++ ) for( i = 0; i < VIPS_NUMBER( vips_colour_routes ); i++ )
if( vips_colour_routes[i].from == x->Type && if( vips_colour_routes[i].from == interpretation &&
vips_colour_routes[i].to == convert->space ) vips_colour_routes[i].to == convert->space )
break; break;
if( i == VIPS_NUMBER( vips_colour_routes ) ) { if( i == VIPS_NUMBER( vips_colour_routes ) ) {
vips_error( "vips_colour_convert", vips_error( "vips_colour_convert",
_( "no known route between '%s' and '%s'" ), _( "no known route between '%s' and '%s'" ),
vips_enum_nick( VIPS_TYPE_INTERPRETATION, x->Type ), vips_enum_nick( VIPS_TYPE_INTERPRETATION,
interpretation ),
vips_enum_nick( VIPS_TYPE_INTERPRETATION, vips_enum_nick( VIPS_TYPE_INTERPRETATION,
convert->space ) ); convert->space ) );
return( -1 ); return( -1 );

View File

@ -85,6 +85,7 @@ int vips_image_get_bands( const VipsImage *image );
VipsBandFormat vips_image_get_format( const VipsImage *image ); VipsBandFormat vips_image_get_format( const VipsImage *image );
VipsCoding vips_image_get_coding( const VipsImage *image ); VipsCoding vips_image_get_coding( const VipsImage *image );
VipsInterpretation vips_image_get_interpretation( const VipsImage *image ); VipsInterpretation vips_image_get_interpretation( const VipsImage *image );
VipsInterpretation vips_image_guess_interpretation( const VipsImage *image );
double vips_image_get_xres( const VipsImage *image ); double vips_image_get_xres( const VipsImage *image );
double vips_image_get_yres( const VipsImage *image ); double vips_image_get_yres( const VipsImage *image );
int vips_image_get_xoffset( const VipsImage *image ); int vips_image_get_xoffset( const VipsImage *image );

View File

@ -364,12 +364,133 @@ vips_image_get_coding( const VipsImage *image )
return( image->Coding ); return( image->Coding );
} }
/* vips_image_get_interpretation:
* @image: image to guess for
*
* Return the #VipsInterpretation set in the image header.
* Use vips_image_guess_interpretation() is you want a sanity-checked value.
*
* Returns: the #VipsInterpretation from the image header.
*/
VipsInterpretation VipsInterpretation
vips_image_get_interpretation( const VipsImage *image ) vips_image_get_interpretation( const VipsImage *image )
{ {
return( image->Type ); return( image->Type );
} }
/* Try to pick a sane value for interpretation, assuming Type has been set
* incorrectly.
*/
static VipsInterpretation
vips_image_default_interpretation( const VipsImage *image )
{
switch( image->Coding ) {
case VIPS_CODING_LABQ:
return( VIPS_INTERPRETATION_LABQ );
case VIPS_CODING_RAD:
return( VIPS_INTERPRETATION_RGB );
default:
break;
}
if( image->Bands == 1 )
return( VIPS_INTERPRETATION_B_W );
else
return( VIPS_INTERPRETATION_MULTIBAND );
}
/* vips_image_guess_interpretation:
* @image: image to guess for
*
* Return the #VipsInterpretation for an image, guessing a default value if
* the set value looks wrong.
*
* Returns: a sensible #VipsInterpretation for the image.
*/
VipsInterpretation
vips_image_guess_interpretation( const VipsImage *image )
{
gboolean sane;
sane = TRUE;
switch( image->Type ) {
case VIPS_INTERPRETATION_MULTIBAND:
if( image->Bands == 1 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_B_W:
if( image->Bands > 1 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_HISTOGRAM:
if( image->Xsize > 1 && image->Ysize > 1 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_FOURIER:
if( !vips_band_format_iscomplex( image->BandFmt ) )
sane = FALSE;
break;
case VIPS_INTERPRETATION_XYZ:
case VIPS_INTERPRETATION_LAB:
case VIPS_INTERPRETATION_RGB:
case VIPS_INTERPRETATION_CMC:
case VIPS_INTERPRETATION_LCH:
case VIPS_INTERPRETATION_sRGB:
case VIPS_INTERPRETATION_YXY:
if( image->Bands < 3 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_CMYK:
if( image->Bands < 4 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_LABQ:
if( image->Coding != VIPS_CODING_LABQ )
sane = FALSE;
break;
case VIPS_INTERPRETATION_LABS:
if( image->BandFmt != VIPS_FORMAT_SHORT )
sane = FALSE;
break;
case VIPS_INTERPRETATION_RGB16:
if( image->BandFmt == VIPS_FORMAT_CHAR ||
image->BandFmt == VIPS_FORMAT_UCHAR ||
image->Bands < 3 )
sane = FALSE;
break;
case VIPS_INTERPRETATION_GREY16:
if( image->BandFmt == VIPS_FORMAT_CHAR ||
image->BandFmt == VIPS_FORMAT_UCHAR )
sane = FALSE;
break;
case VIPS_INTERPRETATION_ARRAY:
if( image->Bands != 1 )
sane = FALSE;
break;
default:
g_assert( 0 );
sane = FALSE;
break;
}
if( sane )
return( vips_image_get_interpretation( image ) );
else
return( vips_image_default_interpretation( image ) );
}
double double
vips_image_get_xres( const VipsImage *image ) vips_image_get_xres( const VipsImage *image )
{ {