c2real(), c2imag() -> classes

This commit is contained in:
John Cupitt 2011-11-21 14:38:11 +00:00
parent 42e631f4d3
commit 0addd7fb6d
13 changed files with 321 additions and 232 deletions

View File

@ -12,7 +12,7 @@
im_rint(), im_equal*(), im_notequal*(), im_less*(), im_lesseq*(), im_more*(),
im_moreeq*(), im_remainder*(), im_and*(), im_or*(), im_eor*(), im_shift*(),
im_pow*(), im_exp*(), im_ifthenelse(), im_blend(), im_c2amph(), im_c2rect(),
im_bandmean()
im_bandmean(), im_c2real(), im_c2imag()
redone as classes
- added argument priorites to help control arg ordering
- generate has a 'stop' param to signal successful early termination

2
TODO
View File

@ -1,5 +1,3 @@
- get real, get_imag can be arith unary ops
- form complex can be an arith binary op
- try

View File

@ -503,6 +503,7 @@ vips_arithmetic_operation_init( void )
extern GType vips_math2_get_type( void );
extern GType vips_math2_const_get_type( void );
extern GType vips_complex_get_type( void );
extern GType vips_complexget_get_type( void );
vips_add_get_type();
vips_subtract_get_type();
@ -529,4 +530,5 @@ vips_arithmetic_operation_init( void )
vips_math2_get_type();
vips_math2_const_get_type();
vips_complex_get_type();
vips_complexget_get_type();
}

View File

