almost compiling

This commit is contained in:
John Cupitt 2014-02-04 08:49:17 +00:00
parent ad5b6be8f6
commit 54f2ea772c
15 changed files with 397 additions and 187 deletions

View File

@ -715,7 +715,7 @@ AC_OUTPUT([
libvips/foreign/Makefile
libvips/freqfilt/Makefile
libvips/histogram/Makefile
libvips/inplace/Makefile
libvips/draw/Makefile
libvips/iofuncs/Makefile
libvips/morphology/Makefile
libvips/mosaicing/Makefile

View File

@ -1,16 +1,19 @@
noinst_LTLIBRARIES = libdraw.la
libdraw_la_SOURCES = \
circle.c \
draw.c \
pdraw.h \
flood.c \
im_draw_circle.c \
im_draw_line.c \
im_draw_image.c \
im_draw_rect.c \
im_draw_line.c \
im_draw_mask.c \
im_draw_point.c \
im_draw_rect.c \
im_draw_smudge.c \
inplace_dispatch.c
inplace_dispatch.c \
old_draw.c \
old_draw.h \
pdraw.h
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -59,12 +59,11 @@
#include "pdraw.h"
G_DEFINE_TYPE( VipsCircle, vips_circle, VIPS_TYPE_DRAW );
typedef struct _VipsCircle {
VipsDraw parent_object;
int x, y;
int cx;
int cy;
int radius;
gboolean fill;
@ -73,173 +72,72 @@ typedef struct _VipsCircle {
typedef VipsDrawClass VipsCircleClass;
static int
vips_circle_build( VipsObject *object )
{
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsCircle *circle = (VipsCircle *) object;
if( VIPS_OBJECT_CLASS( vips_falsecolour_parent_class )->
build( object ) )
return( -1 );
if( x + radius >= 0 && x - radius < image->Xsize &&
y + radius >= 0 && y - radius < image->Ysize ) {
VipsCircle *circle;
if( !(circle = circle_new( image, x, y, radius, fill, ink )) )
return( -1 );
circle_draw( circle );
circle_free( circle );
}
return( 0 );
}
return( 0 );
}
static void
vips_circle_class_init( VipsFalsecolourClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "circle";
vobject_class->description = _( "draw a circle on an image" );
vobject_class->build = vips_circle_build;
VIPS_ARG_INT( class, "x", 2,
_( "x" ),
_( "Centre of circle" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, x ),
-1000000000, 1000000000, 0 );
VIPS_ARG_INT( class, "y", 3,
_( "y" ),
_( "Centre of circle" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, y ),
-1000000000, 1000000000, 0 );
VIPS_ARG_INT( class, "radius", 3,
_( "radius" ),
_( "Radius in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, radius ),
0, 1000000000, 0 );
VIPS_ARG_BOOL( class, "fill", 3,
_( "fill" ),
_( "Draw a solid object" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCircle, fill ),
0, 1000000000, 0 );
}
static void
vips_circle_init( VipsCircle *circle )
{
}
G_DEFINE_TYPE( VipsCircle, vips_circle, VIPS_TYPE_DRAW );
static void
vips_circle_octants( VipsCircle *circle, int x, int y )
{
Draw *draw = DRAW( circle );
VipsDraw *draw = VIPS_DRAW( circle );
const int cx = circle->cx;
const int cy = circle->cy;
if( circle->fill ) {
const int cx = circle->cx;
const int cy = circle->cy;
im__draw_scanline( draw, cy + y, cx - x, cx + x );
im__draw_scanline( draw, cy - y, cx - x, cx + x );
im__draw_scanline( draw, cy + x, cx - y, cx + y );
im__draw_scanline( draw, cy - x, cx - y, cx + y );
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 );
}
else if( DRAW( circle )->noclip ) {
else if( VIPS_DRAW( circle )->noclip ) {
const size_t lsize = draw->lsize;
const size_t psize = draw->psize;
VipsPel *centre = circle->centre;
im__draw_pel( draw, centre + lsize * y - psize * x );
im__draw_pel( draw, centre + lsize * y + psize * x );
im__draw_pel( draw, centre - lsize * y - psize * x );
im__draw_pel( draw, centre - lsize * y + psize * x );
im__draw_pel( draw, centre + lsize * x - psize * y );
im__draw_pel( draw, centre + lsize * x + psize * y );
im__draw_pel( draw, centre - lsize * x - psize * y );
im__draw_pel( draw, centre - lsize * x + psize * y );
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 );
}
else {
const int cx = circle->cx;
const int cy = circle->cy;
im__draw_pel_clip( draw, cx + y, cy - x );
im__draw_pel_clip( draw, cx + y, cy + x );
im__draw_pel_clip( draw, cx - y, cy - x );
im__draw_pel_clip( draw, cx - y, cy + x );
im__draw_pel_clip( draw, cx + x, cy - y );
im__draw_pel_clip( draw, cx + x, cy + y );
im__draw_pel_clip( draw, cx - x, cy - y );
im__draw_pel_clip( draw, cx - x, cy + y );
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 );
}
}
static void
vips_circle_free( VipsCircle *circle )
static int
vips_circle_build( VipsObject *object )
{
im__draw_free( DRAW( circle ) );
im_free( circle );
}
VipsDraw *draw = VIPS_DRAW( object );
VipsCircle *circle = (VipsCircle *) object;
static VipsCircle *
vips_circle_new( IMAGE *im, int cx, int cy, int radius, gboolean fill, VipsPel *ink )
{
VipsCircle *circle;
if( im_check_coding_known( "im_draw_circle", im ) )
return( NULL );
if( !(circle = IM_NEW( NULL, VipsCircle )) )
return( NULL );
if( !im__draw_init( DRAW( circle ), im, ink ) ) {
circle_free( circle );
return( NULL );
}
circle->cx = cx;
circle->cy = cy;
circle->radius = radius;
circle->fill = fill;
circle->centre = IM_IMAGE_ADDR( im, cx, cy );
if( cx - radius >= 0 && cx + radius < im->Xsize &&
cy - radius >= 0 && cy + radius < im->Ysize )
DRAW( circle )->noclip = TRUE;
return( circle );
}
static void
vips_circle_draw( VipsCircle *circle )
{
int x, y, d;
if( VIPS_OBJECT_CLASS( vips_circle_parent_class )->
build( object ) )
return( -1 );
circle->centre = VIPS_IMAGE_ADDR( draw->image, circle->cx, circle->cy );
if( circle->cx - circle->radius >= 0 &&
circle->cx + circle->radius < draw->image->Xsize &&
circle->cy - circle->radius >= 0 &&
circle->cy + circle->radius < draw->image->Ysize )
draw->noclip = TRUE;
y = circle->radius;
d = 3 - 2 * circle->radius;
for( x = 0; x < y; x++ ) {
circle_octants( circle, x, y );
vips_circle_octants( circle, x, y );
if( d < 0 )
d += 4 * x + 6;
@ -250,37 +148,140 @@ vips_circle_draw( VipsCircle *circle )
}
if( x == y )
circle_octants( circle, x, y );
vips_circle_octants( circle, x, y );
return( 0 );
}
static void
vips_circle_class_init( VipsCircleClass *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 = "circle";
vobject_class->description = _( "draw a circle on an image" );
vobject_class->build = vips_circle_build;
VIPS_ARG_INT( class, "cx", 3,
_( "cx" ),
_( "Centre of circle" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, cx ),
-1000000000, 1000000000, 0 );
VIPS_ARG_INT( class, "cy", 4,
_( "cy" ),
_( "Centre of circle" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, cy ),
-1000000000, 1000000000, 0 );
VIPS_ARG_INT( class, "radius", 5,
_( "radius" ),
_( "Radius in pixels" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCircle, radius ),
0, 1000000000, 0 );
VIPS_ARG_BOOL( class, "fill", 6,
_( "fill" ),
_( "Draw a solid object" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCircle, fill ),
FALSE );
}
static void
vips_circle_init( VipsCircle *circle )
{
circle->fill = FALSE;
}
static int
vips_circlev( VipsImage *image,
double *ink, int n, int cx, int cy, int radius, va_list ap )
{
VipsArea *area_ink;
int result;
area_ink = (VipsArea *) vips_array_double_new( ink, n );
result = vips_call_split( "circle", ap,
image, area_ink, cx, cy, radius );
vips_area_unref( area_ink );
return( result );
}
/**
* vips_circle:
* @image: image to draw on
* @x: centre of circle
* @y: centre of circle
* @ink: (array length=n): value to draw
* @n length of ink array
* @cx: centre of circle
* @cy: centre of circle
* @radius: circle radius
*
* Optional arguments:
*
* @fill: fill the circle
* @ink: value to draw
*
* Draws a circle on @image. If @fill is %TRUE then the circle is filled,
* otherwise a 1-pixel-wide perimeter is drawn.
*
* @ink is an array of bytes containing a valid pixel for the image's format.
* It must have at least IM_IMAGE_SIZEOF_PEL( @image ) bytes.
* @ink is an array of double containing values to draw.
*
* See also: im_draw_line().
* See also: vips_circle1(), vips_draw_line().
*
* Returns: 0 on success, or -1 on error.
*/
int
vips_circle( VipsImage *image,
int x, int y, int radius, gboolean fill, VipsPel *ink )
double *ink, int n, int cx, int cy, int radius, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "circle", ap, in, out );
va_start( ap, radius );
result = vips_circlev( image, ink, n, cx, cy, radius, ap );
va_end( ap );
return( result );
}
/**
* vips_circle1:
* @image: image to draw on
* @ink: value to draw
* @cx: centre of circle
* @cy: centre of circle
* @radius: circle radius
*
* Optional arguments:
*
* @fill: fill the circle
*
* As vips_circle(), but just takes a single double for @ink.
*
* See also: vips_circle(), vips_draw_line().
*
* Returns: 0 on success, or -1 on error.
*/
int
vips_circle1( VipsImage *image, double ink, int cx, int cy, int radius, ... )
{
double array_ink[1];
va_list ap;
int result;
array_ink[0] = ink;
va_start( ap, radius );
result = vips_circlev( image, array_ink, 1, cx, cy, radius, ap );
va_end( ap );
return( result );

View File

@ -41,8 +41,9 @@
#include <string.h>
#include <vips/vips.h>
#include <vips/internal.h>
#include "draw.h"
#include "pdraw.h"
/**
* SECTION: draw
@ -74,15 +75,16 @@ vips_draw_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_draw_parent_class )->build( object ) )
return( -1 );
if( vips_image_inplace( draw->im ) )
return( NULL );
if( vips_check_coding_known( class->nickname, draw->image ) ||
vips_image_inplace( draw->image ) )
return( -1 );
draw->lsize = VIPS_IMAGE_SIZEOF_LINE( draw->im );
draw->psize = VIPS_IMAGE_SIZEOF_PEL( draw->im );
draw->lsize = VIPS_IMAGE_SIZEOF_LINE( draw->image );
draw->psize = VIPS_IMAGE_SIZEOF_PEL( draw->image );
draw->noclip = FALSE;
if( !(draw->pixel_ink = vips__vector_to_ink(
class->nickname, draw->im,
class->nickname, draw->image,
draw->ink->data, draw->ink->n )) )
return( -1 );
@ -106,9 +108,9 @@ vips_draw_class_init( VipsDrawClass *class )
_( "Image" ),
_( "Image to draw on" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsDraw, im ) );
G_STRUCT_OFFSET( VipsDraw, image ) );
VIPS_ARG_BOXED( class, "ink", 12,
VIPS_ARG_BOXED( class, "ink", 2,
_( "Ink" ),
_( "Colour for pixels" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
@ -127,9 +129,9 @@ vips_draw_init( VipsDraw *draw )
void
vips_draw_operation_init( void )
{
extern GType vips_copy_get_type( void );
extern GType vips_circle_get_type( void );
vips_copy_get_type();
vips_circle_get_type();
}
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2.
@ -144,18 +146,18 @@ vips__draw_scanline( VipsDraw *draw, int y, int x1, int x2 )
g_assert( x1 <= x2 );
if( y < 0 ||
y >= draw->im->Ysize )
y >= draw->image->Ysize )
return;
if( x1 < 0 &&
x2 < 0 )
return;
if( x1 >= draw->im->Xsize &&
x2 >= draw->im->Xsize )
if( x1 >= draw->image->Xsize &&
x2 >= draw->image->Xsize )
return;
x1 = VIPS_CLIP( 0, x1, draw->im->Xsize - 1 );
x2 = VIPS_CLIP( 0, x2, draw->im->Xsize - 1 );
x1 = VIPS_CLIP( 0, x1, draw->image->Xsize - 1 );
x2 = VIPS_CLIP( 0, x2, draw->image->Xsize - 1 );
mp = VIPS_IMAGE_ADDR( draw->im, x1, y );
mp = VIPS_IMAGE_ADDR( draw->image, x1, y );
len = x2 - x1 + 1;
for( i = 0; i < len; i++ ) {

View File

@ -324,7 +324,7 @@ flood_all( Flood *flood, int x, int y )
/* Test start pixel ... nothing to do?
*/
if( !flood_connected( flood,
IM_IMAGE_ADDR( flood->test, x, y ) ) )
VIPS_IMAGE_ADDR( flood->test, x, y ) ) )
return;
flood_scanline( flood, x, y, &x1, &x2 );

