Esempio n. 1
0
/**
 * im_region_region:
 * @reg: region to operate upon
 * @dest: region to connect to
 * @r: #Rect of pixels you need to be able to address
 * @x: postion of @r in @dest
 * @y: postion of @r in @dest
 *
 * Make IM_REGION_ADDR() on @reg go to @dest instead.
 *
 * @r is the part of @reg which you want to be able to address (this
 * effectively becomes the valid field), (@x, @y) is the top LH corner of the
 * corresponding area in @dest.
 *
 * Performs all clipping necessary to ensure that @reg->valid is indeed
 * valid.
 *
 * If the region we attach to is modified, we can be left with dangling
 * pointers! If the region we attach to is on another image, the two images
 * must have
 * the same sizeof( pel ).
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_region( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
    Rect image;
    Rect wanted;
    Rect clipped;
    Rect clipped2;
    Rect final;

    /* Sanity check.
     */
    if( !dest->data ||
            IM_IMAGE_SIZEOF_PEL( dest->im ) !=
            IM_IMAGE_SIZEOF_PEL( reg->im ) ) {
        im_error( "im_region_region",
                  "%s", _( "inappropriate region type" ) );
        return( -1 );
    }
    im__region_check_ownership( reg );

    /* We can't test

    	g_assert( dest->thread == g_thread_self() );

     * since we can have several threads writing to the same region in
     * threadgroup.
     */

    /* Clip r against size of the image.
     */
    image.top = 0;
    image.left = 0;
    image.width = reg->im->Xsize;
    image.height = reg->im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Translate to dest's coordinate space and clip against the available
     * pixels.
     */
    wanted.left = x + (clipped.left - r->left);
    wanted.top = y + (clipped.top - r->top);
    wanted.width = clipped.width;
    wanted.height = clipped.height;

    /* Test that dest->valid is large enough.
     */
    if( !im_rect_includesrect( &dest->valid, &wanted ) ) {
        im_error( "im_region_region",
                  "%s", _( "dest too small" ) );
        return( -1 );
    }

    /* Clip against the available pixels.
     */
    im_rect_intersectrect( &wanted, &dest->valid, &clipped2 );

    /* Translate back to reg's coordinate space and set as valid.
     */
    final.left = r->left + (clipped2.left - wanted.left);
Esempio n. 2
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 );
}
Esempio n. 3
0
/* Rotate a small piece.
 */
static int
rot270_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;

	/* Output area.
	 */
	Rect *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.
	 */
	Rect need;

	need.left = in->Xsize - bo;
	need.top = le;
	need.width = r->height;
	need.height = r->width;
	if( im_prepare( ir, &need ) )
		return( -1 );
	
	/* Find PEL size and line skip for ir.
	 */
	ps = IM_IMAGE_SIZEOF_PEL( in );
	ls = IM_REGION_LSKIP( ir );

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

		/* Corresponding position in ir.
		 */
		PEL *p = (PEL *) IM_REGION_ADDR( ir, 
			need.left + need.width - (y - to) - 1,
			need.top );

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

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

	return( 0 );
}
Esempio n. 4
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 );
}
Esempio n. 5
0
/**
 * im_region_buffer:
 * @reg: region to operate upon
 * @r: #Rect of pixels you need to be able to address
 *
 * The region is transformed so that at least @r pixels are available as a
 * memory buffer.
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_buffer( REGION *reg, Rect *r )
{
    IMAGE *im = reg->im;

    Rect image;
    Rect clipped;

    im__region_check_ownership( reg );

    /* Clip against image.
     */
    image.top = 0;
    image.left = 0;
    image.width = im->Xsize;
    image.height = im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Test for empty.
     */
    if( im_rect_isempty( &clipped ) ) {
        im_error( "im_region_buffer",
                  "%s", _( "valid clipped to nothing" ) );
        return( -1 );
    }

    /* Have we been asked to drop caches? We want to throw everything
     * away.
     *
     * If not, try to reuse the current buffer.
     */
    if( reg->invalid ) {
        im_region_reset( reg );
        if( !(reg->buffer = im_buffer_new( im, &clipped )) )
            return( -1 );
    }
    else {
        /* Don't call im_region_reset() ... we combine buffer unref
         * and new buffer ref in one call to reduce malloc/free
         * cycling.
         */
        IM_FREEF( im_window_unref, reg->window );
        if( !(reg->buffer =
                    im_buffer_unref_ref( reg->buffer, im, &clipped )) )
            return( -1 );
    }

    /* Init new stuff.
     */
    reg->valid = reg->buffer->area;
    reg->bpl = IM_IMAGE_SIZEOF_PEL( im ) * reg->buffer->area.width;
    reg->type = IM_REGION_BUFFER;
    reg->data = reg->buffer->buf;

    return( 0 );
}
Esempio n. 6
0
/* Flip a small area.
 */
