Esempio n. 1
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. 2
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. 3
0
/* The vector codepath.
 */
static int
morph_vector_gen( REGION *or, void *vseq, void *a, void *b )
{
	MorphSequence *seq = (MorphSequence *) vseq;
	Morph *morph = (Morph *) b;
	INTMASK *mask = morph->mask;
	REGION *ir = seq->ir;
	Rect *r = &or->valid;
	int sz = IM_REGION_N_ELEMENTS( or );

	Rect s;
	int y, j;
	VipsExecutor executor[MAX_PASS];

	/* Prepare the section of the input image we need. A little larger
	 * than the section of the output image we are producing.
	 */
	s = *r;
	s.width += mask->xsize - 1;
	s.height += mask->ysize - 1;
	if( im_prepare( ir, &s ) )
		return( -1 );

#ifdef DEBUG
	printf( "morph_vector_gen: preparing %dx%d@%dx%d pixels\n", 
		s.width, s.height, s.left, s.top );
#endif /*DEBUG*/

	for( j = 0; j < morph->n_pass; j++ ) 
		vips_executor_set_program( &executor[j], 
			morph->pass[j].vector, sz );

	for( y = 0; y < r->height; y++ ) { 
		for( j = 0; j < morph->n_pass; j++ ) {
			void *d;

			/* The last pass goes to the output image,
			 * intermediate passes go to t2.
			 */
			if( j == morph->n_pass - 1 )
				d = IM_REGION_ADDR( or, r->left, r->top + y );
			else 
				d = seq->t2;

			vips_executor_set_scanline( &executor[j], 
				ir, r->left, r->top + y );
			vips_executor_set_array( &executor[j],
				morph->pass[j].r, seq->t1 );
			vips_executor_set_destination( &executor[j], d );
			vips_executor_run( &executor[j] );

			IM_SWAP( void *, seq->t1, seq->t2 );
		}
	}

	return( 0 );
}
Esempio n. 4
0
/* Fastcor generate function.
 */
static int
fastcor_gen( REGION *or, void *seq, void *a, void *b )
{
    REGION *ir = (REGION *) seq;
    IMAGE *ref = (IMAGE *) b;
    Rect irect;
    Rect *r = &or->valid;
    int le = r->left;
    int to = r->top;
    int bo = IM_RECT_BOTTOM(r);
    int ri = IM_RECT_RIGHT(r);

    int x, y, i, j;
    int lsk;

    /* What part of ir do we need?
     */
    irect.left = or->valid.left;
    irect.top = or->valid.top;
    irect.width = or->valid.width + ref->Xsize - 1;
    irect.height = or->valid.height + ref->Ysize - 1;

    if( im_prepare( ir, &irect ) )
        return( -1 );
    lsk = IM_REGION_LSKIP( ir );

    /* Loop over or.
     */
    for( y = to; y < bo; y++ ) {
        PEL *a = (PEL *) IM_REGION_ADDR( ir, le, y );
        unsigned int *q = (unsigned int *) IM_REGION_ADDR( or, le, y );

        for( x = le; x < ri; x++ ) {
            int sum = 0;
            PEL *b = (PEL *) ref->data;
            PEL *a1 = a;

            for( j = 0; j < ref->Ysize; j++ ) {
                PEL *a2 = a1;

                for( i = 0; i < ref->Xsize; i++ ) {
                    int t = *b++ - *a2++;

                    sum += t * t;
                }

                a1 += lsk;
            }

            *q++ = sum;
            a += 1;
        }
    }

    return( 0 );
}
Esempio n. 5
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. 6
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. 7
0
/* A ushort index image.
 */
static int
hist_scan_ushort( REGION *reg, void *seq, void *a, void *b, gboolean *stop )
{
	Histogram *hist = (Histogram *) seq;
	Rect *r = &reg->valid;
	IMAGE *value = hist->value;
	int bands = value->Bands;
	int width = r->width;

	int y, mx;

	/* Need the correspondiing area of the value image.
	 */
	if( im_prepare( hist->vreg, r ) )
		return( -1 );

	/* Accumulate!
	 */
	mx = hist->mx;
	for( y = 0; y < r->height; y++ ) {
		unsigned short *i = (unsigned short *) IM_REGION_ADDR( reg, 
				r->left, r->top + y );
		PEL *v = (PEL *) IM_REGION_ADDR( hist->vreg, 
			r->left, r->top + y );

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

		default:
			g_assert( 0 );
		}
	}

	/* Note the maximum.
	 */
	hist->mx = mx;

	return( 0 );
}
Esempio n. 8
0
/* Fastcor generate function.
 */
static int
fastcor_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *ref = (IMAGE *) b;
	Rect irect;
	Rect *r = &or->valid;

	int x, y, i, j;
	int lsk;

	/* What part of ir do we need?
	 */
	irect.left = or->valid.left;
	irect.top = or->valid.top;
	irect.width = or->valid.width + ref->Xsize - 1;
	irect.height = or->valid.height + ref->Ysize - 1;

	if( im_prepare( ir, &irect ) )
		return( -1 );
	lsk = IM_REGION_LSKIP( ir );

	/* Loop over or.
	 */
	for( y = 0; y < r->height; y++ ) {
		unsigned int *q = (unsigned int *) 
			IM_REGION_ADDR( or, r->left, r->top + y );

		for( x = 0; x < r->width; x++ ) {
			VipsPel *b = ref->data;
			VipsPel *a = 
				IM_REGION_ADDR( ir, r->left + x, r->top + y );

			int sum;

			sum = 0;
			for( j = 0; j < ref->Ysize; j++ ) {
				for( i = 0; i < ref->Xsize; i++ ) {
					int t = b[i] - a[i];

					sum += t * t;
				}
				
				a += lsk;
				b += ref->Xsize;
			}

			q[x] = sum;
		}
	}

	return( 0 );
}
Esempio n. 9
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. 10
0
/* Zerox generate function.
 */
static int
zerox_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	int flag = GPOINTER_TO_INT( b );
	Rect irect;
	Rect *r = &or->valid;

	/* Range of pixels we loop over. 
	 */
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM( r );
	int ba = in->Bands;
	int ne = ba * r->width;

	int i, y;

	/* We need to be able to see one pixel to the right. 
	 */
	irect.top = r->top;
	irect.left = r->left;
	irect.width = r->width + 1;
	irect.height = r->height;
	if( im_prepare( ir, &irect ) )
		return( -1 );
	
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		switch( in->BandFmt ) {
		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:
			g_assert( 0 );
		}
	}

	return( 0 );
} 
Esempio n. 11
0
/* Copy a small area.
 */
static int
copy_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	Rect *r = &or->valid;

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

	/* Attach output region to that.
	 */
	if( im_region_region( or, ir, r, r->left, r->top ) )
		return( -1 );

	return( 0 );
}
Esempio n. 12
0
/** LOCAL FUNCTIONS DEFINITIONS **/
static int
cont_surf_gen (REGION * to_make, void * seq, void *unrequired, void * b)
{
  /* I don't need *in, but I will recieve it anyway since im_start_one() needs it */

  REGION * make_from = (REGION *) seq;
  cont_surf_params_t * params = (cont_surf_params_t *) b;

  unsigned int *row =
    (unsigned int *) IM_REGION_ADDR (to_make, to_make->valid.left,
				     to_make->valid.top);
  int xoff;
  int y;
  int bottom = to_make->valid.top + to_make->valid.height;
  size_t lskip = IM_REGION_LSKIP (to_make) / sizeof (unsigned int);

  Rect area = {
    params->spacing * to_make->valid.left,
    params->spacing * to_make->valid.top,
    DOUBLE_ADD_ONE (params->half_win_size) +
      (params->spacing * (to_make->valid.width - 1)),
    DOUBLE_ADD_ONE (params->half_win_size) +
      (params->spacing * (to_make->valid.height - 1))
  };

  if (im_prepare (make_from, &area)
      || !im_rect_equalsrect (&make_from->valid, &area))
    return -1;

  for (y = to_make->valid.top; y < bottom; ++y, row += lskip)

    for (xoff = 0; xoff < to_make->valid.width; ++xoff)

      row[xoff] =
	calc_cont (make_from, DOUBLE (params->half_win_size),
		   (xoff + to_make->valid.left) * params->spacing,
		   y * params->spacing);

  return 0;
}
Esempio n. 13
0
/* Do a map.
 */
static int 
maplut_gen( REGION *or, void *vseq, void *a, void *b )
{
	Seq *seq = (Seq *) vseq;
	IMAGE *in = (IMAGE *) a;
	LutInfo *st = (LutInfo *) b;
	REGION *ir = seq->ir;
	Rect *r = &or->valid;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int np = r->width;			/* Pels across region */
	int ne = IM_REGION_N_ELEMENTS( or );	/* Number of elements */
	int x, y, z, i;

	/* Get input ready.
	 */
	if( im_prepare( ir, r ) )
		return( -1 );

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

	return( 0 );
}
Esempio n. 14
0
/* Dilate!
 */
