From d085351f0f6ba04f7b842eb1f66a7b85cf73aebd Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 9 Sep 2014 10:07:35 +0100 Subject: [PATCH] fix mono <-> rgb converter extra band handling see https://github.com/jcupitt/libvips/issues/172 thanks James --- ChangeLog | 1 + libvips/colour/colourspace.c | 82 +++++++++++++++++++++++++++++------- libvips/iofuncs/header.c | 5 ++- 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index d1eb608c..7d244f06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 8/9/14 started 7.40.8 - fix configure on rhel6 [Lovell] +- mono <-> rgb converters were not handling extra bands, thanks James 21/8/14 started 7.40.7 - width and height were swapped in matlab load diff --git a/libvips/colour/colourspace.c b/libvips/colour/colourspace.c index 22172696..92368206 100644 --- a/libvips/colour/colourspace.c +++ b/libvips/colour/colourspace.c @@ -11,7 +11,9 @@ * 3/2/14 * - add "source_space", overrides source space guess * 8/5/14 - * - oops, don't treat RGB16 to sRGB + * - oops, don't treat RGB16 as sRGB + * 9/9/14 + * - mono <-> rgb converters were not handling extra bands, thanks James */ /* @@ -59,16 +61,66 @@ #include "pcolour.h" +/* A colour-transforming function. + */ +typedef int (*VipsColourTransformFn)( VipsImage *in, VipsImage **out, ... ); + static int vips_scRGB2RGB16( VipsImage *in, VipsImage **out, ... ) { return( vips_scRGB2sRGB( in, out, "depth", 16, NULL ) ); } +/* Process the first @n bands with @fn, detach and reattach remaining bands. + */ +static int +vips_process_n( const char *domain, VipsImage *in, VipsImage **out, + int n, VipsColourTransformFn fn ) +{ + if( in->Bands > n ) { + VipsImage *scope = vips_image_new(); + VipsImage **t = (VipsImage **) + vips_object_local_array( VIPS_OBJECT( scope ), 3 ); + + if( vips_extract_band( in, &t[0], 0, + "n", n, + NULL ) || + vips_extract_band( in, &t[1], n, + "n", in->Bands - n, + NULL ) || + fn( t[0], &t[2], NULL ) || + vips_bandjoin2( t[2], t[1], out, NULL ) ) { + g_object_unref( scope ); + return( -1 ); + } + + g_object_unref( scope ); + } + else if( in->Bands == n ) { + if( fn( in, out, NULL ) ) + return( -1 ); + } + else { + vips_error( domain, "%s", _( "too few bands for operation" ) ); + return( -1 ); + } + + return( 0 ); +} + +static int +vips_sRGB2BW_op( VipsImage *in, VipsImage **out, ... ) +{ + if( vips_extract_band( in, out, 1, NULL ) ) + return( -1 ); + + return( 0 ); +} + static int vips_sRGB2BW( VipsImage *in, VipsImage **out, ... ) { - if( vips_extract_band( in, out, 1, NULL ) ) + if( vips_process_n( "sRGB2BW", in, out, 3, vips_sRGB2BW_op ) ) return( -1 ); (*out)->Type = VIPS_INTERPRETATION_B_W; @@ -76,16 +128,24 @@ vips_sRGB2BW( VipsImage *in, VipsImage **out, ... ) } static int -vips_BW2sRGB( VipsImage *in, VipsImage **out, ... ) +vips_BW2sRGB_op( VipsImage *in, VipsImage **out, ... ) { VipsImage *t[3]; t[0] = in; t[1] = in; t[2] = in; - if( vips_bandjoin( t, out, 3, NULL ) ) return( -1 ); + + return( 0 ); +} + +static int +vips_BW2sRGB( VipsImage *in, VipsImage **out, ... ) +{ + if( vips_process_n( "BW2sRGB", in, out, 1, vips_BW2sRGB_op ) ) + return( -1 ); (*out)->Type = VIPS_INTERPRETATION_sRGB; return( 0 ); @@ -94,7 +154,7 @@ vips_BW2sRGB( VipsImage *in, VipsImage **out, ... ) static int vips_RGB162GREY16( VipsImage *in, VipsImage **out, ... ) { - if( vips_extract_band( in, out, 1, NULL ) ) + if( vips_process_n( "RGB162GREY16", in, out, 3, vips_sRGB2BW_op ) ) return( -1 ); (*out)->Type = VIPS_INTERPRETATION_GREY16; @@ -104,23 +164,13 @@ vips_RGB162GREY16( VipsImage *in, VipsImage **out, ... ) static int vips_GREY162RGB16( VipsImage *in, VipsImage **out, ... ) { - VipsImage *t[3]; - - t[0] = in; - t[1] = in; - t[2] = in; - - if( vips_bandjoin( t, out, 3, NULL ) ) + if( vips_process_n( "GREY162RGB16", in, out, 1, vips_BW2sRGB_op ) ) return( -1 ); (*out)->Type = VIPS_INTERPRETATION_RGB16; return( 0 ); } -/* A colour-transforming function. - */ -typedef int (*VipsColourTransformFn)( VipsImage *in, VipsImage **out, ... ); - /* Maximum number of steps we allow in a route. 10 steps should be enough * for anyone. */ diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 197865cc..dabff47f 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -457,8 +457,9 @@ vips_image_guess_interpretation( const VipsImage *image ) break; case VIPS_INTERPRETATION_B_W: - if( image->Bands > 1 ) - sane = FALSE; + /* Don't test bands, we allow bands after the first to be + * unused extras, like alpha. + */ break; case VIPS_INTERPRETATION_HISTOGRAM: