diff --git a/ChangeLog b/ChangeLog index e72644f4..853f6266 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,7 +4,7 @@ - fix no-pango build - add im_vips2dz(): run the deepzoom writer from vips7 - vips_magickload() has an option to read all images in a sequence -- redo im_make_xy(), im_*eye(), im_zone*() as classes +- redo im_make_xy(), im_*eye(), im_zone*(), im_sines() as classes 12/3/13 started 7.33.0 - vipsthumbnail lets you specify the sharpening mask diff --git a/libvips/create/Makefile.am b/libvips/create/Makefile.am index 37248256..ffb1fe03 100644 --- a/libvips/create/Makefile.am +++ b/libvips/create/Makefile.am @@ -9,7 +9,7 @@ libcreate_la_SOURCES = \ text.c \ gaussnoise.c \ im_benchmark.c \ - im_sines.c \ + sines.c \ zone.c \ other_dispatch.c diff --git a/libvips/create/create.c b/libvips/create/create.c index 1e8a8e8d..22ff041e 100644 --- a/libvips/create/create.c +++ b/libvips/create/create.c @@ -107,6 +107,7 @@ vips_create_operation_init( void ) extern GType vips_eye_get_type( void ); extern GType vips_grey_get_type( void ); extern GType vips_zone_get_type( void ); + extern GType vips_sines_get_type( void ); vips_black_get_type(); vips_gaussnoise_get_type(); @@ -117,5 +118,6 @@ vips_create_operation_init( void ) vips_eye_get_type(); vips_grey_get_type(); vips_zone_get_type(); + vips_sines_get_type(); } diff --git a/libvips/create/eye.c b/libvips/create/eye.c index 82c170d9..6d099ff1 100644 --- a/libvips/create/eye.c +++ b/libvips/create/eye.c @@ -95,7 +95,7 @@ vips_eye_gen( VipsRegion *or, void *seq, void *a, void *b, float *q = (float *) VIPS_REGION_ADDR( or, le, y ); for( x = le; x < ri; x++ ) - q[x] = y * y * cos( c * x * x ) / h; + *q++ = y * y * cos( c * x * x ) / h; } return( 0 ); diff --git a/libvips/create/im_sines.c b/libvips/create/im_sines.c deleted file mode 100644 index 97cc0dbf..00000000 --- a/libvips/create/im_sines.c +++ /dev/null @@ -1,148 +0,0 @@ -/* creates a 2d sinewave - * - * Copyright: 1990, N. Dessipris. - * - * Author: Nicos Dessipris - * Written on: 02/02/1990 - * Modified on: - * 22/7/93 JC - * - externs removed - * - im_outcheck() added - * 1/2/11 - * - 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301 USA - - */ - -/* - - These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk - - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /*HAVE_CONFIG_H*/ -#include - -#include -#include -#include - -#include - -/** - * im_sines: - * @out: output image - * @xsize: image size - * @ysize: image size - * @horfreq: horizontal frequency - * @verfreq: vertical frequency - * - * im_sines() creates a float one band image of the a sine waveform in two - * dimensions. - * - * The number of horizontal and vertical spatial frequencies are - * determined by the variables @horfreq and @verfreq respectively. The - * function is useful for creating displayable sine waves and - * square waves in two dimensions. - * - * If horfreq and verfreq are integers the resultant image is periodical - * and therfore the Fourier transform doesnot present spikes - * - * See also: im_grey(), im_make_xy(). - * - * Returns: 0 on success, -1 on error - */ -int -im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq ) -{ - int x, y; - float *line, *cpline; - int size; - double cons, factor; - double theta_rad, costheta, sintheta, ysintheta; - -/* Check input args */ - if( im_outcheck( out ) ) - return( -1 ); - if ( xsize <= 0 || ysize <= 0 ) { - im_error( "im_sines", "%s", _( "wrong sizes") ); - return(-1); } - -/* Set now out properly */ - im_initdesc(out, xsize, ysize, 1, IM_BBITS_FLOAT, IM_BANDFMT_FLOAT, - IM_CODING_NONE, IM_TYPE_B_W, 1.0, 1.0, 0, 0); - -/* Set up out checking whether the output is a buffer or a file */ - if (im_setupout( out ) == -1 ) - return( -1 ); -/* Create data */ - size = out->Xsize; - if ( (line=(float *)calloc((unsigned)size, sizeof(float))) == NULL ) { - im_error( "im_sines", "%s", _( "calloc failed") ); - return(-1); } - -/* make angle in rad */ - if (horfreq == 0) - theta_rad = IM_PI/2.0; - else - theta_rad = atan(verfreq/horfreq); - costheta = cos(theta_rad); sintheta = sin(theta_rad); - factor = sqrt ((double)(horfreq*horfreq + verfreq*verfreq)); - cons = factor * IM_PI * 2.0/(double)out->Xsize; -/* There is a bug (rounding error ?) for horfreq=0, - *so do this calculation independantly */ - if ( horfreq != 0 ) - { - for (y=0; yYsize; y++) - { - ysintheta = y * sintheta; - cpline = line; - for (x=0; xXsize; x++) - *cpline++ = - (float)(cos(cons*(x*costheta-ysintheta))); - if ( im_writeline( y, out, (PEL *)line ) == -1 ) - { - free ( (char *)line ); - return( -1 ); - } - } - } - else - { - for (y=0; yYsize; y++) - { - cpline = line; - ysintheta = cos (- cons * y * sintheta); - for (x=0; xXsize; x++) - *cpline++ = (float)ysintheta; - if ( im_writeline( y, out, (PEL *)line ) == -1 ) - { - free ( (char *)line ); - return( -1 ); - } - } - } - free ( (char *)line ); - return(0); -} diff --git a/libvips/create/sines.c b/libvips/create/sines.c new file mode 100644 index 00000000..4726488f --- /dev/null +++ b/libvips/create/sines.c @@ -0,0 +1,245 @@ +/* creates a 2d sinewave + * + * Copyright: 1990, N. Dessipris. + * + * Author: Nicos Dessipris + * Written on: 02/02/1990 + * Modified on: + * 22/7/93 JC + * - externs removed + * - im_outcheck() added + * 1/2/11 + * - gtk-doc + * 13/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 + + */ + +/* +#define VIPS_DEBUG + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include +#include +#include + +#include + +#include "create.h" + +typedef struct _VipsSines { + VipsCreate parent_instance; + + int width; + int height; + + double hfreq; + double vfreq; + gboolean uchar; + +} VipsSines; + +typedef VipsCreateClass VipsSinesClass; + +G_DEFINE_TYPE( VipsSines, vips_sines, VIPS_TYPE_CREATE ); + +static int +vips_sines_gen( VipsRegion *or, void *seq, void *a, void *b, + gboolean *stop ) +{ + VipsSines *sines = (VipsSines *) a; + VipsRect *r = &or->valid; + int le = r->left; + int to = r->top; + int ri = VIPS_RECT_RIGHT( r ); + int bo = VIPS_RECT_BOTTOM( r ); + + double theta = sines->hfreq == 0.0 ? + VIPS_PI / 2.0 : atan( sines->vfreq / sines->hfreq ); + double costheta = cos( theta ); + double sintheta = sin( theta ); + double factor = sqrt( sines->hfreq * sines->hfreq + + sines->vfreq * sines->vfreq ); + double cons = factor * VIPS_PI * 2.0 / sines->width; + + int x, y; + + for( y = to; y < bo; y++ ) { + float *q = (float *) VIPS_REGION_ADDR( or, le, y ); + double ysintheta = y * sintheta; + + for( x = le; x < ri; x++ ) + *q++ = cos( cons * (x * costheta - ysintheta) ); + } + + return( 0 ); +} + +static int +vips_sines_build( VipsObject *object ) +{ + VipsCreate *create = VIPS_CREATE( object ); + VipsSines *sines = (VipsSines *) object; + VipsImage **t = (VipsImage **) vips_object_local_array( object, 7 ); + VipsImage *in; + + if( VIPS_OBJECT_CLASS( vips_sines_parent_class )->build( object ) ) + return( -1 ); + + t[0] = vips_image_new(); + vips_image_init_fields( t[0], + sines->width, sines->height, 1, + VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, + 1.0, 1.0 ); + vips_demand_hint( t[0], + VIPS_DEMAND_STYLE_ANY, NULL ); + if( vips_image_generate( t[0], + NULL, vips_sines_gen, NULL, sines, NULL ) ) + return( -1 ); + + in = t[0]; + if( sines->uchar ) { + if( vips_linear1( in, &t[1], 127.5, 127.5, NULL ) || + vips_cast( t[1], &t[2], VIPS_FORMAT_UCHAR, NULL ) ) + return( -1 ); + in = t[2]; + } + + if( vips_image_write( in, create->out ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_sines_class_init( VipsSinesClass *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 = "sines"; + vobject_class->description = _( "make a 2D sine wave" ); + vobject_class->build = vips_sines_build; + + VIPS_ARG_INT( class, "width", 4, + _( "Width" ), + _( "Image width in pixels" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsSines, width ), + 1, 1000000, 1 ); + + VIPS_ARG_INT( class, "height", 5, + _( "Height" ), + _( "Image height in pixels" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsSines, height ), + 1, 1000000, 1 ); + + VIPS_ARG_DOUBLE( class, "hfreq", 6, + _( "hfreq" ), + _( "Horizontal spatial frequency" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsSines, hfreq ), + 0.0, 10000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "vfreq", 7, + _( "vfreq" ), + _( "Vertical spatial frequency" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsSines, vfreq ), + 0.0, 10000.0, 0.5 ); + + VIPS_ARG_BOOL( class, "uchar", 8, + _( "Uchar" ), + _( "Output an unsigned char image" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsSines, uchar ), + FALSE ); + +} + +static void +vips_sines_init( VipsSines *sines ) +{ + sines->hfreq = 0.5; + sines->vfreq = 0.5; +} + + +/** + * vips_sines: + * @out: output image + * @xsize: image size + * @ysize: image size + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * @hfreq: horizontal frequency + * @vreq: vertical frequency + * @uchar: output a uchar image + * + * Creates a float one band image of the a sine waveform in two + * dimensions. + * + * The number of horizontal and vertical spatial frequencies are + * determined by the variables @hfreq and @vfreq respectively. The + * function is useful for creating displayable sine waves and + * square waves in two dimensions. + * + * If horfreq and verfreq are integers the resultant image is periodical + * and therfore the Fourier transform does not present spikes + * + * Pixels are normally in [-1, +1], set @uchar to output [0, 255]. + * + * See also: vips_grey(), vips_xyz(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_sines( VipsImage **out, int width, int height, ... ) +{ + va_list ap; + int result; + + va_start( ap, height ); + result = vips_call_split( "sines", ap, out, width, height ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/zone.c b/libvips/create/zone.c index 924b4d2a..968a6bb3 100644 --- a/libvips/create/zone.c +++ b/libvips/create/zone.c @@ -96,7 +96,7 @@ vips_zone_gen( VipsRegion *or, void *seq, void *a, void *b, int vp = (y - vsize) * (y - vsize); for( x = le; x < ri; x++ ) - q[x] = cos( c * (vp + ((x - hsize) * (x - hsize))) ); + *q++ = cos( c * (vp + ((x - hsize) * (x - hsize))) ); } return( 0 ); diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index db55be9b..0ed52f9a 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -1609,6 +1609,25 @@ im_fzone( IMAGE *out, int size ) return( 0 ); } +int +im_sines( IMAGE *out, int xsize, int ysize, double horfreq, double verfreq ) +{ + VipsImage *t; + + if( vips_sines( &t, xsize, ysize, + "hfreq", horfreq, + "vfreq", verfreq, + NULL ) ) + return( -1 ); + if( vips_image_write( t, out ) ) { + g_object_unref( t ); + return( -1 ); + } + g_object_unref( t ); + + return( 0 ); +} + int im_text( IMAGE *out, const char *text, const char *font, int width, int align, int dpi ) diff --git a/libvips/include/vips/create.h b/libvips/include/vips/create.h index 83c34dec..fbb8e9ff 100644 --- a/libvips/include/vips/create.h +++ b/libvips/include/vips/create.h @@ -55,14 +55,11 @@ int vips_gaussnoise( VipsImage **out, int width, int height, ... ) __attribute__((sentinel)); int vips_eye( VipsImage **out, int width, int height, ... ) __attribute__((sentinel)); +int vips_sines( VipsImage **out, int width, int height, ... ) + __attribute__((sentinel)); int vips_zone( VipsImage **out, int width, int height, ... ) __attribute__((sentinel)); - - -int im_sines( VipsImage *out, - int xsize, int ysize, double horfreq, double verfreq ); - int im_benchmarkn( VipsImage *in, VipsImage *out, int n ); int im_benchmark2( VipsImage *in, double *out ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index f6a48dc1..407968dd 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -731,6 +731,8 @@ int im_eye( VipsImage *out, const int xsize, const int ysize, const double factor ); int im_grey( VipsImage *out, const int xsize, const int ysize ); int im_fgrey( VipsImage *out, const int xsize, const int ysize ); +int im_sines( VipsImage *out, + int xsize, int ysize, double horfreq, double verfreq ); int im_system( VipsImage *im, const char *cmd, char **out ); VipsImage *im_system_image( VipsImage *im,