im_clip2fmt() redone as a class

plus some rationalisation of member names
This commit is contained in:
John Cupitt 2011-10-27 12:10:24 +01:00
parent 6402fd9487
commit c027528b82
18 changed files with 309 additions and 634 deletions

View File

@ -3,9 +3,9 @@
- im_subtract(), im_avg(), im_min(), im_minpos(), im_copy(), im_embed(),
im_flophor(), im_flipver(), im_insert(), im_insert_noexpand(), im_lrjoin(),
im_tbjoin(), im_extract_area(), im_extract_bands(), im_extract_areabands(),
im_replicate()
im_replicate(), im_clip2fmt()
redone as classes
- added VIPS_ARGUMENT_APPEND to help control arg ordering
- added argument priorites to help control arg ordering
- generate has a 'stop' param to signal successful early termination
- added optional output args, eg. x/y for min
- CLI supports optional output args

12
TODO
View File

@ -1,4 +1,5 @@
- clip next?
- lintra_vec next
@ -55,6 +56,15 @@
bodge it for now, fix properly after we merge
- don't do vips_image_write() at the end of a pipeline, instead try:
g_object_set( object, "output", t );
ie. replace the output object
fails due to "assign once only" rule ... we need "don't assign after
written" instead

View File

@ -10,13 +10,13 @@ libconversion_la_SOURCES = \
join.c \
extract.c \
replicate.c \
cast.c \
conver_dispatch.c \
im_black.c \
im_c2amph.c \
im_c2rect.c \
im_c2imag.c \
im_c2real.c \
im_clip2fmt.c \
im_copy_file.c \
im_falsecolour.c \
im_gbandjoin.c \

View File