static int
flip_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	Rect *r = &or->valid;
	Rect in;
	char *p, *q;
	int x, y, z;

	int le = r->left;
	int ri = IM_RECT_RIGHT(r);
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_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 = IM_RECT_RIGHT( &in ) - 1;

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

	/* Loop, copying and reversing lines.
	 */
	for( y = to; y < bo; y++ ) {
		p = IM_REGION_ADDR( ir, lastx, y );
		q = IM_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 );
}
Esempio n. 7
0
/* Bandjoin generate function.
 */
static int
bandjoin_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION **ir = (REGION **) seq;
	Rect *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, z;
	int i1s = IM_IMAGE_SIZEOF_PEL( ir[0]->im );
	int i2s = IM_IMAGE_SIZEOF_PEL( ir[1]->im );

	/* Ask for input we need.
	 */
	if( im_prepare( ir[0], r ) )
		return( -1 );
	if( im_prepare( ir[1], r ) ) 
		return( -1 );

	/* Perform join.
	 */
	for( y = to; y < bo; y++ ) {
		PEL *i1 = (PEL *) IM_REGION_ADDR( ir[0], le, y );
		PEL *i2 = (PEL *) IM_REGION_ADDR( ir[1], le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		for( x = le; x < ri; x++ ) {
			/* Copy bytes from first file.  
			 */
			for( z = 0; z < i1s; z++ )
				*q++ = *i1++;

			/* Copy bytes from in2.  
			 */
			for( z = 0; z < i2s; z++ )
				*q++ = *i2++;
		}
	}

	return( 0 );
}
Esempio n. 8
0
/* Swap pairs of bytes.
 */
static void
im_copy_swap2_gen( PEL *in, PEL *out, int width, IMAGE *im )
{       
        int x;
        int sz = IM_IMAGE_SIZEOF_PEL( im ) * width;     /* Bytes in buffer */

        for( x = 0; x < sz; x += 2 ) {
                out[x] = in[x + 1];
                out[x + 1] = in[x];
        }
}
Esempio n. 9
0
static int
write_block( REGION *region, Rect *area, void *a )
{
  Write *write = (Write *) a;
  int i;
  
  for( i = 0; i < area->height; i++ ) {
    PEL *p = (PEL *) IM_REGION_ADDR( region, area->left, area->top + i );
    if( im__write( write->fd, p, IM_IMAGE_SIZEOF_PEL(write->in)*area->width ) )
      return( -1 );
  }
  
  return( 0 );
}
Esempio n. 10
0
/* Region should be a pixel buffer. On return, check
 * reg->buffer->done to see if there are pixels there already. Otherwise, you
 * need to calculate.
 */
