/* We need to make pixels using reg's generate function, and write the result * to dest. */ static int im_prepare_to_generate( REGION *reg, REGION *dest, Rect *r, int x, int y ) { IMAGE *im = reg->im; char *p; if( !im->generate ) { im_error( "im_prepare_to", _( "incomplete header" ) ); return( -1 ); } if( im_region_region( reg, dest, r, x, y ) ) return( -1 ); /* Remember where reg is pointing now. */ p = IM_REGION_ADDR( reg, reg->valid.left, reg->valid.top ); /* Run sequence into reg. */ if( fill_region( reg ) ) return( -1 ); /* The generate function may not have actually made any pixels ... it * might just have redirected reg to point somewhere else. If it has, * we need an extra copy operation. */ if( IM_REGION_ADDR( reg, reg->valid.left, reg->valid.top ) != p ) im__copy_region( reg, dest, r, x, y ); 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 ); }
/* 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 ); }
/* 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 = ®->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 ); }
/* 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 ); }
/* 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 ); }
/* Generate function. */ static int make_vert_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 x, y, z; for( y = to; y < bo; y++ ) { VipsPel *q = IM_REGION_ADDR( or, le, y ); VipsPel *p = IM_IMAGE_ADDR( in, 0, y ); switch( in->BandFmt ) { case IM_BANDFMT_UCHAR: VERT( unsigned char ); break; case IM_BANDFMT_CHAR: VERT( signed char ); break; case IM_BANDFMT_USHORT: VERT( unsigned short ); break; case IM_BANDFMT_SHORT: VERT( signed short ); break; case IM_BANDFMT_UINT: VERT( unsigned int ); break; case IM_BANDFMT_INT: VERT( signed int ); break; case IM_BANDFMT_FLOAT: VERT( float ); break; case IM_BANDFMT_DOUBLE: VERT( double ); break; default: g_assert( 0 ); } } return( 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 = ®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 ); }
/** * 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 ); }
/*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 ); }
static int magick_fill_region( REGION *out, void *seq, void *a, void *b ) { Read *read = (Read *) a; Rect *r = &out->valid; int y; for( y = 0; y < r->height; y++ ) { int top = r->top + y; int frame = top / read->frame_height; int line = top % read->frame_height; PixelPacket *pixels; g_mutex_lock( read->lock ); pixels = get_pixels( read->frames[frame], r->left, line, r->width, 1 ); g_mutex_unlock( read->lock ); if( !pixels ) { im_error( "im_magick2vips", "%s", _( "unable to read pixels" ) ); return( -1 ); } unpack_pixels( read->im, (PEL *) IM_REGION_ADDR( out, r->left, top ), pixels, r->width ); } return( 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 ); }
/* 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 ); }
/* Copy rect from from to to. */ static void copy_region( REGION *from, REGION *to, Rect *area ) { int y; /* Area should be inside both from and to. */ g_assert( im_rect_includesrect( &from->valid, area ) ); g_assert( im_rect_includesrect( &to->valid, area ) ); /* Loop down common area, copying. */ for( y = area->top; y < IM_RECT_BOTTOM( area ); y++ ) { PEL *p = (PEL *) IM_REGION_ADDR( from, area->left, y ); PEL *q = (PEL *) IM_REGION_ADDR( to, area->left, y ); memcpy( q, p, IM_IMAGE_SIZEOF_PEL( from->im ) * area->width ); } }
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; }
/* 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 ); }
/* 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; } }
/* 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 int write_block( REGION *region, Rect *area, void *a ) { Write *write = (Write *) a; int i; for( i = 0; i < area->height; i++ ) { PEL *p = (PEL *) IM_REGION_ADDR( region, area->left, area->top + i ); if( im__write( write->fd, p, IM_IMAGE_SIZEOF_PEL(write->in)*area->width ) ) return( -1 ); } return( 0 ); }
/* Return the position of the first non-zero pel from the right. */ static int find_last( REGION *ir, int *pos, int x, int y, int w ) { PEL *pr = (PEL *) IM_REGION_ADDR( ir, x, y ); IMAGE *im = ir->im; int ne = w * im->Bands; int i; /* Double the number of bands in a complex. */ if( vips_bandfmt_iscomplex( im->BandFmt ) ) ne *= 2; /* Search for the first non-zero band element from the right. */ #define rsearch( TYPE ) { \ TYPE *p = (TYPE *) pr; \ \ for( i = ne - 1; i >= 0; i-- )\ if( p[i] )\ break;\ } 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_lrmerge", "%s", _( "internal error" ) ); return( -1 ); } /* i is first non-zero band element, we want first non-zero pixel. */ *pos = x + i / im->Bands; return( 0 ); }
/* A write function for VIPS images. Just write() the pixel data. */ static int write_vips( REGION *region, Rect *area, void *a, void *b ) { size_t nwritten, count; void *buf; count = region->bpl * area->height; buf = IM_REGION_ADDR( region, 0, area->top ); do { nwritten = write( region->im->fd, buf, count ); if( nwritten == (size_t) -1 ) return( errno ); buf = (void *) ((char *) buf + nwritten); count -= nwritten; } while( count > 0 ); return( 0 ); }
/* Generate function. */ static int fgrey_gen( REGION *or, void *seq, void *a, void *b ) { Rect *r = &or->valid; int le = r->left; int to = r->top; int iwm = or->im->Xsize - 1; int x, y; for( y = 0; y < r->height; y++ ) { float *q = (float *) IM_REGION_ADDR( or, le, y + to ); for( x = 0; x < r->width; x++ ) q[x] = (float) (x + le) / iwm; } return( 0 ); }
static int write_jpeg_block( REGION *region, Rect *area, void *a ) { Write *write = (Write *) a; int i; /* We are running in a background thread. We need to catch longjmp()s * here instead. */ if( setjmp( write->eman.jmp ) ) return( -1 ); for( i = 0; i < area->height; i++ ) write->row_pointer[i] = (JSAMPROW) IM_REGION_ADDR( region, 0, area->top + i ); jpeg_write_scanlines( &write->cinfo, write->row_pointer, area->height ); return( 0 ); }
static int find_hist( REGION *reg, void *seq, void *a, void *b ) { Histogram *hist = (Histogram *) seq; Rect *r = ®->valid; IMAGE *im = reg->im; int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); int nb = im->Bands; int max_val = im->BandFmt == IM_BANDFMT_UCHAR ? 256 : 65536; int scale = max_val / hist->bins; int x, y, z, i; int index[3]; /* Fill these with dimensions, backwards. */ index[0] = index[1] = index[2] = 0; /* Accumulate! */ for( y = to; y < bo; y++ ) { char *line = IM_REGION_ADDR( reg, le, y ); switch( im->BandFmt ) { case IM_BANDFMT_UCHAR: LOOP( unsigned char ); break; case IM_BANDFMT_USHORT: LOOP( unsigned char ); break; default: error_exit( "panic #34847563245" ); } } return( 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; }
/* Generate function. */ static int make_xy_gen( REGION *or, void *seq, void *a, void *b ) { 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 x, y; for( y = to; y < bo; y++ ) { unsigned int *q = (unsigned int *) IM_REGION_ADDR( or, le, y ); for( x = le; x < ri; x++ ) { q[0] = x; q[1] = y; q += 2; } } return( 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 ); }