@ -43,6 +43,8 @@
* 27/1/10
* - modernised
* - gtk-doc
* 27/10/11
* - redone as a class
*/
/*
@ -83,6 +85,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
@ -105,16 +108,85 @@
typedef struct _VipsCast {
VipsConversion parent_instance;
VipsImage *input;
VipsImage *in;
VipsBandFormat format;
int underflow; /* Number of underflows */
int overflow; /* Number of overflows */
} VipsCast;
typedef VipsConversionClass VipsCastClass;
G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
/* Clip int types to an int type.
static void
vips_cast_preeval( VipsImage *image, VipsProgress *progress, VipsCast *cast )
{
cast->overflow = 0;
cast->underflow = 0;
}
static void
vips_cast_posteval( VipsImage *image, VipsProgress *progress, VipsCast *cast )
{
if( cast->overflow || cast->underflow )
vips_warn( "VipsCast",
_( "%d underflows and %d overflows detected" ),
cast->underflow, cast->overflow );
}
/* Our sequence value: the region this sequence is using, and two local stats.
*/
typedef struct {
VipsRegion *ir; /* Input region */
int underflow; /* Number of underflows */
int overflow; /* Number of overflows */
} VipsCastSequence;
/* Destroy a sequence value.
*/
static int
vips_cast_stop( void *vseq, void *a, void *b )
{
VipsCastSequence *seq = (VipsCastSequence *) vseq;
VipsCast *cast = (VipsCast *) b;
/* Add to global stats.
*/
cast->underflow += seq->underflow;
cast->overflow += seq->overflow;
VIPS_FREEF( g_object_unref, seq->ir );
g_free( seq );
return( 0 );
}
/* Make a sequence value.
*/
static void *
vips_cast_start( VipsImage *out, void *a, void *b )
{
VipsImage *in = (VipsImage *) a;
VipsCastSequence *seq;
seq = g_new( VipsCastSequence, 1 );
seq->ir = vips_region_new( in );
seq->overflow = 0;
seq->underflow = 0;
if( !seq->ir ) {
vips_cast_stop( seq, NULL, NULL );
return( NULL );
}
return( seq );
}
/* Cast int types to an int type.
*/
#define VIPS_CLIP_INT_INT( ITYPE, OTYPE, VIPS_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
@ -129,7 +201,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
} \
}
/* Clip float types to an int type.
/* Cast float types to an int type.
*/
#define VIPS_CLIP_FLOAT_INT( ITYPE, OTYPE, VIPS_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
@ -144,7 +216,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
} \
}
/* Clip complex types to an int type. Just take the real part.
/* Cast complex types to an int type. Just take the real part.
*/
#define VIPS_CLIP_COMPLEX_INT( ITYPE, OTYPE, VIPS_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
@ -160,7 +232,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
} \
}
/* Clip non-complex types to a float type.
/* Cast non-complex types to a float type.
*/
#define VIPS_CLIP_REAL_FLOAT( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
@ -170,7 +242,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
q[x] = p[x]; \
}
/* Clip complex types to a float type ... just take real.
/* Cast complex types to a float type ... just take real.
*/
#define VIPS_CLIP_COMPLEX_FLOAT( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
@ -182,7 +254,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
} \
}
/* Clip any non-complex to a complex type ... set imaginary to zero.
/* Cast any non-complex to a complex type ... set imaginary to zero.
*/
#define VIPS_CLIP_REAL_COMPLEX( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
@ -195,7 +267,7 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
} \
}
/* Clip any complex to a complex type.
/* Cast any complex to a complex type.
*/
#define VIPS_CLIP_COMPLEX_COMPLEX( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
@ -210,48 +282,60 @@ G_DEFINE_TYPE( VipsCast, vips_cast, VIPS_TYPE_CONVERSION );
}
#define BAND_SWITCH_INNER( ITYPE, INT, FLOAT, COMPLEX ) { \
switch( clip->out->BandFmt ) { \
switch( conversion->out->BandFmt ) { \
case VIPS_FORMAT_UCHAR: \
INT( ITYPE, unsigned char, VIPS_CLIP_UCHAR ); \
break; \
\
case VIPS_FORMAT_CHAR: \
INT( ITYPE, signed char, VIPS_CLIP_CHAR ); \
break; \
\
case VIPS_FORMAT_USHORT: \
INT( ITYPE, unsigned short, VIPS_CLIP_USHORT ); \
break; \
\
case VIPS_FORMAT_SHORT: \
INT( ITYPE, signed short, VIPS_CLIP_SHORT ); \
break; \
\
case VIPS_FORMAT_UINT: \
INT( ITYPE, unsigned int, VIPS_CLIP_NONE ); \
break; \
\
case VIPS_FORMAT_INT: \
INT( ITYPE, signed int, VIPS_CLIP_NONE ); \
break; \
\
case VIPS_FORMAT_FLOAT: \
FLOAT( ITYPE, float ); \
break; \
\
case VIPS_FORMAT_DOUBLE: \
FLOAT( ITYPE, double ); \
break; \
\
case VIPS_FORMAT_COMPLEX: \
COMPLEX( ITYPE, float ); \
break; \
\
case VIPS_FORMAT_DPCOMPLEX: \
COMPLEX( ITYPE, double ); \
break; \
\
default: \
g_assert( 0 ); \
} \
}
static int
vips_cast_gen( VipsRegion *or, void *seq, void *a, void *b,
vips_cast_gen( VipsRegion *or, void *vseq, void *a, void *b,
gboolean *stop )
{
VipsRegion *ir = (VipsRegion *) seq;
Clip *clip = (Clip *) b;
VipsCastSequence *seq = (VipsCastSequence *) vseq;
VipsRegion *ir = seq->ir;
VipsCast *cast = (VipsCast *) b;
VipsConversion *conversion = (VipsConversion *) b;
VipsRect *r = &or->valid;
int le = r->left;
int to = r->top;
@ -266,67 +350,77 @@ vips_cast_gen( VipsRegion *or, void *seq, void *a, void *b,
PEL *in = (PEL *) VIPS_REGION_ADDR( ir, le, y );
PEL *out = (PEL *) VIPS_REGION_ADDR( or, le, y );
switch( clip->in->BandFmt ) {
switch( cast->in->BandFmt ) {
case VIPS_FORMAT_UCHAR:
BAND_SWITCH_INNER( unsigned char,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_CHAR:
BAND_SWITCH_INNER( signed char,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_USHORT:
BAND_SWITCH_INNER( unsigned short,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_SHORT:
BAND_SWITCH_INNER( signed short,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_UINT:
BAND_SWITCH_INNER( unsigned int,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_INT:
BAND_SWITCH_INNER( signed int,
VIPS_CLIP_INT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_FLOAT:
BAND_SWITCH_INNER( float,
VIPS_CLIP_FLOAT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_DOUBLE:
BAND_SWITCH_INNER( double,
VIPS_CLIP_FLOAT_INT,
VIPS_CLIP_REAL_FLOAT,
VIPS_CLIP_REAL_COMPLEX );
break;
case VIPS_FORMAT_COMPLEX:
BAND_SWITCH_INNER( float,
VIPS_CLIP_COMPLEX_INT,
VIPS_CLIP_COMPLEX_FLOAT,
VIPS_CLIP_COMPLEX_COMPLEX );
break;
case VIPS_FORMAT_DPCOMPLEX:
BAND_SWITCH_INNER( double,
VIPS_CLIP_COMPLEX_INT,
VIPS_CLIP_COMPLEX_FLOAT,
VIPS_CLIP_COMPLEX_COMPLEX );
break;
default:
g_assert( 0 );
}
@ -341,25 +435,34 @@ vips_cast_build( VipsObject *object )
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsCast *cast = (VipsCast *) object;
VipsGenerateFn generate_fn;
if( VIPS_OBJECT_CLASS( vips_cast_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( cast->input ) ||
vips_image_pio_output( conversion->output ) )
/* Trivial case: fall back to im_copy().
*/
if( cast->in->BandFmt == cast->format )
return( vips_image_write( cast->in, conversion->out ) );
if( vips_check_uncoded( "VipsCast", cast->in ) ||
vips_image_pio_input( cast->in ) ||
vips_image_pio_output( conversion->out ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, cast->input ) )
if( vips_image_copy_fields( conversion->out, cast->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_THINSTRIP, cast->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_THINSTRIP, cast->in, NULL );
conversion->output->BandFmt = cast->format
conversion->out->BandFmt = cast->format;
if( vips_image_generate( conversion->output,
vips_start_one, generate_fn, vips_stop_one,
cast->input, cast ) )
g_signal_connect( cast->in, "preeval",
G_CALLBACK( vips_cast_preeval ), cast );
g_signal_connect( cast->in, "posteval",
G_CALLBACK( vips_cast_posteval ), cast );
if( vips_image_generate( conversion->out,
vips_cast_start, vips_cast_gen, vips_cast_stop,
cast->in, cast ) )
return( -1 );
return( 0 );
@ -380,11 +483,11 @@ vips_cast_class_init( VipsCastClass *class )
vobject_class->description = _( "cast an image" );
vobject_class->build = vips_cast_build;
VIPS_ARG_IMAGE( class, "input", 1,
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCast, input ) );
G_STRUCT_OFFSET( VipsCast, in ) );
VIPS_ARG_ENUM( class, "format", 6,
_( "Format" ),
@ -405,7 +508,7 @@ vips_cast( VipsImage *in, VipsImage **out, VipsBandFormat format, ... )
va_list ap;
int result;
va_start( ap, direction );
va_start( ap, format );
result = vips_call_split( "cast", ap, in, out, format );
va_end( ap );

View File

@ -88,7 +88,7 @@ vips_conversion_class_init( VipsConversionClass *class )
_( "Output" ),
_( "Output image" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsConversion, output ) );
G_STRUCT_OFFSET( VipsConversion, out ) );
}
static void
@ -110,6 +110,7 @@ vips_conversion_operation_init( void )
extern GType vips_extract_area_get_type( void );
extern GType vips_extract_band_get_type( void );
extern GType vips_replicate_get_type( void );
extern GType vips_cast_get_type( void );
vips_copy_get_type();
vips_embed_get_type();
@ -119,5 +120,6 @@ vips_conversion_operation_init( void )
vips_extract_area_get_type();
vips_extract_band_get_type();
vips_replicate_get_type();
vips_cast_get_type();
}

View File

@ -60,7 +60,7 @@ typedef struct _VipsConversion {
/* All have an output image.
*/
VipsImage *output;
VipsImage *out;
} VipsConversion;

View File

@ -94,8 +94,8 @@
/**
* VipsCopy:
* @input: input image
* @output: output image
* @in: input image
* @out: output image
*
* Copy an image, optionally modifying the header. VIPS copies images by
* copying pointers, so this operation is fast, even for very large images.
@ -113,7 +113,7 @@ typedef struct _VipsCopy {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
/* Swap bytes on the way through.
*/
@ -227,7 +227,7 @@ vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
return( -1 );
if( copy->swap ) {
SwapFn swap = vips_copy_swap_fn[copy->input->BandFmt];
SwapFn swap = vips_copy_swap_fn[copy->in->BandFmt];
int y;
for( y = 0; y < r->height; y++ ) {
@ -236,7 +236,7 @@ vips_copy_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
PEL *q = (PEL *) VIPS_REGION_ADDR( or,
r->left, r->top + y );
swap( p, q, r->width, copy->input );
swap( p, q, r->width, copy->in );
}
}
else
@ -274,14 +274,14 @@ vips_copy_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_copy_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( copy->input ) ||
vips_image_pio_output( conversion->output ) )
if( vips_image_pio_input( copy->in ) ||
vips_image_pio_output( conversion->out ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, copy->input ) )
if( vips_image_copy_fields( conversion->out, copy->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_THINSTRIP, copy->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_THINSTRIP, copy->in, NULL );
/* Use props to adjust header fields.
*/
@ -306,15 +306,15 @@ vips_copy_build( VipsObject *object )
g_value_init( &value, type );
g_object_get_property( G_OBJECT( object ),
name, &value );
g_object_set_property( G_OBJECT( conversion->output ),
g_object_set_property( G_OBJECT( conversion->out ),
name, &value );
g_value_unset( &value );
}
}
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, vips_copy_gen, vips_stop_one,
copy->input, copy ) )
copy->in, copy ) )
return( -1 );
return( 0 );
@ -339,7 +339,7 @@ vips_copy_class_init( VipsCopyClass *class )
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsCopy, input ) );
G_STRUCT_OFFSET( VipsCopy, in ) );
VIPS_ARG_BOOL( class, "swap", 2,
_( "Swap" ),

View File

@ -95,7 +95,7 @@ typedef struct _VipsEmbed {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
VipsExtend extend;
int x;
@ -164,7 +164,7 @@ vips_embed_find_edge( VipsEmbed *embed, VipsRect *r, int i, VipsRect *out )
static void
vips_embed_copy_pixel( VipsEmbed *embed, PEL *q, PEL *p, int n )
{
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->input );
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->in );
int x, b;
@ -181,7 +181,7 @@ static void
vips_embed_paint_edge( VipsEmbed *embed,
VipsRegion *or, int i, VipsRect *r, PEL *p, int plsk )
{
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->input );
const int bs = VIPS_IMAGE_SIZEOF_PEL( embed->in );
VipsRect todo;
PEL *q;
@ -326,7 +326,7 @@ vips_embed_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
}
static int
vips_embed_repeat( VipsPool *pool, VipsImage *input, VipsImage **output,
vips_embed_repeat( VipsPool *pool, VipsImage *in, VipsImage **out,
int x, int y, int width, int height )
{
VipsPoolContext *context = vips_pool_context_new( pool );
@ -335,15 +335,15 @@ vips_embed_repeat( VipsPool *pool, VipsImage *input, VipsImage **output,
* nicely.
*/
const int nx = x < 0 ?
-x % input->Xsize : input->Xsize - x % input->Xsize;
-x % in->Xsize : in->Xsize - x % in->Xsize;
const int ny = y < 0 ?
-y % input->Ysize : input->Ysize - y % input->Ysize;
-y % in->Ysize : in->Ysize - y % in->Ysize;
if(
vips_replicate( input, &VIPS_VI( 1 ),
width / input->Xsize + 2,
height / input->Ysize + 2, NULL ) ||
vips_extract_area( VIPS_VI( 1 ), output,
vips_replicate( in, &VIPS_VI( 1 ),
width / in->Xsize + 2,
height / in->Ysize + 2, NULL ) ||
vips_extract_area( VIPS_VI( 1 ), out,
nx, ny, width, height, NULL ) )
return( -1 );
@ -351,7 +351,7 @@ vips_embed_repeat( VipsPool *pool, VipsImage *input, VipsImage **output,
}
static int
vips_embed_mirror( VipsPool *pool, VipsImage *input, VipsImage **output,
vips_embed_mirror( VipsPool *pool, VipsImage *in, VipsImage **out,
int x, int y, int width, int height )
{
VipsPoolContext *context = vips_pool_context_new( pool );
@ -359,8 +359,8 @@ vips_embed_mirror( VipsPool *pool, VipsImage *input, VipsImage **output,
/* As repeat, but the tiles are twice the size because of
* mirroring.
*/
const int w2 = input->Xsize * 2;
const int h2 = input->Ysize * 2;
const int w2 = in->Xsize * 2;
const int h2 = in->Ysize * 2;
const int nx = x < 0 ? -x % w2 : w2 - x % w2;
const int ny = y < 0 ? -y % h2 : h2 - y % h2;
@ -368,9 +368,9 @@ vips_embed_mirror( VipsPool *pool, VipsImage *input, VipsImage **output,
if(
/* Make a 2x2 mirror tile.
*/
vips_flip( input, &VIPS_VI( 1 ),
vips_flip( in, &VIPS_VI( 1 ),
VIPS_DIRECTION_HORIZONTAL, NULL ) ||
vips_join( input, VIPS_VI( 1 ), &VIPS_VI( 2 ),
vips_join( in, VIPS_VI( 1 ), &VIPS_VI( 2 ),
VIPS_DIRECTION_HORIZONTAL, NULL ) ||
vips_flip( VIPS_VI( 2 ), &VIPS_VI( 3 ),
VIPS_DIRECTION_VERTICAL, NULL ) ||
@ -385,10 +385,10 @@ vips_embed_mirror( VipsPool *pool, VipsImage *input, VipsImage **output,
vips_extract_area( VIPS_VI( 5 ), &VIPS_VI( 6 ),
nx, ny, width, height, NULL ) ||
/* Overwrite the centre with the input, much faster
/* Overwrite the centre with the in, much faster
* for centre pixels.
*/
vips_insert( VIPS_VI( 6 ), input, output,
vips_insert( VIPS_VI( 6 ), in, out,
x, y, NULL ) )
return( -1 );
@ -407,8 +407,8 @@ vips_embed_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_embed_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( embed->input ) ||
vips_image_pio_output( conversion->output ) )
if( vips_image_pio_input( embed->in ) ||
vips_image_pio_output( conversion->out ) )
return( -1 );
if( embed->extend < 0 || embed->extend >= VIPS_EXTEND_LAST ) {
vips_error( "VipsEmbed", "%s", _( "unknown VipsExtend" ) );
@ -419,9 +419,9 @@ vips_embed_build( VipsObject *object )
*/
if( embed->x == 0 &&
embed->y == 0 &&
embed->width == embed->input->Xsize &&
embed->height == embed->input->Ysize )
return( vips_image_write( embed->input, conversion->output ) );
embed->width == embed->in->Xsize &&
embed->height == embed->in->Ysize )
return( vips_image_write( embed->in, conversion->out ) );
pool = vips_pool_new( "VipsEmbed" );
vips_object_local( object, pool );
@ -431,9 +431,9 @@ vips_embed_build( VipsObject *object )
{
VipsPoolContext *context = vips_pool_context_new( pool );
if( vips_embed_repeat( pool, embed->input, &VIPS_VI( 1 ),
if( vips_embed_repeat( pool, embed->in, &VIPS_VI( 1 ),
embed->x, embed->y, embed->width, embed->height ) ||
vips_image_write( VIPS_VI( 1 ), conversion->output ) )
vips_image_write( VIPS_VI( 1 ), conversion->out ) )
return( -1 );
}
@ -443,9 +443,9 @@ vips_embed_build( VipsObject *object )
{
VipsPoolContext *context = vips_pool_context_new( pool );
if( vips_embed_mirror( pool, embed->input, &VIPS_VI( 1 ),
if( vips_embed_mirror( pool, embed->in, &VIPS_VI( 1 ),
embed->x, embed->y, embed->width, embed->height ) ||
vips_image_write( VIPS_VI( 1 ), conversion->output ) )
vips_image_write( VIPS_VI( 1 ), conversion->out ) )
return( -1 );
}
break;
@ -453,28 +453,28 @@ vips_embed_build( VipsObject *object )
case VIPS_EXTEND_BLACK:
case VIPS_EXTEND_WHITE:
case VIPS_EXTEND_COPY:
if( vips_image_copy_fields( conversion->output, embed->input ) )
if( vips_image_copy_fields( conversion->out, embed->in ) )
return( -1 );
conversion->output->Xsize = embed->width;
conversion->output->Ysize = embed->height;
conversion->out->Xsize = embed->width;
conversion->out->Ysize = embed->height;
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_SMALLTILE, embed->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_SMALLTILE, embed->in, NULL );
/* Whole output area.
*/
embed->rout.left = 0;
embed->rout.top = 0;
embed->rout.width = conversion->output->Xsize;
embed->rout.height = conversion->output->Ysize;
embed->rout.width = conversion->out->Xsize;
embed->rout.height = conversion->out->Ysize;
/* Rect occupied by image (can be clipped to nothing).
*/
want.left = embed->x;
want.top = embed->y;
want.width = embed->input->Xsize;
want.height = embed->input->Ysize;
want.width = embed->in->Xsize;
want.height = embed->in->Ysize;
vips_rect_intersectrect( &want, &embed->rout, &embed->rsub );
/* FIXME ... actually, it can't. embed_find_edge() will fail
@ -496,14 +496,14 @@ vips_embed_build( VipsObject *object )
embed->border[1].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[1].top = embed->rsub.top;
embed->border[1].width = conversion->output->Xsize -
embed->border[1].width = conversion->out->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[1].height = embed->rsub.height;
embed->border[2].left = embed->rsub.left;
embed->border[2].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[2].width = embed->rsub.width;
embed->border[2].height = conversion->output->Ysize -
embed->border[2].height = conversion->out->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[3].left = 0;
@ -521,26 +521,26 @@ vips_embed_build( VipsObject *object )
embed->border[5].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[5].top = 0;
embed->border[5].width = conversion->output->Xsize -
embed->border[5].width = conversion->out->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[5].height = embed->rsub.top;
embed->border[6].left = VIPS_RECT_RIGHT( &embed->rsub );
embed->border[6].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[6].width = conversion->output->Xsize -
embed->border[6].width = conversion->out->Xsize -
VIPS_RECT_RIGHT( &embed->rsub );
embed->border[6].height = conversion->output->Ysize -
embed->border[6].height = conversion->out->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[7].left = 0;
embed->border[7].top = VIPS_RECT_BOTTOM( &embed->rsub );
embed->border[7].width = embed->rsub.left;
embed->border[7].height = conversion->output->Ysize -
embed->border[7].height = conversion->out->Ysize -
VIPS_RECT_BOTTOM( &embed->rsub );
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, vips_embed_gen, vips_stop_one,
embed->input, embed ) )
embed->in, embed ) )
return( -1 );
break;
@ -571,7 +571,7 @@ vips_embed_class_init( VipsEmbedClass *class )
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsEmbed, input ) );
G_STRUCT_OFFSET( VipsEmbed, in ) );
VIPS_ARG_INT( class, "x", 2,
_( "x" ),

View File

@ -86,15 +86,15 @@
/**
* VipsExtractArea:
* @input: input image
* @output: output image
* @in: input image
* @out: output image
* @left: left edge of area to extract
* @top: top edge of area to extract
* @width: width of area to extract
* @height: height of area to extract
*
* Extract an area from an image.
* Extracting outside @input will trigger an error.
* Extracting outside @in will trigger an error.
*
* See also: VipsExtractBand().
*/
@ -104,7 +104,7 @@ typedef struct _VipsExtractArea {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
int left;
int top;
@ -153,32 +153,32 @@ vips_extract_area_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_extract_area_parent_class )->build( object ) )
return( -1 );
if( extract->left + extract->width > extract->input->Xsize ||
extract->top + extract->height > extract->input->Ysize ||
if( extract->left + extract->width > extract->in->Xsize ||
extract->top + extract->height > extract->in->Ysize ||
extract->left < 0 || extract->top < 0 ||
extract->width <= 0 || extract->height <= 0 ) {
im_error( "VipsExtractArea", "%s", _( "bad extract area" ) );
return( -1 );
}
if( vips_image_pio_input( extract->input ) ||
vips_image_pio_output( conversion->output ) ||
vips_check_coding_known( "VipsExtractArea", extract->input ) )
if( vips_image_pio_input( extract->in ) ||
vips_image_pio_output( conversion->out ) ||
vips_check_coding_known( "VipsExtractArea", extract->in ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, extract->input ) )
if( vips_image_copy_fields( conversion->out, extract->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_THINSTRIP, extract->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL );
conversion->output->Xsize = extract->width;
conversion->output->Ysize = extract->height;
conversion->output->Xoffset = -extract->left;
conversion->output->Yoffset = -extract->top;
conversion->out->Xsize = extract->width;
conversion->out->Ysize = extract->height;
conversion->out->Xoffset = -extract->left;
conversion->out->Yoffset = -extract->top;
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, vips_extract_area_gen, vips_stop_one,
extract->input, extract ) )
extract->in, extract ) )
return( -1 );
return( 0 );
@ -208,7 +208,7 @@ vips_extract_area_class_init( VipsExtractAreaClass *class )
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsExtractArea, input ) );
G_STRUCT_OFFSET( VipsExtractArea, in ) );
VIPS_ARG_INT( class, "left", 2,
_( "Left" ),
@ -246,14 +246,14 @@ vips_extract_area_init( VipsExtractArea *extract )
}
int
vips_extract_area( VipsImage *input, VipsImage **output,
vips_extract_area( VipsImage *in, VipsImage **out,
int left, int top, int width, int height, ... )
{
va_list ap;
int result;
va_start( ap, height );
result = vips_call_split( "extract_area", ap, input, output,
result = vips_call_split( "extract_area", ap, in, out,
left, top, width, height );
va_end( ap );
@ -262,8 +262,8 @@ vips_extract_area( VipsImage *input, VipsImage **output,
/**
* VipsExtractBand:
* @input: input image
* @output: output image
* @in: input image
* @out: output image
* @band: band to extract
* @n: number of bands to extract
*
@ -277,7 +277,7 @@ typedef struct _VipsExtractBand {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
int band;
int n;
@ -331,26 +331,26 @@ vips_extract_band_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_extract_band_parent_class )->build( object ) )
return( -1 );
if( extract->band + extract->n > extract->input->Bands ) {
if( extract->band + extract->n > extract->in->Bands ) {
im_error( "VipsExtractBand", "%s", _( "bad extract band" ) );
return( -1 );
}
if( vips_image_pio_input( extract->input ) ||
vips_image_pio_output( conversion->output ) ||
vips_check_coding_known( "VipsExtractBand", extract->input ) )
if( vips_image_pio_input( extract->in ) ||
vips_image_pio_output( conversion->out ) ||
vips_check_coding_known( "VipsExtractBand", extract->in ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, extract->input ) )
if( vips_image_copy_fields( conversion->out, extract->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_THINSTRIP, extract->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_THINSTRIP, extract->in, NULL );
conversion->output->Bands = extract->n;
conversion->out->Bands = extract->n;
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, vips_extract_band_gen, vips_stop_one,
extract->input, extract ) )
extract->in, extract ) )
return( -1 );
return( 0 );
@ -371,11 +371,11 @@ vips_extract_band_class_init( VipsExtractBandClass *class )
vobject_class->description = _( "extract band from an image" );
vobject_class->build = vips_extract_band_build;
VIPS_ARG_IMAGE( class, "input", 0,
VIPS_ARG_IMAGE( class, "in", 0,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsExtractBand, input ) );
G_STRUCT_OFFSET( VipsExtractBand, in ) );
VIPS_ARG_INT( class, "band", 3,
_( "Band" ),
@ -399,13 +399,13 @@ vips_extract_band_init( VipsExtractBand *extract )
}
int
vips_extract_band( VipsImage *input, VipsImage **output, int band, ... )
vips_extract_band( VipsImage *in, VipsImage **out, int band, ... )
{
va_list ap;
int result;
va_start( ap, band );
result = vips_call_split( "extract_band", ap, input, output, band );
result = vips_call_split( "extract_band", ap, in, out, band );
va_end( ap );
return( result );

View File

@ -66,8 +66,8 @@
/**
* VipsFlip:
* @input: input image
* @output: output image
* @in: input image
* @out: output image
* @direction: flip horizontally or vertically
*
* Flips an image left-right or up-down.
@ -82,7 +82,7 @@ typedef struct _VipsFlip {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
/* Swap bytes on the way through.
*/
@ -207,29 +207,29 @@ vips_flip_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_flip_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( flip->input ) ||
vips_image_pio_output( conversion->output ) )
if( vips_image_pio_input( flip->in ) ||
vips_image_pio_output( conversion->out ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, flip->input ) )
if( vips_image_copy_fields( conversion->out, flip->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_THINSTRIP, flip->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_THINSTRIP, flip->in, NULL );
if( flip->direction == VIPS_DIRECTION_HORIZONTAL ) {
generate_fn = vips_flip_horizontal_gen;
conversion->output->Xoffset = flip->input->Xsize;
conversion->output->Yoffset = 0;
conversion->out->Xoffset = flip->in->Xsize;
conversion->out->Yoffset = 0;
}
else {
generate_fn = vips_flip_vertical_gen;
conversion->output->Xoffset = 0;
conversion->output->Yoffset = flip->input->Ysize;
conversion->out->Xoffset = 0;
conversion->out->Yoffset = flip->in->Ysize;
}
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, generate_fn, vips_stop_one,
flip->input, flip ) )
flip->in, flip ) )
return( -1 );
return( 0 );
@ -250,11 +250,11 @@ vips_flip_class_init( VipsFlipClass *class )
vobject_class->description = _( "flip an image" );
vobject_class->build = vips_flip_build;
VIPS_ARG_IMAGE( class, "input", 1,
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsFlip, input ) );
G_STRUCT_OFFSET( VipsFlip, in ) );
VIPS_ARG_ENUM( class, "direction", 6,
_( "Direction" ),

View File

@ -1,460 +0,0 @@
/* clip.c ... convert BandFmt, clipping values
*
* Author: Nicos Dessipris
* Written on: 07/03/1991
* Modified on:
* 04/05/1992 JC
* - works for char, uchar too
* - floating point code removed from integer clip operations
* - uses nint() instead of own rounding code
* - calculated the number of >255 clips for float/double input
* incorrectly
* - rejects complex input correctly now
* 27/4/93 JC
* - adapted to work with partial images
* - nint() removed, now just +0.5
* - im_warning code removed
* 30/6/93 JC
* - adapted for partial v2
* 31/8/93 JC
* - now detects and prints over/underflows
* 27/10/93 JC
* - unsigned integer clips now faster!
* - falls back to im_copy() correctly
* 5/5/94 JC
* - switched to rint()
* 18/8/94 JC
* - now uses evalend callback
* 9/5/95 JC
* - now does complex too
* 11/7/95 JC
* - now uses IM_RINT() macro
* 10/3/01 JC
* - slightly faster and simpler
* - generalised to im_clip2fmt(), all other clippers now just call
* this
* 21/4/04 JC
* - now does floor(), not rint() ... you'll need to round yourself
* before calling this if you want round-to-nearest
* 7/11/07
* - use new evalstart/evalend system
* 26/8/08
* - oops, complex->complex conversion was broken
* 27/1/10
* - modernised
* - gtk-doc
*/
/*
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 <math.h>
#include <limits.h>
#include <vips/vips.h>
/* Global state. Track over/under-flows for all sequences in this.
*/
typedef struct {
IMAGE *in; /* Parameters */
IMAGE *out;
int ofmt;
int underflow; /* Number of underflows */
int overflow; /* Number of overflows */
} Clip;
static int
clip_evalstart( Clip *clip )
{
/* Reset counts.
*/
clip->overflow = 0;
clip->underflow = 0;
return( 0 );
}
static int
clip_evalend( Clip *clip )
{
/* Print warnings, if necessary.
*/
if( clip->overflow || clip->underflow )
im_warn( "im_clip",
_( "%d underflows and %d overflows detected" ),
clip->underflow, clip->overflow );
return( 0 );
}
/* Build a Clip.
*/
static Clip *
clip_new( IMAGE *in, IMAGE *out, int ofmt )
{
Clip *clip = IM_NEW( out, Clip );
if( !clip )
return( NULL );
clip->in = in;
clip->out = out;
clip->ofmt = ofmt;
clip->underflow = 0;
clip->overflow = 0;
if( im_add_evalstart_callback( out,
(im_callback_fn) clip_evalstart, clip, NULL ) ||
im_add_evalend_callback( out,
(im_callback_fn) clip_evalend, clip, NULL ) )
return( NULL );
return( clip );
}
/* Our sequence value: the region this sequence is using, and two local stats.
*/
typedef struct {
REGION *ir; /* Input region */
int underflow; /* Number of underflows */
int overflow; /* Number of overflows */
} ClipSequence;
/* Destroy a sequence value.
*/
static int
clip_stop( void *vseq, void *a, void *b )
{
ClipSequence *seq = (ClipSequence *) vseq;
Clip *clip = (Clip *) b;
/* Add to global stats.
*/
clip->underflow += seq->underflow;
clip->overflow += seq->overflow;
IM_FREEF( im_region_free, seq->ir );
return( 0 );
}
/* Make a sequence value.
*/
static void *
clip_start( IMAGE *out, void *a, void *b )
{
IMAGE *in = (IMAGE *) a;
ClipSequence *seq;
if( !(seq = IM_NEW( out, ClipSequence )) )
return( NULL );
/* Init!
*/
seq->ir = NULL;
seq->overflow = 0;
seq->underflow = 0;
if( !(seq->ir = im_region_create( in )) )
return( NULL );
return( seq );
}
/* Clip int types to an int type.
*/
#define IM_CLIP_INT_INT( ITYPE, OTYPE, IM_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
int t = p[x]; \
\
IM_CLIP( t, seq ); \
\
q[x] = t; \
} \
}
/* Clip float types to an int type.
*/
#define IM_CLIP_FLOAT_INT( ITYPE, OTYPE, IM_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
ITYPE v = floor( p[x] ); \
\
IM_CLIP( v, seq ); \
\
q[x] = v; \
} \
}
/* Clip complex types to an int type. Just take the real part.
*/
#define IM_CLIP_COMPLEX_INT( ITYPE, OTYPE, IM_CLIP ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
ITYPE v = floor( p[0] ); \
p += 2; \
\
IM_CLIP( v, seq ); \
\
q[x] = v; \
} \
}
/* Clip non-complex types to a float type.
*/
#define IM_CLIP_REAL_FLOAT( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) \
q[x] = p[x]; \
}
/* Clip complex types to a float type ... just take real.
*/
#define IM_CLIP_COMPLEX_FLOAT( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
q[x] = p[0]; \
p += 2; \
} \
}
/* Clip any non-complex to a complex type ... set imaginary to zero.
*/
#define IM_CLIP_REAL_COMPLEX( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
q[0] = p[x]; \
q[1] = 0.0; \
q += 2; \
} \
}
/* Clip any complex to a complex type.
*/
#define IM_CLIP_COMPLEX_COMPLEX( ITYPE, OTYPE ) { \
ITYPE *p = (ITYPE *) in; \
OTYPE *q = (OTYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
q[0] = p[0]; \
q[1] = p[1]; \
p += 2; \
q += 2; \
} \
}
#define BAND_SWITCH_INNER( ITYPE, INT, FLOAT, COMPLEX ) { \
switch( clip->out->BandFmt ) { \
case IM_BANDFMT_UCHAR: \
INT( ITYPE, unsigned char, IM_CLIP_UCHAR ); \
break; \
case IM_BANDFMT_CHAR: \
INT( ITYPE, signed char, IM_CLIP_CHAR ); \
break; \
case IM_BANDFMT_USHORT: \
INT( ITYPE, unsigned short, IM_CLIP_USHORT ); \
break; \
case IM_BANDFMT_SHORT: \
INT( ITYPE, signed short, IM_CLIP_SHORT ); \
break; \
case IM_BANDFMT_UINT: \
INT( ITYPE, unsigned int, IM_CLIP_NONE ); \
break; \
case IM_BANDFMT_INT: \
INT( ITYPE, signed int, IM_CLIP_NONE ); \
break; \
case IM_BANDFMT_FLOAT: \
FLOAT( ITYPE, float ); \
break; \
case IM_BANDFMT_DOUBLE: \
FLOAT( ITYPE, double ); \
break; \
case IM_BANDFMT_COMPLEX: \
COMPLEX( ITYPE, float ); \
break; \
case IM_BANDFMT_DPCOMPLEX: \
COMPLEX( ITYPE, double ); \
break; \
default: \
g_assert( 0 ); \
} \
}
/* Clip a small area.
*/
static int
clip_gen( REGION *or, void *vseq, void *a, void *b )
{
ClipSequence *seq = (ClipSequence *) vseq;
Clip *clip = (Clip *) b;
REGION *ir = seq->ir;
Rect *r = &or->valid;
int le = r->left;
int to = r->top;
int bo = IM_RECT_BOTTOM(r);
int sz = IM_REGION_N_ELEMENTS( or );
int x, y;
if( im_prepare( ir, r ) )
return( -1 );
for( y = to; y < bo; y++ ) {
PEL *in = (PEL *) IM_REGION_ADDR( ir, le, y );
PEL *out = (PEL *) IM_REGION_ADDR( or, le, y );
switch( clip->in->BandFmt ) {
case IM_BANDFMT_UCHAR:
BAND_SWITCH_INNER( unsigned char,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_CHAR:
BAND_SWITCH_INNER( signed char,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_USHORT:
BAND_SWITCH_INNER( unsigned short,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_SHORT:
BAND_SWITCH_INNER( signed short,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_UINT:
BAND_SWITCH_INNER( unsigned int,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_INT:
BAND_SWITCH_INNER( signed int,
IM_CLIP_INT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_FLOAT:
BAND_SWITCH_INNER( float,
IM_CLIP_FLOAT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_DOUBLE:
BAND_SWITCH_INNER( double,
IM_CLIP_FLOAT_INT,
IM_CLIP_REAL_FLOAT,
IM_CLIP_REAL_COMPLEX );
break;
case IM_BANDFMT_COMPLEX:
BAND_SWITCH_INNER( float,
IM_CLIP_COMPLEX_INT,
IM_CLIP_COMPLEX_FLOAT,
IM_CLIP_COMPLEX_COMPLEX );
break;
case IM_BANDFMT_DPCOMPLEX:
BAND_SWITCH_INNER( double,
IM_CLIP_COMPLEX_INT,
IM_CLIP_COMPLEX_FLOAT,
IM_CLIP_COMPLEX_COMPLEX );
break;
default:
g_assert( 0 );
}
}
return( 0 );
}
/**
* im_clip2fmt:
* @in: input image
* @out: output image
* @fmt: format to convert to
*
* Convert @in to @fmt format. You can convert between any pair of formats.
* Floats are truncated (not rounded). Out of range values are clipped.
*
* See also: im_scale(), im_ri2c().
*
* Returns: 0 on success, -1 on error
*/
int
im_clip2fmt( IMAGE *in, IMAGE *out, VipsBandFmt fmt )
{
Clip *clip;
if( im_check_uncoded( "im_clip2fmt", in ) ||
im_piocheck( in, out ) )
return( -1 );
if( fmt < 0 || fmt > IM_BANDFMT_DPCOMPLEX ) {
im_error( "im_clip2fmt", "%s", _( "fmt out of range" ) );
return( -1 );
}
/* Trivial case: fall back to im_copy().
*/
if( in->BandFmt == fmt )
return( im_copy( in, out ) );
if( !(clip = clip_new( in, out, fmt )) )
return( -1 );
if( im_cp_desc( out, in ) )
return( -1 );
out->BandFmt = fmt;
if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) ||
im_generate( out, clip_start, clip_gen, clip_stop, in, clip ) )
return( -1 );
return( 0 );
}

View File

@ -281,7 +281,7 @@ vips_insert_build( VipsObject *object )
if( vips_image_pio_input( insert->main ) ||
vips_image_pio_input( insert->sub ) ||
vips_image_pio_output( conversion->output ) ||
vips_image_pio_output( conversion->out ) ||
vips_check_bands_1orn( "VipsInsert",
insert->main, insert->sub ) ||
vips_check_coding_known( "VipsInsert", insert->main ) ||
@ -299,13 +299,13 @@ vips_insert_build( VipsObject *object )
return( -1 );
insert->main_processed = t[2];
insert->sub_processed = t[3];
if( !(arry = vips_allocate_input_array( conversion->output,
if( !(arry = vips_allocate_input_array( conversion->out,
insert->main_processed, insert->sub_processed, NULL )) )
return( -1 );
if( vips_image_copy_fields_array( conversion->output, arry ) )
if( vips_image_copy_fields_array( conversion->out, arry ) )
return( -1 );
vips_demand_hint_array( conversion->output,
vips_demand_hint_array( conversion->out,
VIPS_DEMAND_STYLE_SMALLTILE, arry );
/* Calculate geometry.
@ -337,15 +337,15 @@ vips_insert_build( VipsObject *object )
else
insert->rout = insert->rmain;
conversion->output->Xsize = insert->rout.width;
conversion->output->Ysize = insert->rout.height;
conversion->out->Xsize = insert->rout.width;
conversion->out->Ysize = insert->rout.height;
if( !(insert->ink = vips__vector_to_ink(
"VipsInsert", conversion->output,
"VipsInsert", conversion->out,
insert->background->data, insert->background->n )) )
return( -1 );
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_many, vips_insert_gen, vips_stop_many,
arry, insert ) )
return( -1 );

View File

@ -72,7 +72,7 @@
* VipsJoin:
* @in1: first input image
* @in2: second input image
* @output: output image
* @out: output image
* @direction: join horizontally or vertically
* @expand: %TRUE to expand the output image to hold all of the input pixels
* @shim: space between images, in pixels
@ -83,13 +83,13 @@
* of @direction.
*
* If one is taller or wider than the
* other, @output will be has high as the smaller. If @expand is %TRUE, then
* other, @out 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
* Use @background to set the colour of any pixels in @out which are not
* present in either @in1 or @in2.
*
* Use @shim to set the spacing between the images. By default this is 0.
@ -227,7 +227,7 @@ vips_join_build( VipsObject *object )
}
if( vips_image_write( t, conversion->output ) ) {
if( vips_image_write( t, conversion->out ) ) {
g_object_unref( t );
return( -1 );
}
@ -310,14 +310,14 @@ vips_join_init( VipsJoin *join )
}
int
vips_join( VipsImage *in1, VipsImage *in2, VipsImage **output,
vips_join( VipsImage *in1, VipsImage *in2, VipsImage **out,
VipsDirection direction, ... )
{
va_list ap;
int result;
va_start( ap, direction );
result = vips_call_split( "join", ap, in1, in2, output, direction );
result = vips_call_split( "join", ap, in1, in2, out, direction );
va_end( ap );
return( result );

View File

@ -58,7 +58,7 @@
/**
* VipsReplicate:
* @in: input image
* @output: output image
* @out: output image
* @across: repeat input this many times across
* @down: repeat input this many times down
*
@ -72,7 +72,7 @@ typedef struct _VipsReplicate {
/* The input image.
*/
VipsImage *input;
VipsImage *in;
int across;
int down;
@ -170,21 +170,21 @@ vips_replicate_build( VipsObject *object )
if( VIPS_OBJECT_CLASS( vips_replicate_parent_class )->build( object ) )
return( -1 );
if( vips_image_pio_input( replicate->input ) ||
vips_image_pio_output( conversion->output ) )
if( vips_image_pio_input( replicate->in ) ||
vips_image_pio_output( conversion->out ) )
return( -1 );
if( vips_image_copy_fields( conversion->output, replicate->input ) )
if( vips_image_copy_fields( conversion->out, replicate->in ) )
return( -1 );
vips_demand_hint( conversion->output,
VIPS_DEMAND_STYLE_SMALLTILE, replicate->input, NULL );
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_SMALLTILE, replicate->in, NULL );
conversion->output->Xsize *= replicate->across;
conversion->output->Ysize *= replicate->down;
conversion->out->Xsize *= replicate->across;
conversion->out->Ysize *= replicate->down;
if( vips_image_generate( conversion->output,
if( vips_image_generate( conversion->out,
vips_start_one, vips_replicate_gen, vips_stop_one,
replicate->input, replicate ) )
replicate->in, replicate ) )
return( -1 );
return( 0 );
@ -205,11 +205,11 @@ vips_replicate_class_init( VipsReplicateClass *class )
vobject_class->description = _( "replicate an image" );
vobject_class->build = vips_replicate_build;
VIPS_ARG_IMAGE( class, "input", 0,
VIPS_ARG_IMAGE( class, "in", 0,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsReplicate, input ) );
G_STRUCT_OFFSET( VipsReplicate, in ) );
VIPS_ARG_INT( class, "across", 4,
_( "Across" ),

View File

@ -1266,3 +1266,20 @@ im_replicate( IMAGE *in, IMAGE *out, int across, int down )
return( 0 );
}
int
im_clip2fmt( IMAGE *in, IMAGE *out, VipsBandFmt fmt )
{
VipsImage *t;
if( vips_cast( in, &t, fmt,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}

View File

@ -134,6 +134,8 @@ int vips_extract_band( VipsImage *input, VipsImage **output, int band, ... )
__attribute__((sentinel));
int vips_replicate( VipsImage *in, VipsImage **out, int across, int down, ... )
__attribute__((sentinel));
int vips_cast( VipsImage *in, VipsImage **out, VipsBandFormat format, ... )
__attribute__((sentinel));
@ -143,7 +145,6 @@ int im_mask2vips( DOUBLEMASK *in, VipsImage *out );
int im_copy_file( VipsImage *in, VipsImage *out );
int im_clip2fmt( VipsImage *in, VipsImage *out, VipsBandFormat fmt );
int im_scale( VipsImage *in, VipsImage *out );
int im_msb( VipsImage *in, VipsImage *out );
int im_msb_band( VipsImage *in, VipsImage *out, int band );

View File

@ -558,6 +558,8 @@ int im_extract_areabands( VipsImage *in, VipsImage *out,
int im_replicate( VipsImage *in, VipsImage *out, int across, int down );
int im_clip2fmt( VipsImage *in, VipsImage *out, VipsBandFormat fmt );
/* ruby-vips uses this
*/
#define vips_class_map_concrete_all vips_class_map_all

View File

@ -458,9 +458,9 @@ vips_region_new( VipsImage *image )
}
#ifdef DEBUG
#endif /*DEBUG*/
g_assert( vips_object_sanity( VIPS_OBJECT( image ) ) );
g_assert( vips_object_sanity( VIPS_OBJECT( region ) ) );
#endif /*DEBUG*/
return( region );
}