int
im_region_buffer( REGION *reg, Rect *r )
{
	IMAGE *im = reg->im;

	Rect image;
	Rect clipped;

	im__region_check_ownership( reg );

	/* Clip against image.
	 */
	image.top = 0;
	image.left = 0;
	image.width = im->Xsize;
	image.height = im->Ysize;
	im_rect_intersectrect( r, &image, &clipped );

	/* Test for empty.
	 */
	if( im_rect_isempty( &clipped ) ) {
		im_error( "im_region_buffer", _( "valid clipped to nothing" ) );
		return( -1 );
	}

	/* Already have stuff?
	 */
	if( reg->type == IM_REGION_BUFFER &&
		im_rect_includesrect( &reg->valid, &clipped ) &&
		reg->buffer &&
		!reg->buffer->invalid ) 
		return( 0 );

	/* Don't call im_region_reset() ... we combine buffer unref and new
	 * buffer ref in one call to reduce malloc/free cycling.
	 */
	IM_FREEF( im_window_unref, reg->window );
	if( !(reg->buffer = im_buffer_unref_ref( reg->buffer, im, &clipped )) )
		return( -1 );

	/* Init new stuff.
	 */
	reg->valid = reg->buffer->area;
	reg->bpl = IM_IMAGE_SIZEOF_PEL( im ) * reg->buffer->area.width;
	reg->type = IM_REGION_BUFFER;
	reg->data = reg->buffer->buf;

	return( 0 );
}
Esempio n. 11
0
/* Fetch one pixel at a time ... good for very large shrinks.
 */
static int
point_shrink_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	SubsampleInfo *st = (SubsampleInfo *) b;
	Rect *r = &or->valid;

	int le = r->left;
	int ri = IM_RECT_RIGHT( r );
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_IMAGE_SIZEOF_PEL( in );

	Rect s;
	int x, y;
	int k;

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

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

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

	return( 0 );
}
Esempio n. 12
0
/* Swap 8- of bytes.
 */
static void
im_copy_swap8_gen( PEL *in, PEL *out, int width, IMAGE *im )
{
        int x;
        int sz = IM_IMAGE_SIZEOF_PEL( im ) * width;     /* Bytes in buffer */

        for( x = 0; x < sz; x += 8 ) {
                out[x] = in[x + 7];
                out[x + 1] = in[x + 6];
                out[x + 2] = in[x + 5];
                out[x + 3] = in[x + 4];
                out[x + 4] = in[x + 3];
                out[x + 5] = in[x + 2];
                out[x + 6] = in[x + 1];
                out[x + 7] = in[x];
        }
}
Esempio n. 13
0
/* Read a ppm/pgm file using mmap().
 */
static int
read_mmap( FILE *fp, const char *filename, int msb_first, IMAGE *out )
{
	const int header_offset = ftell( fp );
	IMAGE *t[2];

	if( im_open_local_array( out, t, 2, "im_ppm2vips", "p" ) ||
		im_raw2vips( filename, t[0], 
			out->Xsize, out->Ysize, 
			IM_IMAGE_SIZEOF_PEL( out ), header_offset ) ||
		im_copy_morph( t[0], t[1],
			out->Bands, out->BandFmt, out->Coding ) ||
		im_copy_native( t[1], out, msb_first ) ) 
		return( -1 );

	return( 0 );
}
Esempio n. 14
0
/* Copy rect from from to to.
 */
static void
copy_region( REGION *from, REGION *to, Rect *area )
{
	int y;

	/* Area should be inside both from and to.
	 */
	g_assert( im_rect_includesrect( &from->valid, area ) );
	g_assert( im_rect_includesrect( &to->valid, area ) );

	/* Loop down common area, copying.
	 */
	for( y = area->top; y < IM_RECT_BOTTOM( area ); y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( from, area->left, y );
		PEL *q = (PEL *) IM_REGION_ADDR( to, area->left, y );

		memcpy( q, p, IM_IMAGE_SIZEOF_PEL( from->im ) * area->width );
	}
}
Esempio n. 15
0
Draw *
im__draw_init( Draw *draw, IMAGE *im, PEL *ink )
{
	if( im_rwcheck( im ) )
		return( NULL );

	draw->im = im;
	draw->ink = NULL;

	draw->lsize = IM_IMAGE_SIZEOF_LINE( im );
	draw->psize = IM_IMAGE_SIZEOF_PEL( im );
	draw->noclip = FALSE;

	if( ink ) {
		if( !(draw->ink = (PEL *) im_malloc( NULL, draw->psize )) ) 
			return( NULL );
		memcpy( draw->ink, ink, draw->psize );
	}

	return( draw );
}
Esempio n. 16
0
/**
 * im_draw_image:
 * @image: image to draw on
 * @sub: image to draw
 * @x: position to insert
 * @y: position to insert
 *
 * Draw @sub on top of @image at position @x, @y. The two images must have the
 * same
 * Coding. If @sub has 1 band, the bands will be duplicated to match the
 * number of bands in @image. @sub will be converted to @image's format, see
 * im_clip2fmt().
 *
 * See also: im_insert().
 *
 * Returns: 0 on success, or -1 on error.
 */
