im_zoom() -> class

This commit is contained in:
John Cupitt 2013-06-01 10:56:16 +01:00
parent 236b8b99ad
commit 0bbc1b20d6
8 changed files with 467 additions and 378 deletions

View File

@ -4,7 +4,7 @@
it's cheap so caching doesn't help anyway
- auto rshift down to 8 bits on save, if necessary
- im_gaussnoise(), im_copy_file(), im_grid(), im_scale(), im_scaleps(),
im_wrap(), im_rotquad() redone as classes
im_wrap(), im_rotquad(), im_zoom() redone as classes
- add --angle option to dzsave
14/5/13 started 7.32.4

View File

@ -35,6 +35,6 @@ libconversion_la_SOURCES = \
im_system.c \
im_system_image.c \
im_text.c \
im_zoom.c
zoom.c
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@

View File

@ -129,6 +129,7 @@ vips_conversion_operation_init( void )
extern GType vips_grid_get_type( void );
extern GType vips_scale_get_type( void );
extern GType vips_wrap_get_type( void );
extern GType vips_zoom_get_type( void );
vips_copy_get_type();
vips_tile_cache_get_type();
@ -155,6 +156,7 @@ vips_conversion_operation_init( void )
vips_grid_get_type();
vips_scale_get_type();
vips_wrap_get_type();
vips_zoom_get_type();
}
/* The common part of most binary conversion

View File

@ -1,375 +0,0 @@
/* im_zoom
*
* Author: N. Martinez 1991
* 6/6/94 JC
* - rewritten to ANSI-C
* - now works for any type, including IM_CODING_LABQ
* 7/10/94 JC
* - new IM_ARRAY() macro
* 26/1/96 JC
* - separate x and y zoom factors
* 21/8/96 JC
* - partial, yuk! this is so complicated ...
* 30/8/96 JC
* - sets demand_hint
* 10/2/00 JC
* - check for integer overflow in zoom facs ... was happening with ip's
* zoom on large images
* 3/8/02 JC
* - fall back to im_copy() for x & y factors == 1
* 24/3/09
* - added IM_CODING_RAD support
* 1/2/10
* - gtkdoc
*/
/*
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
* TODO:
* Test for pixel size and use memcpy() on individual pixels once they reach
* sizes of the order of tens of bytes. char-wise copy is quicker than
* memcpy() for smaller pixels.
*
* Also, I haven't tested it but int-wise copying may be faster still, as
* long as alignment permits it.
*
* tcv. 2006-09-01
*/
/* Turn on IM_REGION_ADDR() range checks.
#define DEBUG 1
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vips/vips.h>
/* Round N down to P boundary.
*/
#define ROUND_DOWN(N,P) ((N) - ((N) % P))
/* Round N up to P boundary.
*/
#define ROUND_UP(N,P) (ROUND_DOWN( (N) + (P) - 1, (P) ))
/* Our main parameter struct.
*/
typedef struct {
int xfac; /* Scale factors */
int yfac;
} ZoomInfo;
/* Paint the part of the region containing only whole pels.
*/
static void
paint_whole( REGION *or, REGION *ir, ZoomInfo *zm,
const int left, const int right, const int top, const int bottom )
{
const int ps = IM_IMAGE_SIZEOF_PEL( ir->im );
const int ls = IM_REGION_LSKIP( or );
const int rs = ps * (right - left);
/* Transform to ir coordinates.
*/
const int ileft = left / zm->xfac;
const int iright = right / zm->xfac;
const int itop = top / zm->yfac;
const int ibottom = bottom / zm->yfac;
int x, y, z, i;
/* We know this!
*/
g_assert( right > left && bottom > top &&
right % zm->xfac == 0 &&
left % zm->xfac == 0 &&
top % zm->yfac == 0 &&
bottom % zm->yfac == 0 );
/* Loop over input, as we know we are all whole.
*/
for( y = itop; y < ibottom; y++ ) {
VipsPel *p = IM_REGION_ADDR( ir, ileft, y );
VipsPel *q = IM_REGION_ADDR( or, left, y * zm->yfac );
VipsPel *r;
/* Expand the first line of pels.
*/
r = q;
for( x = ileft; x < iright; x++ ) {
/* Copy each pel xfac times.
*/
for( z = 0; z < zm->xfac; z++ ) {
for( i = 0; i < ps; i++ )
r[i] = p[i];
r += ps;
}
p += ps;
}
/* Copy the expanded line yfac-1 times.
*/
r = q + ls;
for( z = 1; z < zm->yfac; z++ ) {
memcpy( r, q, rs );
r += ls;
}
}
}
/* Paint the part of the region containing only part-pels.
*/
static void
paint_part( REGION *or, REGION *ir, const ZoomInfo *zm,
const int left, const int right, const int top, const int bottom )
{
const int ps = IM_IMAGE_SIZEOF_PEL( ir->im );
const int ls = IM_REGION_LSKIP( or );
const int rs = ps * (right - left);
/* Start position in input.
*/
const int ix = left / zm->xfac;
const int iy = top / zm->yfac;
/* Pels down to yfac boundary, pels down to bottom. Do the smallest of
* these for first y loop.
*/
const int ptbound = (iy + 1) * zm->yfac - top;
const int ptbot = bottom - top;
int yt = IM_MIN( ptbound, ptbot );
int x, y, z, i;
/* Only know this.
*/
g_assert( right - left >= 0 && bottom - top >= 0 );
/* Have to loop over output.
*/
for( y = top; y < bottom; ) {
VipsPel *p = IM_REGION_ADDR( ir, ix, y / zm->yfac );
VipsPel *q = IM_REGION_ADDR( or, left, y );
VipsPel *r;
/* Output pels until we jump the input pointer.
*/
int xt = (ix + 1) * zm->xfac - left;
/* Loop for this output line.
*/
r = q;
for( x = left; x < right; x++ ) {
/* Copy 1 pel.
*/
for( i = 0; i < ps; i++ )
r[i] = p[i];
r += ps;
/* Move input if on boundary.
*/
--xt;
if( xt == 0 ) {
xt = zm->xfac;
p += ps;
}
}
/* Repeat that output line until the bottom of this pixel
* boundary, or we hit bottom.
*/
r = q + ls;
for( z = 1; z < yt; z++ ) {
memcpy( r, q, rs );
r += ls;
}
/* Move y on by the number of lines we wrote.
*/
y += yt;
/* Reset yt for next iteration.
*/
yt = zm->yfac;
}
}
/* Zoom a REGION.
*/
static int
zoom_gen( REGION *or, void *seq, void *a, void *b )
{
REGION *ir = (REGION *) seq;
ZoomInfo *zm = (ZoomInfo *) b;
/* Output area we are building.
*/
const Rect *r = &or->valid;
const int ri = IM_RECT_RIGHT( r );
const int bo = IM_RECT_BOTTOM(r);
Rect s;
int left, right, top, bottom;
int width, height;
/* Area of input we need. We have to round out, as we may have
* part-pixels all around the edges.
*/
left = ROUND_DOWN( r->left, zm->xfac );
right = ROUND_UP( ri, zm->xfac );
top = ROUND_DOWN( r->top, zm->yfac );
bottom = ROUND_UP( bo, zm->yfac );
width = right - left;
height = bottom - top;
s.left = left / zm->xfac;
s.top = top / zm->yfac;
s.width = width / zm->xfac;
s.height = height / zm->yfac;
if( im_prepare( ir, &s ) )
return( -1 );
/* Find the part of the output (if any) which uses only whole pels.
*/
left = ROUND_UP( r->left, zm->xfac );
right = ROUND_DOWN( ri, zm->xfac );
top = ROUND_UP( r->top, zm->yfac );
bottom = ROUND_DOWN( bo, zm->yfac );
width = right - left;
height = bottom - top;
/* Stage 1: we just paint the whole pels in the centre of the region.
* As we know they are not clipped, we can do it quickly.
*/
if( width > 0 && height > 0 )
paint_whole( or, ir, zm, left, right, top, bottom );
/* Just fractional pixels left. Paint in the top, left, right and
* bottom parts.
*/
if( top - r->top > 0 )
/* Some top pixels.
*/
paint_part( or, ir, zm,
r->left, ri, r->top, IM_MIN( top, bo ) );
if( left - r->left > 0 && height > 0 )
/* Left pixels.
*/
paint_part( or, ir, zm,
r->left, IM_MIN( left, ri ), top, bottom );
if( ri - right > 0 && height > 0 )
/* Right pixels.
*/
paint_part( or, ir, zm,
IM_MAX( right, r->left ), ri, top, bottom );
if( bo - bottom > 0 && height >= 0 )
/* Bottom pixels.
*/
paint_part( or, ir, zm,
r->left, ri, IM_MAX( bottom, r->top ), bo );
return( 0 );
}
/**
* im_zoom:
* @in: input image
* @out: output image
* @xfac: horizontal scale factor
* @yfac: vertical scale factor
*
* Zoom an image by repeating pixels. This is fast nearest-neighbour
* zoom.
*
* See also: im_affinei(), im_subsample().
*
* Returns: 0 on success, -1 on error.
*/
int
im_zoom( IMAGE *in, IMAGE *out, int xfac, int yfac )
{
ZoomInfo *zm;
/* Check arguments.
*/
if( xfac <= 0 || yfac <= 0 ) {
im_error( "im_zoom", "%s", _( "zoom factors should be >= 0" ) );
return( -1 );
}
if( (double) in->Xsize * xfac > (double) INT_MAX / 2 ||
(double) in->Ysize * yfac > (double) INT_MAX / 2 ) {
/* Make sure we won't get integer overflow.
*/
im_error( "im_zoom", "%s", _( "zoom factors too large" ) );
return( -1 );
}
if( xfac == 1 && yfac == 1 )
return( im_copy( in, out ) );
if( im_piocheck( in, out ) ||
im_check_coding_known( "im_zoom", in ) )
return( -1 );
/* Make output.
*/
if( im_cp_desc( out, in ) )
return( -1 );
out->Xsize = in->Xsize * xfac;
out->Ysize = in->Ysize * yfac;
/* Save parameters.
*/
if( !(zm = IM_NEW( out, ZoomInfo )) )
return( -1 );
zm->xfac = xfac;
zm->yfac = yfac;
/* Set demand hints. THINSTRIP will prevent us from using
* paint_whole() much ... so go for FATSTRIP.
*/
if( im_demand_hint( out, IM_FATSTRIP, in, NULL ) )
return( -1 );
/* Generate!
*/
if( im_generate( out,
im_start_one, zoom_gen, im_stop_one, in, zm ) )
return( -1 );
return( 0 );
}