static int
dilate_gen( REGION *or, void *vseq, void *a, void *b )
{
	SeqInfo *seq = (SeqInfo *) vseq;
	INTMASK *msk = (INTMASK *) b;
	REGION *ir = seq->ir;

	int *soff = seq->soff;
	int *coff = seq->coff;

	Rect *r = &or->valid;
	Rect s;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int sz = IM_REGION_N_ELEMENTS( or );

	int *t;

	int x, y;
	int result, i;

	/* Prepare the section of the input image we need. A little larger
	 * than the section of the output image we are producing.
	 */
	s = *r;
	s.width += msk->xsize - 1;
	s.height += msk->ysize - 1;
	if( im_prepare( ir, &s ) )
		return( -1 );

#ifdef DEBUG
	printf( "erode_gen: preparing %dx%d pixels\n", s.width, s.height );
#endif /*DEBUG*/

	/* Scan mask, building offsets we check when processing. Only do this
	 * if the bpl has changed since the previous im_prepare().
	 */
	if( seq->last_bpl != IM_REGION_LSKIP( ir ) ) {
		seq->last_bpl = IM_REGION_LSKIP( ir );

		seq->ss = 0;
		seq->cs = 0;
		for( t = msk->coeff, y = 0; y < msk->ysize; y++ )
			for( x = 0; x < msk->xsize; x++, t++ )
				switch( *t ) {
				case 255:
					soff[seq->ss++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				case 128:
					break;

				case 0:
					coff[seq->cs++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				default:
					im_error( "im_dilate", 
						_( "bad mask element (%d "
						"should be 0, 128 or 255)" ), 
						*t );
					return( -1 ); 
				}
	}

	/* Dilate!
	 */
	for( y = to; y < bo; y++ ) {
		PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
		PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );

		/* Loop along line.
		 */
		for( x = 0; x < sz; x++, q++, p++ ) {
			/* Search for a hit on the set list.
			 */
			result = 0;
			for( i = 0; i < seq->ss; i++ )
				if( p[soff[i]] ) {
					/* Found a match! 
					 */
					result = 255;
					break;
				}

			/* No set pixels ... search for a hit in the clear
			 * pixels.
			 */
			if( !result )
				for( i = 0; i < seq->cs; i++ )
					if( !p[coff[i]] ) {
						/* Found a match! 
						 */
						result = 255;
						break;
					}

			*q = result;

		}
	}

	return( 0 );
}
Esempio n. 15
0
static int
stretch_gen( REGION *or, void *vseq, void *a, void *b )
{ 
	SeqInfo *seq = (SeqInfo *) vseq;
	StretchInfo *sin = (StretchInfo *) b;
	REGION *ir = seq->ir;
	Rect *r = &or->valid;
	Rect r1;
	int x, y;

	/* What mask do we start with?
	 */
	int xstart = (r->left + sin->xoff) % 34;

	/* What part of input do we need for this output? 
	 */
	r1.left = r->left - (r->left + sin->xoff) / 34;
	r1.top = r->top;
	x = IM_RECT_RIGHT( r );
	x = x - (x + sin->xoff) / 34 + 3;
	r1.width = x - r1.left;
	r1.height = r->height + 3;
        if( im_prepare( ir, &r1 ) )
        	return( -1 );
	
	/* Fill the first three lines of the buffer.
	 */
	for( y = 0; y < 3; y++ ) {
		unsigned short *p = (unsigned short *) 
			IM_REGION_ADDR( ir, r1.left, y + r1.top );
		unsigned short *q = seq->buf + seq->lsk*y;

		make_xline( sin, p, q, r->width, xstart );
	}

	/* Loop for subsequent lines: stretch a new line of x pels, and
	 * interpolate a line of output from the 3 previous xes plus this new
	 * one.
	 */
	for( y = 0; y < r->height; y++ ) {
		/* Next line of fresh input pels.
		 */
		unsigned short *p = (unsigned short *) 
			IM_REGION_ADDR( ir, r1.left, y + r1.top + 3 );

		/* Next line we fill in the buffer.
		 */
		int boff = (y + 3)%4;
		unsigned short *q = seq->buf + boff*seq->lsk;

		/* Line we write in output.
		 */
		unsigned short *q1 = (unsigned short *) 
			IM_REGION_ADDR( or, r->left, y + r->top );

		/* Process this new xline.
		 */
		make_xline( sin, p, q, r->width, xstart );

		/* Generate new output line.
		 */
		make_yline( sin, seq->lsk, boff, 
			seq->buf, q1, r->width, sin->yoff );
	}

	return( 0 );
}
Esempio n. 16
0
/* lhist generate function.
 */
static int
lhist_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	LhistInfo *inf = (LhistInfo *) b;
	Rect *r = &or->valid;

	Rect irect;
	int x, y, i, j;
	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 + inf->xwin;
	irect.height = or->valid.height + inf->ywin;
	if( im_prepare( ir, &irect ) )
		return( -1 );

	lsk = IM_REGION_LSKIP( ir );
	centre = lsk * (inf->ywin / 2) + inf->xwin / 2;

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

		VipsPel *p1;
		int hist[256];

		/* Find histogram for start of this line.
		 */
		memset( hist, 0, 256 * sizeof( int ) );
		p1 = p;
		for( j = 0; j < inf->ywin; j++ ) {
			for( i = 0; i < inf->xwin; i++ )
				hist[p1[i]] += 1;
			
			p1 += lsk;
		}

		/* Loop for output pels.
		 */
		for( x = 0; x < r->width; x++ ) {
			/* Sum histogram up to current pel.
			 */
			int target = p[centre];
			int sum;

			sum = 0;
			for( i = 0; i < target; i++ )
				sum += hist[i];

			/* Transform.
			 */
			q[x] = sum * 256 / inf->npels;

			/* Adapt histogram - remove the pels from the left hand
			 * column, add in pels for a new right-hand column.
			 */
			p1 = p;
			for( j = 0; j < inf->ywin; j++ ) {
				hist[p1[0]] -= 1;
				hist[p1[inf->xwin]] += 1;

				p1 += lsk;
			}

			p += 1;
		}
	}

	return( 0 );
}
Esempio n. 17
0
/* Top-bottom blend function for IM_CODING_LABQ images.
 */
