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?
- 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
- 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 **t;
VipsInterpretation interpretation;
t = (VipsImage **) vips_object_local_array( object, MAX_STEPS );
/* Verify that all input args have been set.
@ -717,9 +719,11 @@ vips_colour_convert_build( VipsObject *object )
build( object ) )
return( -1 );
interpretation = vips_image_guess_interpretation( convert->in );
/* No conversion necessary.
*/
if( convert->in->Type == convert->space ) {
if( interpretation == convert->space ) {
g_object_set( convert, "out", vips_image_new(), NULL );
return( vips_image_write( convert->in, convert->out ) );
@ -728,13 +732,14 @@ vips_colour_convert_build( VipsObject *object )
x = convert->in;
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 )
break;
if( i == VIPS_NUMBER( vips_colour_routes ) ) {
vips_error( "vips_colour_convert",
_( "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,
convert->space ) );
return( -1 );

View File

@ -85,6 +85,7 @@ int vips_image_get_bands( const VipsImage *image );
VipsBandFormat vips_image_get_format( const VipsImage *image );
VipsCoding vips_image_get_coding( 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_yres( 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 );
}
/* 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
vips_image_get_interpretation( const VipsImage *image )
{
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
vips_image_get_xres( const VipsImage *image )
{