/*ARGSUSED*/ static int gnoise_gen( REGION *or, void *seq, void *a, void *b ) { GnoiseInfo *gin = (GnoiseInfo *) a; int x, y, i; int sz = IM_REGION_N_ELEMENTS( or ); for( y = 0; y < or->valid.height; y++ ) { float *q = (float *) IM_REGION_ADDR( or, or->valid.left, y + or->valid.top ); for( x = 0; x < sz; x++ ) { double sum = 0.0; for( i = 0; i < 12; i++ ) #ifdef HAVE_RANDOM sum += (double) random() / RAND_MAX; #else /*HAVE_RANDOM*/ #ifdef HAVE_RAND sum += (double) rand() / RAND_MAX; #else /*HAVE_RAND*/ #error "no random number generator found" #endif /*HAVE_RAND*/ #endif /*HAVE_RAND*/ q[x] = (sum - 6.0) * gin->sigma + gin->mean; } } return( 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 ); }
/* Loop over region, adding to seq. */ static int maxposavg_scan( REGION *reg, void *seq, void *a, void *b, gboolean *stop ) { const Rect *r = ®->valid; const int sz = IM_REGION_N_ELEMENTS( reg ); Maxposavg *maxposavg = (Maxposavg *) seq; int x, y; double max; int xpos, ypos, occurences; xpos = maxposavg->xpos; ypos = maxposavg->ypos; max = maxposavg->max; occurences = maxposavg->occurences; for( y = 0; y < r->height; y++ ) { VipsPel *in = VIPS_REGION_ADDR( reg, r->left, r->top + y ); switch( reg->im->BandFmt ) { case IM_BANDFMT_UCHAR: LOOP( unsigned char ); break; case IM_BANDFMT_CHAR: LOOP( signed char ); break; case IM_BANDFMT_USHORT: LOOP( unsigned short ); break; case IM_BANDFMT_SHORT: LOOP( signed short ); break; case IM_BANDFMT_UINT: LOOP( unsigned int ); break; case IM_BANDFMT_INT: LOOP( signed int ); break; case IM_BANDFMT_FLOAT: LOOP( float ); break; case IM_BANDFMT_DOUBLE: LOOP( double ); break; case IM_BANDFMT_COMPLEX: CLOOP( float ); break; case IM_BANDFMT_DPCOMPLEX: CLOOP( double ); break; default: g_assert( 0 ); } } maxposavg->xpos = xpos; maxposavg->ypos = ypos; maxposavg->max = max; maxposavg->occurences = occurences; return( 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 ); }
/* Loop over region, adding information to the appropriate fields of tmp. */ static int scan_fn( REGION *reg, void *seq, void *a, void *b ) { double *tmp = (double *) seq; Rect *r = ®->valid; IMAGE *im = reg->im; int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); int sz = IM_REGION_N_ELEMENTS( reg ); double s = 0.0; double s2 = 0.0; int x, y; /* Sum pels in this section. */ #define loop(TYPE) \ { TYPE *p; \ \ for( y = to; y < bo; y++ ) { \ p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \ \ for( x = 0; x < sz; x++ ) { \ TYPE v = p[x]; \ \ s += v; \ s2 += (double) v * (double) v; \ }\ }\ } /* Now generate code for all types. */ switch( im->BandFmt ) { case IM_BANDFMT_UCHAR: loop(unsigned char); break; case IM_BANDFMT_CHAR: loop(signed char); break; case IM_BANDFMT_USHORT: loop(unsigned short); break; case IM_BANDFMT_SHORT: loop(signed short); break; case IM_BANDFMT_UINT: loop(unsigned int); break; case IM_BANDFMT_INT: loop(signed int); break; case IM_BANDFMT_FLOAT: loop(float); break; case IM_BANDFMT_DOUBLE: #ifdef HAVE_LIBOIL for( y = to; y < bo; y++ ) { double *p = (double *) IM_REGION_ADDR( reg, le, y ); double t; double t2; oil_sum_f64( &t, p, sizeof( double ), sz ); oil_squaresum_f64( &t2, p, sz ); s += t; s2 += t2; } #else /*!HAVE_LIBOIL*/ loop(double); #endif /*HAVE_LIBOIL*/ break; default: assert( 0 ); } /* Add to sum for this sequence. */ tmp[0] += s; tmp[1] += s2; 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 ); }
/* 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 ); }
/* Loop over region, adding to seq. */ static int scan_fn( REGION *reg, void *vseq, void *a, void *b ) { Seq *seq = (Seq *) vseq; Rect *r = ®->valid; IMAGE *im = reg->im; int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); int nel = IM_REGION_N_ELEMENTS( reg ); int x, y; double m; #ifdef DEBUG printf( "im_min: left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height ); #endif /*DEBUG*/ #define loop(TYPE) { \ m = *((TYPE *) IM_REGION_ADDR( reg, le, to )); \ \ for( y = to; y < bo; y++ ) { \ TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \ \ for( x = 0; x < nel; x++ ) { \ double v = p[x]; \ \ if( v < m ) \ m = v; \ } \ } \ } #define complex_loop(TYPE) { \ TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, to ); \ double real = p[0]; \ double imag = p[1]; \ \ m = real * real + imag * imag; \ \ for( y = to; y < bo; y++ ) { \ TYPE *p = (TYPE *) IM_REGION_ADDR( reg, le, y ); \ \ for( x = 0; x < nel * 2; x += 2 ) { \ double mod; \ \ real = p[x]; \ imag = p[x + 1]; \ mod = real * real + imag * imag; \ \ if( mod < m ) \ m = mod; \ } \ } \ } switch( im->BandFmt ) { case IM_BANDFMT_UCHAR: loop( unsigned char ); break; case IM_BANDFMT_CHAR: loop( signed char ); break; case IM_BANDFMT_USHORT: loop( unsigned short ); break; case IM_BANDFMT_SHORT: loop( signed short ); break; case IM_BANDFMT_UINT: loop( unsigned int ); break; case IM_BANDFMT_INT: loop( signed int ); break; case IM_BANDFMT_FLOAT: loop( float ); break; case IM_BANDFMT_DOUBLE: loop( double ); break; case IM_BANDFMT_COMPLEX: complex_loop( float ); break; case IM_BANDFMT_DPCOMPLEX: complex_loop( double ); break; default: assert( 0 ); } if( seq->valid ) { seq->value = IM_MIN( seq->value, m ); } else { seq->value = m; seq->valid = 1; } return( 0 ); }