int
im_draw_image( VipsImage *image, VipsImage *sub, int x, int y )
{
    Rect br, sr, clip;
    PEL *p, *q;
    int z;

    /* Make rects for main and sub and clip.
     */
    br.left = 0;
    br.top = 0;
    br.width = image->Xsize;
    br.height = image->Ysize;
    sr.left = x;
    sr.top = y;
    sr.width = sub->Xsize;
    sr.height = sub->Ysize;
    im_rect_intersectrect( &br, &sr, &clip );
    if( im_rect_isempty( &clip ) )
        return( 0 );

    if( !(sub = im__inplace_base( "im_draw_image", image, sub, image )) ||
            im_rwcheck( image ) ||
            im_incheck( sub ) )
        return( -1 );

    /* Loop, memcpying sub to main.
     */
    p = (PEL *) IM_IMAGE_ADDR( sub, clip.left - x, clip.top - y );
    q = (PEL *) IM_IMAGE_ADDR( image, clip.left, clip.top );
    for( z = 0; z < clip.height; z++ ) {
        memcpy( (char *) q, (char *) p,
                clip.width * IM_IMAGE_SIZEOF_PEL( sub ) );
        p += IM_IMAGE_SIZEOF_LINE( sub );
        q += IM_IMAGE_SIZEOF_LINE( image );
    }

    return( 0 );
}
Esempio n. 17
0
/* Copy from one region to another. Copy area r from inside reg to dest,
 * positioning the area of pixels at x, y.
 */
void
im__copy_region( REGION *reg, REGION *dest, Rect *r, int x, int y )
{
	int z;
	int len = IM_IMAGE_SIZEOF_PEL( reg->im ) * r->width;
	char *p = IM_REGION_ADDR( reg, r->left, r->top );
	char *q = IM_REGION_ADDR( dest, x, y );
	int plsk = IM_REGION_LSKIP( reg );
	int qlsk = IM_REGION_LSKIP( dest );

#ifdef DEBUG
	/* Find the area we will write to in dest.
	 */
	Rect output;

	printf( "im__copy_region: sanity check\n" );

	output.left = x;
	output.top = y;
	output.width = r->width;
	output.height = r->height;

	/* Must be inside dest->valid.
	 */
	assert( im_rect_includesrect( &dest->valid, &output ) );

	/* Check the area we are reading from in reg.
	 */
	assert( im_rect_includesrect( &reg->valid, r ) );
#endif /*DEBUG*/

	for( z = 0; z < r->height; z++ ) {
		memcpy( q, p, len );

		p += plsk;
		q += qlsk;
	}
}
Esempio n. 18
0
static int
buffer_move( im_buffer_t *buffer, Rect *area )
{
	IMAGE *im = buffer->im;
	size_t new_bsize;

	g_assert( buffer->ref_count == 1 );

	buffer->area = *area;
	im_buffer_undone( buffer );
	g_assert( !buffer->done );

	new_bsize = (size_t) IM_IMAGE_SIZEOF_PEL( im ) * 
		area->width * area->height;
	if( buffer->bsize < new_bsize ) {
		buffer->bsize = new_bsize;
		IM_FREE( buffer->buf );
		if( !(buffer->buf = im_malloc( NULL, buffer->bsize )) ) 
			return( -1 );
	}

	return( 0 );
}
Esempio n. 19
0
/* Make a new buffer.
 */
