/* Copy a small area. */ static int vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsRect *r = &or->valid; VipsCopy *copy = (VipsCopy *) b; SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt]; /* Ask for input we need. */ if( vips_region_prepare( ir, r ) ) return( -1 ); if( copy->swap && swap ) { int y; for( y = 0; y < r->height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y ); VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y ); swap( p, q, r->width, copy->in ); } } else /* Nothing to do, just copy with pointers. */ if( vips_region_region( or, ir, r, r->left, r->top ) ) return( -1 ); return( 0 ); }
static int vips_bandary_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion **ir = (VipsRegion **) seq; VipsBandary *bandary = (VipsBandary *) b; VipsBandaryClass *class = VIPS_BANDARY_GET_CLASS( bandary ); VipsRect *r = &or->valid; VipsPel *p[MAX_INPUT_IMAGES], *q; int y, i; for( i = 0; i < bandary->n; i++ ) { if( vips_region_prepare( ir[i], r ) ) return( -1 ); p[i] = VIPS_REGION_ADDR( ir[i], r->left, r->top ); } p[i] = NULL; q = VIPS_REGION_ADDR( or, r->left, r->top ); VIPS_GATE_START( "vips_bandary_gen: work" ); for( y = 0; y < r->height; y++ ) { class->process_line( bandary, q, p, r->width ); for( i = 0; i < bandary->n; i++ ) p[i] += VIPS_REGION_LSKIP( ir[i] ); q += VIPS_REGION_LSKIP( or ); } VIPS_GATE_STOP( "vips_bandary_gen: work" ); return( 0 ); }
static int vips_colour_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion **ir = (VipsRegion **) seq; VipsColour *colour = VIPS_COLOUR( b ); VipsColourClass *class = VIPS_COLOUR_GET_CLASS( colour ); VipsRect *r = &or->valid; int i, y; VipsPel *p[MAX_INPUT_IMAGES], *q; for( i = 0; ir[i]; i++ ) if( vips_region_prepare( ir[i], r ) ) return( -1 ); VIPS_GATE_START( "vips_colour_gen: work" ); for( y = 0; y < r->height; y++ ) { for( i = 0; ir[i]; i++ ) p[i] = VIPS_REGION_ADDR( ir[i], r->left, r->top + y ); p[i] = NULL; q = VIPS_REGION_ADDR( or, r->left, r->top + y ); class->process_line( colour, q, p, r->width ); } VIPS_GATE_STOP( "vips_colour_gen: work" ); return( 0 ); }
static int vips_rot180_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsImage *in = (VipsImage *) a; /* Output area. */ VipsRect *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; /* Pixel geometry. */ int ps; /* Find the area of the input image we need. */ Rect need; need.left = in->Xsize - ri; need.top = in->Ysize - bo; need.width = r->width; need.height = r->height; if( vips_region_prepare( ir, &need ) ) return( -1 ); /* Find PEL size and line skip for ir. */ ps = VIPS_IMAGE_SIZEOF_PEL( in ); /* Rotate the bit we now have. */ for( y = to; y < bo; y++ ) { /* Start of this output line. */ VipsPel *q = VIPS_REGION_ADDR( or, le, y ); /* Corresponding position in ir. */ VipsPel *p = VIPS_REGION_ADDR( ir, need.left + need.width - 1, need.top + need.height - (y - to) - 1 ); /* Blap across! */ for( x = le; x < ri; x++ ) { memcpy( q, p, ps ); q += ps; p -= ps; } } return( 0 ); }
static int vips_msb_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsMsb *msb = (VipsMsb *) b; VipsConversion *conversion = (VipsConversion *) msb; VipsRect *r = &or->valid; int le = r->left; int to = r->top; int bo = VIPS_RECT_BOTTOM( r ); int sz = r->width * conversion->out->Bands; int x, y, i; if( vips_region_prepare( ir, r ) ) return( -1 ); for( y = to; y < bo; y++ ) { VipsPel *p = VIPS_REGION_ADDR( ir, le, y ); VipsPel *q = VIPS_REGION_ADDR( or, le, y ); if( msb->in->Coding == VIPS_CODING_LABQ && msb->band == -1 ) { /* LABQ, no sub-band select. */ for( x = 0; x < r->width; x++ ) { q[0] = p[0]; q[1] = 0x80 ^ p[1]; q[2] = 0x80 ^ p[2]; q += 4; p += 3; } } else if( msb->sign ) { /* Copy, converting signed to unsigned. */ p += msb->offset; for( i = 0; i < sz; i++ ) { q[i] = 0x80 ^ *p; p += msb->instep; } } else { /* Just pick out bytes. */ p += msb->offset; for( i = 0; i < sz; i++ ) { q[i] = *p; p += msb->instep; } } } return( 0 ); }
/* Paint the part of the region containing only whole pels. */ static void vips_zoom_paint_whole( VipsRegion *or, VipsRegion *ir, VipsZoom *zoom, const int left, const int right, const int top, const int bottom ) { const int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im ); const int ls = VIPS_REGION_LSKIP( or ); const int rs = ps * (right - left); /* Transform to ir coordinates. */ const int ileft = left / zoom->xfac; const int iright = right / zoom->xfac; const int itop = top / zoom->yfac; const int ibottom = bottom / zoom->yfac; int x, y, z, i; /* We know this! */ g_assert( right > left && bottom > top && right % zoom->xfac == 0 && left % zoom->xfac == 0 && top % zoom->yfac == 0 && bottom % zoom->yfac == 0 ); /* Loop over input, as we know we are all whole. */ for( y = itop; y < ibottom; y++ ) { VipsPel *p = VIPS_REGION_ADDR( ir, ileft, y ); VipsPel *q = VIPS_REGION_ADDR( or, left, y * zoom->yfac ); VipsPel *r; /* Expand the first line of pels. */ r = q; for( x = ileft; x < iright; x++ ) { /* Copy each pel xfac times. */ for( z = 0; z < zoom->xfac; z++ ) { for( i = 0; i < ps; i++ ) r[i] = p[i]; r += ps; } p += ps; } /* Copy the expanded line yfac-1 times. */ r = q + ls; for( z = 1; z < zoom->yfac; z++ ) { memcpy( r, q, rs ); r += ls; } } }
static int vips_flip_horizontal_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsRect *r = &or->valid; VipsRect in; VipsPel *p, *q; int x, y, z; int le = r->left; int ri = VIPS_RECT_RIGHT(r); int to = r->top; int bo = VIPS_RECT_BOTTOM(r); int ps = VIPS_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 = VIPS_RECT_RIGHT( &in ) - 1; /* Ask for input we need. */ if( vips_region_prepare( ir, &in ) ) return( -1 ); /* Loop, copying and reversing lines. */ for( y = to; y < bo; y++ ) { p = VIPS_REGION_ADDR( ir, lastx, y ); q = VIPS_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 ); }
/* Generate an area of @or. @ir is large enough. */ static void vips_shrink2_gen2( VipsShrink2 *shrink, VipsShrink2Sequence *seq, VipsRegion *or, VipsRegion *ir, int left, int top, int width, int height ) { VipsResample *resample = VIPS_RESAMPLE( shrink ); const int bands = resample->in->Bands; const int sizeof_pixel = VIPS_IMAGE_SIZEOF_PEL( resample->in ); const int ls = VIPS_REGION_LSKIP( ir ) / VIPS_IMAGE_SIZEOF_ELEMENT( resample->in ); int x, y, i; int x1, y1, b; for( y = 0; y < height; y++ ) { VipsPel *out = VIPS_REGION_ADDR( or, left, top + y ); for( x = 0; x < width; x++ ) { int ix = (left + x) * shrink->xshrink; int iy = (top + y) * shrink->yshrink; VipsPel *in = VIPS_REGION_ADDR( ir, ix, iy ); switch( resample->in->BandFmt ) { case VIPS_FORMAT_UCHAR: ISHRINK( unsigned char ); break; case VIPS_FORMAT_CHAR: ISHRINK( char ); break; case VIPS_FORMAT_USHORT: ISHRINK( unsigned short ); break; case VIPS_FORMAT_SHORT: ISHRINK( short ); break; case VIPS_FORMAT_UINT: ISHRINK( unsigned int ); break; case VIPS_FORMAT_INT: ISHRINK( int ); break; case VIPS_FORMAT_FLOAT: FSHRINK( float ); break; case VIPS_FORMAT_DOUBLE: FSHRINK( double ); break; default: g_assert( 0 ); } out += sizeof_pixel; } } }
/* Paint r of region or. It's a border area, lying entirely within * embed->border[i]. p points to the top-left source pixel to fill with. * plsk is the line stride. */ static void vips_embed_paint_edge( VipsEmbed *embed, VipsRegion *or, int i, VipsRect *r, VipsPel *p, int plsk ) { const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->in ); VipsRect todo; VipsPel *q; int y; VIPS_GATE_START( "vips_embed_paint_edge: work" ); /* Pixels left to paint. */ todo = *r; /* Corner pieces ... copy the single pixel to paint the top line of * todo, then use the line copier below to paint the rest of it. */ if( i > 3 ) { q = VIPS_REGION_ADDR( or, todo.left, todo.top ); vips_embed_copy_pixel( embed, q, p, todo.width ); p = q; todo.top += 1; todo.height -= 1; } if( i == 1 || i == 3 ) { /* Vertical line of pixels to copy. */ for( y = 0; y < todo.height; y++ ) { q = VIPS_REGION_ADDR( or, todo.left, todo.top + y ); vips_embed_copy_pixel( embed, q, p, todo.width ); p += plsk; } } else { /* Horizontal line of pixels to copy. */ for( y = 0; y < todo.height; y++ ) { q = VIPS_REGION_ADDR( or, todo.left, todo.top + y ); memcpy( q, p, bs * todo.width ); } } VIPS_GATE_STOP( "vips_embed_paint_edge: work" ); }
static int write_png_block( VipsRegion *region, VipsRect *area, void *a ) { Write *write = (Write *) a; int i; /* The area to write is always a set of complete scanlines. */ g_assert( area->left == 0 ); g_assert( area->width == region->im->Xsize ); g_assert( area->top + area->height <= region->im->Ysize ); /* Catch PNG errors. Yuk. */ if( setjmp( png_jmpbuf( write->pPng ) ) ) return( -1 ); for( i = 0; i < area->height; i++ ) write->row_pointer[i] = (png_bytep) VIPS_REGION_ADDR( region, 0, area->top + i ); png_write_rows( write->pPng, write->row_pointer, area->height ); return( 0 ); }
static int vips_gaussnoise_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsGaussnoise *gaussnoise = (VipsGaussnoise *) a; int sz = VIPS_REGION_N_ELEMENTS( or ); int y; for( y = 0; y < or->valid.height; y++ ) { float *q = (float *) VIPS_REGION_ADDR( or, or->valid.left, y + or->valid.top ); int x; for( x = 0; x < sz; x++ ) { double sum; int i; sum = 0.0; for( i = 0; i < 12; i++ ) sum += g_random_double(); q[x] = (sum - 6.0) * gaussnoise->sigma + gaussnoise->mean; } } 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; VipsPel *p; VIPS_DEBUG_MSG( "vips_statistic_scan: %d x %d @ %d x %d\n", r->width, r->height, r->left, r->top ); p = VIPS_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 ); }
static int vips_worley_gen( VipsRegion *or, void *vseq, void *a, void *b, gboolean *stop ) { VipsWorley *worley = (VipsWorley *) a; VipsRect *r = &or->valid; Sequence *seq = (Sequence *) vseq; int x, y; for( y = 0; y < r->height; y++ ) { int *q = (int *) VIPS_REGION_ADDR( or, r->left, r->top + y ); for( x = 0; x < r->width; x++ ) { int cell_x = (r->left + x) / worley->cell_size; int cell_y = (r->top + y) / worley->cell_size; if( cell_x != seq->cell_x || cell_y != seq->cell_y ) { vips_worley_create_cells( worley, seq->cells, cell_x, cell_y ); seq->cell_x = cell_x; seq->cell_y = cell_y; } q[x] = vips_worley_distance( worley, seq->cells, r->left + x, r->top + y ); } } return( 0 ); }
static int magick_fill_region( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop ) { Read *read = (Read *) a; VipsRect *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 ) { vips_error( "magick2vips", "%s", _( "unable to read pixels" ) ); return( -1 ); } unpack_pixels( read->im, VIPS_REGION_ADDR( out, r->left, top ), pixels, r->width ); } return( 0 ); }
/* Fetch one pixel at a time ... good for very large shrinks. */ static int vips_subsample_point_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsSubsample *subsample = (VipsSubsample *) b; VipsImage *in = (VipsImage *) a; VipsRect *r = &or->valid; int le = r->left; int ri = VIPS_RECT_RIGHT( r ); int to = r->top; int bo = VIPS_RECT_BOTTOM(r); int ps = VIPS_IMAGE_SIZEOF_PEL( in ); VipsRect s; int x, y; int k; /* Loop down the region. */ for( y = to; y < bo; y++ ) { VipsPel *q = VIPS_REGION_ADDR( or, le, y ); VipsPel *p; /* Loop across the region, in owidth sized pieces. */ for( x = le; x < ri; x++ ) { /* Ask for input. */ s.left = x * subsample->xfac; s.top = y * subsample->yfac; s.width = 1; s.height = 1; if( vips_region_prepare( ir, &s ) ) return( -1 ); /* Append new pels to output. */ p = VIPS_REGION_ADDR( ir, s.left, s.top ); for( k = 0; k < ps; k++ ) q[k] = p[k]; q += ps; } } return( 0 ); }
static int vips_fits_write( VipsRegion *region, VipsRect *area, void *a ) { VipsFits *fits = (VipsFits *) a; VipsImage *image = fits->image; int es = VIPS_IMAGE_SIZEOF_ELEMENT( image ); int ps = VIPS_IMAGE_SIZEOF_PEL( image ); int status; int y, b, x, k; status = 0; VIPS_DEBUG_MSG( "vips_fits_write: " "writing left = %d, top = %d, width = %d, height = %d\n", area->left, area->top, area->width, area->height ); /* We need to write a band at a time. We can't bandsplit in vips, * since vips_sink_disc() can't loop over many images at once, sadly. */ for( y = 0; y < area->height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( region, area->left, area->top + y ); for( b = 0; b < image->Bands; b++ ) { VipsPel *p1, *q; long fpixel[3]; p1 = p + b * es; q = fits->buffer; for( x = 0; x < area->width; x++ ) { for( k = 0; k < es; k++ ) q[k] = p1[k]; q += es; p1 += ps; } fpixel[0] = area->left + 1; fpixel[1] = area->top + y + 1; fpixel[2] = b + 1; /* No need to lock, write functions are single-threaded. */ if( fits_write_pix( fits->fptr, fits->datatype, fpixel, area->width, fits->buffer, &status ) ) { vips_fits_error( status ); return( -1 ); } } } return( 0 ); }
static int vips_flip_vertical_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsRect *r = &or->valid; VipsRect in; VipsPel *p, *q; int y; int le = r->left; int to = r->top; int bo = VIPS_RECT_BOTTOM( r ); int ls; int psk, qsk; /* Transform to input coordinates. */ in = *r; in.top = ir->im->Ysize - bo; /* Ask for input we need. */ if( vips_region_prepare( ir, &in ) ) return( -1 ); /* Loop, copying and reversing lines. */ p = VIPS_REGION_ADDR( ir, le, in.top + in.height - 1 ); q = VIPS_REGION_ADDR( or, le, to ); psk = VIPS_REGION_LSKIP( ir ); qsk = VIPS_REGION_LSKIP( or ); ls = VIPS_REGION_SIZEOF_LINE( or ); for( y = to; y < bo; y++ ) { memcpy( q, p, ls ); p -= psk; q += qsk; } return( 0 ); }
/* Copy rect from @from to @to. */ static void copy_region( VipsRegion *from, VipsRegion *to, VipsRect *area ) { int y; /* Area should be inside both from and to. */ g_assert( vips_rect_includesrect( &from->valid, area ) ); g_assert( vips_rect_includesrect( &to->valid, area ) ); /* Loop down common area, copying. */ for( y = area->top; y < VIPS_RECT_BOTTOM( area ); y++ ) { VipsPel *p = VIPS_REGION_ADDR( from, area->left, y ); VipsPel *q = VIPS_REGION_ADDR( to, area->left, y ); memcpy( q, p, VIPS_IMAGE_SIZEOF_PEL( from->im ) * area->width ); } }
static int read_jpeg_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRect *r = &or->valid; ReadJpeg *jpeg = (ReadJpeg *) a; struct jpeg_decompress_struct *cinfo = &jpeg->cinfo; int sz = cinfo->output_width * cinfo->output_components; int y; #ifdef DEBUG printf( "read_jpeg_generate: line %d, %d rows\n", r->top, r->height ); #endif /*DEBUG*/ /* We're inside a tilecache where tiles are the full image width, so * this should always be true. */ g_assert( r->left == 0 ); g_assert( r->width == or->im->Xsize ); g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize ); /* Tiles should always be on a 8-pixel boundary. */ g_assert( r->top % 8 == 0 ); /* Tiles should always be a strip in height, unless it's the final * strip. */ g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) ); /* Here for longjmp() from vips__new_error_exit(). */ if( setjmp( jpeg->eman.jmp ) ) return( -1 ); for( y = 0; y < r->height; y++ ) { JSAMPROW row_pointer[1]; row_pointer[0] = (JSAMPLE *) VIPS_REGION_ADDR( or, 0, r->top + y ); jpeg_read_scanlines( cinfo, &row_pointer[0], 1 ); if( jpeg->invert_pels ) { int x; for( x = 0; x < sz; x++ ) row_pointer[0][x] = 255 - row_pointer[0][x]; } } return( 0 ); }
/* Generate an area of @or. @ir is large enough. */ static void vips_shrinkh_gen2( VipsShrinkh *shrink, VipsShrinkhSequence *seq, VipsRegion *or, VipsRegion *ir, int left, int top, int width ) { VipsResample *resample = VIPS_RESAMPLE( shrink ); const int bands = resample->in->Bands * (vips_band_format_iscomplex( resample->in->BandFmt ) ? 2 : 1); const int ne = shrink->xshrink * bands; VipsPel *out = VIPS_REGION_ADDR( or, left, top ); VipsPel *in = VIPS_REGION_ADDR( ir, left * shrink->xshrink, top ); int x; int x1, b; switch( resample->in->BandFmt ) { case VIPS_FORMAT_UCHAR: ISHRINK( unsigned char ); break; case VIPS_FORMAT_CHAR: ISHRINK( char ); break; case VIPS_FORMAT_USHORT: ISHRINK( unsigned short ); break; case VIPS_FORMAT_SHORT: ISHRINK( short ); break; case VIPS_FORMAT_UINT: ISHRINK( unsigned int ); break; case VIPS_FORMAT_INT: ISHRINK( int ); break; case VIPS_FORMAT_FLOAT: FSHRINK( float ); break; case VIPS_FORMAT_DOUBLE: FSHRINK( double ); break; case VIPS_FORMAT_COMPLEX: FSHRINK( float ); break; case VIPS_FORMAT_DPCOMPLEX: FSHRINK( double ); break; default: g_assert( 0 ); } }
static int png2vips_generate( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRect *r = &or->valid; Read *read = (Read *) a; int y; #ifdef DEBUG printf( "png2vips_generate: line %d, %d rows\n", r->top, r->height ); #endif /*DEBUG*/ /* We're inside a tilecache where tiles are the full image width, so * this should always be true. */ g_assert( r->left == 0 ); g_assert( r->width == or->im->Xsize ); g_assert( VIPS_RECT_BOTTOM( r ) <= or->im->Ysize ); /* Tiles should always be a strip in height, unless it's the final * strip. */ g_assert( r->height == VIPS_MIN( 8, or->im->Ysize - r->top ) ); /* And check that y_pos is correct. It should be, since we are inside * a vips_sequential(). */ g_assert( r->top == read->y_pos ); for( y = 0; y < r->height; y++ ) { png_bytep q = (png_bytep) VIPS_REGION_ADDR( or, 0, r->top + y ); /* We need to catch and ignore errors from read_row(). */ if( !setjmp( png_jmpbuf( read->pPng ) ) ) png_read_row( read->pPng, q, NULL ); else { #ifdef DEBUG printf( "png2vips_generate: png_read_row() failed, " "line %d\n", r->top + y ); printf( "png2vips_generate: file %s\n", read->name ); printf( "png2vips_generate: thread %p\n", g_thread_self() ); #endif /*DEBUG*/ } read->y_pos += 1; } return( 0 ); }
static int vips_recomb_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsRecomb *recomb = (VipsRecomb *) b; VipsImage *im = recomb->in; int mwidth = recomb->m->Xsize; int mheight = recomb->m->Ysize; int y, x, u, v; if( vips_region_prepare( ir, &or->valid ) ) return( -1 ); for( y = 0; y < or->valid.height; y++ ) { PEL *in = (PEL *) VIPS_REGION_ADDR( ir, or->valid.left, or->valid.top + y ); PEL *out = (PEL *) VIPS_REGION_ADDR( or, or->valid.left, or->valid.top + y ); switch( vips_image_get_format( im ) ) { case VIPS_FORMAT_UCHAR: LOOP( unsigned char, float ); break; case VIPS_FORMAT_CHAR: LOOP( signed char, float ); break; case VIPS_FORMAT_USHORT:LOOP( unsigned short, float ); break; case VIPS_FORMAT_SHORT: LOOP( signed short, float ); break; case VIPS_FORMAT_UINT: LOOP( unsigned int, float ); break; case VIPS_FORMAT_INT: LOOP( signed int, float ); break; case VIPS_FORMAT_FLOAT: LOOP( float, float ); break; case VIPS_FORMAT_DOUBLE:LOOP( double, double ); break; default: g_assert( 0 ); } } return( 0 ); }
/* Byteswap, turning bands into the x axis. */ static int vips_byteswap_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion *ir = (VipsRegion *) seq; VipsImage *im = ir->im; VipsRect *r = &or->valid; SwapFn swap = vips_byteswap_swap_fn[im->BandFmt]; int y; if( vips_region_prepare( ir, r ) ) return( -1 ); for( y = 0; y < r->height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( ir, r->left, r->top + y ); VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y ); swap( p, q, r->width, im ); } return( 0 ); }
void vips_executor_set_scanline( VipsExecutor *executor, VipsRegion *ir, int x, int y ) { VipsVector *vector = executor->vector; VipsPel *base = VIPS_REGION_ADDR( ir, x, y ); int lsk = VIPS_REGION_LSKIP( ir ); int i; for( i = 0; i < vector->n_scanline; i++ ) vips_executor_set_array( executor, vector->sl[i], base + vector->line[i] * lsk ); }
static int vips_bandunfold_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsBandunfold *bandunfold = (VipsBandunfold *) b; VipsRegion *ir = (VipsRegion *) seq; VipsImage *in = ir->im; VipsImage *out = or->im; VipsRect *r = &or->valid; int esize = VIPS_IMAGE_SIZEOF_ELEMENT( in ); int psize = VIPS_IMAGE_SIZEOF_PEL( out ); VipsRect need; int y; need.left = r->left / bandunfold->factor; need.top = r->top; need.width = (1 + r->width) / bandunfold->factor; need.height = r->height; if( vips_region_prepare( ir, &need ) ) return( -1 ); for( y = 0; y < r->height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( ir, r->left / bandunfold->factor, r->top + y ) + (r->left % bandunfold->factor) * esize; VipsPel *q = VIPS_REGION_ADDR( or, r->left, r->top + y ); /* We can't use vips_region_region() since we change pixel * coordinates. */ memcpy( q, p, r->width * psize ); } return( 0 ); }
static int vips_arithmetic_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsRegion **ir = (VipsRegion **) seq; VipsArithmetic *arithmetic = VIPS_ARITHMETIC( b ); VipsArithmeticClass *class = VIPS_ARITHMETIC_GET_CLASS( arithmetic ); Rect *r = &or->valid; VipsPel *p[MAX_INPUT_IMAGES], *q; int i, y; /* Prepare all input regions and make buffer pointers. */ for( i = 0; ir[i]; i++ ) { if( vips_region_prepare( ir[i], r ) ) return( -1 ); p[i] = (VipsPel *) VIPS_REGION_ADDR( ir[i], r->left, r->top ); } p[i] = NULL; q = (VipsPel *) VIPS_REGION_ADDR( or, r->left, r->top ); VIPS_GATE_START( "vips_arithmetic_gen: work" ); for( y = 0; y < r->height; y++ ) { class->process_line( arithmetic, q, p, r->width ); for( i = 0; ir[i]; i++ ) p[i] += VIPS_REGION_LSKIP( ir[i] ); q += VIPS_REGION_LSKIP( or ); } VIPS_GATE_STOP( "vips_arithmetic_gen: work" ); return( 0 ); }
static int write_ppm_block( REGION *region, Rect *area, void *a ) { Write *write = (Write *) a; int i; for( i = 0; i < area->height; i++ ) { VipsPel *p = VIPS_REGION_ADDR( region, 0, area->top + i ); if( write->fn( write->in, write->fp, p ) ) return( -1 ); } return( 0 ); }
static int vips_xyz_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop ) { VipsXyz *xyz = (VipsXyz *) a; VipsRect *r = &or->valid; int le = r->left; int to = r->top; int ri = VIPS_RECT_RIGHT( r ); int bo = VIPS_RECT_BOTTOM( r ); int x, y, i; for( y = to; y < bo; y++ ) { unsigned int *q = (unsigned int *) VIPS_REGION_ADDR( or, le, y ); unsigned int dims[5]; int r; int h; h = xyz->height * xyz->csize * xyz->dsize; dims[4] = y / h; r = y % h; h /= xyz->dsize; dims[3] = r / h; r %= h; h /= xyz->csize; dims[2] = r / h; r %= h; dims[1] = r; for( x = le; x < ri; x++ ) { dims[0] = x; for( i = 0; i < xyz->dimensions; i++ ) q[i] = dims[i]; q += xyz->dimensions; } } return( 0 ); }
static int vips__gdal_generate( VipsRegion *out, void *_seq, void *_read, void *unused, gboolean *stop ) { Read *read = _read; VipsRect *r = &out->valid; int n = r->width * r->height; unsigned char *buf = (unsigned char *) VIPS_REGION_ADDR( out, r->left, r->top ); VIPS_DEBUG_MSG( "vips__gdal_generate: %dx%d @ %dx%d\n", r->width, r->height, r->left, r->top ); /* We're inside a cache, so requests should always be * tile_width by tile_height pixels and on a tile boundary. */ g_assert( (r->left % read->tile_width) == 0 ); g_assert( (r->top % read->tile_height) == 0 ); g_assert( r->width <= read->tile_width ); g_assert( r->height <= read->tile_height ); g_assert( read->data_type == GDT_Byte ); g_assert( GDALGetRasterCount ); for (int channel = 0; channel < 3; ++channel) { GDALRasterBandH hBand; hBand = GDALGetRasterBand( read->hDataset, channel + 1 ); unsigned char* gdal_data; gdal_data = (unsigned char*) CPLMalloc(sizeof(unsigned char) * r->width * r->height); GDALRasterIO( hBand, GF_Read, r->left, r->top, r->width, r->height, gdal_data, r->width, r->height, GDT_Byte, 0, 0 ); for (int i = 0; i < r->width * r->height; ++i) { buf[i * 3 + channel] = gdal_data[i]; } CPLFree (gdal_data); } return( 0 ); }
/* Write tileh scanlines, less for the last strip. */ static int layer_write_strip( Write *write, Layer *layer, VipsRegion *strip ) { VipsImage *im = layer->image; VipsRect *area = &strip->valid; int height = VIPS_MIN( write->tileh, area->height ); int y; #ifdef DEBUG_VERBOSE printf( "Writing %d pixel strip at height %d to image %s\n", height, area->top, TIFFFileName( layer->tif ) ); #endif /*DEBUG_VERBOSE*/ for( y = 0; y < height; y++ ) { VipsPel *p = VIPS_REGION_ADDR( strip, 0, area->top + y ); /* Any repacking necessary. */ if( im->Coding == VIPS_CODING_LABQ ) { LabQ2LabC( write->tbuf, p, im->Xsize ); p = write->tbuf; } else if( im->BandFmt == VIPS_FORMAT_SHORT && im->Type == VIPS_INTERPRETATION_LABS ) { LabS2Lab16( write->tbuf, p, im->Xsize ); p = write->tbuf; } else if( write->onebit ) { eightbit2onebit( write, write->tbuf, p, im->Xsize ); p = write->tbuf; } else if( (im->Bands == 1 || im->Bands == 2) && write->miniswhite ) { invert_band0( write, write->tbuf, p, im->Xsize ); p = write->tbuf; } if( TIFFWriteScanline( layer->tif, p, area->top + y, 0 ) < 0 ) return( -1 ); } return( 0 ); }