start to extend draw_image

This commit is contained in:
John Cupitt 2014-03-27 15:00:29 +00:00
parent 7752eb89e0
commit b522fd79a9
6 changed files with 117 additions and 11 deletions

7
TODO
View File

@ -1,3 +1,10 @@
- add a "mode" param to draw_image.c, get rid of draw_add.c
- hough_line.c should have a main accumulator and use vips_draw_add() to add
threads to that
big memory saving
- need call operation along a circle, see line draw
- use with vips_draw_add() to make amask image for each radius for

View File

@ -1,6 +1,6 @@
#!/bin/sh
# set -x
set -x
# a bunch of cleaning up ... make certain everything will be regenerated
rm -f Makefile Makefile.in aclocal.m4

View File

@ -58,6 +58,19 @@
* They are mostly supposed to be useful for paintbox-style programs.
*/
/**
* VipsCombineMode:
* @VIPS_COMBINE_MODE_SET: set pixels to the new value
* @VIPS_COMBINE_MODE_ADD: add pixels
*
* See vips_draw_image() and so on.
*
* Operations like vips_draw_image() need to be told how to combine images
* from two sources.
*
* See also: vips_join().
*/
G_DEFINE_ABSTRACT_TYPE( VipsDraw, vips_draw, VIPS_TYPE_OPERATION );
static int

View File

@ -1,7 +1,7 @@
/* in-place add, ie. a = a + b
*
* 26/3/14
* - from draw_add.c
* - from draw_image.c
*/
/*

View File

@ -77,6 +77,7 @@ typedef struct _VipsDrawImage {
VipsImage *sub;
int x;
int y;
VipsCombineMode mode;
} VipsDrawImage;
@ -87,12 +88,58 @@ typedef struct _VipsDrawImageClass {
G_DEFINE_TYPE( VipsDrawImage, vips_draw_image, VIPS_TYPE_DRAW );
#define LOOP( TYPE ) { \
TYPE * restrict pt = (TYPE *) p; \
TYPE * restrict qt = (TYPE *) q; \
\
for( x = 0; x < sz; x++ ) \
qt[x] += pt[x]; \
}
static void
vips_draw_image_mode_add( VipsDrawImage *draw_image,
VipsPel *q, VipsPel *p, int n )
{
/* Complex just doubles the size.
*/
const int sz = clip_rect.width * im->Bands *
(vips_band_format_iscomplex( im->BandFmt ) ? 2 : 1);
int x;
switch( im->BandFmt ) {
case VIPS_FORMAT_UCHAR:
LOOP( unsigned char ); break;
case VIPS_FORMAT_CHAR:
LOOP( signed char ); break;
case VIPS_FORMAT_USHORT:
LOOP( unsigned short ); break;
case VIPS_FORMAT_SHORT:
LOOP( signed short ); break;
case VIPS_FORMAT_UINT:
LOOP( unsigned int ); break;
case VIPS_FORMAT_INT:
LOOP( signed int ); break;
case VIPS_FORMAT_FLOAT:
case VIPS_FORMAT_COMPLEX:
LOOP( float ); break;
case VIPS_FORMAT_DOUBLE:
case VIPS_FORMAT_DPCOMPLEX:
LOOP( double ); break;
default:
g_assert( 0 );
}
}
static int
vips_draw_image_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsDraw *draw = VIPS_DRAW( object );
VipsDrawImage *image = (VipsDrawImage *) object;
VipsDrawImage *draw_image = (VipsDrawImage *) object;
VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 );
VipsImage *im;
@ -105,14 +152,21 @@ vips_draw_image_build( VipsObject *object )
if( vips_check_coding_known( class->nickname, draw->image ) ||
vips_check_coding_same( class->nickname,
draw->image, image->sub ) ||
draw->image, draw_image->sub ) ||
vips_check_bands_1orn_unary( class->nickname,
image->sub, draw->image->Bands ) )
draw_image->sub, draw->image->Bands ) )
return( -1 );
/* SET will work for any matching coding, but every other mode needs
* uncoded images.
*/
if( draw_image->mode != VIPS_COMBINE_MODE_SET &&
vips_check_uncoded( class->nickname, draw->image ) )
return( -1 );
/* Cast sub to match main in bands and format.
*/
im = image->sub;
im = draw_image->sub;
if( im->Coding == VIPS_CODING_NONE ) {
if( vips__bandup( class->nickname,
im, &t[0], draw->image->Bands ) ||
@ -128,8 +182,8 @@ vips_draw_image_build( VipsObject *object )
image_rect.top = 0;
image_rect.width = draw->image->Xsize;
image_rect.height = draw->image->Ysize;
sub_rect.left = image->x;
sub_rect.top = image->y;
sub_rect.left = draw_image->x;
sub_rect.top = draw_image->y;
sub_rect.width = im->Xsize;
sub_rect.height = im->Ysize;
vips_rect_intersectrect( &image_rect, &sub_rect, &clip_rect );
@ -142,12 +196,30 @@ vips_draw_image_build( VipsObject *object )
return( -1 );
p = VIPS_IMAGE_ADDR( im,
clip_rect.left - image->x, clip_rect.top - image->y );
clip_rect.left - draw_image->x,
clip_rect.top - draw_image->y );
q = VIPS_IMAGE_ADDR( draw->image,
clip_rect.left, clip_rect.top );
for( y = 0; y < clip_rect.height; y++ ) {
memcpy( (char *) q, (char *) p,
clip_rect.width * VIPS_IMAGE_SIZEOF_PEL( im ) );
switch( draw_image->mode ) {
case VIPS_COMBINE_MODE_SET:
memcpy( (char *) q, (char *) p,
clip_rect.width *
VIPS_IMAGE_SIZEOF_PEL( im ) );
break;
case VIPS_COMBINE_MODE_ADD:
vips_draw_image_add( draw_image,
q, p, clip_rect.width );
break;
default:
g_assert( 0 );
break;
}
p += VIPS_IMAGE_SIZEOF_LINE( im );
q += VIPS_IMAGE_SIZEOF_LINE( draw->image );
}
@ -189,11 +261,19 @@ vips_draw_image_class_init( VipsDrawImageClass *class )
G_STRUCT_OFFSET( VipsDrawImage, y ),
-1000000000, 1000000000, 0 );
VIPS_ARG_ENUM( class, "mode", 8,
_( "Mode" ),
_( "Combining mode" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsDrawImage, mode ),
VIPS_TYPE_COMBINE_MODE, VIPS_COMBINE_MODE_SET );
}
static void
vips_draw_image_init( VipsDrawImage *draw_image )
{
draw_image->mode = VIPS_COMBINE_MODE_SET;
}
/**

View File

@ -38,6 +38,12 @@
extern "C" {
#endif /*__cplusplus*/
typedef enum {
VIPS_COMBINE_MODE_SET,
VIPS_COMBINE_MODE_ADD,
VIPS_COMBINE_MODE_LAST
} VipsCombineMode;
int vips_draw_rect( VipsImage *image,
double *ink, int n, int left, int top, int width, int height, ... )
__attribute__((sentinel));