static int
tb_blend_labpack( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	Rect prr, psr;
	int y, yr, ys;

	/* Make sure we have a complete first/last set for this area. This
	 * will just look at the top 8 bits of L, not all 10, but should be OK.
	 */
	if( make_firstlast( inf, ovlap, oreg ) )
		return( -1 );

	/* Part of rr which we will output.
	 */
	prr = *oreg;
	prr.left -= ovlap->rarea.left;
	prr.top -= ovlap->rarea.top;

	/* Part of sr which we will output.
	 */
	psr = *oreg;
	psr.left -= ovlap->sarea.left;
	psr.top -= ovlap->sarea.top;

	/* Make pixels.
	 */
	if( im_prepare( rir, &prr ) )
		return( -1 );
	if( im_prepare( sir, &psr ) )
		return( -1 );

	/* Loop down overlap area.
	 */
	for( y = oreg->top, yr = prr.top, ys = psr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) { 
		VipsPel *pr = IM_REGION_ADDR( rir, prr.left, yr );
		VipsPel *ps = IM_REGION_ADDR( sir, psr.left, ys );
		VipsPel *q = IM_REGION_ADDR( or, oreg->left, y );

		const int j = oreg->left - ovlap->overlap.left;
		const int *first = ovlap->first + j;
		const int *last = ovlap->last + j;

		float *fq = inf->merge;
		float *r = inf->from1;
		float *s = inf->from2;

		/* Unpack two bits we want.
		 */
		vips__LabQ2Lab_vec( r, pr, oreg->width );
		vips__LabQ2Lab_vec( s, ps, oreg->width );

		/* Blend as floats.
		 */
		fblend( float, 3, r, s, fq ); 

		/* Re-pack to output buffer.
		 */
		vips__Lab2LabQ_vec( q, inf->merge, oreg->width );
	}

	return( 0 );
}
Esempio n. 18
0
/* Top-bottom blend function for non-labpack images.
 */
