libvips/libvips/arithmetic/round.c

178 lines
4.0 KiB
C
Raw Normal View History

2009-09-19 13:13:28 +02:00
/* round.c --- various rounding operations
*
* 20/6/02 JC
* - adapted from im_abs()
* 29/8/09
* - gtkdoc
* - tiny cleanups
* 19/9/09
* - im_ceil.c adapted to make round.c
*/
/*
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 ROUND_LOOP( TYPE, FUN ) { \
TYPE *p = (TYPE *) in; \
TYPE *q = (TYPE *) out; \
\
for( x = 0; x < ne; x++ ) \
q[x] = FUN( p[x] ); \
}
#define ROUND_BUFFER( FUN ) \
static void \
FUN ## _buffer( PEL *in, PEL *out, int width, IMAGE *im ) \
{ \
/* Complex just doubles the size. \
*/ \
2010-01-26 22:28:33 +01:00
const int ne = width * im->Bands * \
(vips_bandfmt_iscomplex( im->BandFmt ) ? 2 : 1); \
2009-09-19 13:13:28 +02:00
\
int x; \
\
switch( im->BandFmt ) { \
case IM_BANDFMT_COMPLEX: \
case IM_BANDFMT_FLOAT: \
ROUND_LOOP( float, FUN ); \
break; \
\
case IM_BANDFMT_DOUBLE: \
case IM_BANDFMT_DPCOMPLEX: \
ROUND_LOOP( double, FUN ); \
break; \
\
default: \
g_assert( 0 ); \
} \
}
static int
im__round( const char *name, IMAGE *in, IMAGE *out, im_wrapone_fn gen )
{
if( im_piocheck( in, out ) ||
im_check_uncoded( name, in ) )
return( -1 );
/* Is this one of the int types? Degenerate to im_copy() if it
* is.
*/
2010-01-26 22:28:33 +01:00
if( vips_bandfmt_isint( in->BandFmt ) )
2009-09-19 13:13:28 +02:00
return( im_copy( in, out ) );
/* Output type == input type.
*/
if( im_cp_desc( out, in ) )
return( -1 );
/* Generate!
*/
if( im_wrapone( in, out, (im_wrapone_fn) gen, in, NULL ) )
return( -1 );
return( 0 );
}
ROUND_BUFFER( ceil )
/**
* im_ceil:
* @in: input #IMAGE
* @out: output #IMAGE
*
* For each pixel, find the smallest integral value not less than.
* Copy for integer types, call <function>ceil(3)</function> for float and
* complex types.
* Output type == input type.
*
* See also: im_floor(), im_rint(), im_clip2fmt()
*
* Returns: 0 on success, -1 on error
*/
int
im_ceil( IMAGE *in, IMAGE *out )
{
return( im__round( "im_ceil", in, out, (im_wrapone_fn) ceil_buffer ) );
}
ROUND_BUFFER( floor )
/**
* im_floor:
* @in: input #IMAGE
* @out: output #IMAGE
*
* For each pixel, find the largest integral value not less than.
* Copy for integer types, call <function>floor()</function> for float and
* complex types.
* Output type == input type.
*
* See also: im_ceil(), im_rint(), im_clip2fmt()
*
* Returns: 0 on success, -1 on error
*/
int
im_floor( IMAGE *in, IMAGE *out )
{
return( im__round( "im_floor", in, out,
(im_wrapone_fn) floor_buffer ) );
}
ROUND_BUFFER( IM_RINT )
/**
* im_rint:
* @in: input #IMAGE
* @out: output #IMAGE
*
* Finds the nearest integral value. Copy for integer types,
* call IM_RINT() for float and complex types. Output type == input type.
*
* IM_RINT() is a pseudo-round-to-nearest. It is much faster than
* <function>rint</function>(3), but does not give the same result for
* negative integral values.
*
* See also: im_ceil(), im_floor(), im_clip2fmt()
*
* Returns: 0 on success, -1 on error
*/
int
im_rint( IMAGE *in, IMAGE *out )
{
return( im__round( "im_rint", in, out, (im_wrapone_fn) IM_RINT_buffer ) );
}