add unary and invert

add a base class for unary operators, try it out with VipsInvert
This commit is contained in:
John Cupitt 2011-10-30 21:45:18 +00:00
parent 12a13d3e39
commit b4531ff24b
11 changed files with 342 additions and 158 deletions

View File

@ -3,7 +3,7 @@
- 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_clip2fmt(), im_gbandjoin(), im_bandjoin()
im_replicate(), im_clip2fmt(), im_gbandjoin(), im_bandjoin(), im_invert()
redone as classes
- added argument priorites to help control arg ordering
- generate has a 'stop' param to signal successful early termination
@ -27,6 +27,7 @@
- added vips_region_paint_pel()
- added VipsArea as a public struct
- added array members and arguments
- Unary
12/10/11 started 7.26.6
- NOCACHE was not being set correctly on OS X causing performance

7
TODO
View File

@ -1,8 +1,11 @@
- invert is useless. make it work for all types at least
- lintra_vec next
so we need a unary.c .. easy copy frombinary.c now that most of binary has
moved into arithmetic

View File

@ -8,7 +8,6 @@ libarithmetic_la_SOURCES = \
im_deviate.c \
im_divide.c \
im_recomb.c \
im_invert.c \
im_linreg.c \
im_lintra.c \
im_maxpos_avg.c \
@ -30,7 +29,10 @@ libarithmetic_la_SOURCES = \
arithmetic.h \
binary.c \
binary.h \
unary.c \
unary.h \
add.c \
invert.c \
power.c \
round.c

View File

