From dde6e4508a3282b0c01145489959e1b7799d1be4 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 2 Jan 2014 18:29:59 +0000 Subject: [PATCH] rewrite (most of) the freq mask builders all classes now, except gauss band filter --- ChangeLog | 1 + TODO | 9 + libvips/create/Makefile.am | 10 ++ libvips/create/create.c | 15 ++ libvips/create/ffilter.c | 145 +++++++++++++++ libvips/create/ffilter.h | 156 ++++++++++++++++ libvips/create/ffilter_butterworth.c | 162 +++++++++++++++++ libvips/create/ffilter_butterworth_band.c | 210 ++++++++++++++++++++++ libvips/create/ffilter_butterworth_ring.c | 168 +++++++++++++++++ libvips/create/ffilter_gaussian.c | 146 +++++++++++++++ libvips/create/ffilter_gaussian_ring.c | 157 ++++++++++++++++ libvips/create/ffilter_ideal.c | 152 ++++++++++++++++ libvips/create/ffilter_ideal_band.c | 166 +++++++++++++++++ libvips/create/ffilter_ideal_ring.c | 151 ++++++++++++++++ libvips/create/point.c | 44 +++-- libvips/create/point.h | 3 + libvips/include/vips/create.h | 28 +++ 17 files changed, 1708 insertions(+), 15 deletions(-) create mode 100644 libvips/create/ffilter.c create mode 100644 libvips/create/ffilter.h create mode 100644 libvips/create/ffilter_butterworth.c create mode 100644 libvips/create/ffilter_butterworth_band.c create mode 100644 libvips/create/ffilter_butterworth_ring.c create mode 100644 libvips/create/ffilter_gaussian.c create mode 100644 libvips/create/ffilter_gaussian_ring.c create mode 100644 libvips/create/ffilter_ideal.c create mode 100644 libvips/create/ffilter_ideal_band.c create mode 100644 libvips/create/ffilter_ideal_ring.c diff --git a/ChangeLog b/ChangeLog index cb25ff76..bc81fe09 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,7 @@ - conv is SMALLTILE, huge mem use saving on wide images - vipsthumbnail has a --crop option - remove video4linux1 code, it was useless on all modern linuxes +- redone freq filter builders as classes 20/11/13 started 7.36.5 - better cache sizing in unbuffered sequential mode diff --git a/TODO b/TODO index e33430fc..32a98463 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,12 @@ +- try: + + time vips dzsave JP2K-33003-1.svs x --layout zoomify + + VIPS:ERROR:buffer.c:390:vips_buffer_new: assertion failed: (!buffer->cache) + Aborted (core dumped) + +- still need to do gaussian band filter + - new_heart.ws fails with libvips master has the sharing fix resolved this? diff --git a/libvips/create/Makefile.am b/libvips/create/Makefile.am index 59c2cf1b..28b632a0 100644 --- a/libvips/create/Makefile.am +++ b/libvips/create/Makefile.am @@ -11,6 +11,16 @@ libcreate_la_SOURCES = \ identity.c \ point.c \ point.h \ + ffilter.c \ + ffilter.h \ + ffilter_ideal.c \ + ffilter_ideal_ring.c \ + ffilter_ideal_band.c \ + ffilter_butterworth.c \ + ffilter_butterworth_ring.c \ + ffilter_butterworth_band.c \ + ffilter_gaussian.c \ + ffilter_gaussian_ring.c \ eye.c \ grey.c \ xyz.c \ diff --git a/libvips/create/create.c b/libvips/create/create.c index 5130e92a..63133fce 100644 --- a/libvips/create/create.c +++ b/libvips/create/create.c @@ -48,6 +48,8 @@ #include #include "pcreate.h" +#include "point.h" +#include "ffilter.h" /** * SECTION: create @@ -126,6 +128,11 @@ vips_create_operation_init( void ) extern GType vips_invertlut_get_type( void ); extern GType vips_tonelut_get_type( void ); extern GType vips_identity_get_type( void ); + extern GType vips_ffilter_butterworth_ring_get_type( void ); + extern GType vips_ffilter_butterworth_band_get_type( void ); + extern GType vips_ffilter_gaussian_ring_get_type( void ); + extern GType vips_ffilter_ideal_ring_get_type( void ); + extern GType vips_ffilter_ideal_band_get_type( void ); vips_black_get_type(); vips_gaussmat_get_type(); @@ -143,5 +150,13 @@ vips_create_operation_init( void ) vips_invertlut_get_type(); vips_tonelut_get_type(); vips_identity_get_type(); + vips_ffilter_ideal_get_type(); + vips_ffilter_ideal_ring_get_type(); + vips_ffilter_ideal_band_get_type(); + vips_ffilter_butterworth_get_type(); + vips_ffilter_butterworth_ring_get_type(); + vips_ffilter_butterworth_band_get_type(); + vips_ffilter_gaussian_get_type(); + vips_ffilter_gaussian_ring_get_type(); } diff --git a/libvips/create/ffilter.c b/libvips/create/ffilter.c new file mode 100644 index 00000000..1ece6b68 --- /dev/null +++ b/libvips/create/ffilter.c @@ -0,0 +1,145 @@ +/* base class for frequency filter create operations + * + * 02/01/14 + * - from sines.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 "ffilter.h" + +G_DEFINE_ABSTRACT_TYPE( VipsFfilter, vips_ffilter, VIPS_TYPE_POINT ); + +static float +vips_ffilter_point( VipsPoint *point, int x, int y ) +{ + VipsFfilter *ffilter = VIPS_FFILTER( point ); + VipsFfilterClass *class = VIPS_FFILTER_GET_CLASS( point ); + int half_width = point->width / 2; + int half_height = point->height / 2; + + double result; + + /* Move centre for an optical transform mask. + */ + if( !ffilter->optical ) { + x = (x + half_width) % point->width; + y = (y + half_height) % point->height; + } + + x = x - half_width; + y = y - half_height; + + if( !ffilter->nodc && + x == 0 && + y == 0 ) + /* DC component is always 1. + */ + result = 1.0; + else { + double dx, dy; + + dx = (double) x / half_width; + dy = (double) y / half_height; + + result = class->point( ffilter, dx, dy ); + + /* Invert filter sense for a highpass filter, or to swap + * band-pass for band-reject. + */ + if( ffilter->reject ) + result = 1.0 - result; + } + + return( result ); +} + +static void +vips_ffilter_class_init( VipsFfilterClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsPointClass *point_class = VIPS_POINT_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter"; + vobject_class->description = _( "base class for frequency filters" ); + + point_class->point = vips_ffilter_point; + point_class->min = 0.0; + point_class->max = 1.0; + point_class->interpretation = VIPS_INTERPRETATION_FOURIER; + + VIPS_ARG_BOOL( class, "optical", 6, + _( "Optical" ), + _( "Rotate quadrants to optical space" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsFfilter, optical ), + FALSE ); + + VIPS_ARG_BOOL( class, "reject", 6, + _( "Reject" ), + _( "Invert the sense of the filter" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsFfilter, reject ), + FALSE ); + + VIPS_ARG_BOOL( class, "nodc", 6, + _( "Nodc" ), + _( "Remove DC component" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsFfilter, nodc ), + FALSE ); + +} + +static void +vips_ffilter_init( VipsFfilter *ffilter ) +{ +} + diff --git a/libvips/create/ffilter.h b/libvips/create/ffilter.h new file mode 100644 index 00000000..a284499b --- /dev/null +++ b/libvips/create/ffilter.h @@ -0,0 +1,156 @@ +/* base class for ffilter generators + */ + +/* + + Copyright (C) 1991-2005 The National Gallery + + This library 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.1 of the License, or (at your option) any later version. + + This library 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 library; 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 + + */ + +#ifndef VIPS_FFILTER_H +#define VIPS_FFILTER_H + +#ifdef __cplusplus +extern "C" { +#endif /*__cplusplus*/ + +#define VIPS_TYPE_FFILTER (vips_ffilter_get_type()) +#define VIPS_FFILTER( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_FFILTER, VipsFfilter )) +#define VIPS_FFILTER_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_FFILTER, VipsFfilterClass)) +#define VIPS_IS_FFILTER( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FFILTER )) +#define VIPS_IS_FFILTER_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FFILTER )) +#define VIPS_FFILTER_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_FFILTER, VipsFfilterClass )) + +typedef struct _VipsFfilter { + VipsPoint parent_instance; + + gboolean optical; + gboolean reject; + gboolean nodc; + +} VipsFfilter; + +typedef struct _VipsFfilterClass { + VipsPointClass parent_class; + + double (*point)( VipsFfilter *, double, double ); + +} VipsFfilterClass; + +GType vips_ffilter_get_type( void ); + +#define VIPS_TYPE_FFILTER_IDEAL (vips_ffilter_ideal_get_type()) +#define VIPS_FFILTER_IDEAL( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_FFILTER_IDEAL, VipsFfilterIdeal )) +#define VIPS_FFILTER_IDEAL_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_FFILTER_IDEAL, VipsFfilterIdealClass)) +#define VIPS_IS_FFILTER_IDEAL( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FFILTER_IDEAL )) +#define VIPS_IS_FFILTER_IDEAL_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FFILTER_IDEAL )) +#define VIPS_FFILTER_IDEAL_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_FFILTER_IDEAL, VipsFfilterIdealClass )) + +typedef struct _VipsFfilterIdeal { + VipsFfilter parent_instance; + + double frequency_cutoff; + +} VipsFfilterIdeal; + +typedef VipsFfilterClass VipsFfilterIdealClass; + +GType vips_ffilter_ideal_get_type( void ); + +#define VIPS_TYPE_FFILTER_BUTTERWORTH (vips_ffilter_butterworth_get_type()) +#define VIPS_FFILTER_BUTTERWORTH( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_FFILTER_BUTTERWORTH, VipsFfilterButterworth )) +#define VIPS_FFILTER_BUTTERWORTH_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_FFILTER_BUTTERWORTH, VipsFfilterButterworthClass)) +#define VIPS_IS_FFILTER_BUTTERWORTH( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FFILTER_BUTTERWORTH )) +#define VIPS_IS_FFILTER_BUTTERWORTH_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FFILTER_BUTTERWORTH )) +#define VIPS_FFILTER_BUTTERWORTH_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_FFILTER_BUTTERWORTH, VipsFfilterButterworthClass )) + +typedef struct _VipsFfilterButterworth { + VipsFfilter parent_instance; + + double order; + double frequency_cutoff; + double amplitude_cutoff; + +} VipsFfilterButterworth; + +typedef VipsFfilterClass VipsFfilterButterworthClass; + +GType vips_ffilter_butterworth_get_type( void ); + +#define VIPS_TYPE_FFILTER_GAUSSIAN (vips_ffilter_gaussian_get_type()) +#define VIPS_FFILTER_GAUSSIAN( obj ) \ + (G_TYPE_CHECK_INSTANCE_CAST( (obj), \ + VIPS_TYPE_FFILTER_GAUSSIAN, VipsFfilterGaussian )) +#define VIPS_FFILTER_GAUSSIAN_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_CAST( (klass), \ + VIPS_TYPE_FFILTER_GAUSSIAN, VipsFfilterGaussianClass)) +#define VIPS_IS_FFILTER_GAUSSIAN( obj ) \ + (G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_FFILTER_GAUSSIAN )) +#define VIPS_IS_FFILTER_GAUSSIAN_CLASS( klass ) \ + (G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_FFILTER_GAUSSIAN )) +#define VIPS_FFILTER_GAUSSIAN_GET_CLASS( obj ) \ + (G_TYPE_INSTANCE_GET_CLASS( (obj), \ + VIPS_TYPE_FFILTER_GAUSSIAN, VipsFfilterGaussianClass )) + +typedef struct _VipsFfilterGaussian { + VipsFfilter parent_instance; + + double frequency_cutoff; + double amplitude_cutoff; + +} VipsFfilterGaussian; + +typedef VipsFfilterClass VipsFfilterGaussianClass; + +GType vips_ffilter_gaussian_get_type( void ); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*VIPS_FFILTER_H*/ diff --git a/libvips/create/ffilter_butterworth.c b/libvips/create/ffilter_butterworth.c new file mode 100644 index 00000000..61e6b555 --- /dev/null +++ b/libvips/create/ffilter_butterworth.c @@ -0,0 +1,162 @@ +/* creates an butterworth filter. + * + * 02/01/14 + * - from butterworth.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 "ffilter.h" + +G_DEFINE_TYPE( VipsFfilterButterworth, vips_ffilter_butterworth, + VIPS_TYPE_FFILTER ); + +static double +vips_ffilter_butterworth_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterButterworth *butterworth = (VipsFfilterButterworth *) ffilter; + double order = butterworth->order; + double fc = butterworth->frequency_cutoff; + double ac = butterworth->amplitude_cutoff; + + double cnst = (1.0 / ac) - 1.0; + double fc2 = fc * fc; + double dist2 = fc2 / (dx * dx + dy * dy); + + return( 1.0 / (1.0 + cnst * pow( dist2, order )) ); +} + +static void +vips_ffilter_butterworth_class_init( VipsFfilterButterworthClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_butterworth"; + vobject_class->description = _( "make a butterworth filter" ); + + ffilter_class->point = vips_ffilter_butterworth_point; + + VIPS_ARG_DOUBLE( class, "order", 6, + _( "Order" ), + _( "Filter order" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworth, order ), + 1.0, 1000000.0, 1.0 ); + + VIPS_ARG_DOUBLE( class, "frequency_cutoff", 7, + _( "Frequency cutoff" ), + _( "Frequency cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworth, frequency_cutoff ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "amplitude_cutoff", 8, + _( "Amplitude cutoff" ), + _( "Amplitude cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworth, amplitude_cutoff ), + 0.0, 1.0, 0.5 ); + +} + +static void +vips_ffilter_butterworth_init( VipsFfilterButterworth *butterworth ) +{ + butterworth->order = 1.0; + butterworth->frequency_cutoff = 0.5; + butterworth->amplitude_cutoff = 0.5; +} + +/** + * vips_ffilter_butterworth: + * @out: output image + * @width: image size + * @height: image size + * @order: filter order + * @frequency_cutoff: frequency threshold + * @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 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 + * @order: higher values give a sharper transition. See Gonzalez and Wintz, + * Digital Image Processing, 1987. + * + * For other arguments, see vips_ffilter_ideal(). + * + * See also: vips_ffilter_gaussian(), vips_ffilter_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_butterworth( VipsImage **out, int width, int height, + double order, double frequency_cutoff, double amplitude_cutoff, ... ) +{ + va_list ap; + int result; + + va_start( ap, amplitude_cutoff ); + result = vips_call_split( "ffilter_butterworth", ap, + out, width, height, + order, frequency_cutoff, amplitude_cutoff ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_butterworth_band.c b/libvips/create/ffilter_butterworth_band.c new file mode 100644 index 00000000..a5861e17 --- /dev/null +++ b/libvips/create/ffilter_butterworth_band.c @@ -0,0 +1,210 @@ +/* creates an butterworth_band filter. + * + * 02/01/14 + * - from butterworth_band.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 "ffilter.h" + +typedef struct _VipsFfilterButterworthBand { + VipsFfilter parent_instance; + + double order; + double frequency_cutoff_x; + double frequency_cutoff_y; + double r; + double amplitude_cutoff; + +} VipsFfilterButterworthBand; + +typedef VipsFfilterClass VipsFfilterButterworthBandClass; + +G_DEFINE_TYPE( VipsFfilterButterworthBand, vips_ffilter_butterworth_band, + VIPS_TYPE_FFILTER ); + +static double +vips_ffilter_butterworth_band_point( VipsFfilter *ffilter, + double dx, double dy ) +{ + VipsFfilterButterworthBand *butterworth_band = + (VipsFfilterButterworthBand *) ffilter; + double order = butterworth_band->order; + double fcx = butterworth_band->frequency_cutoff_x; + double fcy = butterworth_band->frequency_cutoff_y; + double r2 = butterworth_band->r * butterworth_band->r; + double ac = butterworth_band->amplitude_cutoff; + + double cnst = (1.0 / ac) - 1.0; + + /* Normalise the amplitude at (fcx, fcy) to 1.0. + */ + double cnsta = 1.0 / (1.0 + 1.0 / (1.0 + + cnst * pow( 4.0 * (fcx * fcx + fcy * fcy) / r2, order ))); + + double d1 = (dx - fcx) * (dx - fcx) + (dy - fcy) * (dy - fcy); + double d2 = (dx + fcx) * (dx + fcx) + (dy + fcy) * (dy + fcy); + + return( cnsta * (1.0 / (1.0 + cnst * pow( d1 / r2, order )) + + 1.0 / (1.0 + cnst * pow( d2 / r2, order ))) ); +} + +static void +vips_ffilter_butterworth_band_class_init( + VipsFfilterButterworthBandClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_butterworth_band"; + vobject_class->description = _( "make a butterworth_band filter" ); + + ffilter_class->point = vips_ffilter_butterworth_band_point; + + VIPS_ARG_DOUBLE( class, "order", 6, + _( "Order" ), + _( "Filter order" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworthBand, order ), + 1.0, 1000000.0, 1.0 ); + + VIPS_ARG_DOUBLE( class, "frequency_cutoff_x", 7, + _( "Frequency cutoff x" ), + _( "Frequency cutoff x" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworthBand, + 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( VipsFfilterButterworthBand, + 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( VipsFfilterButterworthBand, 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( VipsFfilterButterworthBand, amplitude_cutoff ), + 0.0, 1.0, 0.5 ); + +} + +static void +vips_ffilter_butterworth_band_init( + VipsFfilterButterworthBand *butterworth_band ) +{ + butterworth_band->order = 1.0; + butterworth_band->frequency_cutoff_x = 0.5; + butterworth_band->frequency_cutoff_y = 0.5; + butterworth_band->r = 0.1; + butterworth_band->amplitude_cutoff = 0.5; +} + +/** + * vips_ffilter_butterworth_band: + * @out: output image + * @width: image size + * @height: image size + * @order: filter order + * @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 an butterworth band-pass or band-reject filter, that is, one with a + * variable, smooth transition positioned at @frequency_cutoff_x, + * @frequency_cutoff_y. + * 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_ffilter_ideal(). + * + * See also: vips_ffilter_gaussian(), vips_ffilter_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_butterworth_band( VipsImage **out, int width, int height, + double order, 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( "ffilter_butterworth_band", ap, + out, width, height, + order, frequency_cutoff_x, frequency_cutoff_y, + amplitude_cutoff ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_butterworth_ring.c b/libvips/create/ffilter_butterworth_ring.c new file mode 100644 index 00000000..112bd2fd --- /dev/null +++ b/libvips/create/ffilter_butterworth_ring.c @@ -0,0 +1,168 @@ +/* creates an butterworth filter. + * + * 02/01/14 + * - from butterworth.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 "ffilter.h" + +typedef struct _VipsFfilterButterworthRing { + VipsFfilterButterworth parent_instance; + + double ringwidth; + +} VipsFfilterButterworthRing; + +typedef VipsFfilterButterworthClass VipsFfilterButterworthRingClass; + +G_DEFINE_TYPE( VipsFfilterButterworthRing, vips_ffilter_butterworth_ring, + VIPS_TYPE_FFILTER_BUTTERWORTH ); + +static double +vips_ffilter_butterworth_ring_point( VipsFfilter *ffilter, + double dx, double dy ) +{ + VipsFfilterButterworth *butterworth = + (VipsFfilterButterworth *) ffilter; + VipsFfilterButterworthRing *butterworth_ring = + (VipsFfilterButterworthRing *) ffilter; + + double order = butterworth->order; + double fc = butterworth->frequency_cutoff; + double ac = butterworth->amplitude_cutoff; + double ringwidth = butterworth_ring->ringwidth; + + double df = ringwidth / 2.0; + double cnst = (1.0 / ac) - 1.0; + double df2 = df * df; + double dist = sqrt( dx * dx + dy * dy ); + + return( 1.0 / (1.0 + cnst * pow( + (dist - fc) * (dist - fc) / df2, order )) ); +} + +static void +vips_ffilter_butterworth_ring_class_init( + VipsFfilterButterworthRingClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_butterworth_ring"; + vobject_class->description = _( "make a butterworth ring filter" ); + + ffilter_class->point = vips_ffilter_butterworth_ring_point; + + VIPS_ARG_DOUBLE( class, "ringwidth", 20, + _( "Ringwidth" ), + _( "Ringwidth" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterButterworthRing, ringwidth ), + 0.0, 1000000.0, 0.1 ); + +} + +static void +vips_ffilter_butterworth_ring_init( + VipsFfilterButterworthRing *butterworth_ring ) +{ + butterworth_ring->ringwidth = 0.1; +} + +/** + * vips_ffilter_butterworth_ring: + * @out: output image + * @width: image size + * @height: image size + * @order: filter order + * @frequency_cutoff: frequency threshold + * @amplitude_cutoff: amplitude threshold + * @ringwidth: ringwidth + * @...: %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 butterworth ring-pass or ring-reject filter, that is, one with a + * variable, + * smooth transition + * positioned at @frequency_cutoff of width @width, where @frequency_cutoff is + * in the 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_ffilter_ideal(). + * + * See also: vips_ffilter_gaussian(), vips_ffilter_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_butterworth_ring( VipsImage **out, int width, int height, + double order, double frequency_cutoff, double amplitude_cutoff, + double ringwidth, ... ) +{ + va_list ap; + int result; + + va_start( ap, ringwidth ); + result = vips_call_split( "ffilter_butterworth_ring", ap, + out, width, height, + order, frequency_cutoff, amplitude_cutoff, ringwidth ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_gaussian.c b/libvips/create/ffilter_gaussian.c new file mode 100644 index 00000000..f35dd90f --- /dev/null +++ b/libvips/create/ffilter_gaussian.c @@ -0,0 +1,146 @@ +/* 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 "ffilter.h" + +G_DEFINE_TYPE( VipsFfilterGaussian, vips_ffilter_gaussian, VIPS_TYPE_FFILTER ); + +static double +vips_ffilter_gaussian_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterGaussian *gaussian = (VipsFfilterGaussian *) ffilter; + double fc = gaussian->frequency_cutoff; + double ac = gaussian->amplitude_cutoff; + + double cnst = log( ac ); + double fc2 = fc * fc; + double dist2 = (dx * dx + dy * dy) / fc2; + + return( exp( cnst * dist2 ) ); +} + +static void +vips_ffilter_gaussian_class_init( VipsFfilterGaussianClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_gaussian"; + vobject_class->description = _( "make a gaussian filter" ); + + ffilter_class->point = vips_ffilter_gaussian_point; + + VIPS_ARG_DOUBLE( class, "frequency_cutoff", 7, + _( "Frequency cutoff" ), + _( "Frequency cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterGaussian, frequency_cutoff ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "amplitude_cutoff", 8, + _( "Amplitude cutoff" ), + _( "Amplitude cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterGaussian, amplitude_cutoff ), + 0.0, 1.0, 0.5 ); + +} + +static void +vips_ffilter_gaussian_init( VipsFfilterGaussian *gaussian ) +{ + gaussian->frequency_cutoff = 0.5; + gaussian->amplitude_cutoff = 0.5; +} + +/** + * vips_ffilter_gaussian: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff: frequency threshold + * @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 high- or low-pass filter, that is, one with a variable, + * smooth transition positioned at @frequency_cutoff. + * + * For other arguments, see vips_ffilter_ideal(). + * + * See also: vips_ffilter_butterworth(), vips_ffilter_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_gaussian( VipsImage **out, int width, int height, + double frequency_cutoff, double amplitude_cutoff, ... ) +{ + va_list ap; + int result; + + va_start( ap, amplitude_cutoff ); + result = vips_call_split( "ffilter_gaussian", ap, out, width, height, + frequency_cutoff, amplitude_cutoff ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_gaussian_ring.c b/libvips/create/ffilter_gaussian_ring.c new file mode 100644 index 00000000..a6f914e0 --- /dev/null +++ b/libvips/create/ffilter_gaussian_ring.c @@ -0,0 +1,157 @@ +/* creates a gaussian_ring filter. + * + * 02/01/14 + * - from gaussian_ring.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 "ffilter.h" + +typedef struct _VipsFfilterGaussianRing { + VipsFfilterGaussian parent_instance; + + double ringwidth; + +} VipsFfilterGaussianRing; + +typedef VipsFfilterGaussianClass VipsFfilterGaussianRingClass; + +G_DEFINE_TYPE( VipsFfilterGaussianRing, vips_ffilter_gaussian_ring, + VIPS_TYPE_FFILTER_GAUSSIAN ); + +static double +vips_ffilter_gaussian_ring_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterGaussian *gaussian = (VipsFfilterGaussian *) ffilter; + VipsFfilterGaussianRing *gaussian_ring = + (VipsFfilterGaussianRing *) ffilter; + + double fc = gaussian->frequency_cutoff; + double ac = gaussian->amplitude_cutoff; + double ringwidth = gaussian_ring->ringwidth; + + double df = ringwidth / 2.0; + double df2 = df * df; + double cnst = log( ac ); + double dist = sqrt( dx * dx + dy * dy ); + + return( exp( cnst * (dist - fc) * (dist - fc) / df2 ) ); +} + +static void +vips_ffilter_gaussian_ring_class_init( VipsFfilterGaussianRingClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_gaussian_ring"; + vobject_class->description = _( "make a gaussian ring filter" ); + + ffilter_class->point = vips_ffilter_gaussian_ring_point; + + VIPS_ARG_DOUBLE( class, "ringwidth", 20, + _( "Ringwidth" ), + _( "Ringwidth" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterGaussianRing, ringwidth ), + 0.0, 1000000.0, 0.5 ); + +} + +static void +vips_ffilter_gaussian_ring_init( VipsFfilterGaussianRing *gaussian_ring ) +{ + gaussian_ring->ringwidth = 0.5; +} + +/** + * vips_ffilter_gaussian_ring: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff: frequency threshold + * @amplitude_cutoff: amplitude threshold + * @ringwidth: ringwidth + * @...: %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 ring-pass or ring-reject filter, that is, one with a + * variable, smooth transition positioned at @frequency_cutoff of width + * @ringwidth. + * + * For other arguments, see vips_ffilter_ideal(). + * + * See also: vips_ffilter_butterworth_ring(), vips_ffilter_ideal_ring(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_gaussian_ring( VipsImage **out, int width, int height, + double frequency_cutoff, double amplitude_cutoff, double ringwidth, + ... ) +{ + va_list ap; + int result; + + va_start( ap, ringwidth ); + result = vips_call_split( "ffilter_gaussian_ring", + ap, out, width, height, + frequency_cutoff, amplitude_cutoff, ringwidth ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_ideal.c b/libvips/create/ffilter_ideal.c new file mode 100644 index 00000000..b1cfce25 --- /dev/null +++ b/libvips/create/ffilter_ideal.c @@ -0,0 +1,152 @@ +/* creates an ideal filter. + * + * 02/01/14 + * - from ideal.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 "ffilter.h" + +G_DEFINE_TYPE( VipsFfilterIdeal, vips_ffilter_ideal, VIPS_TYPE_FFILTER ); + +static double +vips_ffilter_ideal_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterIdeal *ideal = (VipsFfilterIdeal *) ffilter; + double fc = ideal->frequency_cutoff; + + double dist2 = dx * dx + dy * dy; + double fc2 = fc * fc; + + return( dist2 <= fc2 ? 1.0 : 0.0 ); +} + +static void +vips_ffilter_ideal_class_init( VipsFfilterIdealClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_ideal"; + vobject_class->description = _( "make an ideal filter" ); + + ffilter_class->point = vips_ffilter_ideal_point; + + VIPS_ARG_DOUBLE( class, "frequency_cutoff", 6, + _( "Frequency cutoff" ), + _( "Frequency cutoff" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterIdeal, frequency_cutoff ), + 0.0, 1000000.0, 0.5 ); + +} + +static void +vips_ffilter_ideal_init( VipsFfilterIdeal *ideal ) +{ + ideal->frequency_cutoff = 0.5; +} + +/** + * vips_ffilter_ideal: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff: + * @...: %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 an ideal high- or low-pass filter, that is, one with a sharp cutoff + * positioned at @frequency_cutoff, where @frequency_cutoff is in + * the range 0 - 1. + * + * This operation creates a one-band float image of the specified size. + * The image has + * values in the range [0, 1] and is typically used for multiplying against + * frequency domain images to filter them. + * Masks are created with the DC component at (0, 0). The DC pixel always + * has the value 1.0. + * + * 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 @reject to invert the sense of + * the filter. For example, low-pass becomes low-reject. + * + * 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_ffilter_gaussian(), vips_ffilter_butterworth(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_ideal( VipsImage **out, int width, int height, + double frequency_cutoff, ... ) +{ + va_list ap; + int result; + + va_start( ap, frequency_cutoff ); + result = vips_call_split( "ffilter_ideal", ap, out, width, height, + frequency_cutoff ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_ideal_band.c b/libvips/create/ffilter_ideal_band.c new file mode 100644 index 00000000..6842b172 --- /dev/null +++ b/libvips/create/ffilter_ideal_band.c @@ -0,0 +1,166 @@ +/* creates an ideal filter. + * + * 02/01/14 + * - from ideal.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 "ffilter.h" + +typedef struct _VipsFfilterIdealBand { + VipsFfilter parent_instance; + + double frequency_cutoff_x; + double frequency_cutoff_y; + double r; + +} VipsFfilterIdealBand; + +typedef VipsFfilterClass VipsFfilterIdealBandClass; + +G_DEFINE_TYPE( VipsFfilterIdealBand, vips_ffilter_ideal_band, + VIPS_TYPE_FFILTER ); + +static double +vips_ffilter_ideal_band_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterIdealBand *ideal_band = (VipsFfilterIdealBand *) ffilter; + double fcx = ideal_band->frequency_cutoff_x; + double fcy = ideal_band->frequency_cutoff_y; + double r2 = ideal_band->r * ideal_band->r; + + double d1 = (dx - fcx) * (dx - fcx) + (dy - fcy) * (dy - fcy); + double d2 = (dx + fcx) * (dx + fcx) + (dy + fcy) * (dy + fcy); + + return( d1 < r2 || d2 < r2 ? 1.0 : 0.0 ); +} + +static void +vips_ffilter_ideal_band_class_init( VipsFfilterIdealBandClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_ideal_band"; + vobject_class->description = _( "make an ideal band filter" ); + + ffilter_class->point = vips_ffilter_ideal_band_point; + + VIPS_ARG_DOUBLE( class, "frequency_cutoff_x", 6, + _( "Frequency cutoff x" ), + _( "Frequency cutoff x" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterIdealBand, frequency_cutoff_x ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "frequency_cutoff_y", 7, + _( "Frequency cutoff y" ), + _( "Frequency cutoff y" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterIdealBand, frequency_cutoff_y ), + 0.0, 1000000.0, 0.5 ); + + VIPS_ARG_DOUBLE( class, "r", 8, + _( "r" ), + _( "radius of circle" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterIdealBand, r ), + 0.0, 1000000.0, 0.1 ); + +} + +static void +vips_ffilter_ideal_band_init( VipsFfilterIdealBand *ideal_band ) +{ + ideal_band->frequency_cutoff_x = 0.5; + ideal_band->frequency_cutoff_y = 0.5; + ideal_band->r = 0.1; +} + +/** + * vips_ffilter_ideal_band: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff_x: position of band + * @frequency_cutoff_y: position of band + * @r: size of band + * @...: %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 an ideal band-pass or band-reject filter, that is, one with a + * sharp cutoff around the point @frequency_cutoff_x, @frequency_cutoff_y, + * of size @r. + * + * See also: vips_ffilter_ideal(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_ideal_band( VipsImage **out, int width, int height, + double frequency_cutoff_x, double frequency_cutoff_y, double r, ... ) +{ + va_list ap; + int result; + + va_start( ap, r ); + result = vips_call_split( "ffilter_ideal", ap, out, width, height, + frequency_cutoff_x, frequency_cutoff_y, r ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/ffilter_ideal_ring.c b/libvips/create/ffilter_ideal_ring.c new file mode 100644 index 00000000..b187fd8a --- /dev/null +++ b/libvips/create/ffilter_ideal_ring.c @@ -0,0 +1,151 @@ +/* creates an ideal ringpass filter. + * + * 02/01/14 + * - from ideal.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 "ffilter.h" + +typedef struct _VipsFfilterIdealRing { + VipsFfilterIdeal parent_instance; + + double ringwidth; + +} VipsFfilterIdealRing; + +typedef VipsFfilterIdealClass VipsFfilterIdealRingClass; + +G_DEFINE_TYPE( VipsFfilterIdealRing, vips_ffilter_ideal_ring, + VIPS_TYPE_FFILTER_IDEAL ); + +static double +vips_ffilter_ideal_ring_point( VipsFfilter *ffilter, double dx, double dy ) +{ + VipsFfilterIdeal *ideal = (VipsFfilterIdeal *) ffilter; + VipsFfilterIdealRing *ideal_ring = (VipsFfilterIdealRing *) ffilter; + double fc = ideal->frequency_cutoff; + double ringwidth = ideal_ring->ringwidth; + + double df = ringwidth / 2.0; + double dist2 = dx * dx + dy * dy; + double fc2_1 = (fc - df) * (fc - df); + double fc2_2 = (fc + df) * (fc + df); + + return( dist2 > fc2_1 && dist2 < fc2_2 ? 1.0 : 0.0 ); +} + +static void +vips_ffilter_ideal_ring_class_init( VipsFfilterIdealClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsFfilterClass *ffilter_class = VIPS_FFILTER_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "ffilter_ideal_ring"; + vobject_class->description = _( "make an ideal ring filter" ); + + ffilter_class->point = vips_ffilter_ideal_ring_point; + + VIPS_ARG_DOUBLE( class, "ringwidth", 20, + _( "Ringwidth" ), + _( "Ringwidth" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsFfilterIdealRing, ringwidth ), + 0.0, 1000000.0, 0.5 ); + +} + +static void +vips_ffilter_ideal_ring_init( VipsFfilterIdealRing *ideal_ring ) +{ + ideal_ring->ringwidth = 0.5; +} + +/** + * vips_ffilter_ideal_ring: + * @out: output image + * @width: image size + * @height: image size + * @frequency_cutoff: + * @ringwidth: ringwidth + * @...: %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 an ideal ring-pass or ring-reject filter, that is, one with a sharp + * 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_ffilter_ideal(). + * + * See also: vips_ffilter_gaussian_ring(), vips_ffilter_butterworth_ring(). + * + * Returns: 0 on success, -1 on error + */ +int +vips_ffilter_ideal_ring( VipsImage **out, int width, int height, + double frequency_cutoff, double ringwidth, ... ) +{ + va_list ap; + int result; + + va_start( ap, ringwidth ); + result = vips_call_split( "ffilter_ideal_ring", ap, out, width, height, + frequency_cutoff, ringwidth ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/create/point.c b/libvips/create/point.c index b26c6cb4..7992119e 100644 --- a/libvips/create/point.c +++ b/libvips/create/point.c @@ -70,18 +70,15 @@ vips_point_gen( VipsRegion *or, void *seq, void *a, void *b, VipsPoint *point = (VipsPoint *) a; VipsPointClass *class = VIPS_POINT_GET_CLASS( point ); VipsRect *r = &or->valid; - int le = r->left; - int to = r->top; - int ri = VIPS_RECT_RIGHT( r ); - int bo = VIPS_RECT_BOTTOM( r ); int x, y; - for( y = to; y < bo; y++ ) { - float *q = (float *) VIPS_REGION_ADDR( or, le, y ); + for( y = 0; y < r->height; y++ ) { + int ay = r->top + y; + float *q = (float *) VIPS_REGION_ADDR( or, r->left, ay ); - for( x = le; x < ri; x++ ) - *q++ = class->point( point, x, y ); + for( x = 0; x < r->width; x++ ) + q[x] = class->point( point, r->left + x, ay ); } return( 0 ); @@ -91,8 +88,10 @@ static int vips_point_build( VipsObject *object ) { VipsCreate *create = VIPS_CREATE( object ); - VipsPoint *point = (VipsPoint *) object; - VipsImage **t = (VipsImage **) vips_object_local_array( object, 3 ); + VipsPoint *point = VIPS_POINT( object ); + VipsPointClass *class = VIPS_POINT_GET_CLASS( point ); + VipsImage **t = (VipsImage **) vips_object_local_array( object, 4 ); + VipsImage *in; if( VIPS_OBJECT_CLASS( vips_point_parent_class )->build( object ) ) @@ -101,20 +100,30 @@ vips_point_build( VipsObject *object ) t[0] = vips_image_new(); vips_image_init_fields( t[0], point->width, point->height, 1, - VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, VIPS_INTERPRETATION_B_W, + VIPS_FORMAT_FLOAT, VIPS_CODING_NONE, class->interpretation, 1.0, 1.0 ); vips_image_pipelinev( t[0], VIPS_DEMAND_STYLE_ANY, NULL ); if( vips_image_generate( t[0], NULL, vips_point_gen, NULL, point, NULL ) ) return( -1 ); - in = t[0]; + if( point->uchar ) { - if( vips_linear1( in, &t[1], 127.5, 127.5, NULL ) || - vips_cast( t[1], &t[2], VIPS_FORMAT_UCHAR, NULL ) ) + float min = class->min; + float max = class->max; + float range = max - min; + + if( vips_linear1( in, &t[2], + 255.0 / range, -min * 255.0 / range, NULL ) || + vips_cast( t[2], &t[3], VIPS_FORMAT_UCHAR, NULL ) ) return( -1 ); - in = t[2]; + in = t[3]; + + /* uchar mode always does B_W. We don't want FOURIER or + * whatever in this case. + */ + t[3]->Type = VIPS_INTERPRETATION_B_W; } if( vips_image_write( in, create->out ) ) @@ -136,6 +145,11 @@ vips_point_class_init( VipsPointClass *class ) vobject_class->description = _( "make a point image" ); vobject_class->build = vips_point_build; + class->point = NULL; + class->min = -1.0; + class->max = 1.0; + class->interpretation = VIPS_INTERPRETATION_B_W; + VIPS_ARG_INT( class, "width", 2, _( "Width" ), _( "Image width in pixels" ), diff --git a/libvips/create/point.h b/libvips/create/point.h index f92d4973..c4635bda 100644 --- a/libvips/create/point.h +++ b/libvips/create/point.h @@ -64,6 +64,9 @@ typedef struct _VipsPointClass { VipsCreateClass parent_class; float (*point)( VipsPoint *, int, int ); + float min; + float max; + VipsInterpretation interpretation; } VipsPointClass; diff --git a/libvips/include/vips/create.h b/libvips/include/vips/create.h index ddcf9c66..540e7fab 100644 --- a/libvips/include/vips/create.h +++ b/libvips/include/vips/create.h @@ -73,6 +73,34 @@ int vips_invertlut( VipsImage *in, VipsImage **out, ... ) int vips_tonelut( VipsImage **out, ... ) __attribute__((sentinel)); +int vips_ffilter_ideal( VipsImage **out, int width, int height, + double frequency_cutoff, ... ) + __attribute__((sentinel)); +int vips_ffilter_ideal_ring( VipsImage **out, int width, int height, + double frequency_cutoff, double bandwidth, ... ) + __attribute__((sentinel)); +int vips_ffilter_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, ... ) + __attribute__((sentinel)); +int vips_ffilter_butterworth_ring( VipsImage **out, int width, int height, + double order, double frequency_cutoff, double amplitude_cutoff, + double ringwidth, ... ) + __attribute__((sentinel)); +int vips_ffilter_butterworth_band( VipsImage **out, int width, int height, + 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_ffilter_gaussian_ring( VipsImage **out, int width, int height, + double frequency_cutoff, double amplitude_cutoff, double ringwidth, + ... ) + __attribute__((sentinel)); + int im_benchmarkn( VipsImage *in, VipsImage *out, int n ); int im_benchmark2( VipsImage *in, double *out );