im_buffer_t *
im_buffer_new( IMAGE *im, Rect *area )
{
	im_buffer_t *buffer;

	if( !(buffer = IM_NEW( NULL, im_buffer_t )) )
		return( NULL );

	buffer->ref_count = 1;
	buffer->im = im;
	buffer->area = *area;
	buffer->done = FALSE;
	buffer->cache = NULL;
	buffer->bsize = (size_t) IM_IMAGE_SIZEOF_PEL( im ) * 
		area->width * area->height;
	if( !(buffer->buf = im_malloc( NULL, buffer->bsize )) ) {
		im_buffer_unref( buffer );
		return( NULL );
	}

#ifdef DEBUG
	printf( "** im_buffer_new: left = %d, top = %d, "
		"width = %d, height = %d (%p)\n",
		buffer->area.left, buffer->area.top, 
		buffer->area.width, buffer->area.height, 
		buffer );
#endif /*DEBUG*/

#ifdef DEBUG
	g_mutex_lock( im__global_lock );
	im__buffers_all = g_slist_prepend( im__buffers_all, buffer );
	printf( "%d buffers in vips\n", g_slist_length( im__buffers_all ) );
	g_mutex_unlock( im__global_lock );
#endif /*DEBUG*/

	return( buffer );
}
Esempio n. 20
0
int 
im_resize_linear( IMAGE *in, IMAGE *out, int X, int Y )
{
    double	dx, dy, xscale, yscale;
    double	Xnew, Ynew;	/* inv. coord. of the interpolated pt */

    int		x, y;
    int		Xint, Yint;
    int		bb;

    PEL		*input, *opline;
    PEL 	*q, *p;

    int 	ils, ips, ies;		/* Input and output line, pel and */
    int 	ols, ops, oes;		/* element sizes */

	if( im_iocheck( in, out ) )
		return( -1 );
	if( im_iscomplex( in ) ) {
		im_errormsg( "im_lowpass: non-complex input only" );
		return( -1 );
	}
	if( in->Coding != IM_CODING_NONE ) {
		im_errormsg("im_lowpass: input should be uncoded");
		return( -1 );
	}
	if( im_cp_desc( out, in ) ) 
		return( -1 );

	out->Xsize = X;
	out->Ysize = Y;

	if( im_setupout( out ) )
		return( -1 );

	ils = IM_IMAGE_SIZEOF_LINE( in );
	ips = IM_IMAGE_SIZEOF_PEL( in );
	ies = IM_IMAGE_SIZEOF_ELEMENT( in );

	ols = IM_IMAGE_SIZEOF_LINE( out );
	ops = IM_IMAGE_SIZEOF_PEL( out );
	oes = IM_IMAGE_SIZEOF_ELEMENT( out );

/* buffer lines
***************/
	if( !(opline = IM_ARRAY( out, ols, PEL )) ) 
		return( -1 );

/* Resampling
*************/
	input = (PEL*) in->data;
	xscale = ((double)in->Xsize-1)/(X-1);
	yscale = ((double)in->Ysize-1)/(Y-1);

for (y=0; y<Y; y++)
  {
    q = opline;
    for (x=0; x<X; x++)
      {
	Xnew = x*xscale;
	Ynew = y*yscale;
	Xint = floor(Xnew);
	Yint = floor(Ynew);
	dx = Xnew - Xint;
	dy = Ynew - Yint;
	p = input + Xint*ips + Yint*ils;

	switch( in->BandFmt ) {
	case IM_BANDFMT_UCHAR:		LOOP( unsigned char); break;
	case IM_BANDFMT_USHORT:		LOOP( unsigned short ); break;
	case IM_BANDFMT_UINT:		LOOP( unsigned int ); break;
	case IM_BANDFMT_CHAR:		LOOP( signed char ); break;
	case IM_BANDFMT_SHORT:		LOOP( signed short ); break;
	case IM_BANDFMT_INT:		LOOP( signed int ); break;
	case IM_BANDFMT_FLOAT:		LOOP( float ); break;
	case IM_BANDFMT_DOUBLE:		LOOP( double ); break;

	default:
		im_errormsg( "im_lowpass: unsupported image type" );
		return( -1 );
		/*NOTREACHED*/
	}
      }

    if (im_writeline(y, out, opline) )
	    return(-1);
  } 
return(0);
}
Esempio n. 21
0
/* Subsample a REGION. We fetch in IM_MAX_WIDTH pixel-wide strips, left-to-right
 * across the input.
 */
