예제 #1
0
파일: copy.c 프로젝트: kjell/libvips
/* Copy a small area.
 */
static int
vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
    VipsRegion *ir = (VipsRegion *) seq;
    VipsRect *r = &or->valid;
    VipsCopy *copy = (VipsCopy *) b;
    SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt];

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

    if( copy->swap && swap ) {
        int y;

        for( y = 0; y < r->height; y++ ) {
            VipsPel *p = VIPS_REGION_ADDR( ir,
                                           r->left, r->top + y );
            VipsPel *q = VIPS_REGION_ADDR( or,
                                           r->left, r->top + y );

            swap( p, q, r->width, copy->in );
        }
    }
    else
        /* Nothing to do, just copy with pointers.
         */
        if( vips_region_region( or, ir, r, r->left, r->top ) )
            return( -1 );

    return( 0 );
}
예제 #2
0
파일: colour.c 프로젝트: homerjam/libvips
static int
vips_colour_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion **ir = (VipsRegion **) seq;
	VipsColour *colour = VIPS_COLOUR( b ); 
	VipsColourClass *class = VIPS_COLOUR_GET_CLASS( colour ); 
	VipsRect *r = &or->valid;

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

	for( i = 0; ir[i]; i++ ) 
		if( vips_region_prepare( ir[i], r ) ) 
			return( -1 );

	VIPS_GATE_START( "vips_colour_gen: work" ); 

	for( y = 0; y < r->height; y++ ) {
		for( i = 0; ir[i]; i++ )
			p[i] = VIPS_REGION_ADDR( ir[i], r->left, r->top + y );
		p[i] = NULL;
		q = VIPS_REGION_ADDR( or, r->left, r->top + y );

		class->process_line( colour, q, p, r->width );
	}

	VIPS_GATE_STOP( "vips_colour_gen: work" ); 

	return( 0 );
}
예제 #3
0
파일: rot.c 프로젝트: achanda101/libvips
static int
vips_rot180_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;

	/* Pixel geometry.
	 */
	int ps;

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

	need.left = in->Xsize - ri;
	need.top = in->Ysize - bo;
	need.width = r->width;
	need.height = r->height;
	if( vips_region_prepare( ir, &need ) )
		return( -1 );

	/* Find PEL size and line skip for ir.
	 */
	ps = VIPS_IMAGE_SIZEOF_PEL( in );

	/* 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 + need.width - 1, 
			need.top + need.height - (y - to) - 1 );

		/* Blap across!
		 */
		for( x = le; x < ri; x++ ) {
			memcpy( q, p, ps );
			q += ps;
			p -= ps;
		}
	}

	return( 0 );
}
예제 #4
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 );
}
예제 #5
0
파일: shrink.c 프로젝트: achanda101/libvips
static int
vips_shrink_gen( VipsRegion *or, void *vseq, void *a, void *b, gboolean *stop )
{
	VipsShrinkSequence *seq = (VipsShrinkSequence *) vseq;
	VipsShrink *shrink = (VipsShrink *) b;
	VipsRegion *ir = seq->ir;
	VipsRect *r = &or->valid;

	/* How do we chunk up the image? We don't want to prepare the whole of
	 * the input region corresponding to *r since it could be huge. 
	 *
	 * Each pixel of *r will depend on roughly mw x mh
	 * pixels, so we walk *r in chunks which map to the tile size.
	 *
	 * Make sure we can't ask for a zero step.
	 *
	 * We don't chunk horizontally. We want "vips shrink x.jpg b.jpg 100
	 * 100" to run sequentially. If we chunk horizontally, we will fetch
	 * 100x100 lines from the top of the image, then 100x100 100 lines
	 * down, etc. for each thread, then when they've finished, fetch
	 * 100x100, 100 pixels across from the top of the image. This will
	 * break sequentiality. 
	 */
	int ystep = shrink->mh > VIPS__TILE_HEIGHT ? 
		1 : VIPS__TILE_HEIGHT / shrink->mh;

	int y;

#ifdef DEBUG
	printf( "vips_shrink_gen: generating %d x %d at %d x %d\n",
		r->width, r->height, r->left, r->top ); 
#endif /*DEBUG*/

	for( y = 0; y < r->height; y += ystep ) {
		/* Clip the this rect against the demand size.
		 */
		int height = VIPS_MIN( ystep, r->height - y );

		VipsRect s;

		s.left = r->left * shrink->xshrink;
		s.top = (r->top + y) * shrink->yshrink;
		s.width = ceil( r->width * shrink->xshrink );
		s.height = ceil( height * shrink->yshrink );
#ifdef DEBUG
		printf( "shrink_gen: requesting %d x %d at %d x %d\n",
			s.width, s.height, s.left, s.top ); 
#endif /*DEBUG*/
		if( vips_region_prepare( ir, &s ) )
			return( -1 );

		vips_shrink_gen2( shrink, seq, 
			or, ir, 
			r->left, r->top + y, r->width, height );
	}

	return( 0 );
}
예제 #6
0
static int
vips_msb_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsMsb *msb = (VipsMsb *) b;
	VipsConversion *conversion = (VipsConversion *) msb;
	VipsRect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM( r );
	int sz = r->width * conversion->out->Bands;

	int x, y, i;

	if( vips_region_prepare( ir, r ) )
		return( -1 );

	for( y = to; y < bo; y++ ) {
		VipsPel *p = VIPS_REGION_ADDR( ir, le, y ); 
		VipsPel *q = VIPS_REGION_ADDR( or, le, y ); 

		if( msb->in->Coding == VIPS_CODING_LABQ &&
			msb->band == -1 ) {
			/* LABQ, no sub-band select.
			 */
			for( x = 0; x < r->width; x++ ) {
				q[0] = p[0];
				q[1] = 0x80 ^ p[1];
				q[2] = 0x80 ^ p[2];

				q += 4;
				p += 3;
			}
		}
		else if( msb->sign ) {
			/* Copy, converting signed to unsigned.
			 */
			p += msb->offset;
			for( i = 0; i < sz; i++ ) {
				q[i] = 0x80 ^ *p;

				p += msb->instep;
			}
		}
		else {
			/* Just pick out bytes. 
			 */
			p += msb->offset;
			for( i = 0; i < sz; i++ ) {
				q[i] = *p;

				p += msb->instep;
			}
		}
	}

	return( 0 );
}
예제 #7
0
파일: flip.c 프로젝트: achanda101/libvips
static int
vips_flip_horizontal_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 x, y, z;

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

	int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im );	/* sizeof pel */

	int hgt = ir->im->Xsize - r->width;

	int lastx;

	/* Transform to input coordinates.
	 */
	in = *r;
	in.left = hgt - r->left;

	/* Find x of final pixel in input area.
	 */
	lastx = VIPS_RECT_RIGHT( &in ) - 1;

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

	/* Loop, copying and reversing lines.
	 */
	for( y = to; y < bo; y++ ) {
		p = VIPS_REGION_ADDR( ir, lastx, y );
		q = VIPS_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			/* Copy the pel.
			 */
			for( z = 0; z < ps; z++ )
				q[z] = p[z];

			/* Skip forwards in out, back in in.
			 */
			q += ps;
			p -= ps;
		}
	}

	return( 0 );
}
예제 #8
0
파일: shrink.c 프로젝트: sepastian/libvips
static int
vips_shrink_gen( VipsRegion *or, void *vseq, void *a, void *b, gboolean *stop )
{
	VipsShrinkSequence *seq = (VipsShrinkSequence *) vseq;
	VipsShrink *shrink = (VipsShrink *) b;
	VipsRegion *ir = seq->ir;
	VipsRect *r = &or->valid;

	/* How do we chunk up the image? We don't want to prepare the whole of
	 * the input region corresponding to *r since it could be huge. 
	 *
	 * Each pixel of *r will depend on roughly mw x mh
	 * pixels, so we walk *r in chunks which map to the tile size.
	 *
	 * Make sure we can't ask for a zero step.
	 */
	int xstep = shrink->mw > VIPS__TILE_WIDTH ? 
		1 : VIPS__TILE_WIDTH / shrink->mw;
	int ystep = shrink->mh > VIPS__TILE_HEIGHT ? 
		1 : VIPS__TILE_HEIGHT / shrink->mh;

	int x, y;

#ifdef DEBUG
	printf( "vips_shrink_gen: generating %d x %d at %d x %d\n",
		r->width, r->height, r->left, r->top ); 
#endif /*DEBUG*/

	for( y = 0; y < r->height; y += ystep )  
		for( x = 0; x < r->width; x += xstep ) { 
			/* Clip the this rect against the demand size.
			 */
			int width = VIPS_MIN( xstep, r->width - x );
			int height = VIPS_MIN( ystep, r->height - y );

			VipsRect s;

			s.left = (r->left + x) * shrink->xshrink;
			s.top = (r->top + y) * shrink->yshrink;
			s.width = ceil( width * shrink->xshrink );
			s.height = ceil( height * shrink->yshrink );
#ifdef DEBUG
			printf( "shrink_gen: requesting %d x %d at %d x %d\n",
				s.width, s.height, s.left, s.top ); 
#endif /*DEBUG*/
			if( vips_region_prepare( ir, &s ) )
				return( -1 );

			vips_shrink_gen2( shrink, seq, 
				or, ir, 
				r->left + x, r->top + y, width, height );
		}

	return( 0 );
}
예제 #9
0
파일: copy.c 프로젝트: jcupitt/libvips
static int
vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsRect *r = &or->valid;

	if( vips_region_prepare( ir, r ) ||
		vips_region_region( or, ir, r, r->left, r->top ) )
		return( -1 );

	return( 0 );
}
예제 #10
0
파일: shrinkh.c 프로젝트: songfj/libvips
static int
vips_shrinkh_gen( VipsRegion *or, void *vseq, 
	void *a, void *b, gboolean *stop )
{
	VipsShrinkhSequence *seq = (VipsShrinkhSequence *) vseq;
	VipsShrinkh *shrink = (VipsShrinkh *) b;
	VipsRegion *ir = seq->ir;
	VipsRect *r = &or->valid;

	int y;

	/* How do we chunk up the image? We don't want to prepare the whole of
	 * the input region corresponding to *r since it could be huge. 
	 *
	 * Request input a line at a time. 
	 *
	 * We don't chunk horizontally. We want "vips shrink x.jpg b.jpg 100
	 * 100" to run sequentially. If we chunk horizontally, we will fetch
	 * 100x100 lines from the top of the image, then 100x100 100 lines
	 * down, etc. for each thread, then when they've finished, fetch
	 * 100x100, 100 pixels across from the top of the image. This will
	 * break sequentiality. 
	 */

#ifdef DEBUG
	printf( "vips_shrinkh_gen: generating %d x %d at %d x %d\n",
		r->width, r->height, r->left, r->top ); 
#endif /*DEBUG*/

	for( y = 0; y < r->height; y ++ ) { 
		VipsRect s;

		s.left = r->left * shrink->xshrink;
		s.top = r->top + y;
		s.width = ceil( r->width * shrink->xshrink );
		s.height = 1;
#ifdef DEBUG
		printf( "shrinkh_gen: requesting line %d\n", s.top ); 
#endif /*DEBUG*/
		if( vips_region_prepare( ir, &s ) )
			return( -1 );

		VIPS_GATE_START( "vips_shrinkh_gen: work" ); 

		vips_shrinkh_gen2( shrink, seq, 
			or, ir, 
			r->left, r->top + y, r->width );

		VIPS_GATE_STOP( "vips_shrinkh_gen: work" ); 
	}

	return( 0 );
}
예제 #11
0
파일: subsample.c 프로젝트: gargsms/libvips
/* Fetch one pixel at a time ... good for very large shrinks.
 */
