/* Plot a point in an image. */ int im_plotpoint( IMAGE *im, int x, int y, PEL *pel ) { int es = IM_IMAGE_SIZEOF_ELEMENT( im ); int ps = es * im->Bands; int ls = ps * im->Xsize; int b; PEL *to; if( im_rwcheck( im ) ) return( -1 ); /* Check coordinates in range. */ if( x > im->Xsize || x < 0 || y > im->Ysize || y < 0 ) return( 0 ); /* Paint single pixel. */ to = (PEL *) im->data + x * ps + y * ls; for( b = 0; b < ps; b++ ) *to++ = *pel++; return( 0 ); }
/* Read a colour from an image. */ int im_readpoint( IMAGE *im, int x, int y, PEL *pel ) { int es = IM_IMAGE_SIZEOF_ELEMENT( im ); int ps = es * im->Bands; int ls = ps * im->Xsize; int b; PEL *from; if( im_rwcheck( im ) ) return( -1 ); /* Check coordinates in range. */ if( x > im->Xsize || x < 0 || y > im->Ysize || y < 0 ) { im_error( "im_readpoint", "%s", _( "invalid cooordinates" ) ); return( 1 ); } /* Suck single pixel. */ from = (PEL *) im->data + x * ps + y * ls; for( b = 0; b < ps; b++ ) *pel++ = *from++; return( 0 ); }
static int mat2vips_get_data( mat_t *mat, matvar_t *var, IMAGE *im ) { int y; PEL *buffer; const int es = IM_IMAGE_SIZEOF_ELEMENT( im ); /* Matlab images are plane-separate, so we have to assemble bands in * image-size chunks. */ const int is = es * im->Xsize * im->Ysize; if( Mat_VarReadDataAll( mat, var ) ) { im_error( "im_mat2vips", "%s", _( "Mat_VarReadDataAll failed" ) ); return( -1 ); } if( im_outcheck( im ) || im_setupout( im ) ) return( -1 ); /* Matlab images are in columns, so we have to transpose into * scanlines with this buffer. */ if( !(buffer = IM_ARRAY( im, IM_IMAGE_SIZEOF_LINE( im ), PEL )) ) return( -1 ); for( y = 0; y < im->Ysize; y++ ) { const PEL *p = var->data + y * es; int x; PEL *q; q = buffer; for( x = 0; x < im->Xsize; x++ ) { int b; for( b = 0; b < im->Bands; b++ ) { const PEL *p2 = p + b * is; int z; for( z = 0; z < es; z++ ) q[z] = p2[z]; q += es; } p += es * im->Ysize; } if( im_writeline( y, im, buffer ) ) return( -1 ); } 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 ); }
static int vips2csv( IMAGE *in, FILE *fp, const char *sep ) { int w = IM_IMAGE_N_ELEMENTS( in ); int es = IM_IMAGE_SIZEOF_ELEMENT( in ); int x, y; PEL *p; p = (PEL *) in->data; for( y = 0; y < in->Ysize; y++ ) { for( x = 0; x < w; x++ ) { if( x > 0 ) fprintf( fp, "%s", sep ); switch( in->BandFmt ) { case IM_BANDFMT_UCHAR: PRINT_INT( unsigned char ); break; case IM_BANDFMT_CHAR: PRINT_INT( char ); break; case IM_BANDFMT_USHORT: PRINT_INT( unsigned short ); break; case IM_BANDFMT_SHORT: PRINT_INT( short ); break; case IM_BANDFMT_UINT: PRINT_INT( unsigned int ); break; case IM_BANDFMT_INT: PRINT_INT( int ); break; case IM_BANDFMT_FLOAT: PRINT_FLOAT( float ); break; case IM_BANDFMT_DOUBLE: PRINT_FLOAT( double ); break; case IM_BANDFMT_COMPLEX: PRINT_COMPLEX( float ); break; case IM_BANDFMT_DPCOMPLEX: PRINT_COMPLEX( double ); break; default: assert( 0 ); } p += es; } fprintf( fp, "\n" ); } return( 0 ); }
/* Build a lut table. */ static LutInfo * build_luts( IMAGE *out, IMAGE *lut ) { LutInfo *st; int i, x; VipsPel *q; if( !(st = IM_NEW( out, LutInfo )) ) return( NULL ); /* Make luts. We unpack the LUT image into a C 2D array to speed * processing. */ st->fmt = lut->BandFmt; st->es = IM_IMAGE_SIZEOF_ELEMENT( lut ); st->nb = lut->Bands; st->sz = lut->Xsize * lut->Ysize; st->clp = st->sz - 1; st->overflow = 0; st->table = NULL; if( im_add_evalstart_callback( out, (im_callback_fn) lut_start, st, NULL ) || im_add_evalend_callback( out, (im_callback_fn) lut_end, st, NULL ) ) return( NULL ); /* Attach tables. */ if( !(st->table = IM_ARRAY( out, lut->Bands, VipsPel * )) ) return( NULL ); for( i = 0; i < lut->Bands; i++ ) if( !(st->table[i] = IM_ARRAY( out, st->sz * st->es, VipsPel )) ) return( NULL ); /* Scan LUT and fill table. */ q = (VipsPel *) lut->data; for( x = 0; x < st->sz; x++ ) for( i = 0; i < st->nb; i++ ) { memcpy( st->table[i] + x * st->es, q, st->es ); q += st->es; } return( st ); }
/** * im_msb: * @in: input image * @out: output image * * Turn any integer image to 8-bit unsigned char by discarding all but the most * significant byte. * Signed values are converted to unsigned by adding 128. * * This operator also works for LABQ coding. * * See also: im_msb_band(). * * Returns: 0 on success, -1 on error */ int im_msb( IMAGE *in, IMAGE *out ) { Msb *msb; im_wrapone_fn func; if( in->Coding == IM_CODING_NONE && in->BandFmt == IM_BANDFMT_UCHAR ) return( im_copy( in, out ) ); if( im_piocheck( in, out ) || !(msb = IM_NEW( out, Msb )) ) return( -1 ); if( in->Coding == IM_CODING_NONE ) { if( im_check_int( "im_msb", in ) ) return( -1 ); msb->width = IM_IMAGE_SIZEOF_ELEMENT( in ); msb->index = im_amiMSBfirst() ? 0 : msb->width - 1; msb->repeat = in->Bands; if( vips_bandfmt_isuint( in->BandFmt ) ) func = (im_wrapone_fn) byte_select; else func = (im_wrapone_fn) byte_select_flip; } else if( IM_CODING_LABQ == in->Coding ) func = (im_wrapone_fn) msb_labq; else { im_error( "im_msb", "%s", _( "unknown coding" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->BandFmt = IM_BANDFMT_UCHAR; out->Coding = IM_CODING_NONE; return( im_wrapone( in, out, func, msb, NULL ) ); }
int im_resize_linear( IMAGE *in, IMAGE *out, int X, int Y ) { double dx, dy, xscale, yscale; double Xnew, Ynew; /* inv. coord. of the interpolated pt */ int x, y; int Xint, Yint; int bb; PEL *input, *opline; PEL *q, *p; int ils, ips, ies; /* Input and output line, pel and */ int ols, ops, oes; /* element sizes */ if( im_iocheck( in, out ) ) return( -1 ); if( im_iscomplex( in ) ) { im_errormsg( "im_lowpass: non-complex input only" ); return( -1 ); } if( in->Coding != IM_CODING_NONE ) { im_errormsg("im_lowpass: input should be uncoded"); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Xsize = X; out->Ysize = Y; if( im_setupout( out ) ) return( -1 ); ils = IM_IMAGE_SIZEOF_LINE( in ); ips = IM_IMAGE_SIZEOF_PEL( in ); ies = IM_IMAGE_SIZEOF_ELEMENT( in ); ols = IM_IMAGE_SIZEOF_LINE( out ); ops = IM_IMAGE_SIZEOF_PEL( out ); oes = IM_IMAGE_SIZEOF_ELEMENT( out ); /* buffer lines ***************/ if( !(opline = IM_ARRAY( out, ols, PEL )) ) return( -1 ); /* Resampling *************/ input = (PEL*) in->data; xscale = ((double)in->Xsize-1)/(X-1); yscale = ((double)in->Ysize-1)/(Y-1); for (y=0; y<Y; y++) { q = opline; for (x=0; x<X; x++) { Xnew = x*xscale; Ynew = y*yscale; Xint = floor(Xnew); Yint = floor(Ynew); dx = Xnew - Xint; dy = Ynew - Yint; p = input + Xint*ips + Yint*ils; switch( in->BandFmt ) { case IM_BANDFMT_UCHAR: LOOP( unsigned char); break; case IM_BANDFMT_USHORT: LOOP( unsigned short ); break; case IM_BANDFMT_UINT: LOOP( unsigned int ); break; 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: im_errormsg( "im_lowpass: unsupported image type" ); return( -1 ); /*NOTREACHED*/ } } if (im_writeline(y, out, opline) ) return(-1); } return(0); }
/* Draw a line on a image. */ int im_fastline( IMAGE *im, int x1, int y1, int x2, int y2, PEL *pel ) { int es = IM_IMAGE_SIZEOF_ELEMENT( im ); int ps = es * im->Bands; int ls = ps * im->Xsize; PEL *p; int x, y, dx, dy; int err; int b; if( im_rwcheck( im ) ) return( -1 ); /* Check coordinates in range. */ if( x1 > im->Xsize || x1 < 0 || y1 > im->Ysize || y1 < 0 || x2 > im->Xsize || x2 < 0 || y2 > im->Ysize || y2 < 0 ) { im_error( "im_fastline", "%s", _( "invalid line cooordinates" ) ); return( -1 ); } /* Find offsets. */ dx = x2 - x1; dy = y2 - y1; /* Swap endpoints to reduce number of cases. */ if( abs( dx ) >= abs( dy ) && dx < 0 ) { /* Swap to get all x greater or equal cases going to the * right. Do diagonals here .. just have up and right and down * and right now. */ SWAP( x1, x2 ); SWAP( y1, y2 ); } else if( abs( dx ) < abs( dy ) && dy < 0 ) { /* Swap to get all y greater cases going down the screen. */ SWAP( x1, x2 ); SWAP( y1, y2 ); } /* Recalculate dx, dy. */ dx = x2 - x1; dy = y2 - y1; /* Start point and offset. */ x = x1; y = y1; p = (PEL *) im->data + x * ps + y * ls; /* Plot point macro. */ #define PLOT \ for( b = 0; b < ps; b++ ) \ p[b] = pel[b]; /* Special case: zero width and height is single point. */ if( dx == 0 && dy == 0 ) { PLOT; } /* Special case vertical and horizontal lines for speed. */ else if( dx == 0 ) { /* Vertical line going down. */ for( ; y <= y2; y++ ) { PLOT; p += ls; } } else if( dy == 0 ) { /* Horizontal line to the right. */ for( ; x <= x2; x++ ) { PLOT; p += ps; } } /* Special case diagonal lines. */ else if( abs( dy ) == abs( dx ) && dy > 0 ) { /* Diagonal line going down and right. */ for( ; x <= x2; x++ ) { PLOT; p += ps + ls; } } else if( abs( dy ) == abs( dx ) && dy < 0 ) { /* Diagonal line going up and right. */ for( ; x <= x2; x++ ) { PLOT; p += ps - ls; } } else if( abs( dy ) < abs( dx ) && dy > 0 ) { /* Between -45 and 0 degrees. */ for( err = 0; x <= x2; x++ ) { PLOT; p += ps; err += dy; if( err >= dx ) { err -= dx; p += ls; } } } else if( abs( dy ) < abs( dx ) && dy < 0 ) { /* Between 0 and 45 degrees. */ for( err = 0; x <= x2; x++ ) { PLOT; p += ps; err -= dy; if( err >= dx ) { err -= dx; p -= ls; } } } else if( abs( dy ) > abs( dx ) && dx > 0 ) { /* Between -45 and -90 degrees. */ for( err = 0; y <= y2; y++ ) { PLOT; p += ls; err += dx; if( err >= dy ) { err -= dy; p += ps; } } } else if( abs( dy ) > abs( dx ) && dx < 0 ) { /* Between -90 and -135 degrees. */ for( err = 0; y <= y2; y++ ) { PLOT; p += ls; err -= dx; if( err >= dy ) { err -= dy; p -= ps; } } } else error_exit( "internal error #9872659823475982375" ); return( 0 ); }
/* Shrink a REGION. */ static int shrink_gen( REGION *or, void *vseq, void *a, void *b ) { SeqInfo *seq = (SeqInfo *) vseq; ShrinkInfo *st = (ShrinkInfo *) b; REGION *ir = seq->ir; Rect *r = &or->valid; Rect s; int le = r->left; int ri = IM_RECT_RIGHT( r ); int to = r->top; int bo = IM_RECT_BOTTOM(r); int x, y, z, k; /* What part of the input image do we need? Very careful: round left * down, round right up. */ s.left = r->left * st->xshrink; s.top = r->top * st->yshrink; s.width = ceil( IM_RECT_RIGHT( r ) * st->xshrink ) - s.left; s.height = ceil( IM_RECT_BOTTOM( r ) * st->yshrink ) - s.top; if( im_prepare( ir, &s ) ) return( -1 ); /* Init offsets for pel addressing. Note that offsets must be for the * type we will address the memory array with. */ for( z = 0, y = 0; y < st->mh; y++ ) for( x = 0; x < st->mw; x++ ) seq->off[z++] = (IM_REGION_ADDR( ir, x, y ) - IM_REGION_ADDR( ir, 0, 0 )) / IM_IMAGE_SIZEOF_ELEMENT( ir->im ); switch( ir->im->BandFmt ) { case IM_BANDFMT_UCHAR: ishrink(unsigned char); break; case IM_BANDFMT_CHAR: ishrink(char); break; case IM_BANDFMT_USHORT: ishrink(unsigned short); break; case IM_BANDFMT_SHORT: ishrink(short); break; case IM_BANDFMT_UINT: ishrink(unsigned int); break; case IM_BANDFMT_INT: ishrink(int); break; case IM_BANDFMT_FLOAT: fshrink(float); break; case IM_BANDFMT_DOUBLE: fshrink(double); break; default: im_error( "im_shrink", "%s", _( "unsupported input format" ) ); return( -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;
/** * im_msb_band: * @in: input image * @out: output image * @band: select this band * * Turn any integer image to a single-band 8-bit unsigned char by discarding * all but the most significant byte from the selected band. * Signed values are converted to unsigned by adding 128. * * This operator also works for LABQ coding. * * See also: im_msb_band(). * * Returns: 0 on success, -1 on error */ int im_msb_band( IMAGE *in, IMAGE *out, int band ) { Msb *msb; im_wrapone_fn func; if( band < 0 ) { im_error( "im_msb_band", "%s", _( "bad arguments" ) ); return( -1 ); } if( im_piocheck( in, out ) || !(msb = IM_NEW( out, Msb )) ) return( -1 ); if( in->Coding == IM_CODING_NONE ) { if( im_check_int( "im_msb_band", in ) ) return( -1 ); if( band >= in->Bands ) { im_error( "im_msb_band", "%s", _( "image does not have that many bands" ) ); return( -1 ); } msb->width = IM_IMAGE_SIZEOF_ELEMENT( in ); msb->index = im_amiMSBfirst() ? msb->width * band : msb->width * (band + 1) - 1; msb->repeat = 1; if( vips_bandfmt_isuint( in->BandFmt ) ) func = (im_wrapone_fn) byte_select; else func = (im_wrapone_fn) byte_select_flip; } else if( IM_CODING_LABQ == in->Coding ) { if( band > 2 ) { im_error( "im_msb_band", "%s", _( "image does not have that many bands" ) ); return( -1 ); } msb->width = 4; msb->repeat = 1; msb->index = band; if( band ) func = (im_wrapone_fn) byte_select_flip; else func = (im_wrapone_fn) byte_select; } else { im_error( "im_msb", "%s", _( "unknown coding" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->BandFmt = IM_BANDFMT_UCHAR; out->Coding = IM_CODING_NONE; out->Bands = 1; return( im_wrapone( in, out, func, msb, NULL ) ); }
static int ifthenelse_gen( REGION *or, void *seq, void *client1, void *client2 ) { REGION **ir = (REGION **) seq; Rect *r = &or->valid; int le = r->left; int to = r->top; int bo = IM_RECT_BOTTOM(r); IMAGE *c = ir[0]->im; IMAGE *a = ir[1]->im; int size, width; int i, x, y, z; int all0, alln0; if( c->Bands == 1 ) { /* Copying PEL-sized units with a one-band conditional. */ size = IM_IMAGE_SIZEOF_PEL( a ); width = r->width; } else { /* Copying ELEMENT sized-units with an n-band conditional. */ size = IM_IMAGE_SIZEOF_ELEMENT( a ); width = r->width * a->Bands; } if( im_prepare( ir[0], r ) ) return( -1 ); /* Is the conditional all zero or all non-zero? We can avoid asking * for one of the inputs to be calculated. */ all0 = *((PEL *) IM_REGION_ADDR( ir[0], le, to )) == 0; alln0 = *((PEL *) IM_REGION_ADDR( ir[0], le, to )) != 0; for( y = to; y < bo; y++ ) { PEL *p = (PEL *) IM_REGION_ADDR( ir[0], le, y ); for( x = 0; x < width; x++ ) { all0 &= p[x] == 0; alln0 &= p[x] != 0; } if( !all0 && !alln0 ) break; } if( alln0 ) { /* All non-zero. Point or at the then image. */ if( im_prepare( ir[1], r ) || im_region_region( or, ir[1], r, r->left, r->top ) ) return( -1 ); } else if( all0 ) { /* All zero. Point or at the else image. */ if( im_prepare( ir[2], r ) || im_region_region( or, ir[2], r, r->left, r->top ) ) return( -1 ); } else { /* Mix of set and clear ... ask for both then and else parts * and interleave. */ if( im_prepare( ir[1], r ) || im_prepare( ir[2], r ) ) return( -1 ); for( y = to; y < bo; y++ ) { PEL *cp = (PEL *) IM_REGION_ADDR( ir[0], le, y ); PEL *ap = (PEL *) IM_REGION_ADDR( ir[1], le, y ); PEL *bp = (PEL *) IM_REGION_ADDR( ir[2], le, y ); PEL *q = (PEL *) IM_REGION_ADDR( or, le, y ); for( x = 0, i = 0; i < width; i++, x += size ) { if( cp[i] ) for( z = x; z < x + size; z++ ) q[z] = ap[z]; else for( z = x; z < x + size; z++ ) q[z] = bp[z]; } } } return( 0 ); }