add a direct path for draw_mask
and get draw_circle ready for draw-along-circle
This commit is contained in:
parent
4c1d07f53a
commit
15ba4a7be2
4
TODO
4
TODO
@ -1,3 +1,7 @@
|
|||||||
|
- test draw_mask on labq images
|
||||||
|
|
||||||
|
we probably need to unpack the ink back to double before blending
|
||||||
|
|
||||||
- vips_draw_image() might need a direct mode? see vips_flood_direct()
|
- vips_draw_image() might need a direct mode? see vips_flood_direct()
|
||||||
|
|
||||||
- need call operation along a circle, see line draw
|
- need call operation along a circle, see line draw
|
||||||
|
@ -4576,15 +4576,11 @@ im_draw_line_user( VipsImage *image,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
im_draw_mask( VipsImage *image, VipsImage *mask_im, int x, int y, VipsPel *ink )
|
im_draw_mask( VipsImage *image, VipsImage *mask, int x, int y, VipsPel *ink )
|
||||||
{
|
{
|
||||||
double *vec;
|
/* Direct call, since this has to be very quick.
|
||||||
int n;
|
*/
|
||||||
|
return( vips__draw_mask_direct( image, mask, ink, x, y ) );
|
||||||
if( !(vec = vips__ink_to_vector( "im_draw_mask", image, ink, &n )) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
return( vips_draw_mask( image, vec, n, mask_im, x, y, NULL ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -67,53 +67,72 @@ typedef struct _VipsDrawCircle {
|
|||||||
int radius;
|
int radius;
|
||||||
gboolean fill;
|
gboolean fill;
|
||||||
|
|
||||||
VipsPel *centre;
|
VipsDrawPoint draw_point;
|
||||||
|
VipsDrawScanline draw_scanline;
|
||||||
} VipsDrawCircle;
|
} VipsDrawCircle;
|
||||||
|
|
||||||
typedef VipsDrawinkClass VipsDrawCircleClass;
|
typedef struct _VipsDrawCircleClass {
|
||||||
|
VipsDrawinkClass parent_class;
|
||||||
|
|
||||||
|
} VipsDrawCircleClass;
|
||||||
|
|
||||||
G_DEFINE_TYPE( VipsDrawCircle, vips_draw_circle, VIPS_TYPE_DRAWINK );
|
G_DEFINE_TYPE( VipsDrawCircle, vips_draw_circle, VIPS_TYPE_DRAWINK );
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_draw_circle_octants( VipsDrawCircle *circle, int x, int y )
|
vips_draw_circle_octants( VipsDrawCircle *circle, int x, int y )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = VIPS_DRAW( circle );
|
|
||||||
VipsDrawink *drawink = VIPS_DRAWINK( circle );
|
VipsDrawink *drawink = VIPS_DRAWINK( circle );
|
||||||
|
VipsDrawPoint draw_point = circle->draw_point;
|
||||||
|
VipsDrawScanline draw_scanline = circle->draw_scanline;
|
||||||
const int cx = circle->cx;
|
const int cx = circle->cx;
|
||||||
const int cy = circle->cy;
|
const int cy = circle->cy;
|
||||||
|
|
||||||
if( circle->fill ) {
|
if( circle->fill ) {
|
||||||
vips__drawink_scanline( drawink, cy + y, cx - x, cx + x );
|
draw_scanline( drawink, cy + y, cx - x, cx + x );
|
||||||
vips__drawink_scanline( drawink, cy - y, cx - x, cx + x );
|
draw_scanline( drawink, cy - y, cx - x, cx + x );
|
||||||
vips__drawink_scanline( drawink, cy + x, cx - y, cx + y );
|
draw_scanline( drawink, cy + x, cx - y, cx + y );
|
||||||
vips__drawink_scanline( drawink, cy - x, cx - y, cx + y );
|
draw_scanline( drawink, cy - x, cx - y, cx + y );
|
||||||
}
|
|
||||||
else if( draw->noclip ) {
|
|
||||||
const size_t lsize = draw->lsize;
|
|
||||||
const size_t psize = draw->psize;
|
|
||||||
VipsPel *centre = circle->centre;
|
|
||||||
|
|
||||||
vips__drawink_pel( drawink, centre + lsize * y - psize * x );
|
|
||||||
vips__drawink_pel( drawink, centre + lsize * y + psize * x );
|
|
||||||
vips__drawink_pel( drawink, centre - lsize * y - psize * x );
|
|
||||||
vips__drawink_pel( drawink, centre - lsize * y + psize * x );
|
|
||||||
vips__drawink_pel( drawink, centre + lsize * x - psize * y );
|
|
||||||
vips__drawink_pel( drawink, centre + lsize * x + psize * y );
|
|
||||||
vips__drawink_pel( drawink, centre - lsize * x - psize * y );
|
|
||||||
vips__drawink_pel( drawink, centre - lsize * x + psize * y );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
vips__drawink_pel_clip( drawink, cx + y, cy - x );
|
draw_point( drawink, cx + y, cy - x );
|
||||||
vips__drawink_pel_clip( drawink, cx + y, cy + x );
|
draw_point( drawink, cx + y, cy + x );
|
||||||
vips__drawink_pel_clip( drawink, cx - y, cy - x );
|
draw_point( drawink, cx - y, cy - x );
|
||||||
vips__drawink_pel_clip( drawink, cx - y, cy + x );
|
draw_point( drawink, cx - y, cy + x );
|
||||||
vips__drawink_pel_clip( drawink, cx + x, cy - y );
|
draw_point( drawink, cx + x, cy - y );
|
||||||
vips__drawink_pel_clip( drawink, cx + x, cy + y );
|
draw_point( drawink, cx + x, cy + y );
|
||||||
vips__drawink_pel_clip( drawink, cx - x, cy - y );
|
draw_point( drawink, cx - x, cy - y );
|
||||||
vips__drawink_pel_clip( drawink, cx - x, cy + y );
|
draw_point( drawink, cx - x, cy + y );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Paint a point, with clip.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
vips_draw_circle_draw_point_clip( VipsDrawink *drawink, int x, int y )
|
||||||
|
{
|
||||||
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
|
|
||||||
|
if( x < 0 ||
|
||||||
|
x >= draw->image->Xsize )
|
||||||
|
return;
|
||||||
|
if( y < 0 ||
|
||||||
|
y >= draw->image->Ysize )
|
||||||
|
return;
|
||||||
|
|
||||||
|
vips__drawink_pel( drawink, VIPS_IMAGE_ADDR( draw->image, x, y ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paint a point, no clipping needed.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
vips_draw_circle_draw_point( VipsDrawink *drawink, int x, int y )
|
||||||
|
{
|
||||||
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
|
|
||||||
|
return( vips__drawink_pel( drawink,
|
||||||
|
VIPS_IMAGE_ADDR( draw->image, x, y ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_circle_build( VipsObject *object )
|
vips_draw_circle_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
@ -126,13 +145,15 @@ vips_draw_circle_build( VipsObject *object )
|
|||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
circle->centre = VIPS_IMAGE_ADDR( draw->image, circle->cx, circle->cy );
|
circle->draw_scanline = vips__drawink_scanline;
|
||||||
|
|
||||||
if( circle->cx - circle->radius >= 0 &&
|
if( circle->cx - circle->radius >= 0 &&
|
||||||
circle->cx + circle->radius < draw->image->Xsize &&
|
circle->cx + circle->radius < draw->image->Xsize &&
|
||||||
circle->cy - circle->radius >= 0 &&
|
circle->cy - circle->radius >= 0 &&
|
||||||
circle->cy + circle->radius < draw->image->Ysize )
|
circle->cy + circle->radius < draw->image->Ysize )
|
||||||
draw->noclip = TRUE;
|
circle->draw_point = vips_draw_circle_draw_point;
|
||||||
|
else
|
||||||
|
circle->draw_point = vips__drawink_pel_clip;
|
||||||
|
|
||||||
y = circle->radius;
|
y = circle->radius;
|
||||||
d = 3 - 2 * circle->radius;
|
d = 3 - 2 * circle->radius;
|
||||||
|
@ -100,12 +100,7 @@ G_DEFINE_TYPE( VipsDrawImage, vips_draw_image, VIPS_TYPE_DRAW );
|
|||||||
\
|
\
|
||||||
v = pt[x] + qt[x]; \
|
v = pt[x] + qt[x]; \
|
||||||
\
|
\
|
||||||
if( v > MAX ) \
|
qt[x] = VIPS_CLIP( MIN, v, MAX ); \
|
||||||
v = MAX; \
|
|
||||||
else if( v < MIN ) \
|
|
||||||
v = MIN; \
|
|
||||||
\
|
|
||||||
qt[x] = v; \
|
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* - gtk-doc
|
* - gtk-doc
|
||||||
* - use draw.c base class
|
* - use draw.c base class
|
||||||
* - do pointwise clipping
|
* - do pointwise clipping
|
||||||
* - rename as im_draw_draw_line() for consistency
|
* - rename as im_draw_line() for consistency
|
||||||
* - cleanups!
|
* - cleanups!
|
||||||
* 6/2/14
|
* 6/2/14
|
||||||
* - redo as a class
|
* - redo as a class
|
||||||
@ -68,8 +68,9 @@ G_DEFINE_TYPE( VipsDrawLine, vips_draw_line, VIPS_TYPE_DRAWINK );
|
|||||||
static int
|
static int
|
||||||
vips_draw_line_draw( VipsDrawLine *line )
|
vips_draw_line_draw( VipsDrawLine *line )
|
||||||
{
|
{
|
||||||
|
VipsDrawink *drawink = VIPS_DRAWINK( line );
|
||||||
VipsDrawLineClass *class = VIPS_DRAW_LINE_GET_CLASS( line );
|
VipsDrawLineClass *class = VIPS_DRAW_LINE_GET_CLASS( line );
|
||||||
VipsDrawLinePlotPoint plot_point = class->plot_point;
|
VipsDrawPoint draw_point = class->draw_point;
|
||||||
|
|
||||||
int x, y, err;
|
int x, y, err;
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
*/
|
*/
|
||||||
if( line->dx == 0 &&
|
if( line->dx == 0 &&
|
||||||
line->dy == 0 ) {
|
line->dy == 0 ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
/* Special case vertical and horizontal lines for speed.
|
/* Special case vertical and horizontal lines for speed.
|
||||||
@ -91,7 +92,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Vertical line going down.
|
/* Vertical line going down.
|
||||||
*/
|
*/
|
||||||
for( ; y <= line->y2; y++ ) {
|
for( ; y <= line->y2; y++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +100,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Horizontal line to the right.
|
/* Horizontal line to the right.
|
||||||
*/
|
*/
|
||||||
for( ; x <= line->x2; x++ ) {
|
for( ; x <= line->x2; x++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +111,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Diagonal line going down and right.
|
/* Diagonal line going down and right.
|
||||||
*/
|
*/
|
||||||
for( ; x <= line->x2; x++, y++ ) {
|
for( ; x <= line->x2; x++, y++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +120,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Diagonal line going up and right.
|
/* Diagonal line going up and right.
|
||||||
*/
|
*/
|
||||||
for( ; x <= line->x2; x++, y-- ) {
|
for( ; x <= line->x2; x++, y-- ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +129,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Between -45 and 0 degrees.
|
/* Between -45 and 0 degrees.
|
||||||
*/
|
*/
|
||||||
for( err = 0; x <= line->x2; x++ ) {
|
for( err = 0; x <= line->x2; x++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
err += line->dy;
|
err += line->dy;
|
||||||
@ -143,7 +144,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Between 0 and 45 degrees.
|
/* Between 0 and 45 degrees.
|
||||||
*/
|
*/
|
||||||
for( err = 0; x <= line->x2; x++ ) {
|
for( err = 0; x <= line->x2; x++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
err -= line->dy;
|
err -= line->dy;
|
||||||
@ -158,7 +159,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Between -45 and -90 degrees.
|
/* Between -45 and -90 degrees.
|
||||||
*/
|
*/
|
||||||
for( err = 0; y <= line->y2; y++ ) {
|
for( err = 0; y <= line->y2; y++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
err += line->dx;
|
err += line->dx;
|
||||||
@ -173,7 +174,7 @@ vips_draw_line_draw( VipsDrawLine *line )
|
|||||||
/* Between -90 and -135 degrees.
|
/* Between -90 and -135 degrees.
|
||||||
*/
|
*/
|
||||||
for( err = 0; y <= line->y2; y++ ) {
|
for( err = 0; y <= line->y2; y++ ) {
|
||||||
if( plot_point( line, x, y ) )
|
if( draw_point( drawink, x, y ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
err -= line->dx;
|
err -= line->dx;
|
||||||
@ -244,10 +245,9 @@ vips_draw_line_build( VipsObject *object )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_line_plot_point( VipsDrawLine *line, int x, int y )
|
vips_draw_line_draw_point( VipsDrawink *drawink, int x, int y )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) line;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
VipsDrawink *drawink = (VipsDrawink *) line;
|
|
||||||
|
|
||||||
if( draw->noclip )
|
if( draw->noclip )
|
||||||
vips__drawink_pel( drawink,
|
vips__drawink_pel( drawink,
|
||||||
@ -271,7 +271,7 @@ vips_draw_line_class_init( VipsDrawLineClass *class )
|
|||||||
vobject_class->description = _( "draw a draw_line on an image" );
|
vobject_class->description = _( "draw a draw_line on an image" );
|
||||||
vobject_class->build = vips_draw_line_build;
|
vobject_class->build = vips_draw_line_build;
|
||||||
|
|
||||||
class->plot_point = vips_draw_line_plot_point;
|
class->draw_point = vips_draw_line_draw_point;
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "x1", 3,
|
VIPS_ARG_INT( class, "x1", 3,
|
||||||
_( "x1" ),
|
_( "x1" ),
|
||||||
|
@ -68,11 +68,9 @@ typedef struct _VipsDrawLine {
|
|||||||
typedef struct _VipsDrawLineClass {
|
typedef struct _VipsDrawLineClass {
|
||||||
VipsDrawinkClass parent_class;
|
VipsDrawinkClass parent_class;
|
||||||
|
|
||||||
int (*plot_point)( VipsDrawLine *, int x, int y );
|
VipsDrawPoint draw_point;
|
||||||
} VipsDrawLineClass;
|
} VipsDrawLineClass;
|
||||||
|
|
||||||
typedef int (*VipsDrawLinePlotPoint)( VipsDrawLine *draw_line, int x, int y );
|
|
||||||
|
|
||||||
GType vips_draw_line_get_type( void );
|
GType vips_draw_line_get_type( void );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -74,11 +74,10 @@ typedef VipsDrawLineClass VipsDrawLineMaskClass;
|
|||||||
G_DEFINE_TYPE( VipsDrawLineMask, vips_draw_line_mask, VIPS_TYPE_DRAW_LINE );
|
G_DEFINE_TYPE( VipsDrawLineMask, vips_draw_line_mask, VIPS_TYPE_DRAW_LINE );
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_line_mask_plot_point( VipsDrawLine *line, int x, int y )
|
vips_draw_line_mask_draw_point( VipsDrawink *drawink, int x, int y )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) line;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
VipsDrawink *drawink = (VipsDrawink *) line;
|
VipsDrawLineMask *mask = (VipsDrawLineMask *) drawink;
|
||||||
VipsDrawLineMask *mask = (VipsDrawLineMask *) line;
|
|
||||||
|
|
||||||
return( vips_draw_mask( draw->image,
|
return( vips_draw_mask( draw->image,
|
||||||
drawink->ink->data, drawink->ink->n,
|
drawink->ink->data, drawink->ink->n,
|
||||||
@ -97,7 +96,7 @@ vips_draw_line_mask_class_init( VipsDrawLineMaskClass *class )
|
|||||||
vobject_class->nickname = "draw_line_mask";
|
vobject_class->nickname = "draw_line_mask";
|
||||||
vobject_class->description = _( "draw a mask along a line" );
|
vobject_class->description = _( "draw a mask along a line" );
|
||||||
|
|
||||||
class->plot_point = vips_draw_line_mask_plot_point;
|
class->draw_point = vips_draw_line_mask_draw_point;
|
||||||
|
|
||||||
VIPS_ARG_IMAGE( class, "mask", 7,
|
VIPS_ARG_IMAGE( class, "mask", 7,
|
||||||
_( "Mask" ),
|
_( "Mask" ),
|
||||||
|
@ -80,10 +80,10 @@ typedef VipsDrawLineClass VipsDrawLineUserClass;
|
|||||||
G_DEFINE_TYPE( VipsDrawLineUser, vips_draw_line_user, VIPS_TYPE_DRAW_LINE );
|
G_DEFINE_TYPE( VipsDrawLineUser, vips_draw_line_user, VIPS_TYPE_DRAW_LINE );
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_line_user_plot_point( VipsDrawLine *line, int x, int y )
|
vips_draw_line_user_draw_point( VipsDrawink *drawink, int x, int y )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) line;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
VipsDrawLineUser *user = (VipsDrawLineUser *) line;
|
VipsDrawLineUser *user = (VipsDrawLineUser *) drawink;
|
||||||
|
|
||||||
return( user->plot_fn( draw->image, x, y, user->a, user->b, user->c ) );
|
return( user->plot_fn( draw->image, x, y, user->a, user->b, user->c ) );
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ vips_draw_line_user_class_init( VipsDrawLineUserClass *class )
|
|||||||
|
|
||||||
operation_class->flags = VIPS_OPERATION_DEPRECATED;
|
operation_class->flags = VIPS_OPERATION_DEPRECATED;
|
||||||
|
|
||||||
class->plot_point = vips_draw_line_user_plot_point;
|
class->draw_point = vips_draw_line_user_draw_point;
|
||||||
|
|
||||||
VIPS_ARG_POINTER( class, "plot_fn", 7,
|
VIPS_ARG_POINTER( class, "plot_fn", 7,
|
||||||
_( "Plot" ),
|
_( "Plot" ),
|
||||||
|
@ -131,13 +131,12 @@ G_DEFINE_TYPE( VipsDrawMask, vips_draw_mask, VIPS_TYPE_DRAWINK );
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_mask_draw_labq( VipsDrawMask *mask )
|
vips_draw_mask_draw_labq( VipsImage *image, VipsImage *mask, VipsPel *ink,
|
||||||
|
VipsRect *image_clip, VipsRect *mask_clip )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = VIPS_DRAW( mask );
|
int width = image_clip->width;
|
||||||
VipsDrawink *drawink = VIPS_DRAWINK( mask );
|
int height = image_clip->height;
|
||||||
int width = mask->image_clip.width;
|
int bands = image->Bands;
|
||||||
int height = mask->image_clip.height;
|
|
||||||
int bands = draw->image->Bands;
|
|
||||||
|
|
||||||
float *lab_buffer;
|
float *lab_buffer;
|
||||||
int y;
|
int y;
|
||||||
@ -146,15 +145,15 @@ vips_draw_mask_draw_labq( VipsDrawMask *mask )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
for( y = 0; y < height; y++ ) {
|
for( y = 0; y < height; y++ ) {
|
||||||
VipsPel *to = VIPS_IMAGE_ADDR( draw->image,
|
VipsPel *to = VIPS_IMAGE_ADDR( image,
|
||||||
mask->image_clip.left,
|
image_clip->left,
|
||||||
y + mask->image_clip.top );
|
y + image_clip->top );
|
||||||
VipsPel *m = VIPS_IMAGE_ADDR( mask->mask,
|
VipsPel *m = VIPS_IMAGE_ADDR( mask,
|
||||||
mask->mask_clip.left,
|
mask_clip->left,
|
||||||
y + mask->mask_clip.top );
|
y + mask_clip->top );
|
||||||
|
|
||||||
vips__LabQ2Lab_vec( lab_buffer, to, width );
|
vips__LabQ2Lab_vec( lab_buffer, to, width );
|
||||||
DBLEND( float, lab_buffer, (double *) drawink->ink->data );
|
DBLEND( float, lab_buffer, (double *) ink );
|
||||||
vips__Lab2LabQ_vec( to, lab_buffer, width );
|
vips__Lab2LabQ_vec( to, lab_buffer, width );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,63 +163,60 @@ vips_draw_mask_draw_labq( VipsDrawMask *mask )
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_mask_draw( VipsDrawMask *mask )
|
vips_draw_mask_draw( VipsImage *image, VipsImage *mask, VipsPel *ink,
|
||||||
|
VipsRect *image_clip, VipsRect *mask_clip )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = VIPS_DRAW( mask );
|
int width = image_clip->width;
|
||||||
VipsDrawink *drawink = VIPS_DRAWINK( mask );
|
int height = image_clip->height;
|
||||||
int width = mask->image_clip.width;
|
int bands = image->Bands;
|
||||||
int height = mask->image_clip.height;
|
|
||||||
int bands = draw->image->Bands;
|
|
||||||
|
|
||||||
int y;
|
int y;
|
||||||
|
|
||||||
for( y = 0; y < height; y++ ) {
|
for( y = 0; y < height; y++ ) {
|
||||||
VipsPel *to = VIPS_IMAGE_ADDR( draw->image,
|
VipsPel *to = VIPS_IMAGE_ADDR( image,
|
||||||
mask->image_clip.left,
|
image_clip->left, y + image_clip->top );
|
||||||
y + mask->image_clip.top );
|
VipsPel *m = VIPS_IMAGE_ADDR( mask,
|
||||||
VipsPel *m = VIPS_IMAGE_ADDR( mask->mask,
|
mask_clip->left, y + mask_clip->top );
|
||||||
mask->mask_clip.left,
|
|
||||||
y + mask->mask_clip.top );
|
|
||||||
|
|
||||||
switch( draw->image->BandFmt ) {
|
switch( image->BandFmt ) {
|
||||||
case VIPS_FORMAT_UCHAR:
|
case VIPS_FORMAT_UCHAR:
|
||||||
IBLEND( unsigned char, to, drawink->pixel_ink );
|
IBLEND( unsigned char, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_CHAR:
|
case VIPS_FORMAT_CHAR:
|
||||||
IBLEND( signed char, to, drawink->pixel_ink );
|
IBLEND( signed char, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_USHORT:
|
case VIPS_FORMAT_USHORT:
|
||||||
IBLEND( unsigned short, to, drawink->pixel_ink );
|
IBLEND( unsigned short, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_SHORT:
|
case VIPS_FORMAT_SHORT:
|
||||||
IBLEND( signed short, to, drawink->pixel_ink );
|
IBLEND( signed short, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_UINT:
|
case VIPS_FORMAT_UINT:
|
||||||
DBLEND( unsigned int, to, drawink->pixel_ink );
|
DBLEND( unsigned int, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_INT:
|
case VIPS_FORMAT_INT:
|
||||||
DBLEND( signed int, to, drawink->pixel_ink );
|
DBLEND( signed int, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_FLOAT:
|
case VIPS_FORMAT_FLOAT:
|
||||||
DBLEND( float, to, drawink->pixel_ink );
|
DBLEND( float, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_DOUBLE:
|
case VIPS_FORMAT_DOUBLE:
|
||||||
DBLEND( double, to, drawink->pixel_ink );
|
DBLEND( double, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_COMPLEX:
|
case VIPS_FORMAT_COMPLEX:
|
||||||
CBLEND( float, to, drawink->pixel_ink );
|
CBLEND( float, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIPS_FORMAT_DPCOMPLEX:
|
case VIPS_FORMAT_DPCOMPLEX:
|
||||||
CBLEND( double, to, drawink->pixel_ink );
|
CBLEND( double, to, ink );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -231,11 +227,73 @@ vips_draw_mask_draw( VipsDrawMask *mask )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Direct path for draw-mask-along-line or draw-mask-along-circle. We want to
|
||||||
|
* avoid function dispatch overhead.
|
||||||
|
*
|
||||||
|
* The vips7 im_draw_mask() wrapper calls this as well.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
vips__draw_mask_direct( VipsImage *image, VipsImage *mask,
|
||||||
|
VipsPel *ink, int x, int y )
|
||||||
|
{
|
||||||
|
VipsRect image_rect;
|
||||||
|
VipsRect area_rect;
|
||||||
|
VipsRect image_clip;
|
||||||
|
VipsRect mask_clip;
|
||||||
|
|
||||||
|
if( vips_check_coding_noneorlabq( "draw_mask_direct", image ) ||
|
||||||
|
vips_image_wio_input( mask ) ||
|
||||||
|
vips_check_mono( "draw_mask_direct", mask ) ||
|
||||||
|
vips_check_uncoded( "draw_mask_direct", mask ) ||
|
||||||
|
vips_check_format( "draw_mask_direct",
|
||||||
|
mask, VIPS_FORMAT_UCHAR ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
/* Find the area we draw on the image.
|
||||||
|
*/
|
||||||
|
area_rect.left = x;
|
||||||
|
area_rect.top = y;
|
||||||
|
area_rect.width = mask->Xsize;
|
||||||
|
area_rect.height = mask->Ysize;
|
||||||
|
image_rect.left = 0;
|
||||||
|
image_rect.top = 0;
|
||||||
|
image_rect.width = image->Xsize;
|
||||||
|
image_rect.height = image->Ysize;
|
||||||
|
vips_rect_intersectrect( &area_rect, &image_rect, &image_clip );
|
||||||
|
|
||||||
|
/* And the area of the mask image we use.
|
||||||
|
*/
|
||||||
|
mask_clip = image_clip;
|
||||||
|
mask_clip.left -= x;
|
||||||
|
mask_clip.top -= y;
|
||||||
|
|
||||||
|
if( !vips_rect_isempty( &image_clip ) )
|
||||||
|
switch( image->Coding ) {
|
||||||
|
case VIPS_CODING_LABQ:
|
||||||
|
if( vips_draw_mask_draw_labq( image, mask, ink,
|
||||||
|
&image_clip, &mask_clip ) )
|
||||||
|
return( -1 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_CODING_NONE:
|
||||||
|
if( vips_draw_mask_draw( image, mask, ink,
|
||||||
|
&image_clip, &mask_clip ) )
|
||||||
|
return( -1 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_draw_mask_build( VipsObject *object )
|
vips_draw_mask_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
|
||||||
VipsDraw *draw = VIPS_DRAW( object );
|
VipsDraw *draw = VIPS_DRAW( object );
|
||||||
|
VipsDrawink *drawink = VIPS_DRAWINK( object );
|
||||||
VipsDrawMask *mask = (VipsDrawMask *) object;
|
VipsDrawMask *mask = (VipsDrawMask *) object;
|
||||||
|
|
||||||
VipsRect area;
|
VipsRect area;
|
||||||
@ -244,49 +302,9 @@ vips_draw_mask_build( VipsObject *object )
|
|||||||
if( VIPS_OBJECT_CLASS( vips_draw_mask_parent_class )->build( object ) )
|
if( VIPS_OBJECT_CLASS( vips_draw_mask_parent_class )->build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_check_coding_noneorlabq( class->nickname, draw->image ) ||
|
if( vips__draw_mask_direct( draw->image, mask->mask, drawink->pixel_ink,
|
||||||
vips_image_wio_input( mask->mask ) ||
|
mask->x, mask->y ) )
|
||||||
vips_check_mono( class->nickname, mask->mask ) ||
|
return( -1 ) ;
|
||||||
vips_check_uncoded( class->nickname, mask->mask ) ||
|
|
||||||
vips_check_format( class->nickname,
|
|
||||||
mask->mask, VIPS_FORMAT_UCHAR ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
/* Find the area we draw on the image.
|
|
||||||
*/
|
|
||||||
area.left = mask->x;
|
|
||||||
area.top = mask->y;
|
|
||||||
area.width = mask->mask->Xsize;
|
|
||||||
area.height = mask->mask->Ysize;
|
|
||||||
image.left = 0;
|
|
||||||
image.top = 0;
|
|
||||||
image.width = draw->image->Xsize;
|
|
||||||
image.height = draw->image->Ysize;
|
|
||||||
vips_rect_intersectrect( &area, &image, &mask->image_clip );
|
|
||||||
|
|
||||||
/* And the area of the mask image we use.
|
|
||||||
*/
|
|
||||||
mask->mask_clip = mask->image_clip;
|
|
||||||
mask->mask_clip.left -= mask->x;
|
|
||||||
mask->mask_clip.top -= mask->y;
|
|
||||||
|
|
||||||
if( !vips_rect_isempty( &mask->image_clip ) )
|
|
||||||
/* Loop through image plotting where required.
|
|
||||||
*/
|
|
||||||
switch( draw->image->Coding ) {
|
|
||||||
case VIPS_CODING_LABQ:
|
|
||||||
if( vips_draw_mask_draw_labq( mask ) )
|
|
||||||
return( -1 );
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VIPS_CODING_NONE:
|
|
||||||
if( vips_draw_mask_draw( mask ) )
|
|
||||||
return( -1 );
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
g_assert( 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ vips_drawink_init( VipsDrawink *drawink )
|
|||||||
|
|
||||||
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2.
|
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2.
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 )
|
vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) drawink;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
@ -117,13 +117,13 @@ vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 )
|
|||||||
|
|
||||||
if( y < 0 ||
|
if( y < 0 ||
|
||||||
y >= draw->image->Ysize )
|
y >= draw->image->Ysize )
|
||||||
return;
|
return( 0 );
|
||||||
if( x1 < 0 &&
|
if( x1 < 0 &&
|
||||||
x2 < 0 )
|
x2 < 0 )
|
||||||
return;
|
return( 0 );
|
||||||
if( x1 >= draw->image->Xsize &&
|
if( x1 >= draw->image->Xsize &&
|
||||||
x2 >= draw->image->Xsize )
|
x2 >= draw->image->Xsize )
|
||||||
return;
|
return( 0 );
|
||||||
x1 = VIPS_CLIP( 0, x1, draw->image->Xsize - 1 );
|
x1 = VIPS_CLIP( 0, x1, draw->image->Xsize - 1 );
|
||||||
x2 = VIPS_CLIP( 0, x2, draw->image->Xsize - 1 );
|
x2 = VIPS_CLIP( 0, x2, draw->image->Xsize - 1 );
|
||||||
|
|
||||||
@ -134,6 +134,8 @@ vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 )
|
|||||||
vips__drawink_pel( drawink, mp );
|
vips__drawink_pel( drawink, mp );
|
||||||
mp += draw->psize;
|
mp += draw->psize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,7 +69,10 @@ typedef struct _VipsDrawinkClass {
|
|||||||
|
|
||||||
GType vips_drawink_get_type( void );
|
GType vips_drawink_get_type( void );
|
||||||
|
|
||||||
static inline void
|
typedef int (*VipsDrawPoint)( VipsDrawink *drawink, int x, int y );
|
||||||
|
typedef int (*VipsDrawScanline)( VipsDrawink *drawink, int y, int x1, int x2 );
|
||||||
|
|
||||||
|
static inline int
|
||||||
vips__drawink_pel( VipsDrawink *drawink, VipsPel *q )
|
vips__drawink_pel( VipsDrawink *drawink, VipsPel *q )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) drawink;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
@ -80,23 +83,27 @@ vips__drawink_pel( VipsDrawink *drawink, VipsPel *q )
|
|||||||
*/
|
*/
|
||||||
for( j = 0; j < draw->psize; j++ )
|
for( j = 0; j < draw->psize; j++ )
|
||||||
q[j] = drawink->pixel_ink[j];
|
q[j] = drawink->pixel_ink[j];
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Paint, with clip.
|
/* Paint, with clip.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline int
|
||||||
vips__drawink_pel_clip( VipsDrawink *drawink, int x, int y )
|
vips__drawink_pel_clip( VipsDrawink *drawink, int x, int y )
|
||||||
{
|
{
|
||||||
VipsDraw *draw = (VipsDraw *) drawink;
|
VipsDraw *draw = (VipsDraw *) drawink;
|
||||||
|
|
||||||
if( x < 0 ||
|
if( x < 0 ||
|
||||||
x >= draw->image->Xsize )
|
x >= draw->image->Xsize )
|
||||||
return;
|
return( 0 );
|
||||||
if( y < 0 ||
|
if( y < 0 ||
|
||||||
y >= draw->image->Ysize )
|
y >= draw->image->Ysize )
|
||||||
return;
|
return( 0 );
|
||||||
|
|
||||||
vips__drawink_pel( drawink, VIPS_IMAGE_ADDR( draw->image, x, y ) );
|
vips__drawink_pel( drawink, VIPS_IMAGE_ADDR( draw->image, x, y ) );
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is p painted?
|
/* Is p painted?
|
||||||
@ -115,7 +122,7 @@ vips__drawink_painted( VipsDrawink *drawink, VipsPel *p )
|
|||||||
return( j == draw->psize );
|
return( j == draw->psize );
|
||||||
}
|
}
|
||||||
|
|
||||||
void vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 );
|
int vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -271,6 +271,8 @@ VipsPel *im__vector_to_ink( const char *domain,
|
|||||||
|
|
||||||
int vips__draw_flood_direct( VipsImage *image, VipsImage *test,
|
int vips__draw_flood_direct( VipsImage *image, VipsImage *test,
|
||||||
int serial, int x, int y );
|
int serial, int x, int y );
|
||||||
|
int vips__draw_mask_direct( VipsImage *image, VipsImage *mask,
|
||||||
|
VipsPel *ink, int x, int y );
|
||||||
|
|
||||||
/* Register base vips interpolators, called during startup.
|
/* Register base vips interpolators, called during startup.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user