static int mask_draw_labq( Mask *mask ) { float *lab_buffer; float ink_buffer[3]; int y; if( !(lab_buffer = IM_ARRAY( NULL, mask->image_clip.width * 3, float )) ) return( -1 ); imb_LabQ2Lab( DRAW( mask )->ink, ink_buffer, 1 ); for( y = 0; y < mask->image_clip.height; y++ ) { PEL *to = (PEL *) IM_IMAGE_ADDR( DRAW( mask )->im, mask->image_clip.left, y + mask->image_clip.top ); PEL *mask_line = (PEL *) IM_IMAGE_ADDR( mask->mask_im, mask->mask_clip.left, y + mask->mask_clip.top ); imb_LabQ2Lab( to, lab_buffer, mask->image_clip.width ); DBLEND( float, lab_buffer, ink_buffer ); imb_Lab2LabQ( lab_buffer, to, mask->image_clip.width ); } im_free( lab_buffer ); return( 0 ); }
/* Like im_insert, but perform an in-place insertion. */ int im_insertplace( IMAGE *big, IMAGE *small, int x, int y ) { Rect br, sr; PEL *p, *q; int z; /* Check IO. */ if( im_rwcheck( big ) || im_incheck( small ) ) return( -1 ); /* Check compatibility. */ if( big->BandFmt != small->BandFmt || big->Bands != small->Bands || big->Coding != small->Coding ) { im_error( "im_insertplace", _( "inputs differ in format" ) ); return( -1 ); } if( big->Coding != IM_CODING_NONE && big->Coding != IM_CODING_LABQ ) { im_error( "im_insertplace", _( "input should be uncoded " "or IM_CODING_LABQ" ) ); return( -1 ); } /* Make rects for big and small. */ br.left = 0; br.top = 0; br.width = big->Xsize; br.height = big->Ysize; sr.left = x; sr.top = y; sr.width = small->Xsize; sr.height = small->Ysize; /* Small fits inside big? */ if( !im_rect_includesrect( &br, &sr ) ) { im_error( "im_insertplace", _( "small not inside big" ) ); return( -1 ); } /* Loop, memcpying small to big. */ p = (PEL *) IM_IMAGE_ADDR( small, 0, 0 ); q = (PEL *) IM_IMAGE_ADDR( big, x, y ); for( z = 0; z < small->Ysize; z++ ) { memcpy( (char *) q, (char *) p, IM_IMAGE_SIZEOF_LINE( small ) ); p += IM_IMAGE_SIZEOF_LINE( small ); q += IM_IMAGE_SIZEOF_LINE( big ); } im_invalidate( big ); 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 ); }
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2. */ void im__draw_scanline( Draw *draw, int y, int x1, int x2 ) { PEL *mp; int i; int len; g_assert( x1 <= x2 ); if( y < 0 || y >= draw->im->Ysize ) return; if( x1 < 0 && x2 < 0 ) return; if( x1 >= draw->im->Xsize && x2 >= draw->im->Xsize ) return; x1 = IM_CLIP( 0, x1, draw->im->Xsize - 1 ); x2 = IM_CLIP( 0, x2, draw->im->Xsize - 1 ); mp = (PEL *) IM_IMAGE_ADDR( draw->im, x1, y ); len = x2 - x1 + 1; for( i = 0; i < len; i++ ) { im__draw_pel( draw, mp ); mp += draw->psize; } }
/* 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 ); }
/** * im_draw_image: * @image: image to draw on * @sub: image to draw * @x: position to insert * @y: position to insert * * Draw @sub on top of @image at position @x, @y. The two images must have the * same * Coding. If @sub has 1 band, the bands will be duplicated to match the * number of bands in @image. @sub will be converted to @image's format, see * im_clip2fmt(). * * See also: im_insert(). * * Returns: 0 on success, or -1 on error. */ int im_draw_image( VipsImage *image, VipsImage *sub, int x, int y ) { Rect br, sr, clip; PEL *p, *q; int z; /* Make rects for main and sub and clip. */ br.left = 0; br.top = 0; br.width = image->Xsize; br.height = image->Ysize; sr.left = x; sr.top = y; sr.width = sub->Xsize; sr.height = sub->Ysize; im_rect_intersectrect( &br, &sr, &clip ); if( im_rect_isempty( &clip ) ) return( 0 ); if( !(sub = im__inplace_base( "im_draw_image", image, sub, image )) || im_rwcheck( image ) || im_incheck( sub ) ) return( -1 ); /* Loop, memcpying sub to main. */ p = (PEL *) IM_IMAGE_ADDR( sub, clip.left - x, clip.top - y ); q = (PEL *) IM_IMAGE_ADDR( image, clip.left, clip.top ); for( z = 0; z < clip.height; z++ ) { memcpy( (char *) q, (char *) p, clip.width * IM_IMAGE_SIZEOF_PEL( sub ) ); p += IM_IMAGE_SIZEOF_LINE( sub ); q += IM_IMAGE_SIZEOF_LINE( image ); } return( 0 ); }
/** * im_draw_point: * @image: image to draw on * @x: position to draw * @y: position to draw * @ink: value to draw * * Draws a single point on an image. * * @ink is an array of bytes containing a valid pixel for the image's format. * It must have at least IM_IMAGE_SIZEOF_PEL( @im ) bytes. * * See also: im_draw_line(). * * Returns: 0 on success, or -1 on error. */ int im_draw_point( VipsImage *image, int x, int y, VipsPel *ink ) { Point point; if( im_check_coding_known( "im_draw_point", image ) || im__draw_init( DRAW( &point ), image, NULL ) ) return( -1 ); /* Check coordinates. */ if( x >= 0 && x < image->Xsize && y >= 0 && y < image->Ysize ) memcpy( IM_IMAGE_ADDR( image, x, y ), ink, DRAW( image )->psize ); im__draw_free( DRAW( &point ) ); return( 0 ); }
/** * im_draw_rect: * @image: image to draw on * @left: area to paint * @top: area to paint * @width: area to paint * @height: area to paint * @fill: fill the rect * @ink: paint with this colour * * Paint pixels within @left, @top, @width, @height in @image with @ink. If * @fill is zero, just paint a 1-pixel-wide outline. * * See also: im_draw_circle(). * * Returns: 0 on success, or -1 on error. */ int im_draw_rect( IMAGE *image, int left, int top, int width, int height, int fill, VipsPel *ink ) { Rect im, rect, clipped; Draw draw; if( !fill ) return( im_draw_rect( image, left, top, width, 1, 1, ink ) || im_draw_rect( image, left + width - 1, top, 1, height, 1, ink ) || im_draw_rect( image, left, top + height - 1, width, 1, 1, ink ) || im_draw_rect( image, left, top, 1, height, 1, ink ) ); int x, y; VipsPel *to; VipsPel *q; /* Find area we plot. */ im.left = 0; im.top = 0; im.width = image->Xsize; im.height = image->Ysize; rect.left = left; rect.top = top; rect.width = width; rect.height = height; im_rect_intersectrect( &rect, &im, &clipped ); /* Any points left to plot? */ if( im_rect_isempty( &clipped ) ) return( 0 ); if( im_check_coding_known( "im_draw_rect", image ) || !im__draw_init( &draw, image, ink ) ) return( -1 ); /* We plot the first line pointwise, then memcpy() it for the * subsequent lines. */ to = IM_IMAGE_ADDR( image, clipped.left, clipped.top ); q = to; for( x = 0; x < clipped.width; x++ ) { im__draw_pel( &draw, q ); q += draw.psize; } q = to + draw.lsize; for( y = 1; y < clipped.height; y++ ) { memcpy( q, to, clipped.width * draw.psize ); q += draw.lsize; } im__draw_free( &draw ); return( 0 ); }
static int mask_draw( Mask *mask ) { int y; for( y = 0; y < mask->image_clip.height; y++ ) { PEL *to = (PEL *) IM_IMAGE_ADDR( DRAW( mask )->im, mask->image_clip.left, y + mask->image_clip.top ); PEL *mask_line = (PEL *) IM_IMAGE_ADDR( mask->mask_im, mask->mask_clip.left, y + mask->mask_clip.top ); switch( DRAW( mask )->im->BandFmt ) { case IM_BANDFMT_UCHAR: IBLEND( unsigned char, to, DRAW( mask )->ink ); break; case IM_BANDFMT_CHAR: IBLEND( signed char, to, DRAW( mask )->ink ); break; case IM_BANDFMT_USHORT: IBLEND( unsigned short, to, DRAW( mask )->ink ); break; case IM_BANDFMT_SHORT: IBLEND( signed short, to, DRAW( mask )->ink ); break; case IM_BANDFMT_UINT: DBLEND( unsigned int, to, DRAW( mask )->ink ); break; case IM_BANDFMT_INT: DBLEND( signed int, to, DRAW( mask )->ink ); break; case IM_BANDFMT_FLOAT: DBLEND( float, to, DRAW( mask )->ink ); break; case IM_BANDFMT_DOUBLE: DBLEND( double, to, DRAW( mask )->ink ); break; case IM_BANDFMT_COMPLEX: CBLEND( float, to, DRAW( mask )->ink ); break; case IM_BANDFMT_DPCOMPLEX: CBLEND( double, to, DRAW( mask )->ink ); break; default: g_assert( 0 ); } } return( 0 ); }
/** * im_profile: * @in: input image * @out: output image * @dir: search direction * * im_profile() searches inward from the edge of @in and finds the * first non-zero pixel. It outputs an image containing a list of the offsets * for each row or column. * * If @dir == 0, then im_profile() searches down from the top edge, writing an * image as wide as the input image, but only 1 pixel high, containing the * number of pixels down to the first non-zero pixel for each column of input * pixels. * * If @dir == 1, then im_profile() searches across from the left edge, * writing an image as high as the input image, but only 1 pixel wide, * containing the number of pixels across to the * first non-zero pixel for each row of input pixels. * * See also: im_cntlines(). * * Returns: 0 on success, -1 on error */ int im_profile( IMAGE *in, IMAGE *out, int dir ) { int sz; unsigned short *buf; int x, y, b; /* If in is not uchar, do (!=0) to make a uchar image. */ if( in->BandFmt != IM_BANDFMT_UCHAR ) { IMAGE *t; if( !(t = im_open_local( out, "im_profile", "p" )) || im_notequalconst( in, t, 0 ) ) return( -1 ); in = t; } /* Check im. */ if( im_iocheck( in, out ) || im_check_uncoded( "im_profile", in ) || im_check_format( "im_profile", in, IM_BANDFMT_UCHAR ) ) return( -1 ); if( dir != 0 && dir != 1 ) { im_error( "im_profile", "%s", _( "dir not 0 or 1" ) ); return( -1 ); } if( im_cp_desc( out, in ) ) return( -1 ); out->Type = IM_TYPE_HISTOGRAM; if( dir == 0 ) { out->Xsize = in->Xsize; out->Ysize = 1; } else { out->Xsize = 1; out->Ysize = in->Ysize; } out->BandFmt = IM_BANDFMT_USHORT; if( im_setupout( out ) ) return( -1 ); sz = IM_IMAGE_N_ELEMENTS( out ); if( !(buf = IM_ARRAY( out, sz, unsigned short )) ) return( -1 ); if( dir == 0 ) { /* Find vertical lines. */ for( x = 0; x < sz; x++ ) { PEL *p = (PEL *) IM_IMAGE_ADDR( in, 0, 0 ) + x; int lsk = IM_IMAGE_SIZEOF_LINE( in ); for( y = 0; y < in->Ysize; y++ ) { if( *p ) break; p += lsk; } buf[x] = y; } if( im_writeline( 0, out, (PEL *) buf ) ) return( -1 ); } else { /* Search horizontal lines. */ for( y = 0; y < in->Ysize; y++ ) { PEL *p = (PEL *) IM_IMAGE_ADDR( in, 0, y ); for( b = 0; b < in->Bands; b++ ) { PEL *p1; p1 = p + b; for( x = 0; x < in->Xsize; x++ ) { if( *p1 ) break; p1 += in->Bands; } buf[b] = x; } if( im_writeline( y, out, (PEL *) buf ) ) return( -1 ); } } return( 0 ); }