im_*join() redone as a class

This commit is contained in:
John Cupitt 2011-10-26 13:26:20 +01:00
parent e159aba7c7
commit b969ce2aa5
13 changed files with 182 additions and 262 deletions

View File

@ -1,8 +1,9 @@
20/8/11 started 7.27.0
- version bump for new dev cycle
- im_subtract(), im_avg(), im_min(), im_minpos(), im_copy(), im_embed(),
im_flophor(), im_flipver(), im_insert(), im_insert_noexpand() redone as
classes
im_flophor(), im_flipver(), im_insert(), im_insert_noexpand(), im_lrjoin(),
im_tbjoin()
redone as classes
- added VIPS_ARGUMENT_APPEND to help control arg ordering
- generate has a 'stop' param to signal successful early termination
- added optional output args, eg. x/y for min

32
TODO
View File

@ -1,22 +1,19 @@
- finish join.c
- do extract_area, needed by join
- note member free stuff in vipsobject docs
- lintra_vec next ... how should we do vips_lin() vs. vips_lin_vec()? do we
need two separate things?
should boxed get freed in finalise rather than dispose?
perhaps just have vips_lin() as a convenience function
how about a "squash" param to VipsLin which clips the output type back to
the input type? maybe not a great idea
- all things that use sizealike could take a --background param? or an
--extend param? maybe not a great idea (maybe handy for convolve affine etc.
though)
- vipsimage should be cached too, eg.
VipsImage *a = vips_image_new_from_file( "poop.jpg" );
can be reused
- we should cache on "written" ... we should emit written for all objects, and
there should be a a vipsarg flag to block updates after written
- the lifetime of an object is
@ -48,14 +45,17 @@
vips im_copy_set /home/john/GIT/nip2/test/tmp/t1.v
/home/john/GIT/nip2/test/tmp/cmyk.v 15 1 1 0 0
- lintra_vec next ... how should we do vips_lin() vs. vips_lin_vec()? do we
need two separate things?
VIPS-WARNING **: object.c:775: VipsImage can only assign 'xoffset' once
perhaps just have vips_lin() as a convenience function
how about a "squash" param to VipsLin which clips the output type back to
the input type? maybe not a great idea
HH
- all things that use sizealike could take a --background param? or an
--extend param? maybe not a great idea (maybe handy for convolve affine etc.
though)

View File

@ -7,6 +7,7 @@ libconversion_la_SOURCES = \
embed.c \
flip.c \
insert.c \
join.c \
conver_dispatch.c \
im_black.c \
im_c2amph.c \
@ -19,7 +20,6 @@ libconversion_la_SOURCES = \
im_falsecolour.c \
im_gbandjoin.c \
im_insert.c \
im_lrjoin.c \
im_mask2vips.c \
im_msb.c \
im_replicate.c \
@ -33,7 +33,6 @@ libconversion_la_SOURCES = \
im_subsample.c \
im_system.c \
im_system_image.c \
im_tbjoin.c \
im_text.c \
im_gaussnoise.c \
im_vips2mask.c \

View File

@ -106,10 +106,12 @@ vips_conversion_operation_init( void )
extern GType vips_embed_get_type( void );
extern GType vips_flip_get_type( void );
extern GType vips_insert_get_type( void );
extern GType vips_join_get_type( void );
vips_copy_get_type();
vips_embed_get_type();
vips_flip_get_type();
vips_insert_get_type();
vips_join_get_type();
}

View File

@ -1,100 +0,0 @@
/* im_lrjoin
*
* Copyright 1990, 1991: Kirk Martinez, N. Dessipris
* Author: Kirk Martinez, N. Dessipris
* Written on: 9/6/90
* Modified on: 17/04/1991
* 31/8/93 JC
* - args to memcpy() were reversed
* 14/11/94 JC
* - tided up and ANSIfied
* - now accepts IM_CODING_LABQ
* - memory leaks removed
* - bug in calculation of output Xsize removed (thanks Thomson!)
* - bug in checking of image compatibility fixed
* 23/10/95 JC
* - rewritten in terms of im_insert()
* 14/4/04
* - sets Xoffset / Yoffset
* 1/2/10
* - gtkdoc
* - cleanups
*/
/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
/**
* im_lrjoin:
* @left: image to go on left
* @right: image to go on right
* @out: output image
*
* Join @left and @right together, left-right. If one is taller than the
* other, @out will be has high as the smaller.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_insert(), im_tbjoin().
*
* Returns: 0 on success, -1 on error
*/
int
im_lrjoin( IMAGE *left, IMAGE *right, IMAGE *out )
{
IMAGE *t1;
/* Paste right and left together, trim the bottom edge.
*/
if( !(t1 = im_open_local( out, "im_lrjoin:1", "p" )) ||
im_insert( left, right, t1, left->Xsize, 0 ) ||
im_extract_area( t1, out,
0, 0, t1->Xsize, IM_MIN( left->Ysize, right->Ysize ) ) )
return( -1 );
out->Xoffset = left->Xsize;
out->Yoffset = 0;
return( 0 );
}

