Example #1
0
static int
vips_bandary_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion **ir = (VipsRegion **) seq;
	VipsBandary *bandary = (VipsBandary *) b;
	VipsBandaryClass *class = VIPS_BANDARY_GET_CLASS( bandary ); 
	VipsRect *r = &or->valid;

	VipsPel *p[MAX_INPUT_IMAGES], *q;
	int y, i;

	for( i = 0; i < bandary->n; i++ ) {
		if( vips_region_prepare( ir[i], r ) )
			return( -1 );
		p[i] = VIPS_REGION_ADDR( ir[i], r->left, r->top );
	}
	p[i] = NULL;
	q = VIPS_REGION_ADDR( or, r->left, r->top );

	VIPS_GATE_START( "vips_bandary_gen: work" ); 

	for( y = 0; y < r->height; y++ ) {
		class->process_line( bandary, q, p, r->width );

		for( i = 0; i < bandary->n; i++ )
			p[i] += VIPS_REGION_LSKIP( ir[i] );
		q += VIPS_REGION_LSKIP( or );
	}

	VIPS_GATE_STOP( "vips_bandary_gen: work" ); 

	return( 0 );
}
Example #2
0
/* Paint the part of the region containing only whole pels.
 */
static void
vips_zoom_paint_whole( VipsRegion *or, VipsRegion *ir, VipsZoom *zoom,
	const int left, const int right, const int top, const int bottom )
{
	const int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im );
	const int ls = VIPS_REGION_LSKIP( or );
	const int rs = ps * (right - left);

	/* Transform to ir coordinates.
	 */
	const int ileft = left / zoom->xfac;
	const int iright = right / zoom->xfac;
	const int itop = top / zoom->yfac;
	const int ibottom = bottom / zoom->yfac;

	int x, y, z, i;

	/* We know this!
	 */
	g_assert( right > left && bottom > top && 
		right % zoom->xfac == 0 &&
		left % zoom->xfac == 0 &&
		top % zoom->yfac == 0 &&
		bottom % zoom->yfac == 0 );

	/* Loop over input, as we know we are all whole.
	 */
	for( y = itop; y < ibottom; y++ ) {
		VipsPel *p = VIPS_REGION_ADDR( ir, ileft, y );
		VipsPel *q = VIPS_REGION_ADDR( or, left, y * zoom->yfac );
		VipsPel *r;

		/* Expand the first line of pels.
		 */
		r = q;
		for( x = ileft; x < iright; x++ ) {
			/* Copy each pel xfac times.
			 */
			for( z = 0; z < zoom->xfac; z++ ) {
				for( i = 0; i < ps; i++ )
					r[i] = p[i];

				r += ps;
			}

			p += ps;
		}

		/* Copy the expanded line yfac-1 times.
		 */
		r = q + ls;
		for( z = 1; z < zoom->yfac; z++ ) {
			memcpy( r, q, rs );
			r += ls;
		}
	}
}
Example #3
0
static int
vips_flip_vertical_gen( VipsRegion *or, void *seq, void *a, void *b,
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsRect *r = &or->valid;
	VipsRect in;
	VipsPel *p, *q;
	int y;

	int le = r->left;
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM( r );

	int ls;
	int psk, qsk;

	/* Transform to input coordinates.
	 */
	in = *r;
	in.top = ir->im->Ysize - bo;

	/* Ask for input we need.
	 */
	if( vips_region_prepare( ir, &in ) )
		return( -1 );

	/* Loop, copying and reversing lines.
	 */
	p = VIPS_REGION_ADDR( ir, le, in.top + in.height - 1 );
	q = VIPS_REGION_ADDR( or, le, to );
	psk = VIPS_REGION_LSKIP( ir );
	qsk = VIPS_REGION_LSKIP( or );
	ls = VIPS_REGION_SIZEOF_LINE( or );

	for( y = to; y < bo; y++ ) {
		memcpy( q, p, ls );

		p -= psk;
		q += qsk;
	}

	return( 0 );
}
Example #4
0
/* Generate an area of @or. @ir is large enough.
 */