@ -389,14 +389,14 @@ vips_arithmetic_class_init( VipsArithmeticClass *class )
/* Just for testing.
*/
VIPS_ARG_BOOL( class, "booltest", 1,
VIPS_ARG_BOOL( class, "booltest", 101,
_( "Bool test" ),
_( "Test optional boolean argument" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsArithmetic, booltest ),
FALSE );
VIPS_ARG_IMAGE( class, "imtest", 2,
VIPS_ARG_IMAGE( class, "imtest", 102,
_( "Image test" ),
_( "Test optional image argument" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
@ -495,11 +495,13 @@ void
vips_arithmetic_operation_init( void )
{
extern GType vips_add_get_type( void );
extern GType vips_invert_get_type( void );
extern GType vips_subtract_get_type( void );
extern GType vips_avg_get_type( void );
extern GType vips_min_get_type( void );
vips_add_get_type();
vips_invert_get_type();
vips_subtract_get_type();
vips_avg_get_type();
vips_min_get_type();

View File

@ -4,6 +4,8 @@
* - argh, forgot to make a private array for the inputs
* 16/5/11
* - added sizealike
* 30/10/11
* - moe most functionality into arithmetic.c
*/
/*

View File

@ -1,148 +0,0 @@
/* im_invert.c
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on :
* 7/7/93 JC
* - memory leaks fixed
* - adapted for partial v2
* - ANSIfied
* 22/2/95 JC
* - tidied up again
* 2/9/09
* - gtk-doc comment
*/
/*
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 <vips/vips.h>
/* Invert a REGION. We are given the REGION we should write to, the REGION we
* should use for input, and the IMAGE we are processing. On entry to
* invert_gen(), or points to the memory we should write to and ir is blank.
*/
static int
invert_gen( REGION *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
/* Left, right, top and bottom for the output region.
*/
int le = or->valid.left;
int to = or->valid.top;
int bo = IM_RECT_BOTTOM( &or->valid );
int x, y;
/* Ask for the section of the input image we need to produce this
* section of the output image.
*/
if( im_prepare( ir, &or->valid ) )
return( -1 );
/* Loop over output.
*/
for( y = to; y < bo; y++ ) {
/* Point p and q at the start of the line of pels we must
* process this loop.
*/
PEL *p = (PEL *) IM_REGION_ADDR( ir, le, y );
PEL *q = (PEL *) IM_REGION_ADDR( or, le, y );
/* Loop along the line, processing pels.
* IM_REGION_N_ELEMENTS(region) gives
* the number of band elements across a region. By looping to
* IM_REGION_N_ELEMENTS() rather than ir->valid.width, we work
* for any number of bands.
*/
for( x = 0; x < IM_REGION_N_ELEMENTS( or ); x++ )
q[x] = 255 - p[x];
}
return( 0 );
}
/**
* im_invert:
* @in: input #IMAGE
* @out: output #IMAGE
*
* this operation calculates (255 - @in).
* The operation works on uchar images only. The input can have any no of
* channels.
*
* This is not a generally useful program -- it is included as an example of
* a very simple new-style IO function.
* See im_exptra() for an example of a VIPS function which can process
* any input image type.
*
* See also: im_exptra(), im_lintra().
*
* Returns: 0 on success, -1 on error
*/
int
im_invert( IMAGE *in, IMAGE *out )
{
/* Check args.
*/
if( im_check_uncoded( "im_invert", in ) ||
im_check_format( "im_invert", in, IM_BANDFMT_UCHAR ) ||
im_piocheck( in, out ) )
return( -1 );
/* Prepare the output header.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Set demand hints. Like most one-to-one operations, we work best
* with long, thin strips.
*/
if( im_demand_hint( out, IM_THINSTRIP, in, NULL ) )
return( -1 );
/* Generate into out. im_start_one() and im_stop_one() are simple
* convenience functions provided by VIPS which do the necessary
* region creation and destruction for one-image-in
* style functions. See im_add(), im_start_many() and im_stop_many()
* for convenience functions for multiple inputs.
*/
if( im_generate( out,
im_start_one, invert_gen, im_stop_one, in, NULL ) )
return( -1 );
return( 0 );
}

152
libvips/arithmetic/invert.c Normal file
View File

@ -0,0 +1,152 @@
/* photographic negative ... just an example, really
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on :
* 7/7/93 JC
* - memory leaks fixed
* - adapted for partial v2
* - ANSIfied
* 22/2/95 JC
* - tidied up again
* 2/9/09
* - gtk-doc comment
* 23/8/11
* - rewrite as a class
*/
/*
Copyright (C) 1991-2005 The National Gallery
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU 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
*/
/*
#define DEBUG
*/
#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 <vips/vips.h>
#include "arithmetic.h"
#include "unary.h"
/**
* VipsInvert:
* @in: input #VipsImage
* @out: output #VipsImage
*
* this operation calculates (255 - @in).
* The operation works on uchar images only. The input can have any
* number of channels.
*
* This is not a generally useful operation -- it is included as an example of
* a very simple operation.
* See im_exptra() for an example of a VIPS function which can process
* any input image type.
*
* See also: im_exptra(), im_lintra().
*
* Returns: 0 on success, -1 on error
*/
typedef VipsUnary VipsInvert;
typedef VipsUnaryClass VipsInvertClass;
G_DEFINE_TYPE( VipsInvert, vips_invert, VIPS_TYPE_UNARY );
static void
vips_invert_buffer( VipsArithmetic *arithmetic, PEL *out, PEL **in, int width )
{
VipsImage *im = arithmetic->ready[0];
PEL *p = in[0];
int ne = width * im->Bands;
int x;
for( x = 0; x < ne; x++ )
out[x] = 255 - p[x];
}
/* Save a bit of typing.
*/
#define UC VIPS_FORMAT_UCHAR
#define C VIPS_FORMAT_CHAR
#define US VIPS_FORMAT_USHORT
#define S VIPS_FORMAT_SHORT
#define UI VIPS_FORMAT_UINT
#define I VIPS_FORMAT_INT
#define F VIPS_FORMAT_FLOAT
#define X VIPS_FORMAT_COMPLEX
#define D VIPS_FORMAT_DOUBLE
#define DX VIPS_FORMAT_DPCOMPLEX
/* Type promotion for invertion. Sign and value preserving. Make sure these
* match the case statement in vips_invert_buffer() above.
*/
static const VipsBandFormat bandfmt_invert[10] = {
/* UC C US S UI I F X D DX */
UC, UC, UC, UC, UC, UC, UC, UC, UC, UC
};
static void
vips_invert_class_init( VipsInvertClass *class )
{
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
object_class->nickname = "invert";
object_class->description = _( "invert an image" );
vips_arithmetic_set_format_table( aclass, bandfmt_invert );
aclass->process_line = vips_invert_buffer;
}
static void
vips_invert_init( VipsInvert *invert )
{
}
int
vips_invert( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_call_split( "invert", ap, in, out );
va_end( ap );
return( result );
}

View File

@ -175,7 +175,8 @@ G_DEFINE_TYPE( VipsSubtract, vips_subtract, VIPS_TYPE_BINARY );
}
static void
subtract_buffer( VipsArithmetic *arithmetic, PEL *out, PEL **in, int width )
vips_subtract_buffer( VipsArithmetic *arithmetic,
PEL *out, PEL **in, int width )
{
VipsImage *im = arithmetic->ready[0];
@ -227,7 +228,7 @@ subtract_buffer( VipsArithmetic *arithmetic, PEL *out, PEL **in, int width )
#define DX VIPS_FORMAT_DPCOMPLEX
/* Type promotion for subtraction. Sign and value preserving. Make sure these
* match the case statement in subtract_buffer() above.
* match the case statement in vips_subtract_buffer() above.
*/
static const VipsBandFormat bandfmt_subtract[10] = {
/* UC C US S UI I F X D DX */
@ -245,7 +246,7 @@ vips_subtract_class_init( VipsSubtractClass *class )
vips_arithmetic_set_format_table( aclass, bandfmt_subtract );
aclass->process_line = subtract_buffer;
aclass->process_line = vips_subtract_buffer;
}
static void

View File

@ -0,0 +1,98 @@
/* base class for all unary operations
*
* 30/10/11
* - from binary.c
*/
/*
Copyright (C) 1991-2005 The National Gallery
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU 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
*/
/*
#define DEBUG
*/
#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 <vips/vips.h>
#include "arithmetic.h"
#include "unary.h"
G_DEFINE_ABSTRACT_TYPE( VipsUnary, vips_unary, VIPS_TYPE_ARITHMETIC );
static int
vips_unary_build( VipsObject *object )
{
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
VipsUnary *unary = VIPS_UNARY( object );
arithmetic->n = 1;
arithmetic->in = (VipsImage **) vips_object_local_array( object, 1 );
arithmetic->in[0] = unary->in;
g_object_ref( arithmetic->in[0] );
if( VIPS_OBJECT_CLASS( vips_unary_parent_class )->build( object ) )
return( -1 );
return( 0 );
}
static void
vips_unary_class_init( VipsUnaryClass *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 = "unary";
vobject_class->description = _( "unary operations" );
vobject_class->build = vips_unary_build;
/* Create properties.
*/
VIPS_ARG_IMAGE( class, "in", 1,
_( "Input" ),
_( "Input image argument" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsUnary, in ) );
}
static void
vips_unary_init( VipsUnary *unary )
{
/* Init our instance fields.
*/
}

View File

@ -0,0 +1,68 @@
/* base class for all unary arithmetic operations
*/
/*
Copyright (C) 1991-2005 The National Gallery
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU 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 General Public License for more details.
You should have received a copy of the GNU 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
*/
#ifndef VIPS_UNARY_H
#define VIPS_UNARY_H
#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
#define VIPS_TYPE_UNARY (vips_unary_get_type())
#define VIPS_UNARY( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_UNARY, VipsUnary ))
#define VIPS_UNARY_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), VIPS_TYPE_UNARY, VipsUnaryClass))
#define VIPS_IS_UNARY( obj ) \
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_UNARY ))
#define VIPS_IS_UNARY_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_UNARY ))
#define VIPS_UNARY_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_UNARY, VipsUnaryClass ))
typedef struct _VipsUnary {
VipsArithmetic parent_instance;
/* The arg we get from the property.
*/
VipsImage *in;
} VipsUnary;
typedef VipsArithmeticClass VipsUnaryClass;
GType vips_unary_get_type( void );
#ifdef __cplusplus
}
#endif /*__cplusplus*/
#endif /*VIPS_UNARY_H*/

View File

@ -578,8 +578,11 @@ vips_cache_operation_build( VipsOperation **operation )
if( (hit = g_hash_table_lookup( vips_cache_table, *operation )) ) {
VIPS_DEBUG_MSG( "\thit %p\n", hit );
g_object_unref( *operation );
/* Ref before unref in case *operation == hit.
*/
vips_cache_ref( hit );
g_object_unref( *operation );
*operation = hit;
}
else {