/* Try to open a file. If full path fails, try the current directory. */ IMAGE * im__global_open_image( SymbolTable *st, char *name ) { IMAGE *im; if( (im = im_open_local( st->im, name, "r" )) ) return( im ); if( (im = im_open_local( st->im, im_skip_dir( name ), "r" )) ) return( im ); return( NULL ); }
/* Morph an image. */ int im_lab_morph( IMAGE *in, IMAGE *out, DOUBLEMASK *mask, double L_offset, double L_scale, double a_scale, double b_scale ) { Params *parm; /* Recurse for coded images. */ if( in->Coding == IM_CODING_LABQ ) { IMAGE *t1 = im_open_local( out, "im_lab_morph:1", "p" ); IMAGE *t2 = im_open_local( out, "im_lab_morph:2", "p" ); if( !t1 || !t2 || im_LabQ2Lab( in, t1 ) || im_lab_morph( t1, t2, mask, L_offset, L_scale, a_scale, b_scale ) || im_Lab2LabQ( t2, out ) ) return( -1 ); return( 0 ); } if( in->Coding != IM_CODING_NONE ) { im_errormsg( "im_lab_morph: must be uncoded or IM_CODING_LABQ" ); return( -1 ); } if( in->BandFmt != IM_BANDFMT_FLOAT && in->BandFmt != IM_BANDFMT_DOUBLE ) { im_errormsg( "im_lab_morph: must be uncoded float or double" ); return( -1 ); } if( in->Bands != 3 ) { im_errormsg( "im_lab_morph: must be 3 bands" ); return( -1 ); } if( !(parm = IM_NEW( out, Params )) || morph_init( parm, in, out, L_scale, L_offset, mask, a_scale, b_scale ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); out->Type = IM_TYPE_LAB; if( im_wrapone( in, out, (im_wrapone_fn) morph_buffer, parm, NULL ) ) return( -1 ); return( 0 ); }
int im_freqflt( IMAGE *in, IMAGE *mask, IMAGE *out ) { IMAGE *dummy; /* Placeholder for memory free. */ if( !(dummy = im_open( "memory-1", "p" )) ) return( -1 ); if( im_iscomplex( in ) ) { /* Easy case! Assume it has already been transformed. */ IMAGE *t1 = im_open_local( dummy, "im_freqflt-1", "p" ); if( !t1 || im_multiply( in, mask, t1 ) || im_invfftr( t1, out ) ) { im_close( dummy ); return( -1 ); } } else { /* Harder - fft first, then mult, then force back to start * type. * * Optimisation: output of im_invfft() is float buffer, we * will usually chagetype to char, so rather than keeping a * large float buffer and partial to char from that, do * changetype to a memory buffer, and copy to out from that. */ IMAGE *t[3]; IMAGE *t3; if( im_open_local_array( dummy, t, 3, "im_freqflt-1", "p" ) || !(t3 = im_open_local( out, "im_freqflt-3", "t" )) || im_fwfft( in, t[0] ) || im_multiply( t[0], mask, t[1] ) || im_invfftr( t[1], t[2] ) || im_clip2fmt( t[2], t3, in->BandFmt ) || im_copy( t3, out ) ) { im_close( dummy ); return( -1 ); } } im_close( dummy ); return( 0 ); }
/* Normalise an image using the rules noted above. */ static int normalise( IMAGE *in, IMAGE *out ) { if( im_check_uncoded( "im_histplot", in ) || im_check_noncomplex( "im_histplot", in ) ) return( -1 ); if( vips_bandfmt_isuint( in->BandFmt ) ) { if( im_copy( in, out ) ) return( -1 ); } else if( vips_bandfmt_isint( in->BandFmt ) ) { IMAGE *t1; double min; /* Move min up to 0. */ if( !(t1 = im_open_local( out, "im_histplot", "p" )) || im_min( in, &min ) || im_lintra( 1.0, in, -min, t1 ) ) return( -1 ); } else { /* Float image: scale min--max to 0--any. Output square * graph. */ IMAGE *t1; DOUBLEMASK *stats; double min, max; int any; if( in->Xsize == 1 ) any = in->Ysize; else any = in->Xsize; if( !(stats = im_stats( in )) ) return( -1 ); min = VIPS_MASK( stats, 0, 0 ); max = VIPS_MASK( stats, 1, 0 ); im_free_dmask( stats ); if( !(t1 = im_open_local( out, "im_histplot", "p" )) || im_lintra( any / (max - min), in, -min * any / (max - min), out ) ) return( -1 ); } return( 0 ); }
int im_heq( IMAGE *in, IMAGE *out, int bandno ) { IMAGE *t1 = im_open_local( out, "im_heq:1", "p" ); IMAGE *t2 = im_open_local( out, "im_heq:2", "p" ); if( !t1 || !t2 || im_histgr( in, t1, bandno ) || im_histeq( t1, t2 ) || im_maplut( in, out, t2 ) ) return( -1 ); return( 0 ); }
/* As above, but make a IM_BANDFMT_UCHAR image. */ int im_zone( IMAGE *im, int size ) { IMAGE *t1 = im_open_local( im, "im_zone:1", "p" ); IMAGE *t2 = im_open_local( im, "im_zone:2", "p" ); if( !t1 || !t2 ) return( -1 ); if( im_fzone( t1, size ) || im_lintra( 127.5, t1, 127.5, t2 ) || im_clip2fmt( t2, im, IM_BANDFMT_UCHAR ) ) return( -1 ); return( 0 ); }
/* Find the stats for an overlap struct. */ static int find_overlap_stats( OverlapInfo *lap ) { IMAGE *t1 = im_open_local( lap->node->im, "find_overlap_stats:1", "p" ); Rect rarea, sarea; /* Translate the overlap area into the coordinate scheme for the main * node. */ rarea = lap->overlap; rarea.left -= lap->node->cumtrn.oarea.left; rarea.top -= lap->node->cumtrn.oarea.top; /* Translate the overlap area into the coordinate scheme for the other * node. */ sarea = lap->overlap; sarea.left -= lap->other->cumtrn.oarea.left; sarea.top -= lap->other->cumtrn.oarea.top; /* Make a mask for the overlap. */ if( make_overlap_mask( lap->node->trnim, lap->other->trnim, t1, &rarea, &sarea ) ) return( -1 ); /* Find stats for that area. */ if( !(lap->nstats = find_image_stats( lap->node->trnim, t1, &rarea )) ) return( -1 ); if( !(lap->ostats = find_image_stats( lap->other->trnim, t1, &sarea )) ) return( -1 ); return( 0 ); }
/* Transform an n-band image with a 1-band processing function. */ int im__fftproc( IMAGE *dummy, IMAGE *in, IMAGE *out, im__fftproc_fn fn ) { if( im_pincheck( in ) || im_outcheck( out ) ) return( -1 ); if( in->Bands == 1 ) { if( fn( dummy, in, out ) ) return( -1 ); } else { IMAGE *acc; int b; for( acc = NULL, b = 0; b < in->Bands; b++ ) { IMAGE *t1 = im_open_local( dummy, "fwfftn:1", "p" ); IMAGE *t2 = im_open_local( dummy, "fwfftn:2", "p" ); if( !t1 || !t2 || im_extract_band( in, t1, b ) || fn( dummy, t1, t2 ) ) return( -1 ); if( !acc ) acc = t2; else { IMAGE *t3 = im_open_local( dummy, "fwfftn:3", "p" ); if( !t3 || im_bandjoin( acc, t2, t3 ) ) return( -1 ); acc = t3; } } if( im_copy( acc, out ) ) return( -1 ); } return( 0 ); }
/* As above, but do IM_CODING_LABQ too. And embed the input. */ static int im__affinei( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate, Transformation *trn ) { IMAGE *t3 = im_open_local( out, "im_affine:3", "p" ); const int window_size = vips_interpolate_get_window_size( interpolate ); const int window_offset = vips_interpolate_get_window_offset( interpolate ); Transformation trn2; /* Add new pixels around the input so we can interpolate at the edges. */ if( !t3 || im_embed( in, t3, 1, window_offset, window_offset, in->Xsize + window_size, in->Ysize + window_size ) ) return( -1 ); /* Set iarea so we know what part of the input we can take. */ trn2 = *trn; trn2.iarea.left += window_offset; trn2.iarea.top += window_offset; #ifdef DEBUG_GEOMETRY printf( "im__affinei: %s\n", in->filename ); im__transform_print( &trn2 ); #endif /*DEBUG_GEOMETRY*/ if( in->Coding == IM_CODING_LABQ ) { IMAGE *t[2]; if( im_open_local_array( out, t, 2, "im_affine:2", "p" ) || im_LabQ2LabS( t3, t[0] ) || affinei( t[0], t[1], interpolate, &trn2 ) || im_LabS2LabQ( t[1], out ) ) return( -1 ); } else if( in->Coding == IM_CODING_NONE ) { if( affinei( t3, out, interpolate, &trn2 ) ) return( -1 ); } else { im_error( "im_affinei", "%s", _( "unknown coding type" ) ); return( -1 ); } /* Finally: can now set Xoffset/Yoffset. */ out->Xoffset = trn->dx - trn->oarea.left; out->Yoffset = trn->dy - trn->oarea.top; return( 0 ); }
/** * im_maplut: * @in: input image * @out: output image * @lut: look-up table * * Map an image through another image acting as a LUT (Look Up Table). * The lut may have any type, and the output image will be that type. * * The input image will be cast to one of the unsigned integer types, that is, * IM_BANDFMT_UCHAR, IM_BANDFMT_USHORT or IM_BANDFMT_UINT. * * If @lut is too small for the input type (for example, if @in is * IM_BANDFMT_UCHAR but @lut only has 100 elements), the lut is padded out * by copying the last element. Overflows are reported at the end of * computation. * If @lut is too large, extra values are ignored. * * If @lut has one band, then all bands of @in pass through it. If @lut * has same number of bands as @in, then each band is mapped * separately. If @in has one band, then @lut may have many bands and * the output will have the same number of bands as @lut. * * See also: im_histgr(), im_identity(). * * Returns: 0 on success, -1 on error */ int im_maplut( IMAGE *in, IMAGE *out, IMAGE *lut ) { IMAGE *t; LutInfo *st; /* Check input output. Old-style IO from lut, for simplicity. */ if( im_check_hist( "im_maplut", lut ) || im_check_uncoded( "im_maplut", lut ) || im_check_uncoded( "im_maplut", in ) || im_check_bands_1orn( "im_maplut", in, lut ) || im_piocheck( in, out ) || im_incheck( lut ) ) return( -1 ); /* Cast in to u8/u16/u32. */ if( !(t = im_open_local( out, "im_maplut", "p" )) || im_clip2fmt( in, t, bandfmt_maplut[in->BandFmt] ) ) return( -1 ); /* Prepare the output header. */ if( im_cp_descv( out, t, lut, NULL ) ) return( -1 ); /* Force output to be the same type as lut. */ out->BandFmt = lut->BandFmt; /* Output has same number of bands as LUT, unless LUT has 1 band, in * which case output has same number of bands as input. */ if( lut->Bands != 1 ) out->Bands = lut->Bands; /* Make tables. */ if( !(st = build_luts( out, lut )) ) return( -1 ); /* Set demand hints. */ if( im_demand_hint( out, IM_THINSTRIP, t, NULL ) ) return( -1 ); /* Process! */ if( im_generate( out, maplut_start, maplut_gen, maplut_stop, t, st ) ) return( -1 ); return( 0 ); }
int im__arith_binary_const( const char *domain, IMAGE *in, IMAGE *out, int n, double *c, VipsBandFmt vfmt, int format_table[10], im_wrapone_fn fn1, im_wrapone_fn fnn ) { PEL *vector; if( im_piocheck( in, out ) || im_check_vector( domain, n, in ) || im_check_uncoded( domain, in ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); out->BandFmt = format_table[in->BandFmt]; /* Some operations need the vector in the input type (eg. * im_equal_vec() where the output type is always uchar and is useless * for comparisons), some need it in the output type (eg. * im_andimage_vec() where we want to get the double to an int so we * can do bitwise-and without having to cast for each pixel), some * need a fixed type (eg. im_powtra_vec(), where we want to keep it as * double). * * Therefore pass in the desired vector type as a param. */ if( !(vector = make_pixel( out, vfmt, n, c )) ) return( -1 ); /* Band-up the input image if we have a >1 vector and * a 1-band image. */ if( n > 1 && out->Bands == 1 ) { IMAGE *t; if( !(t = im_open_local( out, domain, "p" )) || im__bandup( domain, in, t, n ) ) return( -1 ); in = t; } if( n == 1 ) { if( im_wrapone( in, out, fn1, vector, in ) ) return( -1 ); } else { if( im_wrapone( in, out, fnn, vector, in ) ) return( -1 ); } return( 0 ); }
/** * im_benchmark2: * @in: input image * @out: average image value * * This operation runs a single im_benchmarkn() and calculates the average * pixel value. It's useful if you just want to test image input. * * See also: im_benchmarkn(). * * Returns: 0 on success, -1 on error */ int im_benchmark2( IMAGE *in, double *out ) { IMAGE *t; return( !(t = im_open_local( in, "benchmarkn", "p" )) || im_benchmarkn( in, t, 1 ) || im_avg( t, out ) ); }
/** * im_addgnoise: * @in: input image * @out: output image * @sigma: standard deviation of noise * * Add gaussian noise with mean 0 and variance sigma to @in. * The noise is generated by averaging 12 random numbers, * see page 78, PIETGEN, 1989. * * See also: im_gaussnoise(). * * Returns: 0 on success, -1 on error */ int im_addgnoise( IMAGE *in, IMAGE *out, double sigma ) { IMAGE *t; if( !(t = im_open_local( out, "im_addgnoise", "p" )) || im_gaussnoise( t, in->Xsize, in->Ysize, 0, sigma ) || im_add( in, t, out ) ) return( -1 ); return( 0 ); }
/** * im_hist: * @in: input image * @out: output image * @bandno: band to plot * * Find and plot the histogram of @in. If @bandno is -1, plot all bands. * Otherwise plot the specified band. * * See also: im_histgr(), im_histplot(). * * Returns: 0 on success, -1 on error */ int im_hist( IMAGE *in, IMAGE *out, int bandno ) { IMAGE *hist; if( !(hist = im_open_local( out, "im_hist", "p" )) || im_histgr( in, hist, bandno ) || im_histplot( hist, out ) ) return( -1 ); return( 0 ); }
/** * im_cmulnorm * @in1: input #IMAGE 1 * @in2: input #IMAGE 2 * @out: output #IMAGE * * im_cmulnorm() multiplies two complex images. The complex output is * normalised to 1 by dividing both the real and the imaginary part of each * pel with the norm. This is useful for phase correlation. * * This operation used to be important, but now simply calls im_multiply() * then im_sign(). * * See also: im_multiply(), im_sign(). * * Returns: 0 on success, -1 on error */ int im_cmulnorm( IMAGE *in1, IMAGE *in2, IMAGE *out ) { IMAGE *t1; if( !(t1 = im_open_local( out, "im_cmulnorm:1", "p" )) || im_multiply( in1, in2, t1 ) || im_sign( t1, out ) ) return( -1 ); return( 0 ); }
int im_gradcor_raw( IMAGE *large, IMAGE *small, IMAGE *out ){ #define FUNCTION_NAME "im_gradcor_raw" if( im_piocheck( large, out ) || im_pincheck( small ) ) return -1; if( im_check_uncoded( "im_gradcor", large ) || im_check_mono( "im_gradcor", large ) || im_check_uncoded( "im_gradcor", small ) || im_check_mono( "im_gradcor", small ) || im_check_format_same( "im_gradcor", large, small ) || im_check_int( "im_gradcor", large ) ) return( -1 ); if( large-> Xsize < small-> Xsize || large-> Ysize < small-> Ysize ){ im_error( FUNCTION_NAME, "second image must be smaller than first" ); return -1; } if( im_cp_desc( out, large ) ) return -1; out-> Xsize= 1 + large-> Xsize - small-> Xsize; out-> Ysize= 1 + large-> Ysize - small-> Ysize; out-> BandFmt= IM_BANDFMT_FLOAT; if( im_demand_hint( out, IM_FATSTRIP, large, NULL ) ) return -1; { IMAGE *xgrad= im_open_local( out, FUNCTION_NAME ": xgrad", "t" ); IMAGE *ygrad= im_open_local( out, FUNCTION_NAME ": ygrad", "t" ); IMAGE **grads= im_allocate_input_array( out, xgrad, ygrad, NULL ); return ! xgrad || ! ygrad || ! grads || im_grad_x( small, xgrad ) || im_grad_y( small, ygrad ) || im_generate( out, gradcor_start, gradcor_gen, gradcor_stop, (void*) large, (void*) grads ); } #undef FUNCTION_NAME }
/* Just for compatibility. New code should use vips_object_local_array(). */ int im_open_local_array( VipsImage *parent, VipsImage **images, int n, const char *filename, const char *mode ) { int i; for( i = 0; i < n; i++ ) if( !(images[i] = im_open_local( parent, filename, mode )) ) return( -1 ); return( 0 ); }
int im_flood_blob_copy( IMAGE *in, IMAGE *out, int x, int y, PEL *ink ) { IMAGE *t; if( !(t = im_open_local( out, "im_flood_blob_copy", "t" )) || im_copy( in, t ) || im_flood_blob( t, x, y, ink, NULL ) || im_copy( t, out ) ) return( -1 ); return( 0 ); }
int im_flood_other_copy( IMAGE *test, IMAGE *mark, IMAGE *out, int x, int y, int serial ) { IMAGE *t; if( !(t = im_open_local( out, "im_flood_other_copy", "t" )) || im_copy( mark, t ) || im_flood_other( test, t, x, y, serial, NULL ) || im_copy( t, out ) ) return( -1 ); return( 0 ); }
/** * im_histplot: * @in: input image * @out: output image * * Plot a 1 by any or any by 1 image file as a max by any or * any by max image using these rules: * * <emphasis>unsigned char</emphasis> max is always 256 * * <emphasis>other unsigned integer types</emphasis> output 0 - maxium * value of @in. * * <emphasis>signed int types</emphasis> min moved to 0, max moved to max + min. * * <emphasis>float types</emphasis> min moved to 0, max moved to any * (square output) * * See also: im_hist_indexed(), im_histeq(). * * Returns: 0 on success, -1 on error */ int im_histplot( IMAGE *in, IMAGE *out ) { IMAGE *t1; if( im_check_hist( "im_histplot", in ) ) return( -1 ); if( !(t1 = im_open_local( out, "im_histplot:1", "p" )) || normalise( in, t1 ) || plot( t1, out ) ) return( -1 ); return( 0 ); }
/** * im_zerox: * @in: input image * @out: output image * @sign: detect positive or negative zero crossings * * im_zerox() detects the positive or negative zero crossings @in, * depending on @sign. If @sign is -1, negative zero crossings are returned, * if @sign is 1, positive zero crossings are returned. * * The output image is byte with zero crossing set to 255 and all other values * set to zero. Input can have any number of channels, and be any non-complex * type. * * See also: im_conv(), im_rot90. * * Returns: 0 on success, -1 on error */ int im_zerox( IMAGE *in, IMAGE *out, int sign ) { IMAGE *t1; if( sign != -1 && sign != 1 ) { im_error( "im_zerox", "%s", _( "flag not -1 or 1" ) ); return( -1 ); } if( in->Xsize < 2 ) { im_error( "im_zerox", "%s", _( "image too narrow" ) ); return( -1 ); } if( !(t1 = im_open_local( out, "im_zerox" , "p" )) || im_piocheck( in, t1 ) || im_check_uncoded( "im_zerox", in ) || im_check_noncomplex( "im_zerox", in ) ) return( -1 ); if( vips_bandfmt_isuint( in->BandFmt ) ) /* Unsigned type, therefore there will be no zero-crossings. */ return( im_black( out, in->Xsize, in->Ysize, in->Bands ) ); /* Force output to be BYTE. Output is narrower than input by 1 pixel. */ if( im_cp_desc( t1, in ) ) return( -1 ); t1->BandFmt = IM_BANDFMT_UCHAR; t1->Xsize -= 1; /* Set hints - THINSTRIP is ok with us. */ if( im_demand_hint( t1, IM_THINSTRIP, NULL ) ) return( -1 ); /* Generate image. */ if( im_generate( t1, im_start_one, zerox_gen, im_stop_one, in, GINT_TO_POINTER( sign ) ) ) return( -1 ); /* Now embed it in a larger image. */ if( im_embed( t1, out, 0, 0, 0, in->Xsize, in->Ysize ) ) return( -1 ); return( 0 ); }
/** * im_stdif: * @in: input image * @out: output image * @a: weight of new mean * @m0: target mean * @b: weight of new deviation * @s0:target deviation * @xwin: width of region * @ywin: height of region * * im_stdif() preforms statistical differencing according to the formula * given in page 45 of the book "An Introduction to Digital Image * Processing" by Wayne Niblack. This transformation emphasises the way in * which a pel differs statistically from its neighbours. It is useful for * enhancing low-contrast images with lots of detail, such as X-ray plates. * * At point (i,j) the output is given by the equation: * * vout(i,j) = @a * @m0 + (1 - @a) * meanv + * (vin(i,j) - meanv) * (@b * @s0) / (@s0 + @b * stdv) * * Values @a, @m0, @b and @s0 are entered, while meanv and stdv are the values * calculated over a moving window of size @xwin, @ywin centred on pixel (i,j). * @m0 is the new mean, @a is the weight given to it. @s0 is the new standard * deviation, @b is the weight given to it. * * Try: * * vips im_stdif $VIPSHOME/pics/huysum.v fred.v 0.5 128 0.5 50 11 11 * * The operation works on one-band uchar images only, and writes a one-band * uchar image as its result. The output image has the same size as the * input. * * See also: im_lhisteq(). * * Returns: 0 on success, -1 on error */ int im_stdif( IMAGE *in, IMAGE *out, double a, double m0, double b, double s0, int xwin, int ywin ) { IMAGE *t1; if( !(t1 = im_open_local( out, "im_stdif:1", "p" )) || im_embed( in, t1, 1, xwin / 2, ywin / 2, in->Xsize + xwin - 1, in->Ysize + ywin - 1 ) || im_stdif_raw( t1, out, a, m0, b, s0, xwin, ywin ) ) return( -1 ); return( 0 ); }
/** * im_tone_build: * @out: output image * @Lb: black-point [0-100] * @Lw: white-point [0-100] * @Ps: shadow point (eg. 0.2) * @Pm: mid-tone point (eg. 0.5) * @Ph: highlight point (eg. 0.8) * @S: shadow adjustment (+/- 30) * @M: mid-tone adjustment (+/- 30) * @H: highlight adjustment (+/- 30) * * As im_tone_build_range(), but set 32767 and 32767 as values for @in_max * and @out_max. This makes a curve suitable for correcting LABS * images, the most common case. * * See also: im_tone_build_range(). * * Returns: 0 on success, -1 on error */ int im_tone_build( IMAGE *out, double Lb, double Lw, double Ps, double Pm, double Ph, double S, double M, double H ) { IMAGE *t1; if( !(t1 = im_open_local( out, "im_tone_build", "p" )) || im_tone_build_range( t1, 32767, 32767, Lb, Lw, Ps, Pm, Ph, S, M, H ) || im_clip2fmt( t1, out, IM_BANDFMT_SHORT ) ) return( -1 ); return( 0 ); }
/* The above, with a border to make out the same size as in. */ int im_dilate( IMAGE *in, IMAGE *out, INTMASK *m ) { IMAGE *t1 = im_open_local( out, "im_dilate:1", "p" ); if( !t1 || im_embed( in, t1, 1, m->xsize / 2, m->ysize / 2, in->Xsize + m->xsize - 1, in->Ysize + m->ysize - 1 ) || im_dilate_raw( t1, out, m ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = 0; return( 0 ); }
/** * im_lhisteq: * @in: input image * @out: output image * @xwin: width of region * @ywin: height of region * * Performs local histogram equalisation on @in using a * window of size @xwin by @ywin centered on the input pixel. Works only on * monochrome images. * * The output image is the same size as the input image. The edge pixels are * created by copy edge pixels of the input image outwards. * * See also: im_stdif(), im_heq(). * * Returns: 0 on success, -1 on error */ int im_lhisteq( IMAGE *in, IMAGE *out, int xwin, int ywin ) { IMAGE *t1; if( !(t1 = im_open_local( out, "im_lhisteq:1", "p" )) || im_embed( in, t1, 1, xwin / 2, ywin / 2, in->Xsize + xwin - 1, in->Ysize + ywin - 1 ) || im_lhisteq_raw( t1, out, xwin, ywin ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = 0; return( 0 ); }
/** * im_erode: * @in: input image * @out: output image * @mask: mask * * im_erode() performs a morphological erode operation on @in using @mask as a * structuring element. The whole mask must match for the output pixel to be * set, that is, the result is the logical AND of the selected input pixels. * * The image should have 0 (black) for no object and 255 * (non-zero) for an object. Note that this is the reverse of the usual * convention for these operations, but more convenient when combined with the * boolean operators im_andimage() and friends. The output image is the same * size as the input image: edge pxels are made by expanding the input image * as necessary in the manner of im_conv(). * * Mask coefficients can be either 0 (for object) or 255 (for background) * or 128 (for do not care). The origin of the mask is at location * (m.xsize / 2, m.ysize / 2), integer division. All algorithms have been * based on the book "Fundamentals of Digital Image Processing" by A. Jain, * pp 384-388, Prentice-Hall, 1989. * * See the boolean operations im_andimage(), im_orimage() and im_eorimage() * for analogues of the usual set difference and set union operations. * * Operations are performed using the processor's vector unit, * if possible. Disable this with --vips-novector or IM_NOVECTOR. * * See also: im_dilate(). * * Returns: 0 on success, -1 on error */ int im_erode( IMAGE *in, IMAGE *out, INTMASK *mask ) { IMAGE *t1 = im_open_local( out, "im_erode:1", "p" ); if( !t1 || im_embed( in, t1, 1, mask->xsize / 2, mask->ysize / 2, in->Xsize + mask->xsize - 1, in->Ysize + mask->ysize - 1 ) || morphology( t1, out, mask, ERODE ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = 0; return( 0 ); }
/** * im_tbjoin: * @top: image to go on top * @bottom: image to go on bottom * @out: output image * * Join @top and @bottom together, up-down. If one is wider than the * other, @out will be has wide as the smaller. * * If the number of bands differs, one of the images * must have one band. In this case, an n-band image is formed from the * one-band image by joining n copies of the one-band image together, and then * the two n-band images are operated upon. * * The two input images are cast up to the smallest common type (see table * Smallest common format in * <link linkend="VIPS-arithmetic">arithmetic</link>). * * See also: im_insert(), im_tbjoin(). * * Returns: 0 on success, -1 on error */ int im_tbjoin( IMAGE *top, IMAGE *bottom, IMAGE *out ) { IMAGE *t1; /* Paste top and bottom together, cut off any leftovers. */ if( !(t1 = im_open_local( out, "im_tbjoin:1", "p" )) || im_insert( top, bottom, t1, 0, top->Ysize ) || im_extract_area( t1, out, 0, 0, IM_MIN( top->Xsize, bottom->Xsize ), t1->Ysize ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = top->Ysize; return( 0 ); }
/** * im_contrast_surface: * @in: input image * @out: output image * @half_win_size: window radius * @spacing: subsample output by this * * Generate an image where the value of each pixel represents the * contrast within a window of half_win_size from the corresponsing * point in the input image. Sub-sample by a factor of spacing. * * See also: im_spcor(), im_gradcor(). * * Returns: 0 on success, -1 on error. */ int im_contrast_surface (IMAGE * in, IMAGE * out, int half_win_size, int spacing) { IMAGE *t1 = im_open_local (out, "im_contrast_surface intermediate", "p"); if (!t1 || im_embed (in, t1, 1, half_win_size, half_win_size, in->Xsize + DOUBLE (half_win_size), in->Ysize + DOUBLE (half_win_size)) || im_contrast_surface_raw (t1, out, half_win_size, spacing)) return -1; out->Xoffset = 0; out->Yoffset = 0; return 0; }
/* The above, with a border to make out the same size as in. */ int im_fastcor( IMAGE *in, IMAGE *ref, IMAGE *out ) { IMAGE *t1 = im_open_local( out, "im_fastcor intermediate", "p" ); if( !t1 || im_embed( in, t1, 1, ref->Xsize / 2, ref->Ysize / 2, in->Xsize + ref->Xsize - 1, in->Ysize + ref->Ysize - 1 ) || im_fastcor_raw( t1, ref, out ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = 0; return( 0 ); }
/* similarity+tbmerge. */ int im__tbmerge1( IMAGE *ref, IMAGE *sec, IMAGE *out, double a, double b, double dx, double dy, int mwidth ) { VipsTransformation trn; IMAGE *t1 = im_open_local( out, "im_lrmosaic1:2", "p" ); VipsBuf buf; char text[1024]; /* Scale, rotate and displace sec. */ if( !t1 || apply_similarity( &trn, sec, t1, a, b, dx, dy ) ) return( -1 ); /* And join to ref. */ if( im__tbmerge( ref, t1, out, -trn.oarea.left, -trn.oarea.top, mwidth ) ) return( -1 ); /* Note parameters in history file ... for global balance to pick up * later. */ im__add_mosaic_name( out ); vips_buf_init_static( &buf, text, 1024 ); vips_buf_appendf( &buf, "#TBROTSCALE <%s> <%s> <%s> <", im__get_mosaic_name( ref ), im__get_mosaic_name( sec ), im__get_mosaic_name( out ) ); vips_buf_appendg( &buf, a ); vips_buf_appendf( &buf, "> <" ); vips_buf_appendg( &buf, b ); vips_buf_appendf( &buf, "> <" ); vips_buf_appendg( &buf, dx ); vips_buf_appendf( &buf, "> <" ); vips_buf_appendg( &buf, dy ); vips_buf_appendf( &buf, "> <%d>", mwidth ); if( im_histlin( out, "%s", vips_buf_all( &buf ) ) ) return( -1 ); return( 0 ); }