@ -19,6 +19,8 @@
* - gtk-doc
* 19/11/11
* - redo as a class
* 21/11/11
* - add vips_complexget()
*/
/*
@ -223,7 +225,7 @@ vips_complex_class_init( VipsComplexClass *class )
}
static void
vips_complex_init( VipsComplex *complex )
vips_complex_init( VipsComplex *cmplx )
{
}
@ -329,3 +331,247 @@ vips_conj( VipsImage *in, VipsImage **out, ... )
return( result );
}
typedef struct _VipsComplexget {
VipsUnary parent_instance;
VipsOperationComplexget get;
} VipsComplexget;
typedef VipsUnaryClass VipsComplexgetClass;
G_DEFINE_TYPE( VipsComplexget, vips_complexget, VIPS_TYPE_UNARY );
static int
vips_complexget_build( VipsObject *object )
{
VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object );
VipsUnary *unary = (VipsUnary *) object;
VipsComplexget *complexget = (VipsComplexget *) object;
if( unary->in ) {
if( !vips_band_format_iscomplex( unary->in->BandFmt ) &&
complexget->get == VIPS_OPERATION_COMPLEXGET_REAL ) {
g_object_set( arithmetic,
"out", vips_image_new(),
NULL );
return( vips_image_write( unary->in,
arithmetic->out ) );
}
}
if( VIPS_OBJECT_CLASS( vips_complexget_parent_class )->build( object ) )
return( -1 );
return( 0 );
}
#define GETLOOP( TYPE, OP ) { \
TYPE *p __attribute__ ((unused)) = (TYPE *) in[0]; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
OP( q[x], p[x], 0.0 ); \
} \
}
#define CGETLOOP( TYPE, OP ) { \
TYPE *p __attribute__ ((unused)) = (TYPE *) in[0]; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < sz; x++ ) { \
OP( q[x], p[0], p[1] ); \
\
p += 2; \
} \
}
#define GETSWITCH( OP ) \
switch( vips_image_get_format( im ) ) { \
case VIPS_FORMAT_UCHAR: \
GETLOOP( unsigned char, OP ); break; \
case VIPS_FORMAT_CHAR: \
GETLOOP( signed char, OP ); break; \
case VIPS_FORMAT_USHORT: \
GETLOOP( unsigned short, OP ); break; \
case VIPS_FORMAT_SHORT: \
GETLOOP( signed short, OP ); break; \
case VIPS_FORMAT_UINT: \
GETLOOP( unsigned int, OP ); break; \
case VIPS_FORMAT_INT: \
GETLOOP( signed int, OP ); break; \
case VIPS_FORMAT_FLOAT: \
GETLOOP( float, OP ); break; \
case VIPS_FORMAT_DOUBLE: \
GETLOOP( double, OP ); break;\
case VIPS_FORMAT_COMPLEX: \
CGETLOOP( float, OP ); break; \
case VIPS_FORMAT_DPCOMPLEX: \
CGETLOOP( double, OP ); break;\
\
default: \
g_assert( 0 ); \
}
#define REAL( Q, X, Y ) { \
Q = X; \
}
#define IMAG( Q, X, Y ) { \
Q = Y; \
}
static void
vips_complexget_buffer( VipsArithmetic *arithmetic,
PEL *out, PEL **in, int width )
{
VipsComplexget *complexget = (VipsComplexget *) arithmetic;
VipsImage *im = arithmetic->ready[0];
const int sz = width * vips_image_get_bands( im );
int x;
switch( complexget->get ) {
case VIPS_OPERATION_COMPLEXGET_REAL: GETSWITCH( REAL ); break;
case VIPS_OPERATION_COMPLEXGET_IMAG: GETSWITCH( IMAG ); break;
default:
g_assert( 0 );
}
}
/* 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
static const VipsBandFormat vips_bandfmt_complexget[10] = {
/* UC C US S UI I F X D DX */
UC, C, US, S, UI, I, F, F, D, D
};
static void
vips_complexget_class_init( VipsComplexgetClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *object_class = (VipsObjectClass *) class;
VipsArithmeticClass *aclass = VIPS_ARITHMETIC_CLASS( class );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
object_class->nickname = "complexget";
object_class->description = _( "get a component from a complex image" );
object_class->build = vips_complexget_build;
vips_arithmetic_set_format_table( aclass, vips_bandfmt_complexget );
aclass->process_line = vips_complexget_buffer;
VIPS_ARG_ENUM( class, "get", 200,
_( "Operation" ),
_( "complex to perform" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsComplexget, get ),
VIPS_TYPE_OPERATION_COMPLEXGET,
VIPS_OPERATION_COMPLEXGET_REAL );
}
static void
vips_complexget_init( VipsComplexget *complexget )
{
}
static int
vips_complexgetv( VipsImage *in, VipsImage **out,
VipsOperationComplexget get, va_list ap )
{
return( vips_call_split( "complexget", ap, in, out, get ) );
}
/**
* vips_complexget:
* @in: input #VipsImage
* @out: output #VipsImage
* @get: complex operation to perform
* @...: %NULL-terminated list of optional named arguments
*
* Get components of complex images.
*
* The output type is the same as the input type, except #VIPS_FORMAT_COMPLEX
* becomes #VIPS_FORMAT_FLOAT and #VIPS_FORMAT_DPCOMPLEX becomes
* #VIPS_FORMAT_DOUBLE.
*
* Returns: 0 on success, -1 on error
*/
int
vips_complexget( VipsImage *in, VipsImage **out,
VipsOperationComplexget get, ... )
{
va_list ap;
int result;
va_start( ap, get );
result = vips_complexgetv( in, out, get, ap );
va_end( ap );
return( result );
}
/**
* vips_real:
* @in: input #VipsImage
* @out: output #VipsImage
* @...: %NULL-terminated list of optional named arguments
*
* Perform #VIPS_OPERATION_COMPLEXGET_REAL on an image. See vips_complexget().
*
* Returns: 0 on success, -1 on error
*/
int
vips_real( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_complexgetv( in, out,
VIPS_OPERATION_COMPLEXGET_REAL, ap );
va_end( ap );
return( result );
}
/**
* vips_imag:
* @in: input #VipsImage
* @out: output #VipsImage
* @...: %NULL-terminated list of optional named arguments
*
* Perform #VIPS_OPERATION_COMPLEXGET_IMAG on an image. See vips_complexget().
*
* Returns: 0 on success, -1 on error
*/
int
vips_imag( VipsImage *in, VipsImage **out, ... )
{
va_list ap;
int result;
va_start( ap, out );
result = vips_complexgetv( in, out,
VIPS_OPERATION_COMPLEXGET_IMAG, ap );
va_end( ap );
return( result );
}

