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 = ®ion->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 ); }
/* 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 ); }
/* 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 ); }
/* 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; } }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* 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( ®->valid, r ) ); #endif /*DEBUG*/ for( z = 0; z < r->height; z++ ) { memcpy( q, p, len ); p += plsk; q += qlsk; } }
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; }
/** 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; }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* 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 ); }
/* * 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;
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; } }
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; }