static void
vips_shrink2_gen2( VipsShrink2 *shrink, VipsShrink2Sequence *seq,
                   VipsRegion *or, VipsRegion *ir,
                   int left, int top, int width, int height )
{
    VipsResample *resample = VIPS_RESAMPLE( shrink );
    const int bands = resample->in->Bands;
    const int sizeof_pixel = VIPS_IMAGE_SIZEOF_PEL( resample->in );
    const int ls = VIPS_REGION_LSKIP( ir ) /
                   VIPS_IMAGE_SIZEOF_ELEMENT( resample->in );

    int x, y, i;
    int x1, y1, b;

    for( y = 0; y < height; y++ ) {
        VipsPel *out = VIPS_REGION_ADDR( or, left, top + y );

        for( x = 0; x < width; x++ ) {
            int ix = (left + x) * shrink->xshrink;
            int iy = (top + y) * shrink->yshrink;
            VipsPel *in = VIPS_REGION_ADDR( ir, ix, iy );

            switch( resample->in->BandFmt ) {
            case VIPS_FORMAT_UCHAR:
                ISHRINK( unsigned char );
                break;
            case VIPS_FORMAT_CHAR:
                ISHRINK( char );
                break;
            case VIPS_FORMAT_USHORT:
                ISHRINK( unsigned short );
                break;
            case VIPS_FORMAT_SHORT:
                ISHRINK( short );
                break;
            case VIPS_FORMAT_UINT:
                ISHRINK( unsigned int );
                break;
            case VIPS_FORMAT_INT:
                ISHRINK( int );
                break;
            case VIPS_FORMAT_FLOAT:
                FSHRINK( float );
                break;
            case VIPS_FORMAT_DOUBLE:
                FSHRINK( double );
                break;

            default:
                g_assert( 0 );
            }

            out += sizeof_pixel;
        }
    }
}
Example #5
0
static void
vips_fastcor_correlation( VipsCorrelation *correlation,
	VipsRegion *in, VipsRegion *out )
{
	VipsRect *r = &out->valid;
	VipsImage *ref = correlation->ref_ready;
	int bands = vips_band_format_iscomplex( ref->BandFmt ) ? 
		ref->Bands * 2 : ref->Bands; 
	int sz = ref->Xsize * bands; 
	int lsk = VIPS_REGION_LSKIP( in ) / VIPS_IMAGE_SIZEOF_ELEMENT( in->im );

	int x, y, i, j, b;

        switch( vips_image_get_format( ref ) ) {
        case VIPS_FORMAT_CHAR: 	
		CORR_INT( signed char ); 
		break; 

        case VIPS_FORMAT_UCHAR:	
		CORR_INT( unsigned char ); 
		break; 

        case VIPS_FORMAT_SHORT:	
		CORR_INT( signed short ); 
		break; 

        case VIPS_FORMAT_USHORT:
		CORR_INT( unsigned short ); 
		break; 

        case VIPS_FORMAT_INT: 	
		CORR_INT( signed int ); 
		break; 

        case VIPS_FORMAT_UINT: 	
		CORR_INT( unsigned int ); 
		break; 

        case VIPS_FORMAT_FLOAT:	
        case VIPS_FORMAT_COMPLEX: 
		CORR_FLOAT( float ); 
		break; 

        case VIPS_FORMAT_DOUBLE: 
        case VIPS_FORMAT_DPCOMPLEX: 
		CORR_FLOAT( double ); 
		break;

        default:
		g_assert_not_reached();
        }
}
Example #6
0
void
vips_executor_set_scanline( VipsExecutor *executor, 
	VipsRegion *ir, int x, int y )
{
	VipsVector *vector = executor->vector;
	VipsPel *base = VIPS_REGION_ADDR( ir, x, y );
	int lsk = VIPS_REGION_LSKIP( ir );

	int i;

	for( i = 0; i < vector->n_scanline; i++ ) 
		vips_executor_set_array( executor, 
			vector->sl[i], base + vector->line[i] * lsk );
}
Example #7
0
static int
vips_arithmetic_gen( VipsRegion *or,
                     void *seq, void *a, void *b, gboolean *stop )
{
    VipsRegion **ir = (VipsRegion **) seq;
    VipsArithmetic *arithmetic = VIPS_ARITHMETIC( b );
    VipsArithmeticClass *class = VIPS_ARITHMETIC_GET_CLASS( arithmetic );
    Rect *r = &or->valid;

    VipsPel *p[MAX_INPUT_IMAGES], *q;
    int i, y;

    /* Prepare all input regions and make buffer pointers.
     */
    for( i = 0; ir[i]; i++ ) {
        if( vips_region_prepare( ir[i], r ) )
            return( -1 );
        p[i] = (VipsPel *) VIPS_REGION_ADDR( ir[i], r->left, r->top );
    }
    p[i] = NULL;
    q = (VipsPel *) VIPS_REGION_ADDR( or, r->left, r->top );

    VIPS_GATE_START( "vips_arithmetic_gen: work" );

    for( y = 0; y < r->height; y++ ) {
        class->process_line( arithmetic, q, p, r->width );

        for( i = 0; ir[i]; i++ )
            p[i] += VIPS_REGION_LSKIP( ir[i] );
        q += VIPS_REGION_LSKIP( or );
    }

    VIPS_GATE_STOP( "vips_arithmetic_gen: work" );

    return( 0 );
}
Example #8
0
static int
vips_foreign_load_svg_generate( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsForeignLoadSvg *svg = (VipsForeignLoadSvg *) a;
	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( svg );
	VipsRect *r = &or->valid;

	cairo_surface_t *surface;
	cairo_t *cr;
	int y;

	/* rsvg won't always paint the background.
	 */
	vips_region_black( or ); 

	surface = cairo_image_surface_create_for_data( 
		VIPS_REGION_ADDR( or, r->left, r->top ), 
		CAIRO_FORMAT_ARGB32, 
		r->width, r->height, 
		VIPS_REGION_LSKIP( or ) );
	cr = cairo_create( surface );
	cairo_surface_destroy( surface );

	cairo_scale( cr, svg->cairo_scale, svg->cairo_scale );
	cairo_translate( cr, -r->left / svg->cairo_scale,
		-r->top / svg->cairo_scale );

	/* rsvg is single-threaded, but we don't need to lock since we're
	 * running inside a non-threaded tilecache.
	 */
	if( !rsvg_handle_render_cairo( svg->page, cr ) ) {
		vips_operation_invalidate( VIPS_OPERATION( svg ) );
		vips_error( class->nickname, 
			"%s", _( "SVG rendering failed" ) );
		return( -1 );
	}
Example #9
0
  const int iy = (int) (absolute_y + 0.5);

  /*
   * Move the pointer to (the first band of) the top/left pixel of the
   * 2x2 group of pixel centers which contains the sampling location
   * in its convex hull:
   */
  const VipsPel* restrict p = VIPS_REGION_ADDR( in, ix, iy );

  const double relative_x = absolute_x - ix;
  const double relative_y = absolute_y - iy;

  /*
   * VIPS versions of Nicolas's pixel addressing values.
   */
  const int lskip = VIPS_REGION_LSKIP( in ) / 
	  VIPS_IMAGE_SIZEOF_ELEMENT( in->im );

  /*
   * Double the bands for complex images to account for the real and
   * imaginary parts being computed independently:
   */
  const int actual_bands = in->im->Bands;
  const int bands =
    vips_band_format_iscomplex( in->im->BandFmt ) ? 
      2 * actual_bands : actual_bands;

  /* Confirm that absolute_x and absolute_y are >= 1, see above. 
   */
  g_assert( absolute_x >= 1.0 );
  g_assert( absolute_y >= 1.0 );
Example #10
0
static int
vips_embed_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsEmbed *embed = (VipsEmbed *) b;
	VipsRect *r = &or->valid;

	Rect ovl;
	int i;
	VipsPel *p;
	int plsk;

	/* Entirely within the input image? Generate the subimage and copy
	 * pointers.
	 */
	if( vips_rect_includesrect( &embed->rsub, r ) ) {
		VipsRect need;

		need = *r;
		need.left -= embed->x;
		need.top -= embed->y;
		if( vips_region_prepare( ir, &need ) ||
			vips_region_region( or, ir, r, need.left, need.top ) )
			return( -1 );

		return( 0 );
	}

	/* Does any of the input image appear in the area we have been asked 
	 * to make? Paste it in.
	 */
	vips_rect_intersectrect( r, &embed->rsub, &ovl );
	if( !vips_rect_isempty( &ovl ) ) {
		/* Paint the bits coming from the input image.
		 */
		ovl.left -= embed->x;
		ovl.top -= embed->y;
		if( vips_region_prepare_to( ir, or, &ovl, 
			ovl.left + embed->x, ovl.top + embed->y ) )
			return( -1 );
		ovl.left += embed->x;
		ovl.top += embed->y;
	}

	switch( embed->extend ) {
	case VIPS_EXTEND_BLACK:
	case VIPS_EXTEND_WHITE:
		VIPS_GATE_START( "vips_embed_gen: work1" );

		/* Paint the borders a solid value.
		 */
		for( i = 0; i < 8; i++ )
			vips_region_paint( or, &embed->border[i], 
				embed->extend == 0 ? 0 : 255 );

		VIPS_GATE_STOP( "vips_embed_gen: work1" );

		break;

	case VIPS_EXTEND_BACKGROUND:
		VIPS_GATE_START( "vips_embed_gen: work2" );

		/* Paint the borders a solid value.
		 */
		for( i = 0; i < 8; i++ )
			vips_region_paint_pel( or, &embed->border[i], 
				embed->ink ); 

		VIPS_GATE_STOP( "vips_embed_gen: work2" );

		break;

	case VIPS_EXTEND_COPY:
		/* Extend the borders.
		 */
		for( i = 0; i < 8; i++ ) {
			VipsRect todo;
			VipsRect edge;

			vips_rect_intersectrect( r, &embed->border[i], &todo );
			if( !vips_rect_isempty( &todo ) ) {
				vips_embed_find_edge( embed, &todo, i, &edge );

				/* Did we paint any of the input image? If we
				 * did, we can fetch the edge pixels from
				 * that.
				 */
				if( !vips_rect_isempty( &ovl ) ) {
					p = VIPS_REGION_ADDR( or, 
						edge.left, edge.top );
					plsk = VIPS_REGION_LSKIP( or );
				}
				else {
					/* No pixels painted ... fetch
					 * directly from the input image.
					 */
					edge.left -= embed->x;
					edge.top -= embed->y;
					if( vips_region_prepare( ir, &edge ) )
						return( -1 );
					p = VIPS_REGION_ADDR( ir,
						 edge.left, edge.top );
					plsk = VIPS_REGION_LSKIP( ir );
				}

				vips_embed_paint_edge( embed, 
					or, i, &todo, p, plsk );
			}
		}

		break;

	default:	
		g_assert( 0 );
	}

	return( 0 );
}
Example #11
0
static int
fits2vips_generate( VipsRegion *out, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsFits *fits = (VipsFits *) a;
	Rect *r = &out->valid;

	VipsPel *q;
	int z;
	int status;

	long fpixel[MAX_DIMENSIONS];
	long lpixel[MAX_DIMENSIONS];
	long inc[MAX_DIMENSIONS];

	status = 0;

	VIPS_DEBUG_MSG( "fits2vips_generate: "
		"generating left = %d, top = %d, width = %d, height = %d\n", 
		r->left, r->top, r->width, r->height );

	/* Special case: the region we are writing to is exactly the width we
	 * need, ie. we can read a rectangular area into it.
	 */
	if( VIPS_REGION_LSKIP( out ) == VIPS_REGION_SIZEOF_LINE( out ) ) {
		VIPS_DEBUG_MSG( "fits2vips_generate: block read\n" );

		for( z = 0; z < MAX_DIMENSIONS; z++ )
			fpixel[z] = 1;
		fpixel[0] = r->left + 1;
		fpixel[1] = r->top + 1;
		fpixel[2] = fits->band_select + 1;

		for( z = 0; z < MAX_DIMENSIONS; z++ )
			lpixel[z] = 1;
		lpixel[0] = VIPS_RECT_RIGHT( r );
		lpixel[1] = VIPS_RECT_BOTTOM( r );
		lpixel[2] = fits->band_select + 1;

		for( z = 0; z < MAX_DIMENSIONS; z++ )
			inc[z] = 1;

		q = VIPS_REGION_ADDR( out, r->left, r->top );

		/* Break on ffgsv() for this call.
		 */
		g_mutex_lock( fits->lock );
		if( fits_read_subset( fits->fptr, fits->datatype, 
			fpixel, lpixel, inc, 
			NULL, q, NULL, &status ) ) {
			vips_fits_error( status );
			g_mutex_unlock( fits->lock );
			return( -1 );
		}
		g_mutex_unlock( fits->lock );
	}
	else {
		int y;

		for( y = r->top; y < VIPS_RECT_BOTTOM( r ); y ++ ) {
			for( z = 0; z < MAX_DIMENSIONS; z++ )
				fpixel[z] = 1;
			fpixel[0] = r->left + 1;
			fpixel[1] = y + 1;
			fpixel[2] = fits->band_select + 1;

			for( z = 0; z < MAX_DIMENSIONS; z++ )
				lpixel[z] = 1;
			lpixel[0] = VIPS_RECT_RIGHT( r );
			lpixel[1] = y + 1;
			lpixel[2] = fits->band_select + 1;

			for( z = 0; z < MAX_DIMENSIONS; z++ )
				inc[z] = 1;

			q = VIPS_REGION_ADDR( out, r->left, y );

			/* Break on ffgsv() for this call.
			 */
			g_mutex_lock( fits->lock );
			if( fits_read_subset( fits->fptr, fits->datatype, 
				fpixel, lpixel, inc, 
				NULL, q, NULL, &status ) ) {
				vips_fits_error( status );
				g_mutex_unlock( fits->lock );
				return( -1 );
			}
			g_mutex_unlock( fits->lock );
		}
	}

	return( 0 );
}
Example #12
0
/* Paint the part of the region containing only part-pels.
 */