static int
vips_subsample_point_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsSubsample *subsample = (VipsSubsample *) b;
	VipsImage *in = (VipsImage *) a;
	VipsRect *r = &or->valid;
	int le = r->left;
	int ri = VIPS_RECT_RIGHT( r );
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM(r);
	int ps = VIPS_IMAGE_SIZEOF_PEL( in );

	VipsRect s;
	int x, y;
	int k;

	/* Loop down the region.
	 */
	for( y = to; y < bo; y++ ) {
		VipsPel *q = VIPS_REGION_ADDR( or, le, y );
		VipsPel *p;

		/* Loop across the region, in owidth sized pieces.
		 */
		for( x = le; x < ri; x++ ) {
			/* Ask for input.
			 */
			s.left = x * subsample->xfac;
			s.top = y * subsample->yfac;
			s.width = 1;
			s.height = 1;
			if( vips_region_prepare( ir, &s ) )
				return( -1 );

			/* Append new pels to output.
			 */
			p = VIPS_REGION_ADDR( ir, s.left, s.top );
			for( k = 0; k < ps; k++ )
				q[k] = p[k];
			q += ps;
		}
	}

	return( 0 );
}
예제 #12
0
파일: flip.c 프로젝트: achanda101/libvips
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 );
}
예제 #13
0
파일: sequential.c 프로젝트: alon/libvips
static int
vips_sequential_generate( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsSequential *sequential = (VipsSequential *) b;
        VipsRect *r = &or->valid;
	VipsRegion *ir = (VipsRegion *) seq;

	VIPS_DEBUG_MSG( "vips_sequential_generate %d\n", r->top );

	/* The y pos of the request must be the same as our current file
	 * position.
	 */
	if( r->top != sequential->y_pos ) {
		printf( "vips_sequential_generate: error -- "
			"at position %d in file, but position %d requested",
			sequential->y_pos, r->top );

		vips_error( "VipsSequential", 
			_( "non-sequential read --- "
			"at position %d in file, but position %d requested" ),
			sequential->y_pos, r->top );
		return( -1 );
	}

	/* We're inside a tilecache where tiles are the full image width, so
	 * this should always be true.
	 */
	g_assert( r->left == 0 );
	g_assert( r->width == or->im->Xsize );
	g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize );

	/* Pointer copy.
	 */
        if( vips_region_prepare( ir, r ) ||
		vips_region_region( or, ir, r, r->left, r->top ) )
                return( -1 );

	sequential->y_pos += r->height;

	return( 0 );
}
예제 #14
0
파일: insert.c 프로젝트: ImageKit/libvips
/* Trivial case: we just need pels from one of the inputs.
 */