static int
tb_blend( REGION *or, MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	IMAGE *im = or->im;

	Rect prr, psr;
	int y, yr, ys;

	/* Make sure we have a complete first/last set for this area.
	 */
	if( make_firstlast( inf, ovlap, oreg ) )
		return( -1 );

	/* Part of rr which we will output.
	 */
	prr = *oreg;
	prr.left -= ovlap->rarea.left;
	prr.top -= ovlap->rarea.top;

	/* Part of sr which we will output.
	 */
	psr = *oreg;
	psr.left -= ovlap->sarea.left;
	psr.top -= ovlap->sarea.top;

	/* Make pixels.
	 */
	if( im_prepare( rir, &prr ) )
		return( -1 );
	if( im_prepare( sir, &psr ) )
		return( -1 );

	/* Loop down overlap area.
	 */
	for( y = oreg->top, yr = prr.top, ys = psr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) { 
		VipsPel *pr = IM_REGION_ADDR( rir, prr.left, yr );
		VipsPel *ps = IM_REGION_ADDR( sir, psr.left, ys );
		VipsPel *q = IM_REGION_ADDR( or, oreg->left, y );

		const int j = oreg->left - ovlap->overlap.left;
		const int *first = ovlap->first + j;
		const int *last = ovlap->last + j;

		switch( im->BandFmt ) {
		case IM_BANDFMT_UCHAR: 	
			iblend( unsigned char, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_CHAR: 	
			iblend( signed char, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_USHORT: 
			iblend( unsigned short, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_SHORT: 	
			iblend( signed short, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_UINT: 	
			iblend( unsigned int, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_INT: 	
			iblend( signed int, im->Bands, pr, ps, q );  break; 
		case IM_BANDFMT_FLOAT: 	
			fblend( float, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_DOUBLE:	
			fblend( double, im->Bands, pr, ps, q ); break; 
		case IM_BANDFMT_COMPLEX:
			fblend( float, im->Bands*2, pr, ps, q ); break; 
		case IM_BANDFMT_DPCOMPLEX:
			fblend( double, im->Bands*2, pr, ps, q ); break;

		default:
			im_error( "im_tbmerge", "%s", _( "internal error" ) );
			return( -1 );
		}
	}

	return( 0 );
}
Esempio n. 19
0
/* Make first/last for oreg.
 */
static int
make_firstlast( MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	Rect rr, sr;
	int x;
	int missing;

	/* We're going to build first/last ... lock it from other generate
	 * threads. In fact it's harmless if we do get two writers, but we may
	 * avoid duplicating work.
	 */
	g_mutex_lock( ovlap->fl_lock );

	/* Do we already have first/last for this area? Bail out if we do.
	 */
	missing = 0;
	for( x = oreg->left; x < IM_RECT_RIGHT( oreg ); x++ ) {
		const int j = x - ovlap->overlap.left;
		const int first = ovlap->first[j];

		if( first < 0 ) {
			missing = 1;
			break;
		}
	}
	if( !missing ) {
		/* No work to do!
		 */
		g_mutex_unlock( ovlap->fl_lock );
		return( 0 );
	}

	/* Entire height of overlap in ref for oreg ... we know oreg is inside
	 * overlap.
	 */
	rr.left = oreg->left;
	rr.top = ovlap->overlap.top;
	rr.width = oreg->width;
	rr.height = ovlap->overlap.height;
	rr.left -= ovlap->rarea.left;
	rr.top -= ovlap->rarea.top;

	/* Same in sec.
	 */
	sr.left = oreg->left;
	sr.top = ovlap->overlap.top;
	sr.width = oreg->width;
	sr.height = ovlap->overlap.height;
	sr.left -= ovlap->sarea.left;
	sr.top -= ovlap->sarea.top;

	/* Make pixels.
	 */
	if( im_prepare( rir, &rr ) || im_prepare( sir, &sr ) ) {
		g_mutex_unlock( ovlap->fl_lock );
		return( -1 );
	}

	/* Make first/last cache.
	 */
	for( x = 0; x < oreg->width; x++ ) {
		const int j = (x + oreg->left) - ovlap->overlap.left;
		int *first = &ovlap->first[j];
		int *last = &ovlap->last[j];

		/* Done this line already?
		 */
		if( *first < 0 ) {
			/* Search for top/bottom of overlap on this scan-line.
			 */
			if( find_top( sir, first, 
				x + sr.left, sr.top, sr.height ) ||
				find_bot( rir, last, 
					x + rr.left, rr.top, rr.height ) ) {
				g_mutex_unlock( ovlap->fl_lock );
				return( -1 );
			}

			/* Translate to output space.
			 */
			*first += ovlap->sarea.top;
			*last += ovlap->rarea.top;

			/* Clip to maximum blend width, if necessary.
			 */
			if( ovlap->mwidth >= 0 && 
				*last - *first > ovlap->mwidth ) {
				int shrinkby = (*last - *first) - ovlap->mwidth;

				*first += shrinkby / 2;
				*last -= shrinkby / 2;
			}
		}
	}

	g_mutex_unlock( ovlap->fl_lock );

	return( 0 );
}
Esempio n. 20
0
/* stdif generate function.
 */
static int
stdif_gen( REGION *or, void *seq, void *a, void *b )
{
    REGION *ir = (REGION *) seq;
    StdifInfo *inf = (StdifInfo *) b;
    int npel = inf->xwin * inf->ywin;
    Rect *r = &or->valid;

    Rect irect;
    int x, y, i, j;
    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 + inf->xwin;
    irect.height = or->valid.height + inf->ywin;
    if( im_prepare( ir, &irect ) )
        return( -1 );

    lsk = IM_REGION_LSKIP( ir );
    centre = lsk * (inf->ywin / 2) + inf->xwin / 2;

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

        /* Precompute some factors.
         */
        double f1 = inf->a * inf->m0;
        double f2 = 1.0 - inf->a;
        double f3 = inf->b * inf->s0;

        VipsPel *p1;
        int sum;
        int sum2;

        /* Find sum, sum of squares for the start of this line.
         */
        sum = 0;
        sum2 = 0;
        p1 = p;
        for( j = 0; j < inf->ywin; j++ ) {
            for( i = 0; i < inf->xwin; i++ ) {
                int t = p1[i];

                sum += t;
                sum2 += t * t;
            }

            p1 += lsk;
        }

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

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

            /* And write.
             */
            if( res < 0.0 )
                q[x] = 0;
            else if( res >= 256.0 )
                q[x] = 255;
            else
                q[x] = 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 < inf->ywin; j++ ) {
                int t1 = p1[0];
                int t2 = p1[inf->xwin];

                sum -= t1;
                sum2 -= t1 * t1;

                sum += t2;
                sum2 += t2 * t2;

                p1 += lsk;
            }

            p += 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
static int
replicate_gen( REGION *or, void *seq, void *a, void *b )
{
	REGION *ir = (REGION *) seq;
	IMAGE *in = (IMAGE *) a;
	Rect *r = &or->valid;
	int twidth = in->Xsize;
	int theight = in->Ysize;
	int x, y;
	Rect 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( im_rect_includesrect( &tile, r ) ) {
		Rect irect;

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

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

		return( 0 );
	}

	for( y = ys; y < IM_RECT_BOTTOM( r ); y += theight )
		for( x = xs; x < IM_RECT_RIGHT( r ); x += twidth ) {
			Rect 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.
			 */
			im_rect_intersectrect( &tile, r, &paint );

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

			g_assert( !im_rect_isempty( &paint ) );

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

	return( 0 );
}
Esempio n. 23
0
/* Shrink a REGION.
 */
static int
shrink_gen( REGION *or, void *vseq, void *a, void *b )
{
    SeqInfo *seq = (SeqInfo *) vseq;
    ShrinkInfo *st = (ShrinkInfo *) b;
    REGION *ir = seq->ir;
    Rect *r = &or->valid;
    Rect s;
    int le = r->left;
    int ri = IM_RECT_RIGHT( r );
    int to = r->top;
    int bo = IM_RECT_BOTTOM(r);

    int x, y, z, k;

    /* What part of the input image do we need? Very careful: round left
     * down, round right up.
     */
    s.left = r->left * st->xshrink;
    s.top = r->top * st->yshrink;
    s.width = ceil( IM_RECT_RIGHT( r ) * st->xshrink ) - s.left;
    s.height = ceil( IM_RECT_BOTTOM( r ) * st->yshrink ) - s.top;
    if( im_prepare( ir, &s ) )
        return( -1 );

    /* Init offsets for pel addressing. Note that offsets must be for the
     * type we will address the memory array with.
     */
    for( z = 0, y = 0; y < st->mh; y++ )
        for( x = 0; x < st->mw; x++ )
            seq->off[z++] = (IM_REGION_ADDR( ir, x, y ) -
                             IM_REGION_ADDR( ir, 0, 0 )) /
                            IM_IMAGE_SIZEOF_ELEMENT( ir->im );

    switch( ir->im->BandFmt ) {
    case IM_BANDFMT_UCHAR:
        ishrink(unsigned char);
        break;
    case IM_BANDFMT_CHAR:
        ishrink(char);
        break;
    case IM_BANDFMT_USHORT:
        ishrink(unsigned short);
        break;
    case IM_BANDFMT_SHORT:
        ishrink(short);
        break;
    case IM_BANDFMT_UINT:
        ishrink(unsigned int);
        break;
    case IM_BANDFMT_INT:
        ishrink(int);
        break;
    case IM_BANDFMT_FLOAT:
        fshrink(float);
        break;
    case IM_BANDFMT_DOUBLE:
        fshrink(double);
        break;

    default:
        im_error( "im_shrink", "%s", _( "unsupported input format" ) );
        return( -1 );
    }

    return( 0 );
}
Esempio n. 24
0
/* Make sure we have first/last for this area.
 */
static int
make_firstlast( MergeInfo *inf, Overlapping *ovlap, Rect *oreg )
{
	REGION *rir = inf->rir;
	REGION *sir = inf->sir;
	Rect rr, sr;
	int y, yr, ys;
	int missing;

	/* We're going to build first/last ... lock it from other generate
	 * threads. In fact it's harmless if we do get two writers, but we may
	 * avoid duplicating work.
	 */
	g_mutex_lock( ovlap->fl_lock );

	/* Do we already have first/last for this area? Bail out if we do.
	 */
	missing = 0;
	for( y = oreg->top; y < IM_RECT_BOTTOM( oreg ); y++ ) {
		const int j = y - ovlap->overlap.top;
		const int first = ovlap->first[j];

		if( first < 0 ) {
			missing = 1;
			break;
		}
	}
	if( !missing ) {
		/* No work to do!
		 */
		g_mutex_unlock( ovlap->fl_lock );
		return( 0 );
	}

	/* Entire width of overlap in ref for scan-lines we want.
	 */
	rr.left = ovlap->overlap.left;
	rr.top = oreg->top;
	rr.width = ovlap->overlap.width;
	rr.height = oreg->height;
	rr.left -= ovlap->rarea.left;
	rr.top -= ovlap->rarea.top;

	/* Entire width of overlap in sec for scan-lines we want.
	 */
	sr.left = ovlap->overlap.left;
	sr.top = oreg->top;
	sr.width = ovlap->overlap.width;
	sr.height = oreg->height;
	sr.left -= ovlap->sarea.left;
	sr.top -= ovlap->sarea.top;

#ifdef DEBUG
	printf( "im__lrmerge: making first/last for areas:\n" );
	printf( "ref: left = %d, top = %d, width = %d, height = %d\n",
		rr.left, rr.top, rr.width, rr.height );
	printf( "sec: left = %d, top = %d, width = %d, height = %d\n",
		sr.left, sr.top, sr.width, sr.height );
#endif

	/* Make pixels.
	 */
	if( im_prepare( rir, &rr ) || im_prepare( sir, &sr ) ) {
		g_mutex_unlock( ovlap->fl_lock );
		return( -1 );
	}

	/* Make first/last cache.
	 */
	for( y = oreg->top, yr = rr.top, ys = sr.top; 
		y < IM_RECT_BOTTOM( oreg ); y++, yr++, ys++ ) {
		const int j = y - ovlap->overlap.top;
		int *first = &ovlap->first[j];
		int *last = &ovlap->last[j];

		/* Done this line already?
		 */
		if( *first < 0 ) {
			/* Search for start/end of overlap on this scan-line.
			 */
			if( find_first( sir, first, 
				sr.left, ys, sr.width ) ||
				find_last( rir, last, 
					rr.left, yr, rr.width ) ) {
				g_mutex_unlock( ovlap->fl_lock );
				return( -1 );
			}

			/* Translate to output space.
			 */
			*first += ovlap->sarea.left;
			*last += ovlap->rarea.left;

			/* Clip to maximum blend width, if necessary.
			 */
			if( ovlap->mwidth >= 0 && 
				*last - *first > ovlap->mwidth ) {
				int shrinkby = (*last - *first) - ovlap->mwidth;

				*first += shrinkby / 2;
				*last -= shrinkby / 2;
			}
		}
	}

	g_mutex_unlock( ovlap->fl_lock );

	return( 0 );
}
Esempio n. 25
0
static int gradcor_gen( REGION *to_make, void *vptr_seq, void *unrequired, void *vptr_grads ){

  gradcor_seq_t *seq= (gradcor_seq_t*) vptr_seq;
  REGION *make_from= seq-> reg;

  IMAGE **grads= (IMAGE**) vptr_grads;
  IMAGE *small_xgrad= grads[0];
  IMAGE *small_ygrad= grads[1];

  Rect require= {
    to_make-> valid. left,
    to_make-> valid. top,
    to_make-> valid. width + small_xgrad-> Xsize,
    to_make-> valid. height + small_ygrad-> Ysize
  };
  size_t region_xgrad_width= require. width - 1;
  size_t region_ygrad_height= require. height - 1;

  if( im_prepare( make_from, &require ) )
    return -1;

#define FILL_BUFFERS( TYPE )        /* fill region_xgrad */                                         \
  {                                                                                                 \
    TYPE *reading= (TYPE*) IM_REGION_ADDR( make_from, require. left, require. top );                \
    size_t read_skip= ( IM_REGION_LSKIP( make_from ) / sizeof(TYPE) ) - region_xgrad_width;         \
    size_t area_need= region_xgrad_width * require. height;                                         \
                                                                                                    \
    if( seq-> region_xgrad_area < area_need ){                                                      \
      free( seq-> region_xgrad );                                                                   \
      seq-> region_xgrad= malloc( area_need * sizeof(int) );                                        \
      if( ! seq-> region_xgrad )                                                                    \
        return -1;                                                                                  \
      seq-> region_xgrad_area= area_need;                                                           \
    }                                                                                               \
    {                                                                                               \
      int *writing= seq-> region_xgrad;                                                             \
      int *write_end= writing + area_need;                                                          \
      int *write_stop;                                                                              \
      for( ; writing < write_end; reading+= read_skip )                                             \
        for( write_stop= writing + region_xgrad_width; writing < write_stop; ++reading, ++writing ) \
          *writing= reading[1] - reading[0];                                                        \
    }                                                                                               \
  }                                                                                                 \
  {     /* fill region_ygrad */                                                                     \
    TYPE *reading= (TYPE*) IM_REGION_ADDR( make_from, require. left, require. top );                \
    size_t read_line= IM_REGION_LSKIP( make_from ) / sizeof(TYPE);                                  \
    size_t read_skip= read_line - require. width;                                                   \
    size_t area_need= require. width * region_ygrad_height;                                         \
                                                                                                    \
    if( seq-> region_ygrad_area < area_need ){                                                      \
      free( seq-> region_ygrad );                                                                   \
      seq-> region_ygrad= malloc( area_need * sizeof(int) );                                        \
      if( ! seq-> region_ygrad )                                                                    \
        return -1;                                                                                  \
      seq-> region_ygrad_area= area_need;                                                           \
    }                                                                                               \
    {                                                                                               \
      int *writing= seq-> region_ygrad;                                                             \
      int *write_end= writing + area_need;                                                          \
      int *write_stop;                                                                              \
      for( ; writing < write_end; reading+= read_skip )                                             \
        for( write_stop= writing + require. width; writing < write_stop; ++reading, ++writing )     \
          *writing= reading[ read_line ] - reading[0];                                              \
    }                                                                                               \
  }
  switch( make_from-> im-> BandFmt ){
    case IM_BANDFMT_UCHAR:
      FILL_BUFFERS( unsigned char )
      break;
    case IM_BANDFMT_CHAR:
      FILL_BUFFERS( signed char )
      break;
    case IM_BANDFMT_USHORT:
      FILL_BUFFERS( unsigned short int )
      break;
    case IM_BANDFMT_SHORT:
      FILL_BUFFERS( signed short int )
      break;
    case IM_BANDFMT_UINT:
      FILL_BUFFERS( unsigned int )
      break;
    case IM_BANDFMT_INT:
      FILL_BUFFERS( signed int )
      break;
    default:
      g_assert( 0 );
  }
  { /* write to output */
    size_t write_skip= IM_REGION_LSKIP( to_make ) / sizeof( float );
    float *writing= (float*) IM_REGION_ADDR_TOPLEFT( to_make );
    float *write_end= writing + write_skip * to_make-> valid. height;
    float *write_stop;
    size_t write_width= to_make-> valid. width;

    size_t small_xgrad_width= small_xgrad-> Xsize;
    size_t small_ygrad_width= small_ygrad-> Xsize;
    int *small_xgrad_end= (int*) small_xgrad-> data + small_xgrad_width * small_xgrad-> Ysize;
    int *small_ygrad_end= (int*) small_ygrad-> data + small_ygrad_width * small_ygrad-> Ysize;

    int *region_xgrad_start= seq-> region_xgrad;
    int *region_ygrad_start= seq-> region_ygrad;
    size_t region_xgrad_start_skip= region_xgrad_width - write_width;
    size_t region_ygrad_start_skip= require. width - write_width;

    size_t region_xgrad_read_skip= region_xgrad_width - small_xgrad_width;
    size_t region_ygrad_read_skip= require. width - small_ygrad_width;

    write_skip-= write_width;

    for( ; writing < write_end; writing+= write_skip, region_xgrad_start+= region_xgrad_start_skip, region_ygrad_start+= region_ygrad_start_skip )
      for( write_stop= writing + write_width; writing < write_stop; ++writing, ++region_xgrad_start, ++region_ygrad_start ){
        gint64 sum= 0;
        {
          int *small_xgrad_read= (int*) small_xgrad-> data;
          int *small_xgrad_stop;
          int *region_xgrad_read= region_xgrad_start;

          for( ; small_xgrad_read < small_xgrad_end; region_xgrad_read+= region_xgrad_read_skip )
            for( small_xgrad_stop= small_xgrad_read + small_xgrad_width; small_xgrad_read < small_xgrad_stop; ++small_xgrad_read, ++region_xgrad_read )
              sum+= *small_xgrad_read * *region_xgrad_read;
        }
        {
          int *small_ygrad_read= (int*) small_ygrad-> data;
          int *small_ygrad_stop;
          int *region_ygrad_read= region_ygrad_start;

          for( ; small_ygrad_read < small_ygrad_end; region_ygrad_read+= region_ygrad_read_skip )
            for( small_ygrad_stop= small_ygrad_read + small_ygrad_width; small_ygrad_read < small_ygrad_stop; ++small_ygrad_read, ++region_ygrad_read )
              sum+= *small_ygrad_read * *region_ygrad_read;
        }
        *writing= sum;
      }
  }
  return 0;
}
Esempio n. 26
0
/* Erode!
 */
static int
erode_gen( REGION *or, void *vseq, void *a, void *b )
{
	MorphSequence *seq = (MorphSequence *) vseq;
	Morph *morph = (Morph *) b;
	INTMASK *mask = morph->mask;
	REGION *ir = seq->ir;

	int *soff = seq->soff;
	int *coff = seq->coff;

	Rect *r = &or->valid;
	Rect s;
	int le = r->left;
	int to = r->top;
	int bo = IM_RECT_BOTTOM(r);
	int sz = IM_REGION_N_ELEMENTS( or );

	int *t;

	int x, y;
	int result, i;

	/* Prepare the section of the input image we need. A little larger
	 * than the section of the output image we are producing.
	 */
	s = *r;
	s.width += mask->xsize - 1;
	s.height += mask->ysize - 1;
	if( im_prepare( ir, &s ) )
		return( -1 );

#ifdef DEBUG
	printf( "erode_gen: preparing %dx%d@%dx%d pixels\n", 
		s.width, s.height, s.left, s.top );
#endif /*DEBUG*/

	/* Scan mask, building offsets we check when processing. Only do this
	 * if the bpl has changed since the previous im_prepare().
	 */
	if( seq->last_bpl != IM_REGION_LSKIP( ir ) ) {
		seq->last_bpl = IM_REGION_LSKIP( ir );

		seq->ss = 0;
		seq->cs = 0;
		for( t = mask->coeff, y = 0; y < mask->ysize; y++ )
			for( x = 0; x < mask->xsize; x++, t++ )
				switch( *t ) {
				case 255:
					soff[seq->ss++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				case 128:
					break;

				case 0:
					coff[seq->cs++] = 
						IM_REGION_ADDR( ir, 
							x + le, y + to ) - 
						IM_REGION_ADDR( ir, le, to );
					break;

				default:
					g_assert( 0 );
				}
	}

	/* Erode!
	 */
	for( y = to; y < bo; y++ ) {
		VipsPel *p = IM_REGION_ADDR( ir, le, y );
		VipsPel *q = IM_REGION_ADDR( or, le, y );

		/* Loop along line.
		 */
		for( x = 0; x < sz; x++, q++, p++ ) {
			/* Check all set pixels are set.
			 */
			result = 255;
			for( i = 0; i < seq->ss; i++ )
				if( !p[soff[i]] ) {
					/* Found a mismatch! 
					 */
					result = 0;
					break;
				}

			/* Check all clear pixels are clear.
			 */
			if( result )
				for( i = 0; i < seq->cs; i++ )
					if( p[coff[i]] ) {
						result = 0;
						break;
					}

			*q = result;
		}
	}
	
	return( 0 );
}
Esempio n. 27
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. 28
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 );
}