static int
line_shrink_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	SubsampleInfo *st = (SubsampleInfo *) b;
	Rect *r = &or->valid;

	int le = r->left;
	int ri = IM_RECT_RIGHT( r );
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	int ps = IM_IMAGE_SIZEOF_PEL( in );

	int owidth = IM_MAX_WIDTH / st->xshrink;

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

	/* Loop down the region.
	 */
	for( y = to; y < bo; y++ ) {
		char *q = IM_REGION_ADDR( or, le, y );
		char *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 = IM_MIN( owidth, ri - x );

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

			/* Ask for input.
			 */
			s.left = x * st->xshrink;
			s.top = y * st->yshrink;
			s.width = iw;
			s.height = 1;
			if( im_prepare( ir, &s ) )
				return( -1 );

			/* Append new pels to output.
			 */
			p = IM_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 * st->xshrink;
			}
		}
	}

	return( 0 );
}
Esempio n. 22
0
/**
 * im_region_image:
 * @reg: region to operate upon
 * @r: #Rect of pixels you need to be able to address
 *
 * The region is transformed so that at least @r pixels are available directly
 * from the image. The image needs to be a memory buffer or represent a file
 * on disc that has been mapped or can be mapped.
 *
 * Returns: 0 on success, or -1 for error.
 */