static int
vips_insert_just_one( VipsRegion *or, VipsRegion *ir, int x, int y )
{
	VipsRect need;

	/* Find the part of pos we need.
	 */
	need = or->valid;
	need.left -= x;
	need.top -= y;
	if( vips_region_prepare( ir, &need ) )
		return( -1 );

	/* Attach our output to it.
	 */
	if( vips_region_region( or, ir, &or->valid, need.left, need.top ) )
		return( -1 );

	return( 0 );
}
예제 #15
0
파일: recomb.c 프로젝트: nrobidoux/libvips
static int
vips_recomb_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsRecomb *recomb = (VipsRecomb *) b;
	VipsImage *im = recomb->in;
	int mwidth = recomb->m->Xsize;
	int mheight = recomb->m->Ysize;

	int y, x, u, v;

	if( vips_region_prepare( ir, &or->valid ) ) 
		return( -1 );

	for( y = 0; y < or->valid.height; y++ ) {
		PEL *in = (PEL *) VIPS_REGION_ADDR( ir, 
			or->valid.left, or->valid.top + y );
		PEL *out = (PEL *) VIPS_REGION_ADDR( or, 
			or->valid.left, or->valid.top + y );

		switch( vips_image_get_format( im ) ) {
		case VIPS_FORMAT_UCHAR: LOOP( unsigned char, float ); break;
		case VIPS_FORMAT_CHAR: 	LOOP( signed char, float ); break; 
		case VIPS_FORMAT_USHORT:LOOP( unsigned short, float ); break; 
		case VIPS_FORMAT_SHORT: LOOP( signed short, float ); break; 
		case VIPS_FORMAT_UINT: 	LOOP( unsigned int, float ); break; 
		case VIPS_FORMAT_INT: 	LOOP( signed int, float );  break; 
		case VIPS_FORMAT_FLOAT: LOOP( float, float ); break; 
		case VIPS_FORMAT_DOUBLE:LOOP( double, double ); break; 

		default:
			g_assert( 0 );
		}
	}

	return( 0 );
}
예제 #16
0
파일: byteswap.c 프로젝트: Jondeen/libvips
/* Byteswap, turning bands into the x axis.
 */
static int
vips_byteswap_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsImage *im = ir->im;
	VipsRect *r = &or->valid;
	SwapFn swap = vips_byteswap_swap_fn[im->BandFmt];

	int y;

	if( vips_region_prepare( ir, r ) )
		return( -1 );

	for( y = 0; y < r->height; y++ ) {
		VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y );
		VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );

		swap( p, q, r->width, im );
	}

	return( 0 );
}
예제 #17
0
파일: arithmetic.c 프로젝트: imclab/libvips
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 );
}
예제 #18
0
파일: maplut.c 프로젝트: jcupitt/libvips
/* Do a map.
 */
