Esempio n. 1
0
static int
vips_statistic_scan( VipsRegion *region, 
	void *seq, void *a, void *b, gboolean *stop )
{
	VipsStatistic *statistic = VIPS_STATISTIC( a );
	VipsStatisticClass *class = VIPS_STATISTIC_GET_CLASS( statistic );

	VipsRect *r = &region->valid;
	int lsk = IM_REGION_LSKIP( region );

	int y;
	PEL *p;

	VIPS_DEBUG_MSG( "vips_statistic_scan: %d x %d @ %d x %d\n",
		r->width, r->height, r->left, r->top );

	p = (PEL *) IM_REGION_ADDR( region, r->left, r->top ); 
	for( y = 0; y < r->height; y++ ) { 
		if( class->scan( statistic, 
			seq, r->left, r->top + y, p, r->width ) ) 
			return( -1 );
		p += lsk;
	} 

	/* If we've requested stop, pass the message on.
	 */
	if( statistic->stop )
		*stop = TRUE;

	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
/* 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. 4
0
/* Build or->valid a line at a time from ir.
 */
static int
process_region( REGION *or, void *seq, void *unrequired, void *b )
{
  if( im_prepare_many( (REGION**)seq, & or-> valid ))
    return -1;
  {
    void *out= IM_REGION_ADDR_TOPLEFT( or );
    void *in1= IM_REGION_ADDR( ((REGION**)seq)[0], or-> valid. left, or-> valid. top );
    void *in2= IM_REGION_ADDR( ((REGION**)seq)[1], or-> valid. left, or-> valid. top );
    size_t out_skip= IM_REGION_LSKIP( or );
    size_t in1_skip= IM_REGION_LSKIP( ((REGION**)seq)[0] );
    size_t in2_skip= IM_REGION_LSKIP( ((REGION**)seq)[1] );
    void *out_stop= out + out_skip * or-> valid. height;

    for( ; out < out_stop; out+= out_skip, in1+= in1_skip, in2+= in2_skip )
      ((UserBundle*) b)-> fn( in1, in2, out, or-> valid. width, ((UserBundle*) b)-> a, ((UserBundle*) b)-> b );
  
    return 0;
  }
}
Esempio n. 5
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. 6
0
/* Generate function.
 */
static int
make_horz_gen( REGION *or, void *seq, void *a, void *b )
{
    IMAGE *in = (IMAGE *) a;
    Rect *r = &or->valid;
    int le = r->left;
    int to = r->top;
    int ri = IM_RECT_RIGHT( r );
    int bo = IM_RECT_BOTTOM( r );
    int nb = in->Bands;
    int lsk = IM_REGION_LSKIP( or );
    int ht = or->im->Ysize;

    int x, y, z;

    for( x = le; x < ri; x++ ) {
        VipsPel *q = IM_REGION_ADDR( or, x, to );
        VipsPel *p = IM_IMAGE_ADDR( in, x, 0 );

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

        default:
            g_assert( 0 );
        }
    }

    return( 0 );
}
Esempio n. 7
0
/* Return the position of the first non-zero pel from the bottom.
 */