View File

@ -20,8 +20,6 @@ libconversion_la_SOURCES = \
rot.c \
ifthenelse.c \
conver_dispatch.c \
im_c2imag.c \
im_c2real.c \
im_copy_file.c \
im_falsecolour.c \
im_msb.c \

View File

@ -1,109 +0,0 @@
/* im_c2imag ... get imaginary part
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on : 09/05/1990
* 21/12/94 JC
* - im_c2amph() adapted to make im_c2real() and im_c2imag()
* 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 <vips/vips.h>
#define loop(TYPE) { \
TYPE *p = (TYPE *) in + 1; \
TYPE *q = (TYPE *) out; \
int x; \
\
for( x = 0; x < n; x++ ) { \
q[x] = *p; \
p += 2; \
} \
}
/* c2imag buffer processor.
*/
static void
buffer_c2imag( void *in, void *out, int w, IMAGE *im )
{
int n = w * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_DPCOMPLEX: loop(double); break;
case IM_BANDFMT_COMPLEX: loop(float); break;
default:
g_assert( 0 );
}
}
/**
* im_c2imag:
* @in: input image
* @out: output image
*
* Extract the imaginary part of a complex image.
*
* See also: im_c2real().
*
* Returns: 0 on success, -1 on error
*/
int
im_c2imag( IMAGE *in, IMAGE *out )
{
if( im_check_uncoded( "im_c2imag", in ) ||
im_check_complex( "im_c2imag", in ) ||
im_cp_desc( out, in ) )
return( -1 );
/* Output will be float or double.
*/
if( in->BandFmt == IM_BANDFMT_DPCOMPLEX )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
if( im_wrapone( in, out,
(im_wrapone_fn) buffer_c2imag, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -1,115 +0,0 @@
/* im_c2real.c ... get real part of complex image
*
* Copyright: 1990, N. Dessipris.
*
* Author: Nicos Dessipris
* Written on: 12/02/1990
* Modified on : 09/05/1990
* 15/6/93 JC
* - stupid stupid includes and externs fixed
* - I have been editing for 1 1/2 hours and I'm still drowning in
* rubbish extetrnshh
* 13/12/94 JC
* - modernised
* 21/12/94 JC
* - im_c2amph() adapted to make im_c2real() and im_c2imag()
* 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 <vips/vips.h>
#define loop(TYPE) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
int x; \
\
for( x = 0; x < n; x++ ) { \
q[x] = *p; \
p += 2; \
}\
}
/* c2real buffer processor.
*/
static void
buffer_c2real( void *in, void *out, int w, IMAGE *im )
{
int n = w * im->Bands;
switch( im->BandFmt ) {
case IM_BANDFMT_DPCOMPLEX: loop(double); break;
case IM_BANDFMT_COMPLEX: loop(float); break;
default:
g_assert( 0 );
}
}
/**
* im_c2real:
* @in: input image
* @out: output image
*
* Extract the real part of a complex image.
*
* See also: im_c2imag().
*
* Returns: 0 on success, -1 on error
*/
int
im_c2real( IMAGE *in, IMAGE *out )
{
if( im_check_uncoded( "im_c2real", in ) ||
im_check_complex( "im_c2real", in ) ||
im_cp_desc( out, in ) )
return( -1 );
/* Output will be float or double.
*/
if( in->BandFmt == IM_BANDFMT_DPCOMPLEX )
out->BandFmt = IM_BANDFMT_DOUBLE;
else
out->BandFmt = IM_BANDFMT_FLOAT;
if( im_wrapone( in, out,
(im_wrapone_fn) buffer_c2real, in, NULL ) )
return( -1 );
return( 0 );
}

View File

@ -2123,4 +2123,32 @@ im_c2rect( IMAGE *in, IMAGE *out )
return( vips__complex( in, out, VIPS_OPERATION_COMPLEX_RECT ) );
}
static int
vips__complexget( VipsImage *in, VipsImage *out, VipsOperationComplexget get )
{
VipsImage *t;
if( vips_complexget( in, &t, get,
NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}
int
im_c2real( IMAGE *in, IMAGE *out )
{
return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_REAL ) );
}
int
im_c2imag( IMAGE *in, IMAGE *out )
{
return( vips__complexget( in, out, VIPS_OPERATION_COMPLEXGET_IMAG ) );
}

View File

@ -147,6 +147,19 @@ typedef enum {
VIPS_OPERATION_COMPLEX_LAST
} VipsOperationComplex;
/**
* VipsOperationComplexget:
* @VIPS_OPERATION_COMPLEXGET_REAL: get real component
* @VIPS_OPERATION_COMPLEXGET_IMAG: get imaginary component
*
* See also: vips_complexget().
*/
typedef enum {
VIPS_OPERATION_COMPLEXGET_REAL,
VIPS_OPERATION_COMPLEXGET_IMAG,
VIPS_OPERATION_COMPLEXGET_LAST
} VipsOperationComplexget;
int vips_add( VipsImage *left, VipsImage *right, VipsImage **out, ... )
__attribute__((sentinel));
int vips_subtract( VipsImage *in1, VipsImage *in2, VipsImage **out, ... )
@ -217,6 +230,14 @@ int vips_rect( VipsImage *in, VipsImage **out, ... )
int vips_conj( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_complexget( VipsImage *in, VipsImage **out,
VipsOperationComplexget get, ... )
__attribute__((sentinel));
int vips_real( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_imag( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_relational( VipsImage *left, VipsImage *right, VipsImage **out,
VipsOperationRelational relational, ... )
__attribute__((sentinel));

View File

@ -207,8 +207,6 @@ int im_msb( VipsImage *in, VipsImage *out );
int im_msb_band( VipsImage *in, VipsImage *out, int band );
int im_ri2c( VipsImage *in1, VipsImage *in2, VipsImage *out );
int im_c2imag( VipsImage *in, VipsImage *out );
int im_c2real( VipsImage *in, VipsImage *out );
int im_scaleps( VipsImage *in, VipsImage *out );
int im_falsecolour( VipsImage *in, VipsImage *out );

View File

@ -19,6 +19,8 @@ GType vips_operation_boolean_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_BOOLEAN (vips_operation_boolean_get_type())
GType vips_operation_complex_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_COMPLEX (vips_operation_complex_get_type())
GType vips_operation_complexget_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_COMPLEXGET (vips_operation_complexget_get_type())
/* enumerations from "../../../libvips/include/vips/conversion.h" */
GType vips_extend_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_EXTEND (vips_extend_get_type())

View File

@ -632,6 +632,8 @@ int im_black( VipsImage *out, int x, int y, int bands );
int im_c2amph( VipsImage *in, VipsImage *out );
int im_c2rect( VipsImage *in, VipsImage *out );
int im_c2imag( VipsImage *in, VipsImage *out );
int im_c2real( VipsImage *in, VipsImage *out );
int im_rot90( VipsImage *in, VipsImage *out );
int im_rot180( VipsImage *in, VipsImage *out );

View File

@ -209,6 +209,24 @@ vips_operation_complex_get_type( void )
return( etype );
}
GType
vips_operation_complexget_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_OPERATION_COMPLEXGET_REAL, "VIPS_OPERATION_COMPLEXGET_REAL", "real"},
{VIPS_OPERATION_COMPLEXGET_IMAG, "VIPS_OPERATION_COMPLEXGET_IMAG", "imag"},
{VIPS_OPERATION_COMPLEXGET_LAST, "VIPS_OPERATION_COMPLEXGET_LAST", "last"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsOperationComplexget", values );
}
return( etype );
}
/* enumerations from "../../libvips/include/vips/util.h" */
GType
vips_token_get_type( void )