int im_rot270( IMAGE *in, IMAGE *out ) { /* Make output image. */ if( im_piocheck( in, out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE && in->Coding != IM_CODING_LABQ ) { im_error( "im_rot270", _( "uncoded or IM_CODING_LABQ only" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = in->Ysize; out->Ysize = in->Xsize; /* We want smalltile if possible. */ if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) return( -1 ); /* Generate! */ if( im_generate( out, im_start_one, rot270_gen, im_stop_one, in, NULL ) ) return( -1 ); out->Xoffset = 0; out->Yoffset = in->Xsize; return( 0 ); }
/** * im_gaussnoise: * @out: output image * @x: output width * @y: output height * @mean: average value in output * @sigma: standard deviation in output * * Make a one band float image of gaussian noise with the specified * distribution. The noise distribution is created by averaging 12 random * numbers with the appropriate weights. * * See also: im_addgnoise(), im_make_xy(), im_text(), im_black(). * * Returns: 0 on success, -1 on error */ int im_gaussnoise( IMAGE *out, int x, int y, double mean, double sigma ) { GnoiseInfo *gin; if( x <= 0 || y <= 0 ) { im_error( "im_gaussnoise", "%s", _( "bad parameter" ) ); return( -1 ); } if( im_poutcheck( out ) ) return( -1 ); im_initdesc( out, x, y, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 ); if( im_demand_hint( out, IM_ANY, NULL ) ) return( -1 ); /* Save parameters. */ if( !(gin = IM_NEW( out, GnoiseInfo )) ) return( -1 ); gin->mean = mean; gin->sigma = sigma; if( im_generate( out, NULL, gnoise_gen, NULL, gin, NULL ) ) return( -1 ); return( 0 ); }
static int fits2vips( const char *filename, VipsImage *out, int band_select ) { VipsFits *fits; /* The -1 mode is just for reading the header. */ g_assert( band_select >= 0 ); if( !(fits = vips_fits_new_read( filename, out, band_select )) ) return( -1 ); if( vips_fits_get_header( fits, out ) || im_demand_hint( out, VIPS_DEMAND_STYLE_SMALLTILE, NULL ) || im_generate( out, NULL, fits2vips_generate, NULL, fits, NULL ) ) { vips_fits_close( fits ); return( -1 ); } /* Don't vips_fits_close(), we need it to stick around for the * generate. */ return( 0 ); }
/** * im_fgrey: * @out: output image * @xsize: image size * @ysize: image size * * Create a one-band float image with the left-most column zero and the * right-most 1. Intermediate pixels are a linear ramp. * * See also: im_grey(), im_make_xy(), im_identity(). * * Returns: 0 on success, -1 on error */ int im_fgrey( IMAGE *out, const int xsize, const int ysize ) { /* Check args. */ if( xsize <=0 || ysize <= 0 ) { im_error( "im_fgrey", "%s", _( "bad size" ) ); return( -1 ); } if( im_poutcheck( out ) ) return( -1 ); /* Set image. */ im_initdesc( out, xsize, ysize, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0 ); /* Set hints - ANY is ok with us. */ if( im_demand_hint( out, IM_ANY, NULL ) ) return( -1 ); /* Generate image. */ if( im_generate( out, NULL, fgrey_gen, NULL, NULL, NULL ) ) return( -1 ); return( 0 ); }
/* Copy image. */ int im_fliphor( IMAGE *in, IMAGE *out ) { /* Check args. */ if( im_piocheck( in, out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE && in->Coding != IM_CODING_LABQ ) { im_error( "im_fliphor", _( "in must be uncoded" ) ); return( -1 ); } /* Prepare output header. */ if( im_cp_desc( out, in ) ) return( -1 ); /* Set demand hints. */ if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) return( -1 ); /* Generate! */ if( im_generate( out, im_start_one, flip_gen, im_stop_one, in, NULL ) ) return( -1 ); out->Xoffset = in->Xsize; out->Yoffset = 0; return( 0 ); }
static int ifthenelse( IMAGE *c, IMAGE *a, IMAGE *b, IMAGE *out ) { IMAGE **in; /* Check args. */ if( im_check_uncoded( "im_ifthenelse", c ) || im_check_coding_known( "im_ifthenelse", a ) || im_check_coding_known( "im_ifthenelse", b ) || im_check_format( "ifthenelse", c, IM_BANDFMT_UCHAR ) || im_check_format_same( "ifthenelse", a, b ) || im_check_bands_same( "ifthenelse", a, b ) || im_check_bands_1orn( "im_ifthenelse", c, a ) || im_piocheck( c, out ) || im_pincheck( a ) || im_pincheck( b ) ) return( -1 ); /* Make output image. */ if( im_demand_hint( out, IM_THINSTRIP, c, a, b, NULL ) || im_cp_descv( out, a, b, c, NULL ) || !(in = im_allocate_input_array( out, c, a, b, NULL )) || im_generate( out, im_start_many, ifthenelse_gen, im_stop_many, in, NULL ) ) return( -1 ); return( 0 ); }
int im_stdif_raw( IMAGE *in, IMAGE *out, double a, double m0, double b, double s0, int xwin, int ywin ) { StdifInfo *inf; if( xwin > in->Xsize || ywin > in->Ysize ) { im_error( "im_stdif", "%s", _( "window too large" ) ); return( -1 ); } if( xwin <= 0 || ywin <= 0 ) { im_error( "im_lhisteq", "%s", _( "window too small" ) ); return( -1 ); } if( m0 < 0 || m0 > 255 || a < 0 || a > 1.0 || b < 0 || b > 2 || s0 < 0 || s0 > 255 ) { im_error( "im_stdif", "%s", _( "parameters out of range" ) ); return( -1 ); } if( im_check_format( "im_stdif", in, IM_BANDFMT_UCHAR ) || im_check_uncoded( "im_stdif", in ) || im_check_mono( "im_stdif", in ) || im_piocheck( in, out ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize -= xwin; out->Ysize -= ywin; /* Save parameters. */ if( !(inf = IM_NEW( out, StdifInfo )) ) return( -1 ); inf->xwin = xwin; inf->ywin = ywin; inf->a = a; inf->m0 = m0; inf->b = b; inf->s0 = s0; /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); /* Write the hist. */ if( im_generate( out, im_start_one, stdif_gen, im_stop_one, in, inf ) ) return( -1 ); return( 0 ); }
/** * im_grad_y: * @in: input image * @out: output image * * Find vertical differences between adjacent pixels. * * Generates an image where the value of each pixel is the difference between * it and the pixel below it. The output has the same width as the input * and one pixel less height. One-band integer formats only. The result is * always %IM_BANDFMT_INT. * * This operation is much faster than (though equivalent to) im_conv() with the * mask [[-1], [1]]. * * See also: im_grad_x(), im_conv(). * * Returns: 0 on success, -1 on error */ int im_grad_y( IMAGE *in, IMAGE *out ){ #define FUNCTION_NAME "im_grad_y" if( im_piocheck( in, out ) ) return -1; if( im_check_uncoded( "im_grad_y", in ) || im_check_mono( "im_grad_y", in ) || im_check_int( "im_grad_y", in ) ) return( -1 ); if( im_cp_desc( out, in ) ) return -1; -- out-> Ysize; out-> BandFmt= IM_BANDFMT_INT; /* do not change without updating im_gradcor() */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return -1; #define RETURN_GENERATE( TYPE ) return im_generate( out, im_start_one, ygrad_gen_ ## TYPE, im_stop_one, (void*) in, NULL ) switch( in-> BandFmt ){ case IM_BANDFMT_UCHAR: RETURN_GENERATE( guint8 ); case IM_BANDFMT_CHAR: RETURN_GENERATE( gint8 ); case IM_BANDFMT_USHORT: RETURN_GENERATE( guint16 ); case IM_BANDFMT_SHORT: RETURN_GENERATE( gint16 ); case IM_BANDFMT_UINT: RETURN_GENERATE( guint32 ); case IM_BANDFMT_INT: RETURN_GENERATE( gint32 ); #if 0 case IM_BANDFMT_FLOAT: RETURN_GENERATE( float ); case IM_BANDFMT_DOUBLE: RETURN_GENERATE( double ); #endif #undef RETURN_GENERATE default: g_assert( 0 ); } /* Keep gcc happy. */ return 0; #undef FUNCTION_NAME }
int im_contrast_surface_raw (IMAGE * in, IMAGE * out, int half_win_size, int spacing) { #define FUNCTION_NAME "im_contrast_surface_raw" cont_surf_params_t *params; if (im_piocheck (in, out) || im_check_uncoded (FUNCTION_NAME, in) || im_check_mono (FUNCTION_NAME, in) || im_check_format (FUNCTION_NAME, in, IM_BANDFMT_UCHAR)) return -1; if (half_win_size < 1 || spacing < 1) { im_error (FUNCTION_NAME, "%s", _("bad parameters")); return -1; } if (DOUBLE (half_win_size) >= LESSER (in->Xsize, in->Ysize)) { im_error (FUNCTION_NAME, "%s", _("parameters would result in zero size output image")); return -1; } params = IM_NEW (out, cont_surf_params_t); if (!params) return -1; params->half_win_size = half_win_size; params->spacing = spacing; if (im_cp_desc (out, in)) return -1; out->BandFmt = IM_BANDFMT_UINT; out->Xsize = 1 + ((in->Xsize - DOUBLE_ADD_ONE (half_win_size)) / spacing); out->Ysize = 1 + ((in->Ysize - DOUBLE_ADD_ONE (half_win_size)) / spacing); out->Xoffset = -half_win_size; out->Yoffset = -half_win_size; if (im_demand_hint (out, IM_FATSTRIP, in, NULL)) return -1; return im_generate (out, im_start_one, cont_surf_gen, im_stop_one, in, params); #undef FUNCTION_NAME }
/** * 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 ); }
/* Raw fastcor, with no borders. */ int im_fastcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out ) { /* PIO between in and out; WIO from ref. */ if( im_piocheck( in, out ) || im_incheck( ref ) ) return( -1 ); /* Check sizes. */ if( in->Xsize < ref->Xsize || in->Ysize < ref->Ysize ) { im_errormsg( "im_fastcor: ref not smaller than in" ); return( -1 ); } /* Check types. */ if( in->Coding != IM_CODING_NONE || in->Bands != 1 || in->BandFmt != IM_BANDFMT_UCHAR || ref->Coding != IM_CODING_NONE || ref->Bands != 1 || ref->BandFmt != IM_BANDFMT_UCHAR ) { im_errormsg( "im_fastcor_raw: input not uncoded 1 band uchar" ); return( -1 ); } /* Prepare the output image. */ if( im_cp_descv( out, in, ref, NULL ) ) return( -1 ); out->Bbits = IM_BBITS_INT; out->BandFmt = IM_BANDFMT_UINT; out->Xsize = in->Xsize - ref->Xsize + 1; out->Ysize = in->Ysize - ref->Ysize + 1; /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); /* Write the correlation. */ if( im_generate( out, im_start_one, fastcor_gen, im_stop_one, in, ref ) ) return( -1 ); out->Xoffset = -ref->Xsize / 2; out->Yoffset = -ref->Ysize / 2; return( 0 ); }
/* Copy image, changing header fields. */ static int im_copy_set_all( IMAGE *in, IMAGE *out, VipsType type, float xres, float yres, int xoffset, int yoffset, int bands, VipsBandFmt bandfmt, VipsCoding coding ) { /* Check args. */ if( im_check_coding_known( "im_copy", in ) || im_piocheck( in, out ) ) return( -1 ); if( coding != IM_CODING_NONE && coding != IM_CODING_LABQ && coding != IM_CODING_RAD ) { im_error( "im_copy", "%s", _( "coding must be NONE, LABQ or RAD" ) ); return( -1 ); } if( bandfmt < 0 || bandfmt > IM_BANDFMT_DPCOMPLEX ) { im_error( "im_copy", _( "bandfmt must be in range [0,%d]" ), IM_BANDFMT_DPCOMPLEX ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Type = type; out->Xres = xres; out->Yres = yres; out->Xoffset = xoffset; out->Yoffset = yoffset; out->Bands = bands; out->BandFmt = bandfmt; out->Coding = coding; /* Sanity check: we (may) have changed bytes-per-pixel since we've * changed Bands and BandFmt ... bad! */ if( IM_IMAGE_SIZEOF_PEL( in ) != IM_IMAGE_SIZEOF_PEL( out ) ) { im_error( "im_copy", "%s", _( "sizeof( pixel ) has changed" ) ); return( -1 ); } /* Generate! */ if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) || im_generate( out, im_start_one, copy_gen, im_stop_one, in, NULL ) ) return( -1 ); return( 0 ); }
int im_lhisteq_raw( IMAGE *in, IMAGE *out, int xwin, int ywin ) { LhistInfo *inf; if( im_check_mono( "im_lhisteq", in ) || im_check_uncoded( "im_lhisteq", in ) || im_check_format( "im_lhisteq", in, IM_BANDFMT_UCHAR ) || im_piocheck( in, out ) ) return( -1 ); if( xwin > in->Xsize || ywin > in->Ysize ) { im_error( "im_lhisteq", "%s", _( "window too large" ) ); return( -1 ); } if( xwin <= 0 || ywin <= 0 ) { im_error( "im_lhisteq", "%s", _( "window too small" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize -= xwin - 1; out->Ysize -= ywin - 1; /* Save parameters. */ if( !(inf = IM_NEW( out, LhistInfo )) ) return( -1 ); inf->xwin = xwin; inf->ywin = ywin; inf->npels = xwin * ywin; /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); if( im_generate( out, im_start_one, lhist_gen, im_stop_one, in, inf ) ) return( -1 ); out->Xoffset = -xwin / 2; out->Yoffset = -xwin / 2; return( 0 ); }
/* Join two images. out->Bands = in1->Bands + in2->Bands. in1 goes first in * the list. */ int im_bandjoin( IMAGE *in1, IMAGE *in2, IMAGE *out ) { IMAGE **in; /* Check our args. */ if( im_piocheck( in1, out ) ) return( -1 ); if( im_piocheck( in2, out ) ) return( -1 ); if( in1->Xsize != in2->Xsize || in1->Ysize != in2->Ysize ) { im_errormsg( "im_bandjoin: images not same size" ); return( -1 ); } if( in1->BandFmt != in2->BandFmt ) { im_errormsg( "im_bandjoin: images not same type" ); return( -1 ); } if( in1->Coding != IM_CODING_NONE || in2->Coding != IM_CODING_NONE ) { im_errormsg( "im_bandjoin: input coded" ); return( -1 ); } /* Set up the output header. */ if( im_cp_descv( out, in1, in2, NULL ) ) return( -1 ); out->Bands = in1->Bands + in2->Bands; /* Set demand hints. */ if( im_demand_hint( out, IM_THINSTRIP, in1, in2, NULL ) ) return( -1 ); /* Make input array. */ if( !(in = im_allocate_input_array( out, in1, in2, NULL )) ) return( -1 ); /* Make output image. */ if( im_generate( out, im_start_many, bandjoin_gen, im_stop_many, in, NULL ) ) return( -1 ); return( 0 ); }
/* Morph an image. */ static int morphology( IMAGE *in, IMAGE *out, INTMASK *mask, MorphOp op ) { Morph *morph; im_generate_fn generate; /* Check parameters. */ if( !(morph = morph_new( in, out, mask, op )) ) return( -1 ); /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output * would be 1x1. */ if( im_cp_desc( morph->out, morph->in ) ) return( -1 ); morph->out->Xsize -= morph->mask->xsize - 1; morph->out->Ysize -= morph->mask->ysize - 1; if( morph->out->Xsize <= 0 || morph->out->Ysize <= 0 ) { im_error( "morph", "%s", _( "image too small for mask" ) ); return( -1 ); } if( morph->n_pass ) { generate = morph_vector_gen; #ifdef DEBUG printf( "morph_vector_gen: %d passes\n", morph->n_pass ); #endif /*DEBUG*/ } else if( morph->op == DILATE ) generate = dilate_gen; else generate = erode_gen; /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( morph->out, IM_FATSTRIP, morph->in, NULL ) || im_generate( morph->out, morph_start, generate, morph_stop, morph->in, morph ) ) return( -1 ); morph->out->Xoffset = -morph->mask->xsize / 2; morph->out->Yoffset = -morph->mask->ysize / 2; 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 ); }
/* Raw fastcor, with no borders. */ int im_fastcor_raw( IMAGE *in, IMAGE *ref, IMAGE *out ) { /* PIO between in and out; WIO from ref. */ if( im_piocheck( in, out ) || im_incheck( ref ) ) return( -1 ); /* Check sizes. */ if( in->Xsize < ref->Xsize || in->Ysize < ref->Ysize ) { im_error( "im_fastcor", "%s", _( "ref not smaller than or equal to in" ) ); return( -1 ); } /* Check types. */ if( im_check_uncoded( "im_fastcor", in ) || im_check_mono( "im_fastcor", in ) || im_check_format( "im_fastcor", in, IM_BANDFMT_UCHAR ) || im_check_coding_same( "im_fastcor", in, ref ) || im_check_bands_same( "im_fastcor", in, ref ) || im_check_format_same( "im_fastcor", in, ref ) ) return( -1 ); /* Prepare the output image. */ if( im_cp_descv( out, in, ref, NULL ) ) return( -1 ); out->BandFmt = IM_BANDFMT_UINT; out->Xsize = in->Xsize - ref->Xsize + 1; out->Ysize = in->Ysize - ref->Ysize + 1; /* FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) || im_generate( out, im_start_one, fastcor_gen, im_stop_one, in, ref ) ) return( -1 ); out->Xoffset = -ref->Xsize / 2; out->Yoffset = -ref->Ysize / 2; return( 0 ); }
int im__tbmerge( IMAGE *ref, IMAGE *sec, IMAGE *out, int dx, int dy, int mwidth ) { Overlapping *ovlap; if( dy > 0 || dy < 1 - ref->Ysize ) { /* No overlap, use insert instead. */ if( im_insert( ref, sec, out, -dx, -dy ) ) return( -1 ); out->Xoffset = -dx; out->Yoffset = -dy; return( 0 ); } /* Build state for this join. */ if( !(ovlap = build_tbstate( ref, sec, out, dx, dy, mwidth )) ) return( -1 ); /* Prepare the output IMAGE. */ if( im_cp_descv( out, ref, sec, NULL ) ) return( -1 ); out->Xsize = ovlap->oarea.width; out->Ysize = ovlap->oarea.height; out->Xoffset = ovlap->sarea.left; out->Yoffset = ovlap->sarea.top; /* Set demand hints. */ if( im_demand_hint( out, IM_THINSTRIP, ref, sec, NULL ) ) return( -1 ); /* Generate! */ if( im_generate( out, im__start_merge, im__merge_gen, im__stop_merge, ovlap, NULL ) ) return( -1 ); return ( 0 ); }
static int shrink( IMAGE *in, IMAGE *out, double xshrink, double yshrink ) { ShrinkInfo *st; /* Prepare output. Note: we round the output width down! */ if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = in->Xsize / xshrink; out->Ysize = in->Ysize / yshrink; out->Xres = in->Xres / xshrink; out->Yres = in->Yres / yshrink; if( out->Xsize <= 0 || out->Ysize <= 0 ) { im_error( "im_shrink", "%s", _( "image has shrunk to nothing" ) ); return( -1 ); } /* Build and attach state struct. */ if( !(st = IM_NEW( out, ShrinkInfo )) ) return( -1 ); st->xshrink = xshrink; st->yshrink = yshrink; st->mw = ceil( xshrink ); st->mh = ceil( yshrink ); st->np = st->mw * st->mh; /* Set demand hints. We want THINSTRIP, as we will be demanding a * large area of input for each output line. */ if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) return( -1 ); /* Generate! */ if( im_generate( out, shrink_start, shrink_gen, shrink_stop, in, st ) ) return( -1 ); return( 0 ); }
/** * im_rot180: * @in: input image * @out: output image * * Rotate an image 180 degrees. * * See also: im_rot90(), im_rot270(), im_affinei_all(). * * Returns: 0 on success, -1 on error */ int im_rot180( IMAGE *in, IMAGE *out ) { if( im_piocheck( in, out ) || im_check_coding_known( "im_rot180", in ) ) return( -1 ); if( im_cp_desc( out, in ) || im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) return( -1 ); if( im_generate( out, im_start_one, rot180_gen, im_stop_one, in, NULL ) ) return( -1 ); out->Xoffset = in->Xsize; out->Yoffset = in->Ysize; return( 0 ); }
/* Wrap up as a partial. */ int im_wraptwo( IMAGE *in1, IMAGE *in2, IMAGE *out, im_wraptwo_fn fn, void *a, void *b ) { if( im_pincheck( in1 ) || im_pincheck( in2 ) || im_poutcheck( out )) return -1; { UserBundle *bun= IM_NEW( out, UserBundle ); IMAGE **ins= im_allocate_input_array( out, in1, in2, NULL ); if( ! bun || ! ins ) return -1; bun-> fn= fn; bun-> a= a; bun-> b= b; return im_demand_hint( out, IM_THINSTRIP, in1, in2, NULL ) || im_generate( out, im_start_many, process_region, im_stop_many, (void*) ins, (void*) bun ); } }
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 }
/** * im_tile_cache: * @in: input image * @out: output image * @tile_width: tile width * @tile_height: tile height * @max_tiles: maximum number of tiles to cache * * This operation behaves rather like im_copy() between images * @in and @out, except that it keeps a cache of computed pixels. * This cache is made of up to @max_tiles tiles (a value of -1 for * means any number of tiles), and each tile is of size @tile_width * by @tile_height pixels. Each cache tile is made with a single call to * im_prepare(). * * This is a lower-level operation than im_cache() since it does no * subdivision. It is suitable for caching the output of operations like * im_exr2vips() on tiled images. * * See also: im_cache(). * * Returns: 0 on success, -1 on error. */ int im_tile_cache( IMAGE *in, IMAGE *out, int tile_width, int tile_height, int max_tiles ) { Read *read; if( tile_width <= 0 || tile_height <= 0 || max_tiles < -1 ) { im_error( "im_tile_cache", "%s", _( "bad parameters" ) ); return( -1 ); } if( im_piocheck( in, out ) || im_cp_desc( out, in ) || im_demand_hint( out, IM_SMALLTILE, in, NULL ) || !(read = read_new( in, out, tile_width, tile_height, max_tiles )) || im_generate( out, im_start_one, tile_cache_fill, im_stop_one, in, read ) ) return( -1 ); return( 0 ); }
/** * im_replicate: * @in: input image * @out: output image * @across: repeat @in this many times across * @down: repeat @in this many times down * * Replicate an image x times horizontally and vertically. * * See also: im_embed(), im_copy(). * * Returns: 0 on success, -1 on error. */ int im_replicate( IMAGE *in, IMAGE *out, int across, int down ) { if( across <= 0 || down <= 0 ) { im_error( "im_replicate", "%s", _( "bad parameters" ) ); return( -1 ); } if( im_piocheck( in, out ) || im_cp_desc( out, in ) ) return( -1 ); out->Xsize *= across; out->Ysize *= down; /* We can render small tiles with pointer copies. */ if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) return( -1 ); if( im_generate( out, im_start_one, replicate_gen, im_stop_one, in, NULL ) ) return( -1 ); return( 0 ); }
/** * im_magick2vips: * @filename: file to load * @out: image to write to * * Read in an image using libMagick, the ImageMagick library. This library can * read more than 80 file formats, including SVG, BMP, EPS, DICOM and many * others. * The reader can handle any ImageMagick image, including the float and double * formats. It will work with any quantum size, including HDR. Any metadata * attached to the libMagick image is copied on to the VIPS image. * * The reader should also work with most versions of GraphicsMagick. * * See also: #VipsFormat. * * Returns: 0 on success, -1 on error. */ int im_magick2vips( const char *filename, IMAGE *out ) { Read *read; if( !(read = read_new( filename, out )) ) return( -1 ); #ifdef HAVE_SETIMAGEOPTION /* When reading DICOM images, we want to ignore any * window_center/_width setting, since it may put pixels outside the * 0-65535 range and lose data. * * These window settings are attached as vips metadata, so our caller * can interpret them if it wants. */ SetImageOption( read->image_info, "dcm:display-range", "reset" ); #endif /*HAVE_SETIMAGEOPTION*/ read->image = ReadImage( read->image_info, &read->exception ); if( !read->image ) { im_error( "im_magick2vips", _( "unable to read file \"%s\"\n" "libMagick error: %s %s" ), filename, read->exception.reason, read->exception.description ); return( -1 ); } if( parse_header( read ) || im_poutcheck( out ) || im_demand_hint( out, IM_SMALLTILE, NULL ) || im_generate( out, NULL, magick_fill_region, NULL, read, NULL ) ) return( -1 ); return( 0 ); }
static int affinei( IMAGE *in, IMAGE *out, VipsInterpolate *interpolate, Transformation *trn ) { Affine *affine; double edge; /* Make output image. */ if( im_piocheck( in, out ) ) return( -1 ); if( im_cp_desc( out, in ) ) return( -1 ); /* Need a copy of the params for the lifetime of out. */ if( !(affine = IM_NEW( out, Affine )) ) return( -1 ); affine->interpolate = NULL; if( im_add_close_callback( out, (im_callback_fn) affine_free, affine, NULL ) ) return( -1 ); affine->in = in; affine->out = out; affine->interpolate = interpolate; g_object_ref( interpolate ); affine->trn = *trn; if( im__transform_calc_inverse( &affine->trn ) ) return( -1 ); out->Xsize = affine->trn.oarea.width; out->Ysize = affine->trn.oarea.height; /* Normally SMALLTILE ... except if this is a size up/down affine. */ if( affine->trn.b == 0.0 && affine->trn.c == 0.0 ) { if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); } else { if( im_demand_hint( out, IM_SMALLTILE, in, NULL ) ) return( -1 ); } /* Check for coordinate overflow ... we want to be able to hold the * output space inside INT_MAX / TRANSFORM_SCALE. */ edge = INT_MAX / VIPS_TRANSFORM_SCALE; if( affine->trn.oarea.left < -edge || affine->trn.oarea.top < -edge || IM_RECT_RIGHT( &affine->trn.oarea ) > edge || IM_RECT_BOTTOM( &affine->trn.oarea ) > edge ) { im_error( "im_affinei", "%s", _( "output coordinates out of range" ) ); return( -1 ); } /* Generate! */ if( im_generate( out, im_start_one, affinei_gen, im_stop_one, in, affine ) ) return( -1 ); return( 0 ); }
/* Dilate an image. */ int im_dilate_raw( IMAGE *in, IMAGE *out, INTMASK *m ) { INTMASK *msk; /* Check mask has odd number of elements in width and height. */ if( m->xsize < 1 || !(m->xsize & 0x1) || m->ysize < 1 || !(m->ysize & 0x1) ) { im_error( "im_dilate", _( "mask size not odd" ) ); return( -1 ); } /* Standard checks. */ if( im_piocheck( in, out ) ) return( -1 ); if( in->Coding != IM_CODING_NONE || in->Bbits != 8 || in->BandFmt != IM_BANDFMT_UCHAR ) { im_error( "im_dilate", _( "uchar uncoded only" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); /* Prepare output. Consider a 7x7 mask and a 7x7 image --- the output * would be 1x1. */ if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize -= m->xsize - 1; out->Ysize -= m->ysize - 1; if( out->Xsize <= 0 || out->Ysize <= 0 ) { im_error( "im_dilate", _( "image too small for mask" ) ); return( -1 ); } /* Take a copy of m. */ if( !(msk = im_dup_imask( m, "conv_mask" )) ) return( -1 ); if( im_add_close_callback( out, (im_callback_fn) im_free_imask, msk, NULL ) ) { im_free_imask( msk ); return( -1 ); } /* Set demand hints. FATSTRIP is good for us, as THINSTRIP will cause * too many recalculations on overlaps. */ if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); /* Generate! */ if( im_generate( out, dilate_start, dilate_gen, dilate_stop, in, msk ) ) return( -1 ); out->Xoffset = -m->xsize / 2; out->Yoffset = -m->ysize / 2; return( 0 ); }
int im_stretch3( IMAGE *in, IMAGE *out, double dx, double dy ) { StretchInfo *sin; int i; /* Check our args. */ if( in->Coding != IM_CODING_NONE || in->BandFmt != IM_BANDFMT_USHORT ) { im_error( "im_stretch3", "%s", _( "not uncoded unsigned short" ) ); return( -1 ); } if( dx < 0 || dx >= 1.0 || dy < 0 || dy >= 1.0 ) { im_error( "im_stretch3", "%s", _( "displacements out of range [0,1)" ) ); return( -1 ); } if( im_piocheck( in, out ) ) return( -1 ); /* Prepare the output image. */ if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = 34*(in->Xsize / 33) + in->Xsize%33 - 3; out->Ysize = in->Ysize - 3; if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) ) return( -1 ); if( !(sin = IM_NEW( out, StretchInfo )) ) return( -1 ); /* Save parameters. */ sin->in = in; sin->dx = dx; sin->dy = dy; /* Generate masks. */ for( i = 0; i < 34; i++ ) { double d = (34.0 - i)/34.0; double y0 = 2.0*d*d - d - d*d*d; double y1 = 1.0 - 2.0*d*d + d*d*d; double y2 = d + d*d - d*d*d; double y3 = -d*d + d*d*d; sin->mask[i][0] = IM_RINT( y0 * 32768 ); sin->mask[i][1] = IM_RINT( y1 * 32768 ); sin->mask[i][2] = IM_RINT( y2 * 32768 ); sin->mask[i][3] = IM_RINT( y3 * 32768 ); } /* Which mask do we start with to apply these offsets? */ sin->xoff = (dx * 33.0) + 0.5; sin->yoff = (dy * 33.0) + 0.5; if( im_generate( out, stretch_start, stretch_gen, stretch_stop, in, sin ) ) return( -1 ); return( 0 ); }
/** * im_subsample: * @in: input image * @out: output image * @xshrink: horizontal shrink factor * @yshrink: vertical shrink factor * * Subsample an image by an integer fraction. This is fast nearest-neighbour * shrink. * * See also: im_shrink(), im_affinei(), im_zoom(). * * Returns: 0 on success, -1 on error. */ int im_subsample( IMAGE *in, IMAGE *out, int xshrink, int yshrink ) { SubsampleInfo *st; /* Check parameters. */ if( xshrink < 1 || yshrink < 1 ) { im_error( "im_subsample", "%s", _( "factors should both be >= 1" ) ); return( -1 ); } if( xshrink == 1 && yshrink == 1 ) return( im_copy( in, out ) ); if( im_piocheck( in, out ) || im_check_coding_known( "im_subsample", in ) ) return( -1 ); /* Prepare output. Note: we round the output width down! */ if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = in->Xsize / xshrink; out->Ysize = in->Ysize / yshrink; out->Xres = in->Xres / xshrink; out->Yres = in->Yres / yshrink; if( out->Xsize <= 0 || out->Ysize <= 0 ) { im_error( "im_subsample", "%s", _( "image has shrunk to nothing" ) ); return( -1 ); } /* Build and attach state struct. */ if( !(st = IM_NEW( out, SubsampleInfo )) ) return( -1 ); st->xshrink = xshrink; st->yshrink = yshrink; /* Set demand hints. We want THINSTRIP, as we will be demanding a * large area of input for each output line. */ if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ) return( -1 ); /* Generate! If this is a very large shrink, then it's * probably faster to do it a pixel at a time. */ if( xshrink > 10 ) { if( im_generate( out, im_start_one, point_shrink_gen, im_stop_one, in, st ) ) return( -1 ); } else { if( im_generate( out, im_start_one, line_shrink_gen, im_stop_one, in, st ) ) return( -1 ); } return( 0 ); }
/* Plot image. */ static int plot( IMAGE *in, IMAGE *out ) { double max; int tsize; int xsize; int ysize; if( im_incheck( in ) || im_poutcheck( out ) ) return( -1 ); /* Find range we will plot. */ if( im_max( in, &max ) ) return( -1 ); g_assert( max >= 0 ); if( in->BandFmt == IM_BANDFMT_UCHAR ) tsize = 256; else tsize = ceil( max ); /* Make sure we don't make a zero height image. */ if( tsize == 0 ) tsize = 1; if( in->Xsize == 1 ) { /* Vertical graph. */ xsize = tsize; ysize = in->Ysize; } else { /* Horizontal graph. */ xsize = in->Xsize; ysize = tsize; } /* Set image. */ im_initdesc( out, xsize, ysize, in->Bands, IM_BBITS_BYTE, IM_BANDFMT_UCHAR, IM_CODING_NONE, IM_TYPE_HISTOGRAM, 1.0, 1.0, 0, 0 ); /* Set hints - ANY is ok with us. */ if( im_demand_hint( out, IM_ANY, NULL ) ) return( -1 ); /* Generate image. */ if( in->Xsize == 1 ) { if( im_generate( out, NULL, make_vert_gen, NULL, in, NULL ) ) return( -1 ); } else { if( im_generate( out, NULL, make_horz_gen, NULL, in, NULL ) ) return( -1 ); } return( 0 ); }