static int 
vips_maplut_gen( VipsRegion *or, void *vseq, void *a, void *b, 
	gboolean *stop )
{
	VipsMaplutSequence *seq = (VipsMaplutSequence *) vseq;
	VipsImage *in = (VipsImage *) a;
	VipsMaplut *maplut = (VipsMaplut *) b;
	VipsRegion *ir = seq->ir;
	VipsRect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM( r );
	int np = r->width;			/* Pels across region */
	int ne = VIPS_REGION_N_ELEMENTS( or );	/* Number of elements */

	int x, y, z, i;

	if( vips_region_prepare( ir, r ) )
		return( -1 );

	if( maplut->nb == 1 )
		/* One band lut.
		 */
		outer_switch( loop1, loop1c, loop1g, loop1cg ) 
	else 
		/* Many band lut.
		 */
		if( in->Bands == 1 )
			/* ... but 1 band input.
			 */
			outer_switch( loop1m, loop1cm, loop1gm, loop1cgm ) 
		else
			outer_switch( loop, loopc, loopg, loopcg )

	return( 0 );
}
예제 #19
0
static int
vips_bandunfold_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsBandunfold *bandunfold = (VipsBandunfold *) b;
	VipsRegion *ir = (VipsRegion *) seq;
	VipsImage *in = ir->im;
	VipsImage *out = or->im;
	VipsRect *r = &or->valid;
	int esize = VIPS_IMAGE_SIZEOF_ELEMENT( in );
	int psize = VIPS_IMAGE_SIZEOF_PEL( out );

	VipsRect need;
	int y;

	need.left = r->left / bandunfold->factor;
	need.top = r->top;
	need.width = (1 + r->width) / bandunfold->factor;
	need.height = r->height;
	if( vips_region_prepare( ir, &need ) )
		return( -1 );

	for( y = 0; y < r->height; y++ ) {
		VipsPel *p = VIPS_REGION_ADDR( ir, 
			r->left / bandunfold->factor, r->top + y ) + 
			(r->left % bandunfold->factor) * esize;
		VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y );

		/* We can't use vips_region_region() since we change pixel
		 * coordinates.
		 */
		memcpy( q, p, r->width * psize );
	}

	return( 0 );
}
예제 #20
0
파일: extract.c 프로젝트: xuxiandi/libvips
/* Extract an area. Can just use pointers.
 */
static int
vips_extract_area_gen( VipsRegion *or, void *seq, void *a, void *b, 
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsExtractArea *extract = (VipsExtractArea *) b;
	VipsRect iarea;

	/* Ask for input we need. Translate from demand in or's space to
	 * demand in ir's space.
	 */
	iarea = or->valid;
	iarea.left += extract->left;
	iarea.top += extract->top;
	if( vips_region_prepare( ir, &iarea ) )
		return( -1 );

	/* Attach or to ir.
	 */
	if( vips_region_region( or, ir, &or->valid, iarea.left, iarea.top ) )
		return( -1 );
	
	return( 0 );
}
예제 #21
0
파일: replicate.c 프로젝트: alon/libvips
static int
vips_replicate_gen( VipsRegion *or, void *seq, void *a, void *b, 
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsImage *in = (VipsImage *) a;
	VipsRect *r = &or->valid;
	int twidth = in->Xsize;
	int theight = in->Ysize;

	int x, y;
	VipsRect tile;

	/* Find top left of tiles we need.
	 */
	int xs = (r->left / twidth) * twidth;
	int ys = (r->top / theight) * theight;

	/* The tile enclosing the top-left corner of the requested area.
	 */
	tile.left = xs;
	tile.top = ys;
	tile.width = twidth;
	tile.height = theight;

	/* If the request fits inside a single tile, we can just pointer-copy.
	 */
	if( vips_rect_includesrect( &tile, r ) ) {
		VipsRect irect;

		/* Translate request to input space.
		 */
		irect = *r;
		irect.left -= xs;
		irect.top -= ys;
		if( vips_region_prepare( ir, &irect ) )
			return( -1 );

		if( vips_region_region( or, ir, r, irect.left, irect.top ) )
			return( -1 );

		return( 0 );
	}

	for( y = ys; y < VIPS_RECT_BOTTOM( r ); y += theight )
		for( x = xs; x < VIPS_RECT_RIGHT( r ); x += twidth ) {
			VipsRect paint;

			/* Whole tile at x, y
			 */
			tile.left = x;
			tile.top = y;
			tile.width = twidth;
			tile.height = theight;

			/* Which parts touch the area of the output we are
			 * building.
			 */
			vips_rect_intersectrect( &tile, r, &paint );

			/* Translate back to ir coordinates.
			 */
			paint.left -= x;
			paint.top -= y;

			g_assert( !vips_rect_isempty( &paint ) );

			/* Render into or.
			 */
			if( vips_region_prepare_to( ir, or, &paint,
				paint.left + x,
				paint.top + y ) )
				return( -1 );
		}

	return( 0 );
}
예제 #22
0
파일: subsample.c 프로젝트: gargsms/libvips
/* Subsample a VipsRegion. We fetch in VIPS_MAX_WIDTH pixel-wide strips, 
 * left-to-right across the input.
 */
static int
vips_subsample_line_gen( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsSubsample *subsample = (VipsSubsample *) b;
	VipsImage *in = (VipsImage *) a;
	VipsRect *r = &or->valid;
	int le = r->left;
	int ri = VIPS_RECT_RIGHT( r );
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM( r );
	int ps = VIPS_IMAGE_SIZEOF_PEL( in );
	int owidth = VIPS_MAX_WIDTH / subsample->xfac;

	VipsRect s;
	int x, y;
	int z, k;

	/* Loop down the region.
	 */
	for( y = to; y < bo; y++ ) {
		VipsPel *q = VIPS_REGION_ADDR( or, le, y );
		VipsPel *p;

		/* Loop across the region, in owidth sized pieces.
		 */
		for( x = le; x < ri; x += owidth ) {
			/* How many pixels do we make this time?
			 */
			int ow = VIPS_MIN( owidth, ri - x );

			/* Ask for this many from input ... can save a 
			 * little here!
			 */
			int iw = ow * subsample->xfac - (subsample->xfac - 1);

			/* Ask for input.
			 */
			s.left = x * subsample->xfac;
			s.top = y * subsample->yfac;
			s.width = iw;
			s.height = 1;
			if( vips_region_prepare( ir, &s ) )
				return( -1 );

			/* Append new pels to output.
			 */
			p = VIPS_REGION_ADDR( ir, s.left, s.top );
			for( z = 0; z < ow; z++ ) {
				for( k = 0; k < ps; k++ )
					q[k] = p[k];

				q += ps;
				p += ps * subsample->xfac;
			}
		}
	}

	return( 0 );
}
예제 #23
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 );
}
예제 #24
0
파일: affine.c 프로젝트: Jondeen/libvips
static int
vips_affine_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	const VipsAffine *affine = (VipsAffine *) b;
	const VipsImage *in = (VipsImage *) a;
	const int window_size = 
		vips_interpolate_get_window_size( affine->interpolate );
	const int window_offset = 
		vips_interpolate_get_window_offset( affine->interpolate );
	const VipsInterpolateMethod interpolate = 
		vips_interpolate_get_method( affine->interpolate );

	/* Area we generate in the output image.
	 */
	const VipsRect *r = &or->valid;
	const int le = r->left;
	const int ri = VIPS_RECT_RIGHT( r );
	const int to = r->top;
	const int bo = VIPS_RECT_BOTTOM( r );

	const VipsRect *iarea = &affine->trn.iarea;
	const VipsRect *oarea = &affine->trn.oarea;

	int ps = VIPS_IMAGE_SIZEOF_PEL( in );
	int x, y, z;
	
	VipsRect image, want, need, clipped;

