diff --git a/TODO b/TODO index 4eda420f..99b20608 100644 --- a/TODO +++ b/TODO @@ -17,33 +17,6 @@ we must insist vector.length == 2 or bands * 2 for complex, or have the current behaviour of imaginary == 0 always -- try: - - $ vips draw_smudge - usage: - draw_smudge image ink left top width height - blur a rectangle on an image - where: - image - Image to draw on, input VipsImage - ink - Colour for pixels, input VipsArrayDouble - left - Rect to fill, input gint - top - Rect to fill, input gint - width - Rect to fill, input gint - height - Rect to fill, input gint - - nice if we could hide the "ink" param - - also for - - draw_image - draw_line_user - - we could either move ink to the other operations or make a new subclass of - draw containing the ink arg - - - - - try diff --git a/libvips/draw/Makefile.am b/libvips/draw/Makefile.am index 6d00e579..20f8ece2 100644 --- a/libvips/draw/Makefile.am +++ b/libvips/draw/Makefile.am @@ -3,6 +3,8 @@ noinst_LTLIBRARIES = libdraw.la libdraw_la_SOURCES = \ draw.c \ pdraw.h \ + drawink.c \ + drawink.h \ draw_circle.c \ draw_flood.c \ draw_mask.c \ diff --git a/libvips/draw/draw.c b/libvips/draw/draw.c index 2848d0ef..e127cdf6 100644 --- a/libvips/draw/draw.c +++ b/libvips/draw/draw.c @@ -83,12 +83,6 @@ vips_draw_build( VipsObject *object ) draw->psize = VIPS_IMAGE_SIZEOF_PEL( draw->image ); draw->noclip = FALSE; - if( draw->ink && - !(draw->pixel_ink = vips__vector_to_ink( - class->nickname, draw->image, - draw->ink->data, draw->ink->n )) ) - return( -1 ); - return( 0 ); } @@ -111,20 +105,11 @@ vips_draw_class_init( VipsDrawClass *class ) VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsDraw, image ) ); - VIPS_ARG_BOXED( class, "ink", 2, - _( "Ink" ), - _( "Colour for pixels" ), - VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsDraw, ink ), - VIPS_TYPE_ARRAY_DOUBLE ); - } static void vips_draw_init( VipsDraw *draw ) { - draw->ink = vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), 1 ); - ((double *) (draw->ink->data))[0] = 0; } void @@ -151,35 +136,3 @@ vips_draw_operation_init( void ) vips_draw_smudge_get_type(); } -/* Fill a scanline between points x1 and x2 inclusive. x1 < x2. - */ -void -vips__draw_scanline( VipsDraw *draw, int y, int x1, int x2 ) -{ - VipsPel *mp; - int i; - int len; - - g_assert( x1 <= x2 ); - - if( y < 0 || - y >= draw->image->Ysize ) - return; - if( x1 < 0 && - x2 < 0 ) - return; - if( x1 >= draw->image->Xsize && - x2 >= draw->image->Xsize ) - return; - x1 = VIPS_CLIP( 0, x1, draw->image->Xsize - 1 ); - x2 = VIPS_CLIP( 0, x2, draw->image->Xsize - 1 ); - - mp = VIPS_IMAGE_ADDR( draw->image, x1, y ); - len = x2 - x1 + 1; - - for( i = 0; i < len; i++ ) { - vips__draw_pel( draw, mp ); - mp += draw->psize; - } -} - diff --git a/libvips/draw/draw_circle.c b/libvips/draw/draw_circle.c index aa33bb7b..eec0d940 100644 --- a/libvips/draw/draw_circle.c +++ b/libvips/draw/draw_circle.c @@ -57,10 +57,10 @@ #include -#include "pdraw.h" +#include "drawink.h" typedef struct _VipsDrawCircle { - VipsDraw parent_object; + VipsDrawink parent_object; int cx; int cy; @@ -70,46 +70,47 @@ typedef struct _VipsDrawCircle { VipsPel *centre; } VipsDrawCircle; -typedef VipsDrawClass VipsDrawCircleClass; +typedef VipsDrawinkClass VipsDrawCircleClass; -G_DEFINE_TYPE( VipsDrawCircle, vips_draw_circle, VIPS_TYPE_DRAW ); +G_DEFINE_TYPE( VipsDrawCircle, vips_draw_circle, VIPS_TYPE_DRAWINK ); static void vips_draw_circle_octants( VipsDrawCircle *circle, int x, int y ) { VipsDraw *draw = VIPS_DRAW( circle ); + VipsDrawink *drawink = VIPS_DRAWINK( circle ); const int cx = circle->cx; const int cy = circle->cy; if( circle->fill ) { - vips__draw_scanline( draw, cy + y, cx - x, cx + x ); - vips__draw_scanline( draw, cy - y, cx - x, cx + x ); - vips__draw_scanline( draw, cy + x, cx - y, cx + y ); - vips__draw_scanline( draw, cy - x, cx - y, cx + y ); + vips__drawink_scanline( drawink, cy + y, cx - x, cx + x ); + vips__drawink_scanline( drawink, cy - y, cx - x, cx + x ); + vips__drawink_scanline( drawink, cy + x, cx - y, cx + y ); + vips__drawink_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__draw_pel( draw, centre + lsize * y - psize * x ); - vips__draw_pel( draw, centre + lsize * y + psize * x ); - vips__draw_pel( draw, centre - lsize * y - psize * x ); - vips__draw_pel( draw, centre - lsize * y + psize * x ); - vips__draw_pel( draw, centre + lsize * x - psize * y ); - vips__draw_pel( draw, centre + lsize * x + psize * y ); - vips__draw_pel( draw, centre - lsize * x - psize * y ); - vips__draw_pel( draw, centre - lsize * x + psize * y ); + 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 { - vips__draw_pel_clip( draw, cx + y, cy - x ); - vips__draw_pel_clip( draw, cx + y, cy + x ); - vips__draw_pel_clip( draw, cx - y, cy - x ); - vips__draw_pel_clip( draw, cx - y, cy + x ); - vips__draw_pel_clip( draw, cx + x, cy - y ); - vips__draw_pel_clip( draw, cx + x, cy + y ); - vips__draw_pel_clip( draw, cx - x, cy - y ); - vips__draw_pel_clip( draw, cx - x, cy + y ); + vips__drawink_pel_clip( drawink, cx + y, cy - x ); + vips__drawink_pel_clip( drawink, cx + y, cy + x ); + vips__drawink_pel_clip( drawink, cx - y, cy - x ); + vips__drawink_pel_clip( drawink, cx - y, cy + x ); + vips__drawink_pel_clip( drawink, cx + x, cy - y ); + vips__drawink_pel_clip( drawink, cx + x, cy + y ); + vips__drawink_pel_clip( drawink, cx - x, cy - y ); + vips__drawink_pel_clip( drawink, cx - x, cy + y ); } } @@ -121,7 +122,8 @@ vips_draw_circle_build( VipsObject *object ) int x, y, d; - if( VIPS_OBJECT_CLASS( vips_draw_circle_parent_class )->build( object ) ) + if( VIPS_OBJECT_CLASS( vips_draw_circle_parent_class )-> + build( object ) ) return( -1 ); circle->centre = VIPS_IMAGE_ADDR( draw->image, circle->cx, circle->cy ); diff --git a/libvips/draw/draw_flood.c b/libvips/draw/draw_flood.c index 3537728f..f265904b 100644 --- a/libvips/draw/draw_flood.c +++ b/libvips/draw/draw_flood.c @@ -71,7 +71,7 @@ #include #include -#include "pdraw.h" +#include "drawink.h" /* Size of a scanline buffer. We allocate a list of these to hold scanlines * we need to visit. @@ -103,7 +103,7 @@ typedef struct _Buffer { /* Base class. */ typedef struct _VipsDrawFlood { - VipsDraw draw; + VipsDrawink parent_object; /* Parameters. */ @@ -130,9 +130,9 @@ typedef struct _VipsDrawFlood { Buffer *out; } VipsDrawFlood; -typedef VipsDrawClass VipsDrawFloodClass; +typedef VipsDrawinkClass VipsDrawFloodClass; -G_DEFINE_TYPE( VipsDrawFlood, vips_draw_flood, VIPS_TYPE_DRAW ); +G_DEFINE_TYPE( VipsDrawFlood, vips_draw_flood, VIPS_TYPE_DRAWINK ); /* Alloc a new buffer. */ @@ -220,6 +220,7 @@ static void vips_draw_flood_scanline( VipsDrawFlood *flood, int x, int y, int *x1, int *x2 ) { VipsDraw *draw = VIPS_DRAW( flood ); + VipsDrawink *drawink = VIPS_DRAWINK( flood ); const int width = flood->test->Xsize; VipsPel *tp; @@ -227,7 +228,7 @@ vips_draw_flood_scanline( VipsDrawFlood *flood, int x, int y, int *x1, int *x2 ) g_assert( vips_draw_flood_connected( flood, VIPS_IMAGE_ADDR( flood->test, x, y ) ) ); - g_assert( !vips__draw_painted( draw, + g_assert( !vips__drawink_painted( drawink, VIPS_IMAGE_ADDR( draw->image, x, y ) ) ); /* Search to the right for the first non-connected pixel. If the start @@ -254,7 +255,7 @@ vips_draw_flood_scanline( VipsDrawFlood *flood, int x, int y, int *x1, int *x2 ) /* Paint the range we discovered. */ - vips__draw_scanline( draw, y, *x1, *x2 ); + vips__drawink_scanline( drawink, y, *x1, *x2 ); flood->left = VIPS_MIN( flood->left, *x1 ); flood->right = VIPS_MAX( flood->right, *x2 ); @@ -269,6 +270,7 @@ static void vips_draw_flood_around( VipsDrawFlood *flood, Scan *scan ) { VipsDraw *draw = VIPS_DRAW( flood ); + VipsDrawink *drawink = VIPS_DRAWINK( flood ); VipsPel *tp; int x; @@ -292,7 +294,7 @@ vips_draw_flood_around( VipsDrawFlood *flood, Scan *scan ) VipsPel *mp = VIPS_IMAGE_ADDR( draw->image, x, scan->y ); - if( vips__draw_painted( draw, mp ) ) + if( vips__drawink_painted( drawink, mp ) ) continue; } @@ -368,6 +370,7 @@ vips_draw_flood_build( VipsObject *object ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsDraw *draw = VIPS_DRAW( object ); + VipsDrawink *drawink = VIPS_DRAWINK( object ); VipsDrawFlood *flood = (VipsDrawFlood *) object; int j; @@ -409,8 +412,7 @@ vips_draw_flood_build( VipsObject *object ) */ if( flood->test == draw->image ) { for( j = 0; j < flood->tsize; j++ ) - if( flood->edge[j] != - VIPS_DRAW( flood )->pixel_ink[j] ) + if( flood->edge[j] != drawink->pixel_ink[j] ) break; if( j != flood->tsize ) @@ -424,7 +426,7 @@ vips_draw_flood_build( VipsObject *object ) * @ink. */ if( !(flood->edge = vips__vector_to_ink( class->nickname, - flood->test, draw->ink->data, draw->ink->n )) ) + flood->test, drawink->ink->data, drawink->ink->n )) ) return( -1 ); vips_draw_flood_all( flood ); diff --git a/libvips/draw/draw_image.c b/libvips/draw/draw_image.c index 0bf2491a..d095e03b 100644 --- a/libvips/draw/draw_image.c +++ b/libvips/draw/draw_image.c @@ -219,8 +219,7 @@ vips_draw_image( VipsImage *image, VipsImage *sub, int x, int y, ... ) int result; va_start( ap, y ); - result = vips_call_split( "draw_image", ap, - image, NULL, sub, x, y ); + result = vips_call_split( "draw_image", ap, image, sub, x, y ); va_end( ap ); return( result ); diff --git a/libvips/draw/draw_line.c b/libvips/draw/draw_line.c index 7a2348fd..91d216b0 100644 --- a/libvips/draw/draw_line.c +++ b/libvips/draw/draw_line.c @@ -61,10 +61,9 @@ #include -#include "pdraw.h" #include "draw_line.h" -G_DEFINE_TYPE( VipsDrawLine, vips_draw_line, VIPS_TYPE_DRAW ); +G_DEFINE_TYPE( VipsDrawLine, vips_draw_line, VIPS_TYPE_DRAWINK ); static int vips_draw_line_draw( VipsDrawLine *line ) @@ -248,11 +247,13 @@ static int vips_draw_line_plot_point( VipsDrawLine *line, int x, int y ) { VipsDraw *draw = (VipsDraw *) line; + VipsDrawink *drawink = (VipsDrawink *) line; if( draw->noclip ) - vips__draw_pel( draw, VIPS_IMAGE_ADDR( draw->image, x, y ) ); + vips__drawink_pel( drawink, + VIPS_IMAGE_ADDR( draw->image, x, y ) ); else - vips__draw_pel_clip( draw, x, y ); + vips__drawink_pel_clip( drawink, x, y ); return( 0 ); } diff --git a/libvips/draw/draw_line.h b/libvips/draw/draw_line.h index efcb197e..23fb3e27 100644 --- a/libvips/draw/draw_line.h +++ b/libvips/draw/draw_line.h @@ -35,6 +35,8 @@ extern "C" { #endif /*__cplusplus*/ +#include "drawink.h" + #define VIPS_TYPE_DRAW_LINE (vips_draw_line_get_type()) #define VIPS_DRAW_LINE( obj ) \ (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ @@ -51,7 +53,7 @@ extern "C" { VIPS_TYPE_DRAW_LINE, VipsDrawLineClass )) typedef struct _VipsDrawLine { - VipsDraw parent_object; + VipsDrawink parent_object; int x1; int y1; @@ -64,7 +66,7 @@ typedef struct _VipsDrawLine { } VipsDrawLine; typedef struct _VipsDrawLineClass { - VipsDrawClass parent_class; + VipsDrawinkClass parent_class; int (*plot_point)( VipsDrawLine *, int x, int y ); } VipsDrawLineClass; diff --git a/libvips/draw/draw_line_mask.c b/libvips/draw/draw_line_mask.c index 4303fa66..f27a68e1 100644 --- a/libvips/draw/draw_line_mask.c +++ b/libvips/draw/draw_line_mask.c @@ -60,7 +60,6 @@ #include -#include "pdraw.h" #include "draw_line.h" typedef struct _VipsDrawLineMask { @@ -78,10 +77,12 @@ static int vips_draw_line_mask_plot_point( VipsDrawLine *line, int x, int y ) { VipsDraw *draw = (VipsDraw *) line; + VipsDrawink *drawink = (VipsDrawink *) line; VipsDrawLineMask *mask = (VipsDrawLineMask *) line; return( vips_draw_mask( draw->image, - draw->ink->data, draw->ink->n, mask->mask, x, y, NULL ) ); + drawink->ink->data, drawink->ink->n, + mask->mask, x, y, NULL ) ); } static void @@ -155,7 +156,8 @@ vips_draw_line_mask( VipsImage *image, int result; va_start( ap, mask ); - result = vips_draw_line_maskv( image, ink, n, x1, y1, x2, y2, mask, ap ); + result = vips_draw_line_maskv( image, + ink, n, x1, y1, x2, y2, mask, ap ); va_end( ap ); return( result ); diff --git a/libvips/draw/draw_mask.c b/libvips/draw/draw_mask.c index 81c05b6e..e118be5c 100644 --- a/libvips/draw/draw_mask.c +++ b/libvips/draw/draw_mask.c @@ -60,10 +60,10 @@ #include #include -#include "pdraw.h" +#include "drawink.h" typedef struct _VipsDrawMask { - VipsDraw parent_object; + VipsDrawink parent_object; /* Parameters. */ @@ -78,11 +78,11 @@ typedef struct _VipsDrawMask { } VipsDrawMask; typedef struct _VipsDrawMaskClass { - VipsDrawClass parent_class; + VipsDrawinkClass parent_class; } VipsDrawMaskClass; -G_DEFINE_TYPE( VipsDrawMask, vips_draw_mask, VIPS_TYPE_DRAW ); +G_DEFINE_TYPE( VipsDrawMask, vips_draw_mask, VIPS_TYPE_DRAWINK ); /* Paint ink into an 8 or 16 bit integer image. */ @@ -134,6 +134,7 @@ static int vips_draw_mask_draw_labq( VipsDrawMask *mask ) { VipsDraw *draw = VIPS_DRAW( mask ); + VipsDrawink *drawink = VIPS_DRAWINK( mask ); int width = mask->image_clip.width; int height = mask->image_clip.height; int bands = draw->image->Bands; @@ -153,7 +154,7 @@ vips_draw_mask_draw_labq( VipsDrawMask *mask ) y + mask->mask_clip.top ); vips__LabQ2Lab_vec( lab_buffer, to, width ); - DBLEND( float, lab_buffer, (double *) draw->ink->data ); + DBLEND( float, lab_buffer, (double *) drawink->ink->data ); vips__Lab2LabQ_vec( to, lab_buffer, width ); } @@ -166,6 +167,7 @@ static int vips_draw_mask_draw( VipsDrawMask *mask ) { VipsDraw *draw = VIPS_DRAW( mask ); + VipsDrawink *drawink = VIPS_DRAWINK( mask ); int width = mask->image_clip.width; int height = mask->image_clip.height; int bands = draw->image->Bands; @@ -182,43 +184,43 @@ vips_draw_mask_draw( VipsDrawMask *mask ) switch( draw->image->BandFmt ) { case VIPS_FORMAT_UCHAR: - IBLEND( unsigned char, to, draw->pixel_ink ); + IBLEND( unsigned char, to, drawink->pixel_ink ); break; case VIPS_FORMAT_CHAR: - IBLEND( signed char, to, draw->pixel_ink ); + IBLEND( signed char, to, drawink->pixel_ink ); break; case VIPS_FORMAT_USHORT: - IBLEND( unsigned short, to, draw->pixel_ink ); + IBLEND( unsigned short, to, drawink->pixel_ink ); break; case VIPS_FORMAT_SHORT: - IBLEND( signed short, to, draw->pixel_ink ); + IBLEND( signed short, to, drawink->pixel_ink ); break; case VIPS_FORMAT_UINT: - DBLEND( unsigned int, to, draw->pixel_ink ); + DBLEND( unsigned int, to, drawink->pixel_ink ); break; case VIPS_FORMAT_INT: - DBLEND( signed int, to, draw->pixel_ink ); + DBLEND( signed int, to, drawink->pixel_ink ); break; case VIPS_FORMAT_FLOAT: - DBLEND( float, to, draw->pixel_ink ); + DBLEND( float, to, drawink->pixel_ink ); break; case VIPS_FORMAT_DOUBLE: - DBLEND( double, to, draw->pixel_ink ); + DBLEND( double, to, drawink->pixel_ink ); break; case VIPS_FORMAT_COMPLEX: - CBLEND( float, to, draw->pixel_ink ); + CBLEND( float, to, drawink->pixel_ink ); break; case VIPS_FORMAT_DPCOMPLEX: - CBLEND( double, to, draw->pixel_ink ); + CBLEND( double, to, drawink->pixel_ink ); break; default: diff --git a/libvips/draw/draw_rect.c b/libvips/draw/draw_rect.c index cb5863e7..0575435d 100644 --- a/libvips/draw/draw_rect.c +++ b/libvips/draw/draw_rect.c @@ -60,10 +60,10 @@ #include #include -#include "pdraw.h" +#include "drawink.h" typedef struct _VipsDrawRect { - VipsDraw parent_object; + VipsDrawink parent_object; /* Parameters. */ @@ -76,16 +76,17 @@ typedef struct _VipsDrawRect { } VipsDrawRect; typedef struct _VipsDrawRectClass { - VipsDrawClass parent_class; + VipsDrawinkClass parent_class; } VipsDrawRectClass; -G_DEFINE_TYPE( VipsDrawRect, vips_draw_rect, VIPS_TYPE_DRAW ); +G_DEFINE_TYPE( VipsDrawRect, vips_draw_rect, VIPS_TYPE_DRAWINK ); static int vips_draw_rect_build( VipsObject *object ) { VipsDraw *draw = VIPS_DRAW( object ); + VipsDrawink *drawink = VIPS_DRAWINK( object ); VipsDrawRect *draw_rect = (VipsDrawRect *) object; int left = draw_rect->left; int top = draw_rect->top; @@ -105,16 +106,16 @@ vips_draw_rect_build( VipsObject *object ) width > 2 && height > 2 ) return( vips_draw_rect( draw->image, - draw->ink->data, draw->ink->n, + drawink->ink->data, drawink->ink->n, left, top, width, 1, NULL ) || vips_draw_rect( draw->image, - draw->ink->data, draw->ink->n, + drawink->ink->data, drawink->ink->n, left + width - 1, top, 1, height, NULL ) || vips_draw_rect( draw->image, - draw->ink->data, draw->ink->n, + drawink->ink->data, drawink->ink->n, left, top + height - 1, width, 1, NULL ) || vips_draw_rect( draw->image, - draw->ink->data, draw->ink->n, + drawink->ink->data, drawink->ink->n, left, top, 1, height, NULL ) ); image.left = 0; @@ -140,7 +141,7 @@ vips_draw_rect_build( VipsObject *object ) q = to; for( x = 0; x < clip.width; x++ ) { - vips__draw_pel( draw, q ); + vips__drawink_pel( drawink, q ); q += draw->psize; } diff --git a/libvips/draw/draw_smudge.c b/libvips/draw/draw_smudge.c index c1a5425f..1e1abeef 100644 --- a/libvips/draw/draw_smudge.c +++ b/libvips/draw/draw_smudge.c @@ -252,7 +252,7 @@ vips_draw_smudge( VipsImage *image, va_start( ap, height ); result = vips_call_split( "draw_smudge", ap, - image, NULL, left, top, width, height ); + image, left, top, width, height ); va_end( ap ); return( result ); diff --git a/libvips/draw/drawink.c b/libvips/draw/drawink.c new file mode 100644 index 00000000..7427a530 --- /dev/null +++ b/libvips/draw/drawink.c @@ -0,0 +1,138 @@ +/* drawink with a constant ink + * + * 27/9/10 + * - from im_drawink_circle() + * 17/11/10 + * - oops, scanline clipping was off by 1 + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include + +#include +#include + +#include "drawink.h" + +G_DEFINE_ABSTRACT_TYPE( VipsDrawink, vips_drawink, VIPS_TYPE_DRAW ); + +static int +vips_drawink_build( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsDraw *draw = VIPS_DRAW( object ); + VipsDrawink *drawink = VIPS_DRAWINK( object ); + +#ifdef DEBUG + printf( "vips_drawink_build: " ); + vips_object_print_name( object ); + printf( "\n" ); +#endif /*DEBUG*/ + + if( VIPS_OBJECT_CLASS( vips_drawink_parent_class )->build( object ) ) + return( -1 ); + + if( drawink->ink && + !(drawink->pixel_ink = vips__vector_to_ink( + class->nickname, draw->image, + drawink->ink->data, drawink->ink->n )) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_drawink_class_init( VipsDrawinkClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "drawink"; + vobject_class->description = _( "Draw with ink operations" ); + vobject_class->build = vips_drawink_build; + + VIPS_ARG_BOXED( class, "ink", 2, + _( "Ink" ), + _( "Colour for pixels" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsDrawink, ink ), + VIPS_TYPE_ARRAY_DOUBLE ); + +} + +static void +vips_drawink_init( VipsDrawink *drawink ) +{ + drawink->ink = + vips_area_new_array( G_TYPE_DOUBLE, sizeof( double ), 1 ); + ((double *) (drawink->ink->data))[0] = 0; +} + +/* Fill a scanline between points x1 and x2 inclusive. x1 < x2. + */ +void +vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 ) +{ + VipsDraw *draw = (VipsDraw *) drawink; + + VipsPel *mp; + int i; + int len; + + g_assert( x1 <= x2 ); + + if( y < 0 || + y >= draw->image->Ysize ) + return; + if( x1 < 0 && + x2 < 0 ) + return; + if( x1 >= draw->image->Xsize && + x2 >= draw->image->Xsize ) + return; + x1 = VIPS_CLIP( 0, x1, draw->image->Xsize - 1 ); + x2 = VIPS_CLIP( 0, x2, draw->image->Xsize - 1 ); + + mp = VIPS_IMAGE_ADDR( draw->image, x1, y ); + len = x2 - x1 + 1; + + for( i = 0; i < len; i++ ) { + vips__drawink_pel( drawink, mp ); + mp += draw->psize; + } +} + diff --git a/libvips/draw/drawink.h b/libvips/draw/drawink.h new file mode 100644 index 00000000..9400788e --- /dev/null +++ b/libvips/draw/drawink.h @@ -0,0 +1,126 @@ +/* a drawink operation with an ink param + */ + +/* + + This file is part of VIPS. + + VIPS is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifndef VIPS_DRAWINK_H +#define VIPS_DRAWINK_H + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#include "pdraw.h" + +#define VIPS_TYPE_DRAWINK (vips_drawink_get_type()) +#define VIPS_DRAWINK( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_DRAWINK, VipsDrawink )) +#define VIPS_DRAWINK_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_DRAWINK, VipsDrawinkClass)) +#define VIPS_IS_DRAWINK( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_DRAWINK )) +#define VIPS_IS_DRAWINK_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_DRAWINK )) +#define VIPS_DRAWINK_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_DRAWINK, VipsDrawinkClass )) + +typedef struct _VipsDrawink { + VipsDraw parent_instance; + + /* Parameters. + */ + VipsArea *ink; /* With this */ + + /* Ink cast to pixel type. + */ + VipsPel *pixel_ink; +} VipsDrawink; + +typedef struct _VipsDrawinkClass { + VipsDrawClass parent_class; + +} VipsDrawinkClass; + +GType vips_drawink_get_type( void ); + +static inline void +vips__drawink_pel( VipsDrawink *drawink, VipsPel *q ) +{ + VipsDraw *draw = (VipsDraw *) drawink; + + int j; + + /* Faster than memcopy() for n < about 20. + */ + for( j = 0; j < draw->psize; j++ ) + q[j] = drawink->pixel_ink[j]; +} + +/* Paint, with clip. + */ +static inline void +vips__drawink_pel_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 ) ); +} + +/* Is p painted? + */ +static inline gboolean +vips__drawink_painted( VipsDrawink *drawink, VipsPel *p ) +{ + VipsDraw *draw = (VipsDraw *) drawink; + + int j; + + for( j = 0; j < draw->psize; j++ ) + if( p[j] != drawink->pixel_ink[j] ) + break; + + return( j == draw->psize ); +} + +void vips__drawink_scanline( VipsDrawink *drawink, int y, int x1, int x2 ); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*VIPS_DRAWINK_H*/ diff --git a/libvips/draw/pdraw.h b/libvips/draw/pdraw.h index 26e22762..21a51ccf 100644 --- a/libvips/draw/pdraw.h +++ b/libvips/draw/pdraw.h @@ -56,17 +56,12 @@ typedef struct _VipsDraw { /* Parameters. */ VipsImage *image; /* Draw here */ - VipsArea *ink; /* With this */ /* Derived stuff. */ size_t lsize; size_t psize; - /* Ink cast to pixel type. - */ - VipsPel *pixel_ink; - /* If the object to draw is entirely within the image, we have a * faster noclip path. */ @@ -80,48 +75,6 @@ typedef struct _VipsDrawClass { GType vips_draw_get_type( void ); -static inline void -vips__draw_pel( VipsDraw *draw, VipsPel *q ) -{ - int j; - - /* Faster than memcopy() for n < about 20. - */ - for( j = 0; j < draw->psize; j++ ) - q[j] = draw->pixel_ink[j]; -} - -/* Paint, with clip. - */ -static inline void -vips__draw_pel_clip( VipsDraw *draw, int x, int y ) -{ - if( x < 0 || - x >= draw->image->Xsize ) - return; - if( y < 0 || - y >= draw->image->Ysize ) - return; - - vips__draw_pel( draw, VIPS_IMAGE_ADDR( draw->image, x, y ) ); -} - -/* Is p painted? - */ -static inline gboolean -vips__draw_painted( VipsDraw *draw, VipsPel *p ) -{ - int j; - - for( j = 0; j < draw->psize; j++ ) - if( p[j] != draw->pixel_ink[j] ) - break; - - return( j == draw->psize ); -} - -void vips__draw_scanline( VipsDraw *draw, int y, int x1, int x2 ); - #ifdef __cplusplus } #endif /*__cplusplus*/