diff --git a/libvips/colour/colour.c b/libvips/colour/colour.c index 229696d5..94b26f15 100644 --- a/libvips/colour/colour.c +++ b/libvips/colour/colour.c @@ -294,6 +294,10 @@ vips_colour_build( VipsObject *object ) VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsColour *colour = VIPS_COLOUR( object ); + VipsImage **in; + VipsImage **extra_bands; + VipsImage *out; + int i; #ifdef DEBUG @@ -306,8 +310,6 @@ vips_colour_build( VipsObject *object ) build( object ) ) return( -1 ); - g_object_set( colour, "out", vips_image_new(), NULL ); - if( colour->n > MAX_INPUT_IMAGES ) { vips_error( class->nickname, "%s", _( "too many input images" ) ); @@ -322,23 +324,82 @@ vips_colour_build( VipsObject *object ) */ g_assert( !colour->in[colour->n] ); - if( vips_image_pipeline_array( colour->out, - VIPS_DEMAND_STYLE_THINSTRIP, colour->in ) ) + in = colour->in; + extra_bands = (VipsImage **) + vips_object_local_array( object, colour->n ); + + /* If there are more than @input_bands bands, we detach and reattach + * after processing. + */ + if( colour->input_bands > 0 ) { + VipsImage **new_in = (VipsImage **) + vips_object_local_array( object, colour->n ); + + for( i = 0; i < colour->n; i++ ) { + if( vips_check_bands_atleast( class->nickname, + in[i], colour->input_bands ) ) + return( -1 ); + + if( vips_extract_band( in[i], &new_in[i], 0, + "n", colour->input_bands, + NULL ) ) + return( -1 ); + + if( in[i]->Bands > colour->input_bands ) + if( vips_extract_band( in[i], &extra_bands[i], + colour->input_bands, + "n", in[i]->Bands - + colour->input_bands, + NULL ) ) + return( -1 ); + } + + in = new_in; + } + + out = vips_image_new(); + if( vips_image_pipeline_array( out, + VIPS_DEMAND_STYLE_THINSTRIP, in ) ) { + g_object_unref( out ); return( -1 ); - colour->out->Coding = colour->coding; - colour->out->Type = colour->interpretation; - colour->out->BandFmt = colour->format; - colour->out->Bands = colour->bands; + } + out->Coding = colour->coding; + out->Type = colour->interpretation; + out->BandFmt = colour->format; + out->Bands = colour->bands; if( colour->profile_filename ) - if( vips_colour_attach_profile( colour->out, - colour->profile_filename ) ) + if( vips_colour_attach_profile( out, + colour->profile_filename ) ) { + g_object_unref( out ); return( -1 ); + } - if( vips_image_generate( colour->out, + if( vips_image_generate( out, vips_start_many, vips_colour_gen, vips_stop_many, - colour->in, colour ) ) + in, colour ) ) { + g_object_unref( out ); return( -1 ); + } + + /* Reattach higher bands, if necessary. If we have more than one input + * image, just use the first extra bands. + */ + for( i = 0; i < colour->n; i++ ) + if( extra_bands[i] ) { + VipsImage *x; + + if( vips_bandjoin2( out, extra_bands[i], &x, + NULL ) ) { + g_object_unref( out ); + return( -1 ); + } + g_object_unref( out ); + out = x; + break; + } + + g_object_set( colour, "out", out, NULL ); return( 0 ); } @@ -373,6 +434,7 @@ vips_colour_init( VipsColour *colour ) colour->interpretation = VIPS_INTERPRETATION_sRGB; colour->format = VIPS_FORMAT_UCHAR; colour->bands = 3; + colour->input_bands = -1; } G_DEFINE_ABSTRACT_TYPE( VipsColourSpace, vips_colour_space, VIPS_TYPE_COLOUR ); @@ -382,62 +444,24 @@ vips_colour_space_build( VipsObject *object ) { VipsColour *colour = VIPS_COLOUR( object ); VipsColourSpace *space = VIPS_COLOUR_SPACE( object ); - - VipsImage **t; - VipsImage *in; - VipsImage *extra; - - t = (VipsImage **) vips_object_local_array( object, 4 ); - - in = space->in; - extra = NULL; + VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 ); /* We only process float. */ - if( vips_cast_float( in, &t[0], NULL ) ) + if( vips_cast_float( space->in, &t[0], NULL ) ) return( -1 ); - in = t[0]; - /* If there are more than n bands, process just the first three and - * reattach the rest after. This lets us handle RGBA etc. + /* We always do 3 bands -> 3 bands. */ - if( in->Bands > 3 ) { - if( vips_extract_band( in, &t[1], 0, "n", 3, NULL ) || - vips_extract_band( in, &t[2], 3, - "n", in->Bands - 3, NULL ) ) - return( -1 ); - - in = t[1]; - extra = t[2]; - } - else if( vips_check_bands_atleast( - VIPS_OBJECT_GET_CLASS( object )->nickname, in, 3 ) ) - return( -1 ); + colour->input_bands = 3; colour->n = 1; - colour->in = (VipsImage **) vips_object_local_array( object, 2 ); - colour->in[0] = in; - colour->in[1] = NULL; - if( colour->in[0] ) - g_object_ref( colour->in[0] ); + colour->in = t; if( VIPS_OBJECT_CLASS( vips_colour_space_parent_class )-> build( object ) ) return( -1 ); - /* Reattach higher bands, if necessary. - */ - if( extra ) { - VipsImage *x; - - if( vips_bandjoin2( colour->out, extra, &x, NULL ) ) - return( -1 ); - - VIPS_UNREF( colour->out ); - - colour->out = x; - } - return( 0 ); } diff --git a/libvips/colour/pcolour.h b/libvips/colour/pcolour.h index 7bfc2ad9..ee4a5349 100644 --- a/libvips/colour/pcolour.h +++ b/libvips/colour/pcolour.h @@ -65,6 +65,11 @@ typedef struct _VipsColour { VipsImage **in; int n; + /* If this is >0, only process this many bands from the input. Extra + * bands are removed and reattached after processing. + */ + int input_bands; + VipsImage *out; /* Set fields on ->out from these.