#ifdef DEBUG_VERBOSE
	printf( "vips_affine_gen: "
		"generating left=%d, top=%d, width=%d, height=%d\n", 
		r->left,
		r->top,
		r->width,
		r->height );
#endif /*DEBUG_VERBOSE*/

	/* We are generating this chunk of the transformed image. This takes
	 * us to space 4.
	 */
	want = *r;
	want.left += oarea->left;
	want.top += oarea->top;

	/* Find the area of the input image we need. This takes us to space 3. 
	 */
	vips__transform_invert_rect( &affine->trn, &want, &need );

	/* That does round-to-nearest, because it has to stop rounding errors
	 * growing images unexpectedly. We need round-down, so we must
	 * add half a pixel along the left and top. But we are int :( so add 1
	 * pixel. 
	 *
	 * Add an extra line along the right and bottom as well, for rounding.
	 */
	vips_rect_marginadjust( &need, 1 );

	/* We need to fetch a larger area for the interpolator.
	 */
	need.left -= window_offset;
	need.top -= window_offset;
	need.width += window_size - 1;
	need.height += window_size - 1;

	/* Now go to space 2, the expanded input image. This is the one we
	 * read pixels from. 
	 */
	need.left += window_offset;
	need.top += window_offset;

	/* Clip against the size of (2).
	 */
	image.left = 0;
	image.top = 0;
	image.width = in->Xsize;
	image.height = in->Ysize;
	vips_rect_intersectrect( &need, &image, &clipped );

#ifdef DEBUG_VERBOSE
	printf( "vips_affine_gen: "
		"preparing left=%d, top=%d, width=%d, height=%d\n", 
		clipped.left,
		clipped.top,
		clipped.width,
		clipped.height );
#endif /*DEBUG_VERBOSE*/

	if( vips_rect_isempty( &clipped ) ) {
		vips_region_black( or );
		return( 0 );
	}
	if( vips_region_prepare( ir, &clipped ) )
		return( -1 );

	VIPS_GATE_START( "vips_affine_gen: work" ); 

	/* Resample! x/y loop over pixels in the output image (5).
	 */
	for( y = to; y < bo; y++ ) {
		/* Input clipping rectangle. We offset this so we can clip in
		 * space 2. 
		 */
		const int ile = iarea->left + window_offset;
		const int ito = iarea->top + window_offset;
		const int iri = ile + iarea->width;
		const int ibo = ito + iarea->height;

		/* Derivative of matrix.
		 */
		const double ddx = affine->trn.ia;
		const double ddy = affine->trn.ic;

		/* Continuous cods in transformed space.
		 */
		const double ox = le + oarea->left - affine->trn.odx;
		const double oy = y + oarea->top - affine->trn.ody;

		/* Continuous cods in input space.
		 */
		double ix, iy;

		VipsPel *q;

		/* To (3).
		 */
		ix = affine->trn.ia * ox + affine->trn.ib * oy;
		iy = affine->trn.ic * ox + affine->trn.id * oy;

		/* And the input offset in (3). 
		 */
		ix -= affine->trn.idx;
		iy -= affine->trn.idy;

		/* Finally to 2. 
		 */
		ix += window_offset;
		iy += window_offset;

		q = VIPS_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			int fx, fy; 	

			fx = FAST_PSEUDO_FLOOR( ix );
			fy = FAST_PSEUDO_FLOOR( iy );

			/* Clip against iarea.
			 */
			if( fx >= ile &&
				fx < iri &&
				fy >= ito &&
				fy < ibo ) {
				/* Verify that we can read the whole stencil.
				 * With DEBUG on this will range-check.
				 */
				g_assert( VIPS_REGION_ADDR( ir, 
					(int) ix - window_offset,
					(int) iy - window_offset ) );
				g_assert( VIPS_REGION_ADDR( ir, 
					(int) ix - window_offset + 
						window_size - 1,
					(int) iy - window_offset + 
						window_size - 1 ) );

				interpolate( affine->interpolate, 
					q, ir, ix, iy );
			}
			else {
				for( z = 0; z < ps; z++ ) 
					q[z] = 0;
			}

			ix += ddx;
			iy += ddy;
			q += ps;
		}
	}

	VIPS_GATE_STOP( "vips_affine_gen: work" ); 

	return( 0 );
}
예제 #25
0
파일: flatten.c 프로젝트: Fasjul/libvips
/* Any background.
 */
