From 4ac08bc2d684137c94d92e85a5cc36703ddee6c7 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 22 Jan 2014 13:26:59 +0000 Subject: [PATCH 1/2] add some auto unpack stuff so RAD etc get unpacked automatically --- TODO | 21 +++++++++++++++++++++ libvips/convolution/conv.c | 17 ++++++++++++++--- libvips/include/vips/internal.h | 2 ++ libvips/resample/affine.c | 30 ++++++++++++++++++++++++------ libvips/resample/shrink.c | 26 +++++++++++++++++++------- 5 files changed, 80 insertions(+), 16 deletions(-) diff --git a/TODO b/TODO index 701fda57..32b3a8bf 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,24 @@ +- shrink does not auto unpack labq or rad, should it? + +- others .. differences in: + +grep -l CODING_LABQ */*.c +conversion/join.c +conversion/msb.c +inplace/im_draw_mask.c +resample/shrink.c + +grep -l CODING_RAD */*.c +conversion/embed.c +inplace/flood.c +inplace/im_draw_image.c + +- add unpack everywhere, eg. arithmetic + + + + +- move vips__image_decode() into the public API - need to do mosaicing and inplace, plus im_label_regions in morph diff --git a/libvips/convolution/conv.c b/libvips/convolution/conv.c index 441cb550..3608b031 100644 --- a/libvips/convolution/conv.c +++ b/libvips/convolution/conv.c @@ -65,7 +65,10 @@ vips_conv_build( VipsObject *object ) VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsConvolution *convolution = (VipsConvolution *) object; VipsConv *conv = (VipsConv *) object; + VipsImage **t = (VipsImage **) + vips_object_local_array( object, 4 ); + VipsImage *in; INTMASK *imsk; DOUBLEMASK *dmsk; @@ -74,6 +77,8 @@ vips_conv_build( VipsObject *object ) if( VIPS_OBJECT_CLASS( vips_conv_parent_class )->build( object ) ) return( -1 ); + in = convolution->in; + /* printf( "vips_conv_build: convolving with:\n" ); vips_matrixprint( convolution->M, NULL ); @@ -86,19 +91,25 @@ vips_conv_build( VipsObject *object ) !im_local_dmask( convolution->out, dmsk ) ) return( -1 ); + /* Unpack for processing. + */ + if( vips__image_decode( in, &t[0] ) ) + return( -1 ); + in = t[0]; + switch( conv->precision ) { case VIPS_PRECISION_INTEGER: - if( im_conv( convolution->in, convolution->out, imsk ) ) + if( im_conv( in, convolution->out, imsk ) ) return( -1 ); break; case VIPS_PRECISION_FLOAT: - if( im_conv_f( convolution->in, convolution->out, dmsk ) ) + if( im_conv_f( in, convolution->out, dmsk ) ) return( -1 ); break; case VIPS_PRECISION_APPROXIMATE: - if( im_aconv( convolution->in, convolution->out, dmsk, + if( im_aconv( in, convolution->out, dmsk, conv->layers, conv->cluster ) ) return( -1 ); break; diff --git a/libvips/include/vips/internal.h b/libvips/include/vips/internal.h index 39c233b6..e29d64df 100644 --- a/libvips/include/vips/internal.h +++ b/libvips/include/vips/internal.h @@ -297,6 +297,8 @@ IMAGE *vips__deprecated_open_write( const char *filename ); int vips__input_interpolate_init( im_object *obj, char *str ); +int vips__image_decode( VipsImage *in, VipsImage **out ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/resample/affine.c b/libvips/resample/affine.c index a8988f3e..c8e325f1 100644 --- a/libvips/resample/affine.c +++ b/libvips/resample/affine.c @@ -373,13 +373,33 @@ vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) return( 0 ); } +/* Unpack to a format that we can compute with. + */ +int +vips__image_decode( VipsImage *in, VipsImage **out ) +{ + if( in->Coding == VIPS_CODING_LABQ ) { + if( vips_LabQ2LabS( in, out, NULL ) ) + return( -1 ); + } + else if( in->Coding == VIPS_CODING_RAD ) { + if( vips_rad2float( in, out, NULL ) ) + return( -1 ); + } + else { + if( vips_copy( in, out, NULL ) ) + return( -1 ); + } + + return( 0 ); +} + static int vips_affine_build( VipsObject *object ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsResample *resample = VIPS_RESAMPLE( object ); VipsAffine *affine = (VipsAffine *) object; - VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 ); @@ -465,11 +485,9 @@ vips_affine_build( VipsObject *object ) /* Unpack labq for processing. */ - if( in->Coding == VIPS_CODING_LABQ ) { - if( vips_LabQ2LabS( in, &t[0], NULL ) ) - return( -1 ); - in = t[0]; - } + if( vips__image_decode( in, &t[0] ) ) + return( -1 ); + in = t[0]; /* Add new pixels around the input so we can interpolate at the edges. */ diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index d15731e7..f70b4ded 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -310,6 +310,10 @@ vips_shrink_build( VipsObject *object ) VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsResample *resample = VIPS_RESAMPLE( object ); VipsShrink *shrink = (VipsShrink *) object; + VipsImage **t = (VipsImage **) + vips_object_local_array( object, 1 ); + + VipsImage *in; if( VIPS_OBJECT_CLASS( vips_shrink_parent_class )->build( object ) ) return( -1 ); @@ -318,7 +322,9 @@ vips_shrink_build( VipsObject *object ) shrink->mh = ceil( shrink->yshrink ); shrink->np = shrink->mw * shrink->mh; - if( vips_check_noncomplex( class->nickname, resample->in ) ) + in = resample->in; + + if( vips_check_noncomplex( class->nickname, in ) ) return( -1 ); if( shrink->xshrink < 1.0 || @@ -336,14 +342,20 @@ vips_shrink_build( VipsObject *object ) if( shrink->xshrink == 1.0 && shrink->yshrink == 1.0 ) - return( vips_image_write( resample->in, resample->out ) ); + return( vips_image_write( in, resample->out ) ); + + /* Unpack for processing. + */ + if( vips__image_decode( in, &t[0] ) ) + return( -1 ); + in = t[0]; /* THINSTRIP will work, anything else will break seq mode. If you * combine shrink with conv you'll need to use a line cache to maintain * sequentiality. */ if( vips_image_pipelinev( resample->out, - VIPS_DEMAND_STYLE_THINSTRIP, resample->in, NULL ) ) + VIPS_DEMAND_STYLE_THINSTRIP, in, NULL ) ) return( -1 ); /* Size output. Note: we round the output width down! @@ -352,8 +364,8 @@ vips_shrink_build( VipsObject *object ) * example, vipsthumbnail knows the true shrink factor (including the * fractional part), we just see the integer part here. */ - resample->out->Xsize = resample->in->Xsize / shrink->xshrink; - resample->out->Ysize = resample->in->Ysize / shrink->yshrink; + resample->out->Xsize = in->Xsize / shrink->xshrink; + resample->out->Ysize = in->Ysize / shrink->yshrink; if( resample->out->Xsize <= 0 || resample->out->Ysize <= 0 ) { vips_error( class->nickname, @@ -363,7 +375,7 @@ vips_shrink_build( VipsObject *object ) #ifdef DEBUG printf( "vips_shrink_build: shrinking %d x %d image to %d x %d\n", - resample->in->Xsize, resample->in->Ysize, + in->Xsize, in->Ysize, resample->out->Xsize, resample->out->Ysize ); printf( "vips_shrink_build: %d x %d block average\n", shrink->mw, shrink->mh ); @@ -371,7 +383,7 @@ vips_shrink_build( VipsObject *object ) if( vips_image_generate( resample->out, vips_shrink_start, vips_shrink_gen, vips_shrink_stop, - resample->in, shrink ) ) + in, shrink ) ) return( -1 ); return( 0 ); From d0594318672f3acb6b4a61fa0a6fe12928a9a58a Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Wed, 22 Jan 2014 14:53:48 +0000 Subject: [PATCH 2/2] more auto-decode stuff more to do though --- TODO | 5 +++++ libvips/arithmetic/arithmetic.c | 17 +++++++++++------ libvips/arithmetic/linear.c | 16 +++++++++++++++- libvips/convolution/conv.c | 1 + libvips/morphology/morph.c | 16 ++++++++++++---- libvips/morphology/rank.c | 12 ++++++++---- libvips/resample/shrink.c | 1 + 7 files changed, 53 insertions(+), 15 deletions(-) diff --git a/TODO b/TODO index 32b3a8bf..c1c3f7ae 100644 --- a/TODO +++ b/TODO @@ -15,6 +15,11 @@ inplace/im_draw_image.c - add unpack everywhere, eg. arithmetic + look for + + vips_check_uncoded + + certainly can use it there diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index bf631dea..a8aea1de 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -51,6 +51,7 @@ #include #include +#include #include "parithmetic.h" @@ -500,6 +501,7 @@ vips_arithmetic_build( VipsObject *object ) VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object ); VipsArithmeticClass *aclass = VIPS_ARITHMETIC_GET_CLASS( arithmetic ); + VipsImage **decode; VipsImage **format; VipsImage **band; VipsImage **size; @@ -524,12 +526,9 @@ vips_arithmetic_build( VipsObject *object ) "%s", _( "too many input images" ) ); return( -1 ); } - for( i = 0; i < arithmetic->n; i++ ) - if( vips_image_pio_input( arithmetic->in[i] ) || - vips_check_uncoded( class->nickname, - arithmetic->in[i] ) ) - return( -1 ); + decode = (VipsImage **) + vips_object_local_array( object, arithmetic->n ); format = (VipsImage **) vips_object_local_array( object, arithmetic->n ); band = (VipsImage **) @@ -537,9 +536,15 @@ vips_arithmetic_build( VipsObject *object ) size = (VipsImage **) vips_object_local_array( object, arithmetic->n ); + /* Decode RAD/LABQ etc. + */ + for( i = 0; i < arithmetic->n; i++ ) + if( vips__image_decode( arithmetic->in[i], &decode[i] ) ) + return( -1 ); + /* Cast our input images up to a common format, bands and size. */ - if( vips__formatalike_vec( arithmetic->in, format, arithmetic->n ) || + if( vips__formatalike_vec( decode, format, arithmetic->n ) || vips__bandalike_vec( class->nickname, format, band, arithmetic->n, arithmetic->base_bands ) || vips__sizealike_vec( band, size, arithmetic->n ) ) diff --git a/libvips/arithmetic/linear.c b/libvips/arithmetic/linear.c index 26ee9d48..a44b296b 100644 --- a/libvips/arithmetic/linear.c +++ b/libvips/arithmetic/linear.c @@ -122,8 +122,22 @@ vips_linear_build( VipsObject *object ) VipsUnary *unary = (VipsUnary *) object; VipsLinear *linear = (VipsLinear *) object; + int bands; int i; + /* How many bands will our input image have after decoding? + */ + switch( unary->in->Coding ) { + case VIPS_CODING_RAD: + case VIPS_CODING_LABQ: + bands = 3; + break; + + default: + bands = unary->in->Bands; + break; + } + /* If we have a three-element vector we need to bandup the image to * match. */ @@ -133,7 +147,7 @@ vips_linear_build( VipsObject *object ) if( linear->b ) linear->n = VIPS_MAX( linear->n, linear->b->n ); if( unary->in ) - linear->n = VIPS_MAX( linear->n, unary->in->Bands ); + linear->n = VIPS_MAX( linear->n, bands ); arithmetic->base_bands = linear->n; if( unary->in && linear->a && linear->b ) { diff --git a/libvips/convolution/conv.c b/libvips/convolution/conv.c index 3608b031..151a23bb 100644 --- a/libvips/convolution/conv.c +++ b/libvips/convolution/conv.c @@ -44,6 +44,7 @@ #include #include +#include #include "pconvolution.h" diff --git a/libvips/morphology/morph.c b/libvips/morphology/morph.c index 5270a581..8ce26671 100644 --- a/libvips/morphology/morph.c +++ b/libvips/morphology/morph.c @@ -44,6 +44,7 @@ #include #include +#include #include "pmorphology.h" @@ -83,15 +84,22 @@ vips_morph_build( VipsObject *object ) VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 ); INTMASK *imsk; + VipsImage *in; g_object_set( morph, "out", vips_image_new(), NULL ); if( VIPS_OBJECT_CLASS( vips_morph_parent_class )->build( object ) ) return( -1 ); - if( vips_check_matrix( class->nickname, morph->mask, &t[0] ) ) + in = morphology->in; + + if( vips__image_decode( in, &t[0] ) ) + return( -1 ); + in = t[0]; + + if( vips_check_matrix( class->nickname, morph->mask, &t[1] ) ) return( -1 ); - morph->M = t[0]; + morph->M = t[1]; if( !(imsk = im_vips2imask( morph->M, class->nickname )) || !im_local_imask( morph->out, imsk ) ) @@ -99,12 +107,12 @@ vips_morph_build( VipsObject *object ) switch( morph->morph ) { case VIPS_OPERATION_MORPHOLOGY_DILATE: - if( im_dilate( morphology->in, morph->out, imsk ) ) + if( im_dilate( in, morph->out, imsk ) ) return( -1 ); break; case VIPS_OPERATION_MORPHOLOGY_ERODE: - if( im_erode( morphology->in, morph->out, imsk ) ) + if( im_erode( in, morph->out, imsk ) ) return( -1 ); break; diff --git a/libvips/morphology/rank.c b/libvips/morphology/rank.c index fdc47695..b88154a5 100644 --- a/libvips/morphology/rank.c +++ b/libvips/morphology/rank.c @@ -64,6 +64,7 @@ #include #include +#include #include "pmorphology.h" @@ -340,8 +341,11 @@ vips_rank_build( VipsObject *object ) in = morphology->in; - if( vips_check_uncoded( class->nickname, in ) || - vips_check_noncomplex( class->nickname, in ) ) + if( vips__image_decode( in, &t[0] ) ) + return( -1 ); + in = t[0]; + + if( vips_check_noncomplex( class->nickname, in ) ) return( -1 ); if( rank->width > in->Xsize || rank->height > in->Ysize ) { @@ -356,13 +360,13 @@ vips_rank_build( VipsObject *object ) /* Expand the input. */ - if( vips_embed( in, &t[0], + if( vips_embed( in, &t[1], rank->width / 2, rank->height / 2, in->Xsize + rank->width - 1, in->Ysize + rank->height - 1, "extend", VIPS_EXTEND_COPY, NULL ) ) return( -1 ); - in = t[0]; + in = t[1]; g_object_set( object, "out", vips_image_new(), NULL ); diff --git a/libvips/resample/shrink.c b/libvips/resample/shrink.c index f70b4ded..f27e4bf9 100644 --- a/libvips/resample/shrink.c +++ b/libvips/resample/shrink.c @@ -85,6 +85,7 @@ #include #include +#include #include "presample.h"