View File

@ -1,99 +0,0 @@
/* im_tbjoin
*
* Copyright: 1990, 1991 Kirk Martinez, N. Dessipris
* Author: Kirk Martinez, N. Dessipris
* Written on: 9/6/90
* Updated: 15/03/1991, N. Dessipris
* 31/8/93 JC
* - externs removed
* 14/11/94 JC
* - tidied up
* - now works for IM_CODING_LABQ too
* - image compatibility bug fixed
* 28/4/95 JC
* - y arg to 2nd set of im_writeline()s was wrong
* 23/10/95 JC
* - rewritten in terms of im_insert()
* 14/4/04
* - sets Xoffset / Yoffset
* 1/2/10
* - gtkdoc
* - cleanups
*/
/*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 <stdio.h>
#include <stdlib.h>
#include <vips/vips.h>
/**
* im_tbjoin:
* @top: image to go on top
* @bottom: image to go on bottom
* @out: output image
*
* Join @top and @bottom together, up-down. If one is wider than the
* other, @out will be has wide as the smaller.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
* the two n-band images are operated upon.
*
* The two input images are cast up to the smallest common type (see table
* Smallest common format in
* <link linkend="VIPS-arithmetic">arithmetic</link>).
*
* See also: im_insert(), im_tbjoin().
*
* Returns: 0 on success, -1 on error
*/
int
im_tbjoin( IMAGE *top, IMAGE *bottom, IMAGE *out )
{
IMAGE *t1;
/* Paste top and bottom together, cut off any leftovers.
*/
if( !(t1 = im_open_local( out, "im_tbjoin:1", "p" )) ||
im_insert( top, bottom, t1, 0, top->Ysize ) ||
im_extract_area( t1, out,
0, 0, IM_MIN( top->Xsize, bottom->Xsize ), t1->Ysize ) )
return( -1 );
out->Xoffset = 0;
out->Yoffset = top->Ysize;
return( 0 );
}

View File