static int
vips_flatten_gen( VipsRegion *or, void *vseq, void *a, void *b,
	gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) vseq;
	VipsFlatten *flatten = (VipsFlatten *) b;
	VipsRect *r = &or->valid;
	int width = r->width;
	int bands = ir->im->Bands; 
	double max_alpha = flatten->max_alpha;

	int x, y;

	if( vips_region_prepare( ir, r ) )
		return( -1 );

	for( y = 0; y < r->height; y++ ) {
		VipsPel *in = VIPS_REGION_ADDR( ir, r->left, r->top + y ); 
		VipsPel *out = VIPS_REGION_ADDR( or, r->left, r->top + y ); 

		switch( flatten->in->BandFmt ) { 
		case VIPS_FORMAT_UCHAR: 
			VIPS_FLATTEN( unsigned char ); 
			break; 

		case VIPS_FORMAT_CHAR: 
			VIPS_FLATTEN( signed char ); 
			break; 

		case VIPS_FORMAT_USHORT: 
			VIPS_FLATTEN( unsigned short ); 
			break; 

		case VIPS_FORMAT_SHORT: 
			VIPS_FLATTEN( signed short ); 
			break; 

		case VIPS_FORMAT_UINT: 
			VIPS_FLATTEN_FLOAT( unsigned int ); 
			break; 

		case VIPS_FORMAT_INT: 
			VIPS_FLATTEN_FLOAT( signed int ); 
			break; 

		case VIPS_FORMAT_FLOAT: 
			VIPS_FLATTEN_FLOAT( float ); 
			break; 

		case VIPS_FORMAT_DOUBLE: 
			VIPS_FLATTEN_FLOAT( double ); 
			break; 

		case VIPS_FORMAT_COMPLEX: 
		case VIPS_FORMAT_DPCOMPLEX: 
		default: 
			g_assert_not_reached(); 
		} 
	}

	return( 0 );
}
예제 #26
0
static int
vips_premultiply_gen( VipsRegion *or, void *vseq, void *a, void *b,
	gboolean *stop )
{
	VipsPremultiply *premultiply = (VipsPremultiply *) b;
	VipsRegion *ir = (VipsRegion *) vseq;
	VipsImage *im = ir->im;
	VipsRect *r = &or->valid;
	int width = r->width;
	int bands = im->Bands; 
	double max_alpha = premultiply->max_alpha;

	int x, y, i;

	if( vips_region_prepare( ir, r ) )
		return( -1 );

	for( y = 0; y < r->height; y++ ) {
		VipsPel *in = VIPS_REGION_ADDR( ir, r->left, r->top + y ); 
		VipsPel *out = VIPS_REGION_ADDR( or, r->left, r->top + y ); 

		switch( im->BandFmt ) { 
		case VIPS_FORMAT_UCHAR: 
			PRE( unsigned char, float ); 
			break; 

		case VIPS_FORMAT_CHAR: 
			PRE( signed char, float ); 
			break; 

		case VIPS_FORMAT_USHORT: 
			PRE( unsigned short, float ); 
			break; 

		case VIPS_FORMAT_SHORT: 
			PRE( signed short, float ); 
			break; 

		case VIPS_FORMAT_UINT: 
			PRE( unsigned int, float ); 
			break; 

		case VIPS_FORMAT_INT: 
			PRE( signed int, float ); 
			break; 

		case VIPS_FORMAT_FLOAT: 
			PRE( float, float ); 
			break; 

		case VIPS_FORMAT_DOUBLE: 
			PRE( double, double ); 
			break; 

		case VIPS_FORMAT_COMPLEX: 
		case VIPS_FORMAT_DPCOMPLEX: 
		default: 
			g_assert( 0 ); 
		} 
	}

	return( 0 );
}
예제 #27
0
/* Zoom a VipsRegion.
 */
static int
vips_zoom_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRegion *ir = (VipsRegion *) seq;
	VipsZoom *zoom = (VipsZoom *) b;

	/* Output area we are building.
	 */
	const VipsRect *r = &or->valid;
	const int ri = VIPS_RECT_RIGHT( r );
	const int bo = VIPS_RECT_BOTTOM(r);

	VipsRect s;
	int left, right, top, bottom;
	int width, height;

	/* Area of input we need. We have to round out, as we may have
	 * part-pixels all around the edges.
	 */
	left = ROUND_DOWN( r->left, zoom->xfac );
	right = ROUND_UP( ri, zoom->xfac );
	top = ROUND_DOWN( r->top, zoom->yfac );
	bottom = ROUND_UP( bo, zoom->yfac );
	width = right - left;
	height = bottom - top;
	s.left = left / zoom->xfac;
	s.top = top / zoom->yfac;
	s.width = width / zoom->xfac;
	s.height = height / zoom->yfac;
	if( vips_region_prepare( ir, &s ) )
		return( -1 );
	
	/* Find the part of the output (if any) which uses only whole pels.
	 */
	left = ROUND_UP( r->left, zoom->xfac );
	right = ROUND_DOWN( ri, zoom->xfac );
	top = ROUND_UP( r->top, zoom->yfac );
	bottom = ROUND_DOWN( bo, zoom->yfac );
	width = right - left;
	height = bottom - top;

	/* Stage 1: we just paint the whole pels in the centre of the region.
	 * As we know they are not clipped, we can do it quickly.
	 */
	if( width > 0 && height > 0 ) 
		vips_zoom_paint_whole( or, ir, zoom, left, right, top, bottom );

	/* Just fractional pixels left. Paint in the top, left, right and
	 * bottom parts.
	 */
	if( top - r->top > 0 ) 
		/* Some top pixels.
		 */
		vips_zoom_paint_part( or, ir, zoom, 
			r->left, ri, r->top, VIPS_MIN( top, bo ) );
	if( left - r->left > 0 && height > 0 )
		/* Left pixels.
		 */
		vips_zoom_paint_part( or, ir, zoom, 
			r->left, VIPS_MIN( left, ri ), top, bottom );
	if( ri - right > 0 && height > 0 )
		/* Right pixels.
		 */
		vips_zoom_paint_part( or, ir, zoom, 
			VIPS_MAX( right, r->left ), ri, top, bottom );
	if( bo - bottom > 0 && height >= 0 )
		/* Bottom pixels.
		 */
		vips_zoom_paint_part( or, ir, zoom, 
			r->left, ri, VIPS_MAX( bottom, r->top ), bo );

	return( 0 );
}
예제 #28
0
파일: mapim.c 프로젝트: lovell/libvips
static int
vips_mapim_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
	VipsRect *r = &or->valid;
	VipsRegion **ir = (VipsRegion **) seq;
	const VipsImage **in_array = (const VipsImage **) a;
	const VipsMapim *mapim = (VipsMapim *) b; 
	const VipsResample *resample = VIPS_RESAMPLE( mapim );
	const VipsImage *in = in_array[0];
	const int window_size = 
		vips_interpolate_get_window_size( mapim->interpolate );
	const int window_offset = 
		vips_interpolate_get_window_offset( mapim->interpolate );
	const VipsInterpolateMethod interpolate = 
		vips_interpolate_get_method( mapim->interpolate );
	const int ps = VIPS_IMAGE_SIZEOF_PEL( in );
	const int clip_width = resample->in->Xsize;
	const int clip_height = resample->in->Ysize;

	VipsRect bounds, image, clipped;
	int x, y, z;
	