static int
find_bot( REGION *ir, int *pos, int x, int y, int h )
{
	VipsPel *pr = IM_REGION_ADDR( ir, x, y );
	IMAGE *im = ir->im;
	int ls = IM_REGION_LSKIP( ir ) / IM_IMAGE_SIZEOF_ELEMENT( ir->im );
	int b = im->Bands;
	int i, j;

	/* Double the number of bands in a complex.
	 */
	if( vips_bandfmt_iscomplex( im->BandFmt ) )
		b *= 2;

/* Search for the first non-zero band element from the top edge of the image.
 */
#define rsearch( TYPE ) { \
	TYPE *p = (TYPE *) pr + (h - 1) * ls; \
	\
	for( i = h - 1; i >= 0; i-- ) { \
		for( j = 0; j < b; j++ ) \
			if( p[j] ) \
				break; \
		if( j < b ) \
			break; \
		\
		p -= ls; \
	} \
}

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

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

	*pos = y + i;

	return( 0 );
}
Esempio n. 8
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. 9
0
static unsigned int
calc_cont (REGION * reg, int win_size_less_one, int x_left, int y_top)
{
  unsigned char val;
  unsigned char all_black = 1;
  unsigned char *row;
  unsigned int contrast = 0;
  int xoff;
  int yoff;
  size_t lskip = IM_REGION_LSKIP (reg) / sizeof (unsigned char);

  row = (unsigned char *) IM_REGION_ADDR (reg, x_left, y_top);
  val = *row;

  for (yoff = 0; yoff <= win_size_less_one && all_black; ++yoff, row += lskip)
    for (xoff = 0; xoff <= win_size_less_one; ++xoff)
      if (row[xoff] != val)
	{
	  all_black = 0;
	  break;
	}

  if (all_black)
    return contrast;

  row = (unsigned char *) IM_REGION_ADDR (reg, x_left, y_top);

  for (yoff = 0; yoff < win_size_less_one; ++yoff, row += lskip)
    {
      for (xoff = 0; xoff < win_size_less_one; ++xoff)
	contrast +=
	  abs (row[xoff + 1] - row[xoff]) + abs (row[xoff + lskip] -
						 row[xoff]);

      contrast += abs (row[xoff + lskip] - row[xoff]);
    }

  for (xoff = 0; xoff < win_size_less_one; ++xoff)
    contrast += abs (row[xoff + 1] - row[xoff]);

  return contrast;
}
Esempio n. 10
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. 11
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. 12
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. 13
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. 14
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. 15
0
  /*
   * Move the pointer to (the first band of) the top/left pixel of the
   * 2x2 group of pixel centers which contains the sampling location
   * in its convex hull:
   */
  const PEL* restrict p = (PEL *) IM_REGION_ADDR( in, ix, iy );

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

  /*
   * VIPS versions of Nicolas's pixel addressing values.
   */
  const int actual_bands = in->im->Bands;
  const int lskip = IM_REGION_LSKIP( in ) / IM_IMAGE_SIZEOF_ELEMENT( in->im );
  /*
   * Double the bands for complex images to account for the real and
   * imaginary parts being computed independently:
   */
  const int bands =
    vips_bandfmt_iscomplex( in->im->BandFmt ) ? 2 * actual_bands : actual_bands;

  switch( in->im->BandFmt ) {
  case IM_BANDFMT_UCHAR:
    CALL( unsigned char, nosign );
    break;

  case IM_BANDFMT_CHAR:
    CALL( signed char, withsign );
    break;
Esempio n. 16
0
static void
vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
	void *out, REGION *in, double x, double y )
{
	/* Find the mask index. We round-to-nearest, so we need to generate 
	 * indexes in 0 to VIPS_TRANSFORM_SCALE, 2^n + 1 values. We multiply 
	 * by 2 more than we need to, add one, mask, then shift down again to 
	 * get the extra range.
	 */
	const int sx = x * VIPS_TRANSFORM_SCALE * 2;
	const int sy = y * VIPS_TRANSFORM_SCALE * 2;

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

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

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

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

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

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

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

	switch( in->im->BandFmt ) {
	case IM_BANDFMT_UCHAR:
		bicubic_int_tab<unsigned char, 0, UCHAR_MAX>(
			out, p, bands, lskip,
			cxi, cyi );
	/*

	   Handy for benchmarking

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

	 */
		break;

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

	case IM_BANDFMT_USHORT:
		bicubic_int_tab<unsigned short, 0, USHRT_MAX>(
			out, p, bands, lskip,
			cxi, cyi );
		break;

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

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

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

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

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

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

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

	default:
		break;
	}
}
Esempio n. 17
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;
}