static void
vips_zoom_paint_part( VipsRegion *or, VipsRegion *ir, VipsZoom *zoom,
	const int left, const int right, const int top, const int bottom )
{
	const int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im );
	const int ls = VIPS_REGION_LSKIP( or );
	const int rs = ps * (right - left);

	/* Start position in input.
	 */
	const int ix = left / zoom->xfac;
	const int iy = top / zoom->yfac;

	/* Pels down to yfac boundary, pels down to bottom. Do the smallest of
	 * these for first y loop.
	 */
	const int ptbound = (iy + 1) * zoom->yfac - top;
	const int ptbot = bottom - top;

	int yt = VIPS_MIN( ptbound, ptbot );

	int x, y, z, i;

	/* Only know this.
	 */
	g_assert( right - left >= 0 && bottom - top >= 0 );

	/* Have to loop over output.
	 */
	for( y = top; y < bottom; ) {
		VipsPel *p = VIPS_REGION_ADDR( ir, ix, y / zoom->yfac );
		VipsPel *q = VIPS_REGION_ADDR( or, left, y );
		VipsPel *r;

		/* Output pels until we jump the input pointer.
		 */
		int xt = (ix + 1) * zoom->xfac - left;

		/* Loop for this output line.
		 */
		r = q;
		for( x = left; x < right; x++ ) {
			/* Copy 1 pel.
			 */
			for( i = 0; i < ps; i++ )
				r[i] = p[i];
			r += ps;

			/* Move input if on boundary.
			 */
			--xt;
			if( xt == 0 ) {
				xt = zoom->xfac;
				p += ps;
			}
		}

		/* Repeat that output line until the bottom of this pixel
		 * boundary, or we hit bottom.
		 */
		r = q + ls;
		for( z = 1; z < yt; z++ ) {
			memcpy( r, q, rs );
			r += ls;
		}

		/* Move y on by the number of lines we wrote.
		 */
		y += yt;

		/* Reset yt for next iteration.
		 */
		yt = zoom->yfac;
	}
}
Example #13
0
static void
vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
	void *out, VipsRegion *in, double x, double y )
{
	/* Find the mask index. We round-to-nearest, so we need to generate 
	 * indexes in 0 to VIPS_TRANSFORM_SCALE, 2^n + 1 values. We multiply 
	 * by 2 more than we need to, add one, mask, then shift down again to 
	 * get the extra range.
	 */
	const int sx = x * VIPS_TRANSFORM_SCALE * 2;
	const int sy = y * VIPS_TRANSFORM_SCALE * 2;

	const int six = sx & (VIPS_TRANSFORM_SCALE * 2 - 1);
	const int siy = sy & (VIPS_TRANSFORM_SCALE * 2 - 1);

	const int tx = (six + 1) >> 1;
	const int ty = (siy + 1) >> 1;

	/* We know x/y are always positive, so we can just (int) them. 
	 */
	const int ix = (int) x;
	const int iy = (int) y;

	/* Back and up one to get the top-left of the 4x4.
	 */
	const VipsPel *p = VIPS_REGION_ADDR( in, ix - 1, iy - 1 ); 

	/* Look up the tables we need.
	 */
	const int *cxi = vips_bicubic_matrixi[tx];
	const int *cyi = vips_bicubic_matrixi[ty];
	const double *cxf = vips_bicubic_matrixf[tx];
	const double *cyf = vips_bicubic_matrixf[ty];

	/* Pel size and line size.
	 */
	const int bands = in->im->Bands;
	const int lskip = VIPS_REGION_LSKIP( in );

	g_assert( ix - 1 >= in->valid.left );
	g_assert( iy - 1 >= in->valid.top );
	g_assert( ix + 2 < VIPS_RECT_RIGHT( &in->valid ) );
	g_assert( iy + 2 < VIPS_RECT_BOTTOM( &in->valid ) );

	/* Confirm that absolute_x and absolute_y are >= 1, because of
	 * window_offset.
	 */
	g_assert( x >= 1.0 );
	g_assert( y >= 1.0 );

#ifdef DEBUG
	printf( "vips_interpolate_bicubic_interpolate: %g %g\n", x, y );
	printf( "\tleft=%d, top=%d, width=%d, height=%d\n",
		ix - 1, iy - 1, 4, 4 );
	printf( "\tmaskx=%d, masky=%d\n", tx, ty );
#endif /*DEBUG*/

	switch( in->im->BandFmt ) {
	case VIPS_FORMAT_UCHAR:
		bicubic_unsigned_int_tab<unsigned char, UCHAR_MAX>(
			out, p, bands, lskip,
			cxi, cyi );

	/*

	   Handy for benchmarking

		bicubic_float_tab<unsigned char>(
			out, p, bands, lskip,
			cxf, cyf );

		bicubic_notab<unsigned char>(
			out, p, bands, lskip,
			x - ix, y - iy );

	 */

		break;

	case VIPS_FORMAT_CHAR:
		bicubic_signed_int_tab<signed char, SCHAR_MIN, SCHAR_MAX>(
			out, p, bands, lskip,
			cxi, cyi );
		break;

	case VIPS_FORMAT_USHORT:
		bicubic_unsigned_int_tab<unsigned short, USHRT_MAX>(
			out, p, bands, lskip,
			cxi, cyi );
		break;

	case VIPS_FORMAT_SHORT:
		bicubic_signed_int_tab<signed short, SHRT_MIN, SHRT_MAX>(
			out, p, bands, lskip,
			cxi, cyi );
		break;

	case VIPS_FORMAT_UINT:
		bicubic_float_tab<unsigned int>( out, p, bands, lskip,
			cxf, cyf );
		break;

	case VIPS_FORMAT_INT:
		bicubic_float_tab<signed int>( out, p, bands, lskip,
			cxf, cyf );
		break;

	case VIPS_FORMAT_FLOAT:
		bicubic_float_tab<float>( out, p, bands, lskip,
			cxf, cyf );
		break;

	case VIPS_FORMAT_DOUBLE:
		bicubic_notab<double>( out, p, bands, lskip,
			x - ix, y - iy );
		break;

	case VIPS_FORMAT_COMPLEX:
		bicubic_float_tab<float>( out, p, bands * 2, lskip,
			cxf, cyf );
		break;

	case VIPS_FORMAT_DPCOMPLEX:
		bicubic_notab<double>( out, p, bands * 2, lskip,
			x - ix, y - iy );
		break;

	default:
		break;
	}
}
Example #14
0
static int
vips_stdif_generate( VipsRegion *or, 
	void *vseq, void *a, void *b, gboolean *stop )
{
	VipsRect *r = &or->valid;
	VipsRegion *ir = (VipsRegion *) vseq;
	VipsImage *in = (VipsImage *) a;
	VipsStdif *stdif = (VipsStdif *) b;
	int bands = in->Bands; 
	int npel = stdif->width * stdif->width;

	VipsRect irect;
	int y;
	int lsk;
	int centre;			/* Offset to move to centre of window */

	/* What part of ir do we need?
	 */
	irect.left = or->valid.left;
	irect.top = or->valid.top;
	irect.width = or->valid.width + stdif->width;
	irect.height = or->valid.height + stdif->height;
	if( vips_region_prepare( ir, &irect ) )
		return( -1 );

	lsk = VIPS_REGION_LSKIP( ir );
	centre = lsk * (stdif->height / 2) + stdif->width / 2;

	for( y = 0; y < r->height; y++ ) {
		/* Get input and output pointers for this line.
		 */
		VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y );
		VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );

		double f1 = stdif->a * stdif->m0;
		double f2 = 1.0 - stdif->a;
		double f3 = stdif->b * stdif->s0;

		VipsPel *p1;
		int x, i, j, b;

		/* We will get int overflow for windows larger than about 256
		 * x 256, sadly.
		 */
		unsigned int sum[MAX_BANDS];
		unsigned int sum2[MAX_BANDS];

		/* Find sum, sum of squares for the start of this line.
		 */
		for( b = 0; b < bands; b++ ) {
			memset( sum, 0, bands * sizeof( unsigned int ) );
			memset( sum2, 0, bands * sizeof( unsigned int ) );
		}
		p1 = p;
		for( j = 0; j < stdif->height; j++ ) {
			i = 0;
			for( x = 0; x < stdif->width; x++ ) {
				for( b = 0; b < bands; b++ ) { 
					int t = p1[i++];

					sum[b] += t;
					sum2[b] += t * t;
				}
			}

			p1 += lsk;
		}

		/* Loop for output pels.
		 */
		for( x = 0; x < r->width; x++ ) {
			for( b = 0; b < bands; b++ ) { 
				/* Find stats.
				 */
				double mean = (double) sum[b] / npel;
				double var = (double) sum2[b] / npel - 
					(mean * mean);
				double sig = sqrt( var );

				/* Transform.
				 */
				double res = f1 + f2 * mean + 
					((double) p[centre] - mean) * 
					(f3 / (stdif->s0 + stdif->b * sig));

				/* And write.
				 */
				if( res < 0.0 )
					*q++ = 0;
				else if( res >= 256.0 )
					*q++ = 255;
				else
					*q++ = res + 0.5;

				/* Adapt sums - remove the pels from the left 
				 * hand column, add in pels for a new 
				 * right-hand column.
				 */
				p1 = p;
				for( j = 0; j < stdif->height; j++ ) {
					int t1 = p1[0];
					int t2 = p1[bands * stdif->width];

					sum[b] -= t1;
					sum2[b] -= t1 * t1;

					sum[b] += t2;
					sum2[b] += t2 * t2;

					p1 += lsk;
				}

				p += 1;
			}
		}
	}

	return( 0 );
}
Example #15
0
static int
vips_rot90_gen( VipsRegion *or, void *seq, void *a, void *b,
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsImage *in = (VipsImage *) a;

	/* Output area.
	 */
	VipsRect *r = &or->valid;
	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int x, y, i;

	/* Pixel geometry.
	 */
	int ps, ls;

	/* Find the area of the input image we need.
	 */
	VipsRect need;

	need.left = to;
	need.top = in->Ysize - ri;
	need.width = r->height;
	need.height = r->width;
	if( vips_region_prepare( ir, &need ) )
		return( -1 );
	
	/* Find PEL size and line skip for ir.
	 */
	ps = VIPS_IMAGE_SIZEOF_PEL( in );
	ls = VIPS_REGION_LSKIP( ir );

	/* Rotate the bit we now have.
	 */
	for( y = to; y < bo; y++ ) {
		/* Start of this output line.
		 */
		VipsPel *q = VIPS_REGION_ADDR( or, le, y );

		/* Corresponding position in ir.
		 */
		VipsPel *p = VIPS_REGION_ADDR( ir, 
			need.left + y - to, 
			need.top + need.height - 1 );

		for( x = le; x < ri; x++ ) {
			for( i = 0; i < ps; i++ )
				q[i] = p[i];

			q += ps;
			p -= ls;
		}
	}

	return( 0 );
}