#ifdef DEBUG_VERBOSE
	printf( "vips_mapim_gen: "
		"generating left=%d, top=%d, width=%d, height=%d\n", 
		r->left,
		r->top,
		r->width,
		r->height );
#endif /*DEBUG_VERBOSE*/

	/* Fetch the chunk of the mapim image we need, and find the max/min in
	 * x and y.
	 */
	if( vips_region_prepare( ir[1], r ) )
		return( -1 );

	VIPS_GATE_START( "vips_mapim_gen: work" ); 

	vips_mapim_region_minmax( ir[1], r, &bounds ); 

	VIPS_GATE_STOP( "vips_mapim_gen: work" ); 

	/* The bounding box of that area is what we will need from @in. Add
	 * enough for the interpolation stencil as well.
	 * 
	 */
	bounds.width += window_size - 1;
	bounds.height += window_size - 1;

	/* Clip against the expanded image.
	 */
	image.left = 0;
	image.top = 0;
	image.width = in->Xsize;
	image.height = in->Ysize;
	vips_rect_intersectrect( &bounds, &image, &clipped );

#ifdef DEBUG_VERBOSE
	printf( "vips_mapim_gen: "
		"preparing left=%d, top=%d, width=%d, height=%d\n", 
		clipped.left,
		clipped.top,
		clipped.width,
		clipped.height );