View File

@ -55,7 +55,7 @@
#include <vips/vips.h>
#include "draw.h"
#include "old_draw.h"
/* Our state.
*/

View File

@ -59,7 +59,7 @@
#include <vips/vips.h>
#include "draw.h"
#include "old_draw.h"
typedef struct _Line {
Draw draw;

View File

@ -57,7 +57,7 @@
#include <vips/vips.h>
#include <vips/internal.h>
#include "draw.h"
#include "old_draw.h"
typedef struct _Mask {
Draw draw;

View File

@ -55,7 +55,7 @@
#include <vips/vips.h>
#include "draw.h"
#include "old_draw.h"
typedef struct _Point {
Draw draw;

View File

@ -57,7 +57,7 @@
#include <vips/vips.h>
#include "draw.h"
#include "old_draw.h"
/**
* im_draw_rect:

102
libvips/draw/old_draw.c Normal file
View File

@ -0,0 +1,102 @@
/* base class for drawing operations
*
* 27/9/10
* - from im_draw_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 <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <string.h>
#include <vips/vips.h>
#include "draw.h"
/* Fill a scanline between points x1 and x2 inclusive. x1 < x2.
*/
void
im__draw_scanline( Draw *draw, int y, int x1, int x2 )
{
VipsPel *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 = 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;
}
}
void
im__draw_free( Draw *draw )
{
IM_FREE( draw->ink );
}
Draw *
im__draw_init( Draw *draw, IMAGE *im, VipsPel *ink )
{
if( im_rwcheck( im ) )
return( NULL );
draw->im = im;
draw->ink = NULL;
draw->lsize = IM_IMAGE_SIZEOF_LINE( im );
draw->psize = IM_IMAGE_SIZEOF_PEL( im );
draw->noclip = FALSE;
if( ink ) {
if( !(draw->ink = (VipsPel *) im_malloc( NULL, draw->psize )) )
return( NULL );
memcpy( draw->ink, ink, draw->psize );
}
return( draw );
}

92
libvips/draw/old_draw.h Normal file
View File

@ -0,0 +1,92 @@
/* base class for drawing operations
*/
/*
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
*/
/* Our state.
*/
typedef struct _Draw {
/* Parameters.
*/
IMAGE *im; /* Draw here */
VipsPel *ink; /* Copy of ink param */
/* Derived stuff.
*/
size_t lsize;
size_t psize;
/* If the object to draw is entirely within the image, we have a
* faster noclip path.
*/
gboolean noclip;
} Draw;
#define DRAW(X) ((Draw *)(X))
static inline void
im__draw_pel( Draw *draw, VipsPel *q )
{
int j;
/* Faster than memcopy() for n < about 20.
*/
for( j = 0; j < draw->psize; j++ )
q[j] = draw->ink[j];
}
/* Paint, with clip.
*/
static inline void
im__draw_pel_clip( Draw *draw, int x, int y )
{
if( x < 0 || x >= draw->im->Xsize )
return;
if( y < 0 || y >= draw->im->Ysize )
return;
im__draw_pel( draw, IM_IMAGE_ADDR( draw->im, x, y ) );
}
/* Is p painted?
*/
static inline gboolean
im__draw_painted( Draw *draw, VipsPel *p )
{
int j;
for( j = 0; j < draw->psize; j++ )
if( p[j] != draw->ink[j] )
break;
return( j == draw->psize );
}
void im__draw_scanline( Draw *draw, int y, int x1, int x2 );
void im__draw_free( Draw *draw );
Draw *im__draw_init( Draw *draw, IMAGE *im, VipsPel *ink );

View File

@ -97,13 +97,13 @@ static inline void
vips__draw_pel_clip( VipsDraw *draw, int x, int y )
{
if( x < 0 ||
x >= draw->im->Xsize )
x >= draw->image->Xsize )
return;
if( y < 0 ||
y >= draw->im->Ysize )
y >= draw->image->Ysize )
return;
vips__draw_pel( draw, VIPS_IMAGE_ADDR( draw->im, x, y ) );
vips__draw_pel( draw, VIPS_IMAGE_ADDR( draw->image, x, y ) );
}
/* Is p painted?

View File

@ -38,6 +38,16 @@
extern "C" {
#endif /*__cplusplus*/
int vips_circle( VipsImage *image,
double *ink, int n, int cx, int cy, int radius, ... )
__attribute__((sentinel));
int vips_circle1( VipsImage *image,
double ink, int cx, int cy, int radius, ... )
__attribute__((sentinel));
int im_draw_rect( VipsImage *image,
int left, int top, int width, int height, int fill, VipsPel *ink );
int im_draw_circle( VipsImage *image,

View File

@ -134,7 +134,7 @@ extern "C" {
#include <vips/freqfilt.h>
#include <vips/resample.h>
#include <vips/colour.h>
#include <vips/inplace.h>
#include <vips/draw.h>
#include <vips/create.h>
#include <vips/video.h>
#include <vips/cimg_funcs.h>