/** * im_remainder: * @in1: input #IMAGE 1 * @in2: input #IMAGE 2 * @out: output #IMAGE * * This operation calculates @in1 % @in2 (remainder after division) and writes * the result to @out. The images may have any * non-complex format. For float formats, im_remainder() calculates @in1 - * @in2 * floor (@in1 / @in2). * * If the images differ in size, the smaller image is enlarged to match the * larger by adding zero pixels along the bottom and right. * * 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>), and that format is the * result type. * * See also: im_remainderconst(), im_divide(). * * Returns: 0 on success, -1 on error */ int im_remainder( IMAGE *in1, IMAGE *in2, IMAGE *out ) { if( im_check_noncomplex( "im_remainder", in1 ) || im_check_noncomplex( "im_remainder", in2 ) ) return( -1 ); return( im__arith_binary( "im_remainder", in1, in2, out, bandfmt_remainder, (im_wrapmany_fn) remainder_buffer, NULL ) ); }
/** * im_shrink: * @in: input image * @out: output image * @xshrink: horizontal shrink * @yshrink: vertical shrink * * Shrink @in by a pair of factors with a simple box filter. * * You will get aliasing for non-integer shrinks. In this case, shrink with * this function to the nearest integer size above the target shrink, then * downsample to the exact size with im_affinei() and your choice of * interpolator. * * im_rightshift_size() is faster for factors which are integer powers of two. * * See also: im_rightshift_size(), im_affinei(). * * Returns: 0 on success, -1 on error */ int im_shrink( IMAGE *in, IMAGE *out, double xshrink, double yshrink ) { if( im_check_noncomplex( "im_shrink", in ) || im_check_coding_known( "im_shrink", in ) || im_piocheck( in, out ) ) return( -1 ); if( xshrink < 1.0 || yshrink < 1.0 ) { im_error( "im_shrink", "%s", _( "shrink factors should be >= 1" ) ); return( -1 ); } if( xshrink == 1 && yshrink == 1 ) { return( im_copy( in, out ) ); } else if( in->Coding == IM_CODING_LABQ ) { IMAGE *t[2]; if( im_open_local_array( out, t, 2, "im_shrink:1", "p" ) || im_LabQ2LabS( in, t[0] ) || shrink( t[0], t[1], xshrink, yshrink ) || im_LabS2LabQ( t[1], out ) ) return( -1 ); } else if( shrink( in, out, xshrink, yshrink ) ) return( -1 ); return( 0 ); }
/** * im_expntra_vec: * @in: input #IMAGE * @out: output #IMAGE * @n: number of elements in array * @e: array of constants * * im_expntra_vec() transforms element x of input to * <function>pow</function>(@b, x) in output. * It detects division by zero, setting those pixels to zero in the output. * Beware: it does this silently! * * If the array of constants has one element, that constant is used for each * image band. If the array has more than one element, it must have the same * number of elements as there are bands in the image, and one array element * is used for each band. * * See also: im_logtra(), im_powtra() * * Returns: 0 on success, -1 on error */ int im_expntra_vec( IMAGE *in, IMAGE *out, int n, double *c ) { if( im_check_noncomplex( "im_expntra_vec", in ) ) return( -1 ); return( im__arith_binary_const( "im_expntra_vec", in, out, n, c, IM_BANDFMT_DOUBLE, bandfmt_power, (im_wrapone_fn) POWC1_buffer, (im_wrapone_fn) POWCn_buffer ) ); }
/** * im_remainder_vec: * @in: input #IMAGE * @out: output #IMAGE * @n: number of elements in array * @c: array of constants * * This operation calculates @in % @c (remainder after division by constant) * and writes the result to @out. * The image may have any * non-complex format. For float formats, im_remainder() calculates @in - * @c * floor (@in / @c). * * If the number of image bands end array elements differs, one of them * must have one band. Either the image is up-banded by joining n copies of * the one-band image together, or the array is upbanded by copying the single * element n times. * * See also: im_remainder(), im_remainderconst(), im_divide(). * * Returns: 0 on success, -1 on error */ int im_remainder_vec( IMAGE *in, IMAGE *out, int n, double *c ) { if( im_check_noncomplex( "im_remainder", in ) ) return( -1 ); return( im__arith_binary_const( "im_remainder", in, out, n, c, in->BandFmt, bandfmt_remainder, (im_wrapone_fn) remainderconst1_buffer, (im_wrapone_fn) remainderconstn_buffer ) ); }
/* 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 ); }
/** * im_hist_indexed: * @index: input image * @value: input image * @out: output image * * Make a histogram of @value, but use image @index to pick the bins. In other * words, element zero in @out contains the sum of all the pixels in @value * whose corresponding pixel in @index is zero. * * @index must have just one band and be u8 or u16. @value must be * non-complex. @out always has the same size and format as @value. * * This operation is useful in conjunction with im_label_regions(). You can * use it to find the centre of gravity of blobs in an image, for example. * * See also: im_histgr(), im_label_regions(). * * Returns: 0 on success, -1 on error */ int im_hist_indexed( IMAGE *index, IMAGE *value, IMAGE *out ) { int size; /* Length of hist */ Histogram *mhist; VipsGenerateFn scanfn; /* Check images. PIO from in, WIO to out. */ if( im_pincheck( index ) || im_pincheck( value ) || im_outcheck( out ) || im_check_uncoded( "im_hist_indexed", index ) || im_check_uncoded( "im_hist_indexed", value ) || im_check_noncomplex( "im_hist_indexed", value ) || im_check_size_same( "im_hist_indexed", index, value ) || im_check_u8or16( "im_hist_indexed", index ) || im_check_mono( "im_hist_indexed", index ) ) return( -1 ); /* Find the range of pixel values we must handle. */ if( index->BandFmt == IM_BANDFMT_UCHAR ) { size = 256; scanfn = hist_scan_uchar; } else { size = 65536; scanfn = hist_scan_ushort; } /* Build main hist we accumulate data in. */ if( !(mhist = hist_build( index, value, out, value->Bands, size )) ) return( -1 ); /* Accumulate data. */ if( vips_sink( index, hist_start, scanfn, hist_stop, mhist, NULL ) || hist_write( out, mhist ) ) { hist_free( mhist ); return( -1 ); } hist_free( mhist ); 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_measure_area: * @im: image to measure * @left: area of image containing chart * @top: area of image containing chart * @width: area of image containing chart * @height: area of image containing chart * @h: patches across chart * @v: patches down chart * @sel: array of patch numbers to measure (numbered from 1 in row-major order) * @nsel: length of patch number array * @name: name to give to returned @DOUBLEMASK * * Analyse a grid of colour patches, producing a #DOUBLEMASK of patch averages. * The mask has a row for each measured patch, and a column for each image * band. The operations issues a warning if any patch has a deviation more * than 20% of * the mean. Only the central 50% of each patch is averaged. If @sel is %NULL * then all patches are measured. * * Example: 6 band image of 4x2 block of colour patches. * * <tgroup cols='4' align='left' colsep='1' rowsep='1'> * <tbody> * <row> * <entry>1</entry> * <entry>2</entry> * <entry>3</entry> * <entry>4</entry> * </row> * <row> * <entry>5</entry> * <entry>6</entry> * <entry>7</entry> * <entry>8</entry> * </row> * </tbody> * </tgroup> * * Then call im_measure( im, box, 4, 2, { 2, 4 }, 2, "fred" ) makes a mask * "fred" which has 6 columns, two rows. The first row contains the averages * for patch 2, the second for patch 4. * * See also: im_avg(), im_deviate(), im_stats(). * * Returns: #DOUBLEMASK of measurements. */ DOUBLEMASK * im_measure_area( IMAGE *im, int left, int top, int width, int height, int u, int v, int *sel, int nsel, const char *name ) { DOUBLEMASK *mask; /* Check input image. */ if( im->Coding == IM_CODING_LABQ ) { IMAGE *t1; if( !(t1 = im_open( "measure-temp", "p" )) ) return( NULL ); if( im_LabQ2Lab( im, t1 ) || !(mask = im_measure_area( t1, left, top, width, height, u, v, sel, nsel, name )) ) { im_close( t1 ); return( NULL ); } im_close( t1 ); return( mask ); } if( im_check_uncoded( "im_measure", im ) || im_check_noncomplex( "im_measure", im ) ) return( NULL ); /* Default to all patches if sel == NULL. */ if( sel == NULL ) { int i; nsel = u * v; if( !(sel = IM_ARRAY( im, nsel, int )) ) return( NULL ); for( i = 0; i < nsel; i++ ) sel[i] = i + 1; }
static DOUBLEMASK * internal_im_measure_area( IMAGE *im, int left, int top, int width, int height, int u, int v, int *sel, int nsel, const char *name ) { DOUBLEMASK *mask; if( im_check_uncoded( "im_measure", im ) || im_check_noncomplex( "im_measure", im ) ) return( NULL ); /* Default to all patches if sel == NULL. */ if( sel == NULL ) { int i; nsel = u * v; if( !(sel = IM_ARRAY( im, nsel, int )) ) return( NULL ); for( i = 0; i < nsel; i++ ) sel[i] = i + 1; }
static VipsFits * vips_fits_new_write( VipsImage *in, const char *filename ) { VipsImage *flip; VipsImage *type; VipsFits *fits; int status; status = 0; if( im_check_noncomplex( "im_vips2fits", in ) || im_check_uncoded( "im_vips2fits", in ) ) return( NULL ); /* Cast to a supported format. */ if( !(type = vips_image_new()) || vips_object_local( in, type ) || im_clip2fmt( in, type, vips_fits_bandfmt[in->BandFmt] ) ) return( NULL ); in = type; /* FITS has (0,0) in the bottom left, we need to flip. */ if( !(flip = vips_image_new()) || vips_object_local( in, flip ) || im_flipver( in, flip ) ) return( NULL ); in = flip; if( !(fits = VIPS_NEW( in, VipsFits )) ) return( NULL ); fits->filename = im_strdup( NULL, filename ); fits->image = in; fits->fptr = NULL; fits->lock = NULL; fits->band_select = -1; fits->buffer = NULL; g_signal_connect( in, "close", G_CALLBACK( vips_fits_close_cb ), fits ); if( !(fits->filename = im_strdup( NULL, filename )) ) return( NULL ); /* We need to be able to hold one scanline of one band. */ if( !(fits->buffer = VIPS_ARRAY( NULL, VIPS_IMAGE_SIZEOF_ELEMENT( in ) * in->Xsize, PEL )) ) return( NULL ); /* fits_create_file() will fail if there's a file of thet name, unless * we put a "!" in front ofthe filename. This breaks conventions with * the rest of vips, so just unlink explicitly. */ g_unlink( filename ); if( fits_create_file( &fits->fptr, filename, &status ) ) { im_error( "fits", _( "unable to write to \"%s\"" ), filename ); vips_fits_error( status ); return( NULL ); } fits->lock = g_mutex_new(); return( fits ); }