#endif /*DEBUG_VERBOSE*/

	if( vips_rect_isempty( &clipped ) ) {
		vips_region_black( or );
		return( 0 );
	}
	if( vips_region_prepare( ir[0], &clipped ) )
		return( -1 );

	VIPS_GATE_START( "vips_mapim_gen: work" ); 

	/* Resample! x/y loop over pixels in the output image (5).
	 */
	for( y = 0; y < r->height; y++ ) {
		VipsPel * restrict p = 
			VIPS_REGION_ADDR( ir[1], r->left, y + r->top );
		VipsPel * restrict q = 
			VIPS_REGION_ADDR( or, r->left, y + r->top );

		switch( ir[1]->im->BandFmt ) {
		case VIPS_FORMAT_UCHAR: 	
			ULOOKUP( unsigned char ); break; 
		case VIPS_FORMAT_CHAR: 	
			LOOKUP( signed char ); break; 
		case VIPS_FORMAT_USHORT: 
			ULOOKUP( unsigned short ); break; 
		case VIPS_FORMAT_SHORT: 	
			LOOKUP( signed short ); break; 
		case VIPS_FORMAT_UINT: 	
			ULOOKUP( unsigned int ); break; 
		case VIPS_FORMAT_INT: 	
			LOOKUP( signed int ); break; 

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

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

		default:
			g_assert_not_reached();
		}
	}

	VIPS_GATE_STOP( "vips_mapim_gen: work" ); 

	return( 0 );
}
예제 #29
0
static int
vips_ifthenelse_gen( VipsRegion *or, void *seq, void *client1, void *client2,
	gboolean *stop )
{
	VipsRegion **ir = (VipsRegion **) seq;
	VipsIfthenelse *ifthenelse = (VipsIfthenelse *) client2;
	VipsRect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = VIPS_RECT_BOTTOM( r );

	VipsImage *c = ir[2]->im;
	VipsImage *a = ir[0]->im;

	int size, width;
	int i, x, y, z;

	int all0, alln0;

	if( c->Bands == 1 ) {
		/* Copying PEL-sized units with a one-band conditional.
		 */
		size = VIPS_IMAGE_SIZEOF_PEL( a );
		width = r->width;
	}
	else {
		/* Copying ELEMENT sized-units with an n-band conditional.
		 */
		size = VIPS_IMAGE_SIZEOF_ELEMENT( a );
		width = r->width * a->Bands;
	}

	if( vips_region_prepare( ir[2], r ) )
		return( -1 );

	/* Is the conditional all zero or all non-zero? We can avoid asking
	 * for one of the inputs to be calculated.
	 */
	all0 = *((PEL *) VIPS_REGION_ADDR( ir[2], le, to )) == 0;
	alln0 = *((PEL *) VIPS_REGION_ADDR( ir[2], le, to )) != 0;
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) VIPS_REGION_ADDR( ir[2], le, y );

		for( x = 0; x < width; x++ ) {
			all0 &= p[x] == 0;
			alln0 &= p[x] != 0;
		}

		if( !all0 && !alln0 )
			break;
	}

	if( alln0 ) {
		/* All non-zero. Point or at the then image.
		 */
		if( vips_region_prepare( ir[0], r ) ||
			vips_region_region( or, ir[0], r, r->left, r->top ) )
			return( -1 );
	}
	else if( all0 ) {
		/* All zero. Point or at the else image.
		 */
		if( vips_region_prepare( ir[1], r ) ||
			vips_region_region( or, ir[1], r, r->left, r->top ) )
			return( -1 );
	}
	else {
		/* Mix of set and clear ... ask for both then and else parts 
		 * and interleave.
		 */
		if( vips_region_prepare( ir[0], r ) || 
			vips_region_prepare( ir[1], r ) ) 
			return( -1 );

		for( y = to; y < bo; y++ ) {
			PEL *ap = (PEL *) VIPS_REGION_ADDR( ir[0], le, y );
			PEL *bp = (PEL *) VIPS_REGION_ADDR( ir[1], le, y );
			PEL *cp = (PEL *) VIPS_REGION_ADDR( ir[2], le, y );
			PEL *q = (PEL *) VIPS_REGION_ADDR( or, le, y );

			if( ifthenelse->blend ) {
				if( c->Bands == 1 ) 
					vips_blend1_buffer( q, 
						cp, ap, bp, r->width, a );
				else
					vips_blendn_buffer( q, 
						cp, ap, bp, r->width, a );
			}
			else {
				for( x = 0, i = 0; i < width; i++, x += size ) 
					if( cp[i] )
						for( z = x; z < x + size; z++ )
							q[z] = ap[z];
					else
						for( z = x; z < x + size; z++ )
							q[z] = bp[z];
			}
		}
	}

	return( 0 );
}
예제 #30
0
static int
vips_sequential_generate( VipsRegion *or, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsSequential *sequential = (VipsSequential *) b;
	VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( sequential );
        VipsRect *r = &or->valid;
	VipsRegion *ir = (VipsRegion *) seq;

	VIPS_DEBUG_MSG_GREEN( "thread %p request for line %d, height %d\n", 
		g_thread_self(), r->top, r->height );

	if( sequential->trace )
		vips_info( class->nickname, 
			"request for line %d, height %d", 
			r->top, r->height );

	VIPS_GATE_START( "vips_sequential_generate: wait" );

	g_mutex_lock( sequential->lock );

	VIPS_GATE_STOP( "vips_sequential_generate: wait" );

	VIPS_DEBUG_MSG_GREEN( "thread %p has lock ...\n", g_thread_self() ); 

	/* If we've seen an error, everything must stop.
	 */
	if( sequential->error ) {
		g_mutex_unlock( sequential->lock );
		return( -1 );
	}

	if( r->top > sequential->y_pos &&
		sequential->y_pos > 0 ) {
		/* This request is for stuff beyond the current read position, 
		 * and this is not the first request. We 
		 * stall for a while to give other threads time to catch up.
		 * 
		 * The stall can be cancelled by a signal on @ready.
		 *
		 * We don't stall forever, since an error would be better than
		 * deadlock, and we don't fail on timeout, since the timeout 
		 * may be harmless.
		 */

#ifdef HAVE_COND_INIT
		gint64 time;

		time = g_get_monotonic_time() + 
			STALL_TIME * G_TIME_SPAN_SECOND;
#else
		GTimeVal time;

		g_get_current_time( &time );
		g_time_val_add( &time, STALL_TIME * 1000000 );
#endif

		VIPS_DEBUG_MSG_GREEN( "thread %p stalling for up to %gs ...\n", 
			g_thread_self(), STALL_TIME ); 

		VIPS_GATE_START( "vips_sequential_generate: wait" );

		/* Exit the loop on timeout or condition passes. We have to
		 * be wary of spurious wakeups. 
		 */
		while( r->top > sequential->y_pos ) {
#ifdef HAVE_COND_INIT
			if( !g_cond_wait_until( sequential->ready, 
				sequential->lock, time ) )
				break;
#else
			if( !g_cond_timed_wait( sequential->ready, 
				sequential->lock, &time ) )
				break;
#endif

			/* We may have woken up because of an eval error.
			 */
			if( sequential->error ) {
				g_mutex_unlock( sequential->lock );
				return( -1 );
			}
		}

		VIPS_GATE_STOP( "vips_sequential_generate: wait" );

		VIPS_DEBUG_MSG_GREEN( "thread %p awake again ...\n", 
			g_thread_self() ); 
	}

	if( r->top > sequential->y_pos ) {
		/* This is a request for something some way down the image, 
		 * and we've fallen through from the stall above. 
		 *
		 * Probably the operation is something like extract_area and 
		 * we should skip the initial part of the image. In fact, 
		 * we read to cache, since it may be useful.
		 */
		VipsRect area;

		VIPS_DEBUG_MSG_GREEN( "thread %p skipping to line %d ...\n", 
			g_thread_self(),
			r->top );

		area.left = 0;
		area.top = sequential->y_pos;
		area.width = 1;
		area.height = r->top - sequential->y_pos;
		if( vips_region_prepare( ir, &area ) ) {
			VIPS_DEBUG_MSG( "thread %p error, unlocking #1 ...\n", 
				g_thread_self() ); 
			sequential->error = -1;
			g_cond_broadcast( sequential->ready );
			g_mutex_unlock( sequential->lock );
			return( -1 );
		}

		sequential->y_pos = VIPS_RECT_BOTTOM( &area );
	}

	/* This is a request for old or present pixels -- serve from cache.
	 * This may trigger further, sequential reads.
	 */
	VIPS_DEBUG_MSG_GREEN( "thread %p reading ...\n", g_thread_self() ); 
	if( vips_region_prepare( ir, r ) ||
		vips_region_region( or, ir, r, r->left, r->top ) ) {
		VIPS_DEBUG_MSG( "thread %p error, unlocking #2 ...\n", 
			g_thread_self() ); 
		sequential->error = -1;
		g_cond_broadcast( sequential->ready );
		g_mutex_unlock( sequential->lock );
		return( -1 );
	}

	if( VIPS_RECT_BOTTOM( r ) > sequential->y_pos ) {
		/* This request has moved the read point. Update it, and wake 
		 * up all stalled threads for a retry.
		 */
		sequential->y_pos = VIPS_RECT_BOTTOM( r );

		VIPS_DEBUG_MSG_GREEN( "thread %p updating y_pos to %d and "
			"waking stalled\n", 
			g_thread_self(),
			sequential->y_pos ); 

		g_cond_broadcast( sequential->ready );
	}

	VIPS_DEBUG_MSG_GREEN( "thread %p unlocking ...\n", g_thread_self() ); 

	g_mutex_unlock( sequential->lock );

	return( 0 );
}