444
libvips/conversion/zoom.c Normal file
View File

@ -0,0 +1,444 @@
/* im_zoom
*
* Author: N. Martinez 1991
* 6/6/94 JC
* - rewritten to ANSI-C
* - now works for any type, including IM_CODING_LABQ
* 7/10/94 JC
* - new IM_ARRAY() macro
* 26/1/96 JC
* - separate x and y zoom factors
* 21/8/96 JC
* - partial, yuk! this is so complicated ...
* 30/8/96 JC
* - sets demand_hint
* 10/2/00 JC
* - check for integer overflow in zoom facs ... was happening with ip's
* zoom on large images
* 3/8/02 JC
* - fall back to im_copy() for x & y factors == 1
* 24/3/09
* - added IM_CODING_RAD support
* 1/2/10
* - gtkdoc
* 1/6/13
* - redo as a class
*/
/*
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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
*/
/*
* TODO:
* Test for pixel size and use memcpy() on individual pixels once they reach
* sizes of the order of tens of bytes. char-wise copy is quicker than
* memcpy() for smaller pixels.
*
* Also, I haven't tested it but int-wise copying may be faster still, as
* long as alignment permits it.
*
* tcv. 2006-09-01
*/
/* Turn on ADDR() range checks.
#define DEBUG 1
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
#include <vips/intl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <vips/vips.h>
#include "conversion.h"
typedef struct _VipsZoom {
VipsConversion parent_instance;
/* The input image.
*/
VipsImage *in;
int xfac; /* Scale factors */
int yfac;
} VipsZoom;
typedef VipsConversionClass VipsZoomClass;
G_DEFINE_TYPE( VipsZoom, vips_zoom, VIPS_TYPE_CONVERSION );
/* Round N down to P boundary.
*/
#define ROUND_DOWN( N, P ) ((N) - ((N) % P))
/* Round N up to P boundary.
*/
#define ROUND_UP( N, P ) (ROUND_DOWN( (N) + (P) - 1, (P) ))
/* Paint the part of the region containing only whole pels.
*/
static void
vips_zoom_paint_whole( VipsRegion *or, VipsRegion *ir, VipsZoom *zoom,
const int left, const int right, const int top, const int bottom )
{
const int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im );
const int ls = VIPS_REGION_LSKIP( or );
const int rs = ps * (right - left);
/* Transform to ir coordinates.
*/
const int ileft = left / zoom->xfac;
const int iright = right / zoom->xfac;
const int itop = top / zoom->yfac;
const int ibottom = bottom / zoom->yfac;
int x, y, z, i;
/* We know this!
*/
g_assert( right > left && bottom > top &&
right % zoom->xfac == 0 &&
left % zoom->xfac == 0 &&
top % zoom->yfac == 0 &&
bottom % zoom->yfac == 0 );
/* Loop over input, as we know we are all whole.
*/
for( y = itop; y < ibottom; y++ ) {
VipsPel *p = VIPS_REGION_ADDR( ir, ileft, y );
VipsPel *q = VIPS_REGION_ADDR( or, left, y * zoom->yfac );
VipsPel *r;
/* Expand the first line of pels.
*/
r = q;
for( x = ileft; x < iright; x++ ) {
/* Copy each pel xfac times.
*/
for( z = 0; z < zoom->xfac; z++ ) {
for( i = 0; i < ps; i++ )
r[i] = p[i];
r += ps;
}
p += ps;
}
/* Copy the expanded line yfac-1 times.
*/
r = q + ls;
for( z = 1; z < zoom->yfac; z++ ) {
memcpy( r, q, rs );
r += ls;
}
}
}
/* Paint the part of the region containing only part-pels.
*/
static void
vips_zoom_paint_part( VipsRegion *or, VipsRegion *ir, VipsZoom *zoom,
const int left, const int right, const int top, const int bottom )
{
const int ps = VIPS_IMAGE_SIZEOF_PEL( ir->im );
const int ls = VIPS_REGION_LSKIP( or );
const int rs = ps * (right - left);
/* Start position in input.
*/
const int ix = left / zoom->xfac;
const int iy = top / zoom->yfac;
/* Pels down to yfac boundary, pels down to bottom. Do the smallest of
* these for first y loop.
*/
const int ptbound = (iy + 1) * zoom->yfac - top;
const int ptbot = bottom - top;
int yt = VIPS_MIN( ptbound, ptbot );
int x, y, z, i;
/* Only know this.
*/
g_assert( right - left >= 0 && bottom - top >= 0 );
/* Have to loop over output.
*/
for( y = top; y < bottom; ) {
VipsPel *p = VIPS_REGION_ADDR( ir, ix, y / zoom->yfac );
VipsPel *q = VIPS_REGION_ADDR( or, left, y );
VipsPel *r;
/* Output pels until we jump the input pointer.
*/
int xt = (ix + 1) * zoom->xfac - left;
/* Loop for this output line.
*/
r = q;
for( x = left; x < right; x++ ) {
/* Copy 1 pel.
*/
for( i = 0; i < ps; i++ )
r[i] = p[i];
r += ps;
/* Move input if on boundary.
*/
--xt;
if( xt == 0 ) {
xt = zoom->xfac;
p += ps;
}
}
/* Repeat that output line until the bottom of this pixel
* boundary, or we hit bottom.
*/
r = q + ls;
for( z = 1; z < yt; z++ ) {
memcpy( r, q, rs );
r += ls;
}
/* Move y on by the number of lines we wrote.
*/
y += yt;
/* Reset yt for next iteration.
*/
yt = zoom->yfac;
}
}
/* Zoom a VipsRegion.
*/
static int
vips_zoom_gen( VipsRegion *or, void *seq, void *a, void *b, gboolean *stop )
{
VipsRegion *ir = (VipsRegion *) seq;
VipsZoom *zoom = (VipsZoom *) b;
/* Output area we are building.
*/
const VipsRect *r = &or->valid;
const int ri = VIPS_RECT_RIGHT( r );
const int bo = VIPS_RECT_BOTTOM(r);
VipsRect s;
int left, right, top, bottom;
int width, height;
/* Area of input we need. We have to round out, as we may have
* part-pixels all around the edges.
*/
left = ROUND_DOWN( r->left, zoom->xfac );
right = ROUND_UP( ri, zoom->xfac );
top = ROUND_DOWN( r->top, zoom->yfac );
bottom = ROUND_UP( bo, zoom->yfac );
width = right - left;
height = bottom - top;
s.left = left / zoom->xfac;
s.top = top / zoom->yfac;
s.width = width / zoom->xfac;
s.height = height / zoom->yfac;
if( vips_region_prepare( ir, &s ) )
return( -1 );
/* Find the part of the output (if any) which uses only whole pels.
*/
left = ROUND_UP( r->left, zoom->xfac );
right = ROUND_DOWN( ri, zoom->xfac );
top = ROUND_UP( r->top, zoom->yfac );
bottom = ROUND_DOWN( bo, zoom->yfac );
width = right - left;
height = bottom - top;
/* Stage 1: we just paint the whole pels in the centre of the region.
* As we know they are not clipped, we can do it quickly.
*/
if( width > 0 && height > 0 )
vips_zoom_paint_whole( or, ir, zoom, left, right, top, bottom );
/* Just fractional pixels left. Paint in the top, left, right and
* bottom parts.
*/
if( top - r->top > 0 )
/* Some top pixels.
*/
vips_zoom_paint_part( or, ir, zoom,
r->left, ri, r->top, VIPS_MIN( top, bo ) );
if( left - r->left > 0 && height > 0 )
/* Left pixels.
*/
vips_zoom_paint_part( or, ir, zoom,
r->left, VIPS_MIN( left, ri ), top, bottom );
if( ri - right > 0 && height > 0 )
/* Right pixels.
*/
vips_zoom_paint_part( or, ir, zoom,
VIPS_MAX( right, r->left ), ri, top, bottom );
if( bo - bottom > 0 && height >= 0 )
/* Bottom pixels.
*/
vips_zoom_paint_part( or, ir, zoom,
r->left, ri, VIPS_MAX( bottom, r->top ), bo );
return( 0 );
}
static int
vips_zoom_build( VipsObject *object )
{
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsConversion *conversion = VIPS_CONVERSION( object );
VipsZoom *zoom = (VipsZoom *) object;
if( VIPS_OBJECT_CLASS( vips_zoom_parent_class )->build( object ) )
return( -1 );
g_assert( zoom->xfac > 0 );
g_assert( zoom->yfac > 0 );
/* Make sure we won't get integer overflow.
*/
if( (double) zoom->in->Xsize * zoom->xfac > (double) INT_MAX / 2 ||
(double) zoom->in->Ysize * zoom->yfac > (double) INT_MAX / 2 ) {
vips_error( class->nickname,
"%s", _( "zoom factors too large" ) );
return( -1 );
}
if( zoom->xfac == 1 &&
zoom->yfac == 1 )
return( vips_image_write( zoom->in, conversion->out ) );
if( vips_image_pio_input( zoom->in ) ||
vips_check_coding_known( class->nickname, zoom->in ) )
return( -1 );
if( vips_image_copy_fields( conversion->out, zoom->in ) )
return( -1 );
/* Set demand hints. THINSTRIP will prevent us from using
* vips_zoom_paint_whole() much ... so go for FATSTRIP.
*/
vips_demand_hint( conversion->out,
VIPS_DEMAND_STYLE_FATSTRIP, zoom->in, NULL );
conversion->out->Xsize = zoom->in->Xsize * zoom->xfac;
conversion->out->Ysize = zoom->in->Ysize * zoom->yfac;
if( vips_image_generate( conversion->out,
vips_start_one, vips_zoom_gen, vips_stop_one,
zoom->in, zoom ) )
return( -1 );
return( 0 );
}
/* xy range we sanity check on ... just to stop crazy numbers from divide by 0
* etc. causing g_assert() failures later.
*/
#define RANGE (100000000)
static void
vips_zoom_class_init( VipsZoomClass *class )
{
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
gobject_class->set_property = vips_object_set_property;
gobject_class->get_property = vips_object_get_property;
vobject_class->nickname = "zoom";
vobject_class->description = _( "zoom an image" );
vobject_class->build = vips_zoom_build;
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
VIPS_ARG_IMAGE( class, "input", 0,
_( "Input" ),
_( "Input image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsZoom, in ) );
VIPS_ARG_INT( class, "xfac", 2,
_( "Xfac" ),
_( "Horizontal zoom factor" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsZoom, xfac ),
1, RANGE, 1 );
VIPS_ARG_INT( class, "yfac", 3,
_( "Yfac" ),
_( "Vertical zoom factor" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsZoom, yfac ),
1, RANGE, 1 );
}
static void
vips_zoom_init( VipsZoom *zoom )
{
}
/**
* vips_zoom:
* @in: input image
* @out: output image
* @xfac: horizontal scale factor
* @yfac: vertical scale factor
* @...: %NULL-terminated list of optional named arguments
*
* Zoom an image by repeating pixels. This is fast nearest-neighbour
* zoom.
*
* See also: vips_affine(), vips_subsample().
*
* Returns: 0 on success, -1 on error.
*/
int
vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )
{
va_list ap;
int result;
va_start( ap, yfac );
result = vips_call_split( "zoom", ap, in, out, xfac, yfac );
va_end( ap );
return( result );
}

View File

@ -1565,6 +1565,22 @@ im_scaleps( VipsImage *in, VipsImage *out )
return( 0 );
}
int
im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac )
{
VipsImage *t;
if( vips_zoom( in, &t, xfac, yfac, NULL ) )
return( -1 );
if( vips_image_write( t, out ) ) {
g_object_unref( t );
return( -1 );
}
g_object_unref( t );
return( 0 );
}
static int
vips__math( VipsImage *in, VipsImage *out, VipsOperationMath math )
{

View File

@ -194,6 +194,8 @@ int vips_grid( VipsImage *in, VipsImage **out,
__attribute__((sentinel));
int vips_wrap( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_zoom( VipsImage *in, VipsImage **out, int xfac, int yfac, ... )
__attribute__((sentinel));
int vips_cast( VipsImage *in, VipsImage **out, VipsBandFormat format, ... )
__attribute__((sentinel));
@ -268,7 +270,6 @@ int im_text( VipsImage *out, const char *text, const char *font,
int im_insertset( VipsImage *main, VipsImage *sub, VipsImage *out, int n, int *x, int *y );
int im_subsample( VipsImage *in, VipsImage *out, int xshrink, int yshrink );
int im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac );
int im_system( VipsImage *im, const char *cmd, char **out );
VipsImage *im_system_image( VipsImage *im,

View File

@ -715,6 +715,7 @@ int im_gaussnoise( VipsImage *out, int x, int y, double mean, double sigma );
int im_grid( VipsImage *in, VipsImage *out, int tile_height, int across, int down );
int im_scale( VipsImage *in, VipsImage *out );
int im_scaleps( VipsImage *in, VipsImage *out );
int im_zoom( VipsImage *in, VipsImage *out, int xfac, int yfac );
int im_c2amph( VipsImage *in, VipsImage *out );
int im_c2rect( VipsImage *in, VipsImage *out );