int
im_region_image( REGION *reg, Rect *r )
{
    Rect image;
    Rect clipped;

    /* Sanity check.
     */
    im__region_check_ownership( reg );

    /* Clip against image.
     */
    image.top = 0;
    image.left = 0;
    image.width = reg->im->Xsize;
    image.height = reg->im->Ysize;
    im_rect_intersectrect( r, &image, &clipped );

    /* Test for empty.
     */
    if( im_rect_isempty( &clipped ) ) {
        im_error( "im_region_image",
                  "%s", _( "valid clipped to nothing" ) );
        return( -1 );
    }

    if( reg->im->data ) {
        /* We have the whole image available ... easy!
         */
        im_region_reset( reg );

        /* We can't just set valid = clipped, since this may be an
         * incompletely calculated memory buffer. Just set valid to r.
         */
        reg->valid = clipped;
        reg->bpl = IM_IMAGE_SIZEOF_LINE( reg->im );
        reg->data = reg->im->data +
                    (gint64) clipped.top * IM_IMAGE_SIZEOF_LINE( reg->im ) +
                    clipped.left * IM_IMAGE_SIZEOF_PEL( reg->im );
        reg->type = IM_REGION_OTHER_IMAGE;
    }
    else if( reg->im->dtype == IM_OPENIN ) {
        /* No complete image data ... but we can use a rolling window.
         */
        if( reg->type != IM_REGION_WINDOW || !reg->window ||
                reg->window->top > clipped.top ||
                reg->window->top + reg->window->height <
                clipped.top + clipped.height ) {
            im_region_reset( reg );

            if( !(reg->window = im_window_ref( reg->im,
                                               clipped.top, clipped.height )) )
                return( -1 );

            reg->type = IM_REGION_WINDOW;
        }

        /* Note the area the window actually represents.
         */
        reg->valid.left = 0;
        reg->valid.top = reg->window->top;
        reg->valid.width = reg->im->Xsize;
        reg->valid.height = reg->window->height;
        reg->bpl = IM_IMAGE_SIZEOF_LINE( reg->im );
        reg->data = reg->window->data;
    }
    else {
        im_error( "im_region_image",
                  "%s", _( "bad image type" ) );
        return( -1 );
    }

    return( 0 );
}
Esempio n. 23
0
static int
affinei_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	const IMAGE *in = (IMAGE *) a;
	const Affine *affine = (Affine *) b;
	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 Rect *r = &or->valid;
	const int le = r->left;
	const int ri = IM_RECT_RIGHT( r );
	const int to = r->top;
	const int bo = IM_RECT_BOTTOM( r );

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

	int ps = IM_IMAGE_SIZEOF_PEL( in );
	int x, y, z;
	
	Rect image, want, need, clipped;

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

	/* We are generating this chunk of the transformed image.
	 */
	want = *r;
	want.left += oarea->left;
	want.top += oarea->top;

	/* Find the area of the input image we need.
	 */
	im__transform_invert_rect( &affine->trn, &want, &need );

	/* Now go to space (2) above.
	 */
	need.left += iarea->left;
	need.top += iarea->top;

	/* Add a border for interpolation. Plus one for rounding errors.
	 */
	im_rect_marginadjust( &need, window_offset + 1 );

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

	/* Outside input image? All black.
	 */
	if( im_rect_isempty( &clipped ) ) {
		im_region_black( or );
		return( 0 );
	}

	/* We do need some pixels from the input image to make our output -
	 * ask for them.
	 */
	if( im_prepare( ir, &clipped ) )
		return( -1 );

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

	/* Resample! x/y loop over pixels in the output image (5).
	 */
	for( y = to; y < bo; y++ ) {
		/* Input clipping rectangle. 
		 */
		const int ile = iarea->left;
		const int ito = iarea->top;
		const int iri = iarea->left + iarea->width;
		const int ibo = iarea->top + 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.dx;
		const double oy = y + oarea->top - affine->trn.dy;

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

		PEL *q;

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

		/* Now move to (2).
		 */
		ix += iarea->left;
		iy += iarea->top;

		q = (PEL *) IM_REGION_ADDR( or, le, y );

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

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

			/* Clipping! 
			 */
			if( fx < ile || fx >= iri || fy < ito || fy >= ibo ) {
				for( z = 0; z < ps; z++ ) 
					q[z] = 0;
			}
			else {
				interpolate( affine->interpolate, 
					q, ir, ix, iy );
			}

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

	return( 0 );
}
Esempio n. 24
0
static int
ifthenelse_gen( REGION *or, void *seq, void *client1, void *client2 )
{
	REGION **ir = (REGION **) seq;
	Rect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);

	IMAGE *c = ir[0]->im;
	IMAGE *a = ir[1]->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 = IM_IMAGE_SIZEOF_PEL( a );
		width = r->width;
	}
	else {
		/* Copying ELEMENT sized-units with an n-band conditional.
		 */
		size = IM_IMAGE_SIZEOF_ELEMENT( a );
		width = r->width * a->Bands;
	}

	if( im_prepare( ir[0], 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 *) IM_REGION_ADDR( ir[0], le, to )) == 0;
	alln0 = *((PEL *) IM_REGION_ADDR( ir[0], le, to )) != 0;
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( ir[0], 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( im_prepare( ir[1], r ) ||
			im_region_region( or, ir[1], r, r->left, r->top ) )
			return( -1 );
	}
	else if( all0 ) {
		/* All zero. Point or at the else image.
		 */
		if( im_prepare( ir[2], r ) ||
			im_region_region( or, ir[2], r, r->left, r->top ) )
			return( -1 );
	}
	else {
		/* Mix of set and clear ... ask for both then and else parts 
		 * and interleave.
		 */
		if( im_prepare( ir[1], r ) || im_prepare( ir[2], r ) ) 
			return( -1 );

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

			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 );
}