diff --git a/libvips/create/Makefile.am b/libvips/create/Makefile.am index 40ede05b..9a31c3f2 100644 --- a/libvips/create/Makefile.am +++ b/libvips/create/Makefile.am @@ -21,6 +21,7 @@ libcreate_la_SOURCES = \ mask_butterworth_band.c \ mask_gaussian.c \ mask_gaussian_ring.c \ + mask_gaussian_band.c \ eye.c \ grey.c \ xyz.c \ diff --git a/libvips/create/create.c b/libvips/create/create.c index cc4ad0d9..2886ba99 100644 --- a/libvips/create/create.c +++ b/libvips/create/create.c @@ -131,6 +131,7 @@ vips_create_operation_init( void ) extern GType vips_mask_butterworth_ring_get_type( void ); extern GType vips_mask_butterworth_band_get_type( void ); extern GType vips_mask_gaussian_ring_get_type( void ); + extern GType vips_mask_gaussian_band_get_type( void ); extern GType vips_mask_ideal_ring_get_type( void ); extern GType vips_mask_ideal_band_get_type( void ); @@ -158,5 +159,6 @@ vips_create_operation_init( void ) vips_mask_butterworth_band_get_type(); vips_mask_gaussian_get_type(); vips_mask_gaussian_ring_get_type(); + vips_mask_gaussian_band_get_type(); } diff --git a/libvips/create/mask.c b/libvips/create/mask.c index 01d33287..5d3739b6 100644 --- a/libvips/create/mask.c +++ b/libvips/create/mask.c @@ -115,21 +115,21 @@ vips_mask_class_init( VipsMaskClass *class ) point_class->max = 1.0; point_class->interpretation = VIPS_INTERPRETATION_FOURIER; - VIPS_ARG_BOOL( class, "optical", 6, + VIPS_ARG_BOOL( class, "optical", 5, _( "Optical" ), _( "Rotate quadrants to optical space" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsMask, optical ), FALSE ); - VIPS_ARG_BOOL( class, "reject", 6, + VIPS_ARG_BOOL( class, "reject", 5, _( "Reject" ), _( "Invert the sense of the filter" ), VIPS_ARGUMENT_OPTIONAL_INPUT, G_STRUCT_OFFSET( VipsMask, reject ), FALSE ); - VIPS_ARG_BOOL( class, "nodc", 6, + VIPS_ARG_BOOL( class, "nodc", 5, _( "Nodc" ), _( "Remove DC component" ), VIPS_ARGUMENT_OPTIONAL_INPUT, diff --git a/libvips/create/mask_butterworth.c b/libvips/create/mask_butterworth.c index eefbc8ed..80ee1b23 100644 --- a/libvips/create/mask_butterworth.c +++ b/libvips/create/mask_butterworth.c @@ -134,14 +134,12 @@ vips_mask_butterworth_init( VipsMaskButterworth *butterworth ) * * Make an butterworth high- or low-pass filter, that is, one with a variable, * smooth transition - * positioned at @frequency_cutoff, where @frequency_cutoff is a percentage - * expressed as the range 0 - 1. The shape of the curve is controlled by + * positioned at @frequency_cutoff, where @frequency_cutoff is in + * range 0 - 1. The shape of the curve is controlled by * @order: higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_gaussian(), vips_mask_ideal(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_butterworth_band.c b/libvips/create/mask_butterworth_band.c index 2d72d3e7..9cb19a44 100644 --- a/libvips/create/mask_butterworth_band.c +++ b/libvips/create/mask_butterworth_band.c @@ -120,16 +120,14 @@ vips_mask_butterworth_band_class_init( _( "Frequency cutoff x" ), _( "Frequency cutoff x" ), VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsMaskButterworthBand, - frequency_cutoff_x ), + G_STRUCT_OFFSET( VipsMaskButterworthBand, frequency_cutoff_x ), 0.0, 1000000.0, 0.5 ); VIPS_ARG_DOUBLE( class, "frequency_cutoff_y", 8, _( "Frequency cutoff y" ), _( "Frequency cutoff y" ), VIPS_ARGUMENT_REQUIRED_INPUT, - G_STRUCT_OFFSET( VipsMaskButterworthBand, - frequency_cutoff_y ), + G_STRUCT_OFFSET( VipsMaskButterworthBand, frequency_cutoff_y ), 0.0, 1000000.0, 0.5 ); VIPS_ARG_DOUBLE( class, "r", 9, @@ -180,14 +178,12 @@ vips_mask_butterworth_band_init( * * Make an butterworth band-pass or band-reject filter, that is, one with a * variable, smooth transition positioned at @frequency_cutoff_x, - * @frequency_cutoff_y. + * @frequency_cutoff_y, of radius @r. * The shape of the curve is controlled by * @order: higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_gaussian(), vips_mask_ideal(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ @@ -202,7 +198,7 @@ vips_mask_butterworth_band( VipsImage **out, int width, int height, va_start( ap, amplitude_cutoff ); result = vips_call_split( "mask_butterworth_band", ap, out, width, height, - order, frequency_cutoff_x, frequency_cutoff_y, + order, frequency_cutoff_x, frequency_cutoff_y, r, amplitude_cutoff ); va_end( ap ); diff --git a/libvips/create/mask_butterworth_ring.c b/libvips/create/mask_butterworth_ring.c index e72be0f8..010ad14f 100644 --- a/libvips/create/mask_butterworth_ring.c +++ b/libvips/create/mask_butterworth_ring.c @@ -144,9 +144,7 @@ vips_mask_butterworth_ring_init( * @order: higher values give a sharper transition. See Gonzalez and Wintz, * Digital Image Processing, 1987. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_gaussian(), vips_mask_ideal(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_gaussian.c b/libvips/create/mask_gaussian.c index aa640adb..ecf268d8 100644 --- a/libvips/create/mask_gaussian.c +++ b/libvips/create/mask_gaussian.c @@ -124,9 +124,7 @@ vips_mask_gaussian_init( VipsMaskGaussian *gaussian ) * Make a gaussian high- or low-pass filter, that is, one with a variable, * smooth transition positioned at @frequency_cutoff. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_butterworth(), vips_mask_ideal(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_gaussian_band.c b/libvips/create/mask_gaussian_band.c new file mode 100644 index 00000000..34b219e5 --- /dev/null +++ b/libvips/create/mask_gaussian_band.c @@ -0,0 +1,186 @@ +/* creates a gaussian filter. + * + * 02/01/14 + * - from gaussian.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., 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 "pcreate.h" +#include "point.h" +#include "pmask.h" + +typedef struct _VipsMaskGaussianBand { + VipsMask parent_instance; + + double frequency_cutoff_x; + double frequency_cutoff_y; + double r; + double amplitude_cutoff; + +} VipsMaskGaussianBand; + +typedef VipsMaskClass VipsMaskGaussianBandClass; + +G_DEFINE_TYPE( VipsMaskGaussianBand, vips_mask_gaussian_band, VIPS_TYPE_MASK ); + +static double +vips_mask_gaussian_band_point( VipsMask *mask, double dx, double dy ) +{ + VipsMaskGaussianBand *gaussian_band = (VipsMaskGaussianBand *) mask; + + double fcx = gaussian_band->frequency_cutoff_x; + double fcy = gaussian_band->frequency_cutoff_y; + double r2 = gaussian_band->r * gaussian_band->r; + double ac = gaussian_band->amplitude_cutoff; + + double cnst = log( ac ); + + double d1 = (dx - fcx) * (dx - fcx) + (dy - fcy) * (dy - fcy); + double d2 = (dx + fcx) * (dx + fcx) + (dy + fcy) * (dy + fcy); + + /* Normalise the amplitude at (fcx, fcy) to 1.0. + */ + double cnsta = 1.0 / (1.0 + + exp( cnst * 4.0 * (fcx * fcx + fcy * fcy) / r2 )); + + return( cnsta * (exp( cnst * d1 / r2 ) + exp( cnst * d2 / r2 )) ); +} + +static void +vips_mask_gaussian_band_class_init( VipsMaskGaussianBandClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsMaskClass *mask_class = VIPS_MASK_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "mask_gaussian_band"; + vobject_class->description = _( "make a gaussian filter" ); + + mask_class->point = vips_mask_gaussian_band_point; + + VIPS_ARG_DOUBLE( class, "frequency_cutoff_x", 7, + _( "Frequency cutoff x" ), + _( "Frequency cutoff x" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMaskGaussianBand, frequency_cutoff_x ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "frequency_cutoff_y", 8, + _( "Frequency cutoff y" ), + _( "Frequency cutoff y" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMaskGaussianBand, frequency_cutoff_y ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "r", 9, + _( "r" ), + _( "radius of circle" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMaskGaussianBand, r ), + 0.0, 1000000.0, 0.1 ); + + VIPS_ARG_DOUBLE( class, "amplitude_cutoff", 10, + _( "Amplitude cutoff" ), + _( "Amplitude cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMaskGaussianBand, amplitude_cutoff ), + 0.0, 1.0, 0.5 ); + +} + +static void +vips_mask_gaussian_band_init( VipsMaskGaussianBand *gaussian_band ) +{ + gaussian_band->frequency_cutoff_x = 0.5; + gaussian_band->frequency_cutoff_x = 0.5; + gaussian_band->r = 0.1; + gaussian_band->amplitude_cutoff = 0.5; +} + +/** + * vips_mask_gaussian_band: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff_x: band position + * @frequency_cutoff_y: band position + * @r: band radius + * @amplitude_cutoff: amplitude threshold + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * @nodc: don't set the DC pixel + * @reject: invert the filter sense + * @optical: coordinates in optical space + * @uchar: output a uchar image + * + * Make a gaussian band-pass or band-reject filter, that is, one with a + * variable, smooth transition positioned at @frequency_cutoff_x, + * @frequency_cutoff_y, of radius @r. + * + * See also: vips_mask_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_mask_gaussian_band( VipsImage **out, int width, int height, + double frequency_cutoff_x, double frequency_cutoff_y, double r, + double amplitude_cutoff, ... ) +{ + va_list ap; + int result; + + va_start( ap, amplitude_cutoff ); + result = vips_call_split( "mask_gaussian_band", ap, out, width, height, + frequency_cutoff_x, frequency_cutoff_y, r, + amplitude_cutoff ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/mask_gaussian_ring.c b/libvips/create/mask_gaussian_ring.c index 22d25ad6..c99a0b18 100644 --- a/libvips/create/mask_gaussian_ring.c +++ b/libvips/create/mask_gaussian_ring.c @@ -133,9 +133,7 @@ vips_mask_gaussian_ring_init( VipsMaskGaussianRing *gaussian_ring ) * variable, smooth transition positioned at @frequency_cutoff of width * @ringwidth. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_butterworth_ring(), vips_mask_ideal_ring(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_ideal.c b/libvips/create/mask_ideal.c index 3d6b596b..6336b657 100644 --- a/libvips/create/mask_ideal.c +++ b/libvips/create/mask_ideal.c @@ -123,8 +123,9 @@ vips_mask_ideal_init( VipsMaskIdeal *ideal ) * * Set @nodc to not set the DC pixel. * - * Set @optical to position the DC component in the centre of the image. See - * vips_wrap(). + * Set @optical to position the DC component in the centre of the image. This + * makes the mask suitable for multiplying against optical Fourier transforms. + * See vips_wrap(). * * Set @reject to invert the sense of * the filter. For example, low-pass becomes low-reject. @@ -132,7 +133,11 @@ vips_mask_ideal_init( VipsMaskIdeal *ideal ) * Set @uchar to output an 8-bit unsigned char image rather than a * float image. In this case, pixels are in the range [0 - 255]. * - * See also: vips_mask_gaussian(), vips_mask_butterworth(). + * See also: vips_mask_ideal(), vips_mask_ideal_ring(), + * vips_mask_ideal_band(), vips_mask_butterworth(), + * vips_mask_butterworth_ring(), vips_mask_butterworth_band(), + * vips_mask_gaussian(), vips_mask_gaussian_ring(), + * vips_mask_gaussian_band(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/mask_ideal_ring.c b/libvips/create/mask_ideal_ring.c index eda148a8..59b8b8e7 100644 --- a/libvips/create/mask_ideal_ring.c +++ b/libvips/create/mask_ideal_ring.c @@ -129,9 +129,7 @@ vips_mask_ideal_ring_init( VipsMaskIdealRing *ideal_ring ) * ring positioned at @frequency_cutoff of width @width, where * @frequency_cutoff and @width are expressed as the range 0 - 1. * - * For other arguments, see vips_mask_ideal(). - * - * See also: vips_mask_gaussian_ring(), vips_mask_butterworth_ring(). + * See also: vips_mask_ideal(). * * Returns: 0 on success, -1 on error */ diff --git a/libvips/create/point.c b/libvips/create/point.c index 7992119e..0964e660 100644 --- a/libvips/create/point.c +++ b/libvips/create/point.c @@ -164,7 +164,7 @@ vips_point_class_init( VipsPointClass *class ) G_STRUCT_OFFSET( VipsPoint, height ), 1, 1000000, 1 ); - VIPS_ARG_BOOL( class, "uchar", 7, + VIPS_ARG_BOOL( class, "uchar", 4, _( "Uchar" ), _( "Output an unsigned char image" ), VIPS_ARGUMENT_OPTIONAL_INPUT, diff --git a/libvips/include/vips/create.h b/libvips/include/vips/create.h index 2e38004e..b2034739 100644 --- a/libvips/include/vips/create.h +++ b/libvips/include/vips/create.h @@ -77,28 +77,35 @@ int vips_mask_ideal( VipsImage **out, int width, int height, double frequency_cutoff, ... ) __attribute__((sentinel)); int vips_mask_ideal_ring( VipsImage **out, int width, int height, - double frequency_cutoff, double bandwidth, ... ) + double frequency_cutoff, double ringwidth, ... ) __attribute__((sentinel)); int vips_mask_ideal_band( VipsImage **out, int width, int height, double frequency_cutoff_x, double frequency_cutoff_y, double r, ... ) __attribute__((sentinel)); int vips_mask_butterworth( VipsImage **out, int width, int height, - double order, double frequency_cutoff, double amplitude_cutoff, ... ) + double order, + double frequency_cutoff, double amplitude_cutoff, ... ) __attribute__((sentinel)); int vips_mask_butterworth_ring( VipsImage **out, int width, int height, - double order, double frequency_cutoff, double amplitude_cutoff, + double order, + double frequency_cutoff, double amplitude_cutoff, double ringwidth, ... ) __attribute__((sentinel)); int vips_mask_butterworth_band( VipsImage **out, int width, int height, - double order, double frequency_cutoff_x, double frequency_cutoff_y, - double r, double amplitude_cutoff, ... ) + double order, + double frequency_cutoff_x, double frequency_cutoff_y, double r, + double amplitude_cutoff, ... ) __attribute__((sentinel)); int vips_mask_gaussian( VipsImage **out, int width, int height, double frequency_cutoff, double amplitude_cutoff, ... ) __attribute__((sentinel)); int vips_mask_gaussian_ring( VipsImage **out, int width, int height, - double frequency_cutoff, double amplitude_cutoff, double ringwidth, - ... ) + double frequency_cutoff, double amplitude_cutoff, + double ringwidth, ... ) + __attribute__((sentinel)); +int vips_mask_gaussian_band( VipsImage **out, int width, int height, + double frequency_cutoff_x, double frequency_cutoff_y, double r, + double amplitude_cutoff, ... ) __attribute__((sentinel)); int im_benchmarkn( VipsImage *in, VipsImage *out, int n );