@ -267,11 +267,6 @@ vips__vector_to_ink( const char *domain, VipsImage *im, double *vec, int n )
return( (PEL *) t[2]->data );
}
/* xy range we sanity check on ... just to stop crazy numbers from 1/0 etc.
* causing g_assert() failures later.
*/
#define RANGE (100000000)
static int
vips_insert_build( VipsObject *object )
{
@ -281,14 +276,6 @@ vips_insert_build( VipsObject *object )
VipsImage *t[4];
VipsImage **arry;
/* Check args.
*/
if( insert->x > RANGE || insert->x < -RANGE ||
insert->y > RANGE || insert->y < -RANGE ) {
vips_error( "VipsInsert", "%s", _( "xy out of range" ) );
return( -1 );
}
if( VIPS_OBJECT_CLASS( vips_insert_parent_class )->build( object ) )
return( -1 );
@ -366,6 +353,11 @@ vips_insert_build( VipsObject *object )
return( 0 );
}
/* xy range we sanity check on ... just to stop crazy numbers from 1/0 etc.
* causing g_assert() failures later.
*/
#define RANGE (100000000)
static void
vips_insert_class_init( VipsInsertClass *class )
{
@ -398,14 +390,14 @@ vips_insert_class_init( VipsInsertClass *class )
_( "Left edge of sub in main" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsInsert, x ),
0, 1000000, 0 );
-RANGE, RANGE, 0 );
VIPS_ARG_INT( class, "y", 3,
_( "Y" ),
_( "Top edge of sub in main" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsInsert, y ),
0, 1000000, 0 );
-RANGE, RANGE, 0 );
VIPS_ARG_BOOL( class, "expand", 4,
_( "Expand" ),

View File

@ -72,16 +72,28 @@
* VipsJoin:
* @in1: first input image
* @in2: second input image
* @out: output image
* @output: output image
* @direction: join horizontally or vertically
* @expand: TRUE to expand the output image to hold all of the input pixels
* @expand: %TRUE to expand the output image to hold all of the input pixels
* @shim: space between images, in pixels
* @background: background ink colour
* @align: low, centre or high alignment
*
* Join @left and @right together, left-right. If one is taller than the
* other, @out will be has high as the smaller.
* Join @in1 and @in2 together, left-right or up-down depending on the value
* of @direction.
*
* If one is taller or wider than the
* other, @output will be has high as the smaller. If @expand is %TRUE, then
* the output will be expanded to contain all of the input pixels.
*
* Use @align to set the edge that the images align on. By default, they align
* on the edge with the lower value coordinate.
*
* Use @background to set the colour of any pixels in @output which are not
* present in either @in1 or @in2.
*
* Use @shim to set the spacing between the images. By default this is 0.
*
* If the number of bands differs, one of the images
* must have one band. In this case, an n-band image is formed from the
* one-band image by joining n copies of the one-band image together, and then
@ -101,8 +113,8 @@ typedef struct _VipsJoin {
/* Params.
*/
VipsImage *main;
VipsImage *sub;
VipsImage *in1;
VipsImage *in2;
VipsDirection direction;
gboolean expand;
int shim;
@ -119,14 +131,16 @@ vips_join_build( VipsObject *object )
{
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsJoin *join = (VipsJoin *) object;
int x, y;
VipsImage *t;
if( VIPS_OBJECT_CLASS( vips_join_parent_class )->build( object ) )
return( -1 );
switch( join->direction ) {
case VIPS_DIRECTION_HORIZONTAL:
x = join->main->Xsize + join->shim;
x = join->in1->Xsize + join->shim;
switch( join->align ) {
case VIPS_ALIGN_LOW:
@ -134,21 +148,90 @@ vips_join_build( VipsObject *object )
break;
case VIPS_ALIGN_CENTRE:
mx = VIPS_MAX( join->main->Ysize, join->sub->Ysize );
y =
y = join->in1->Ysize / 2 - join->in2->Ysize / 2;
break;
case VIPS_ALIGN_HIGH:
y = 0;
y = join->in1->Ysize - join->in2->Ysize;
break;
default:
g_assert( 0 );
}
break;
case VIPS_DIRECTION_VERTICAL:
y = join->in1->Ysize + join->shim;
switch( join->align ) {
case VIPS_ALIGN_LOW:
x = 0;
break;
case VIPS_ALIGN_CENTRE:
x = join->in1->Xsize / 2 - join->in2->Xsize / 2;
break;
case VIPS_ALIGN_HIGH:
x = join->in1->Xsize - join->in2->Xsize;
break;
default:
g_assert( 0 );
}
break;
default:
g_asert( 0 );
g_assert( 0 );
}
if( vips_insert( join->in1, join->in2, &t, x, y,
"expand", TRUE,
"background", join->background,
NULL ) )
return( -1 );
if( !join->expand ) {
VipsImage *t2;
int left, top, width, height;
switch( join->direction ) {
case VIPS_DIRECTION_HORIZONTAL:
left = 0;
top = VIPS_MAX( 0, y ) - y;
width = t->Xsize;
height = VIPS_MIN( join->in1->Ysize, join->in2->Ysize );
break;
case VIPS_DIRECTION_VERTICAL:
left = VIPS_MAX( 0, x ) - x;
top = 0;
width = VIPS_MIN( join->in1->Xsize, join->in2->Xsize );
height = t->Ysize;
break;
default:
g_assert( 0 );
}
if( vips_call( "extract_area", t, &t2,
left, top, width, height, NULL ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
t = t2;
}
if( vips_image_write( t, conversion->output ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}
@ -168,17 +251,17 @@ vips_join_class_init( VipsJoinClass *class )
vobject_class->description = _( "join an image" );
vobject_class->build = vips_join_build;
VIPS_ARG_IMAGE( class, "main", -1,
_( "Main" ),
_( "Main input image" ),
VIPS_ARG_IMAGE( class, "in1", -1,
_( "in1" ),
_( "First input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsJoin, main ) );
G_STRUCT_OFFSET( VipsJoin, in1 ) );
VIPS_ARG_IMAGE( class, "sub", 0,
_( "Sub-image" ),
_( "Sub-image to join into main image" ),
VIPS_ARG_IMAGE( class, "in2", 0,
_( "in2" ),
_( "Second input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsJoin, sub ) );
G_STRUCT_OFFSET( VipsJoin, in2 ) );
VIPS_ARG_ENUM( class, "direction", 2,
_( "direction" ),
@ -198,7 +281,7 @@ vips_join_class_init( VipsJoinClass *class )
_( "Shim" ),
_( "Pixels between images" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsInsert, shim ),
G_STRUCT_OFFSET( VipsJoin, shim ),
0, 1000000, 0 );
VIPS_ARG_BOXED( class, "background", 6,
@ -211,7 +294,7 @@ vips_join_class_init( VipsJoinClass *class )
VIPS_ARG_ENUM( class, "align", 2,
_( "Align" ),
_( "Align on the low, centre or high coordinate edge" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsJoin, align ),
VIPS_TYPE_ALIGN, VIPS_ALIGN_LOW );
}
@ -227,14 +310,14 @@ vips_join_init( VipsJoin *join )
}
int
vips_join( VipsImage *main, VipsImage *sub, VipsImage **out,
vips_join( VipsImage *in1, VipsImage *in2, VipsImage **output,
VipsDirection direction, ... )
{
va_list ap;
int result;
va_start( ap, y );
result = vips_call_split( "join", ap, main, sub, out, direction );
va_start( ap, direction );
result = vips_call_split( "join", ap, in1, in2, output, direction );
va_end( ap );
return( result );

View File

@ -1146,4 +1146,37 @@ im_insert_noexpand( IMAGE *main, IMAGE *sub, IMAGE *out, int x, int y )
return( 0 );
}
int
im_lrjoin( IMAGE *left, IMAGE *right, IMAGE *out )
{
VipsImage *t;
if( vips_join( left, right, &t, VIPS_DIRECTION_HORIZONTAL,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}
int
im_tbjoin( IMAGE *left, IMAGE *right, IMAGE *out )
{
VipsImage *t;
if( vips_join( left, right, &t, VIPS_DIRECTION_VERTICAL,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}

View File

@ -801,7 +801,6 @@ vips_wrap7_subclass_class_init( VipsWrap7Class *class )
case VIPS_WRAP7_INTVEC:
case VIPS_WRAP7_GVALUE:
case VIPS_WRAP7_INTERPOLATE:
case VIPS_WRAP7_INT:
case VIPS_WRAP7_COMPLEX:
case VIPS_WRAP7_STRING:
case VIPS_WRAP7_NONE:
@ -812,6 +811,14 @@ vips_wrap7_subclass_class_init( VipsWrap7Class *class )
pspec = NULL;
break;
case VIPS_WRAP7_INT:
pspec = g_param_spec_int( arg->name,
arg->name,
arg->name,
-G_MAXINT, G_MAXINT, 0,
G_PARAM_READWRITE );
break;
case VIPS_WRAP7_DOUBLE:
pspec = g_param_spec_double( arg->name,
arg->name,

View File

@ -164,8 +164,6 @@ int im_extract_areabands( VipsImage *in, VipsImage *out,
int im_bandjoin( VipsImage *in1, VipsImage *in2, VipsImage *out );
int im_gbandjoin( VipsImage **in, VipsImage *out, int n );
int im_insertset( VipsImage *main, VipsImage *sub, VipsImage *out, int n, int *x, int *y );
int im_lrjoin( VipsImage *left, VipsImage *right, VipsImage *out );
int im_tbjoin( VipsImage *top, VipsImage *bottom, VipsImage *out );
int im_replicate( VipsImage *in, VipsImage *out, int across, int down );
int im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down );
int im_wrap( VipsImage *in, VipsImage *out, int x, int y );

View File

@ -546,6 +546,9 @@ int im_flipver( VipsImage *in, VipsImage *out );
int im_insert( VipsImage *main, VipsImage *sub, VipsImage *out, int x, int y );
int im_insert_noexpand( VipsImage *main, VipsImage *sub, VipsImage *out, int x, int y );
int im_lrjoin( VipsImage *left, VipsImage *right, VipsImage *out );
int im_tbjoin( VipsImage *top, VipsImage *bottom, VipsImage *out );
/* ruby-vips uses this
*/
#define vips_class_map_concrete_all vips_class_map_all

View File

@ -54,6 +54,7 @@ vips_align_get_type( void )
{VIPS_ALIGN_LOW, "VIPS_ALIGN_LOW", "low"},
{VIPS_ALIGN_CENTRE, "VIPS_ALIGN_CENTRE", "centre"},
{VIPS_ALIGN_HIGH, "VIPS_ALIGN_HIGH", "high"},
{VIPS_ALIGN_LAST, "VIPS_ALIGN_LAST", "last"},
{0, NULL, NULL}
};