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 ); }
/** * 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_read_point: * @image: image to read from * @x: position to read * @y: position to read * @ink: read value here * * Reads a single point on an image. * * @ink is an array of bytes to contain a valid pixel for the image's format. * It must have at least IM_IMAGE_SIZEOF_PEL( @im ) bytes. * * See also: im_draw_point(). * * Returns: 0 on success, or -1 on error. */ int im_read_point( VipsImage *image, int x, int y, VipsPel *ink ) { REGION *reg; Rect area; if( im_check_coding_known( "im_draw_point", image ) || !(reg = im_region_create( image )) ) return( -1 ); area.left = x; area.top = y; area.width = 1; area.height = 1; if( im_prepare( reg, &area ) ) { im_region_free( reg ); return( -1 ); } memcpy( ink, IM_REGION_ADDR( reg, x, y ), IM_IMAGE_SIZEOF_PEL( image ) ); im_region_free( reg ); 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 ); }
/** * im_draw_point: * @image: image to draw on * @x: position to draw * @y: position to draw * @ink: value to draw * * Draws a single point on an image. * * @ink is an array of bytes containing a valid pixel for the image's format. * It must have at least IM_IMAGE_SIZEOF_PEL( @im ) bytes. * * See also: im_draw_line(). * * Returns: 0 on success, or -1 on error. */ int im_draw_point( VipsImage *image, int x, int y, VipsPel *ink ) { Point point; if( im_check_coding_known( "im_draw_point", image ) || im__draw_init( DRAW( &point ), image, NULL ) ) return( -1 ); /* Check coordinates. */ if( x >= 0 && x < image->Xsize && y >= 0 && y < image->Ysize ) memcpy( IM_IMAGE_ADDR( image, x, y ), ink, DRAW( image )->psize ); im__draw_free( DRAW( &point ) ); 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 ); }
/* The common part of most binary inplace operators. * * Unlike im__formatalike() and friends, we can only change one of the images, * since the other is being updated. */ VipsImage * im__inplace_base( const char *domain, VipsImage *main, VipsImage *sub, VipsImage *out ) { VipsImage *t[2]; if( im_rwcheck( main ) || im_pincheck( sub ) || im_check_coding_known( domain, main ) || im_check_coding_same( domain, main, sub ) || im_check_bands_1orn_unary( domain, sub, main->Bands ) ) return( NULL ); /* Cast sub to match main in bands and format. */ if( im_open_local_array( out, t, 2, domain, "p" ) || im__bandup( domain, sub, t[0], main->Bands ) || im_clip2fmt( t[0], t[1], main->BandFmt ) ) return( NULL ); return( t[1] ); }
/** * im_draw_rect: * @image: image to draw on * @left: area to paint * @top: area to paint * @width: area to paint * @height: area to paint * @fill: fill the rect * @ink: paint with this colour * * Paint pixels within @left, @top, @width, @height in @image with @ink. If * @fill is zero, just paint a 1-pixel-wide outline. * * See also: im_draw_circle(). * * Returns: 0 on success, or -1 on error. */ int im_draw_rect( IMAGE *image, int left, int top, int width, int height, int fill, VipsPel *ink ) { Rect im, rect, clipped; Draw draw; if( !fill ) return( im_draw_rect( image, left, top, width, 1, 1, ink ) || im_draw_rect( image, left + width - 1, top, 1, height, 1, ink ) || im_draw_rect( image, left, top + height - 1, width, 1, 1, ink ) || im_draw_rect( image, left, top, 1, height, 1, ink ) ); int x, y; VipsPel *to; VipsPel *q; /* Find area we plot. */ im.left = 0; im.top = 0; im.width = image->Xsize; im.height = image->Ysize; rect.left = left; rect.top = top; rect.width = width; rect.height = height; im_rect_intersectrect( &rect, &im, &clipped ); /* Any points left to plot? */ if( im_rect_isempty( &clipped ) ) return( 0 ); if( im_check_coding_known( "im_draw_rect", image ) || !im__draw_init( &draw, image, ink ) ) return( -1 ); /* We plot the first line pointwise, then memcpy() it for the * subsequent lines. */ to = IM_IMAGE_ADDR( image, clipped.left, clipped.top ); q = to; for( x = 0; x < clipped.width; x++ ) { im__draw_pel( &draw, q ); q += draw.psize; } q = to + draw.lsize; for( y = 1; y < clipped.height; y++ ) { memcpy( q, to, clipped.width * draw.psize ); q += draw.lsize; } im__draw_free( &draw ); 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 ); }