1 /* creates an butterworth_band filter.
2  *
3  * 02/01/14
4  * 	- from butterworth_band.c
5  */
6 
7 /*
8 
9     This file is part of VIPS.
10 
11     VIPS is free software; you can redistribute it and/or modify
12     it under the terms of the GNU Lesser General Public License as published by
13     the Free Software Foundation; either version 2 of the License, or
14     (at your option) any later version.
15 
16     This program is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU Lesser General Public License for more details.
20 
21     You should have received a copy of the GNU Lesser General Public License
22     along with this program; if not, write to the Free Software
23     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24     02110-1301  USA
25 
26  */
27 
28 /*
29 
30     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
31 
32  */
33 
34 /*
35 #define VIPS_DEBUG
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif /*HAVE_CONFIG_H*/
41 #include <vips/intl.h>
42 
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <math.h>
47 
48 #include <vips/vips.h>
49 
50 #include "pcreate.h"
51 #include "point.h"
52 #include "pmask.h"
53 
54 typedef struct _VipsMaskButterworthBand {
55 	VipsMask parent_instance;
56 
57 	double order;
58 	double frequency_cutoff_x;
59 	double frequency_cutoff_y;
60 	double radius;
61 	double amplitude_cutoff;
62 
63 } VipsMaskButterworthBand;
64 
65 typedef VipsMaskClass VipsMaskButterworthBandClass;
66 
67 G_DEFINE_TYPE( VipsMaskButterworthBand, vips_mask_butterworth_band,
68 	VIPS_TYPE_MASK );
69 
70 static double
vips_mask_butterworth_band_point(VipsMask * mask,double dx,double dy)71 vips_mask_butterworth_band_point( VipsMask *mask,
72 	double dx, double dy )
73 {
74 	VipsMaskButterworthBand *butterworth_band =
75 		(VipsMaskButterworthBand *) mask;
76 	double order = butterworth_band->order;
77 	double fcx = butterworth_band->frequency_cutoff_x;
78 	double fcy = butterworth_band->frequency_cutoff_y;
79 	double r2 = butterworth_band->radius * butterworth_band->radius;
80 	double ac = butterworth_band->amplitude_cutoff;
81 
82 	double cnst = (1.0 / ac) - 1.0;
83 
84 	/* Normalise the amplitude at (fcx, fcy) to 1.0.
85 	 */
86 	double cnsta = 1.0 / (1.0 + 1.0 / (1.0 +
87 		cnst * pow( 4.0 * (fcx * fcx + fcy * fcy) / r2, order )));
88 
89 	double d1 = (dx - fcx) * (dx - fcx) + (dy - fcy) * (dy - fcy);
90 	double d2 = (dx + fcx) * (dx + fcx) + (dy + fcy) * (dy + fcy);
91 
92 	return( cnsta * (1.0 / (1.0 + cnst * pow( d1 / r2, order )) +
93 			 1.0 / (1.0 + cnst * pow( d2 / r2, order ))) );
94 }
95 
96 static void
vips_mask_butterworth_band_class_init(VipsMaskButterworthBandClass * class)97 vips_mask_butterworth_band_class_init(
98 	VipsMaskButterworthBandClass *class )
99 {
100 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
101 	VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
102 	VipsMaskClass *mask_class = VIPS_MASK_CLASS( class );
103 
104 	gobject_class->set_property = vips_object_set_property;
105 	gobject_class->get_property = vips_object_get_property;
106 
107 	vobject_class->nickname = "mask_butterworth_band";
108 	vobject_class->description = _( "make a butterworth_band filter" );
109 
110 	mask_class->point = vips_mask_butterworth_band_point;
111 
112 	VIPS_ARG_DOUBLE( class, "order", 6,
113 		_( "Order" ),
114 		_( "Filter order" ),
115 		VIPS_ARGUMENT_REQUIRED_INPUT,
116 		G_STRUCT_OFFSET( VipsMaskButterworthBand, order ),
117 		1.0, 1000000.0, 1.0 );
118 
119 	VIPS_ARG_DOUBLE( class, "frequency_cutoff_x", 7,
120 		_( "Frequency cutoff x" ),
121 		_( "Frequency cutoff x" ),
122 		VIPS_ARGUMENT_REQUIRED_INPUT,
123 		G_STRUCT_OFFSET( VipsMaskButterworthBand, frequency_cutoff_x ),
124 		0.0, 1000000.0, 0.5 );
125 
126 	VIPS_ARG_DOUBLE( class, "frequency_cutoff_y", 8,
127 		_( "Frequency cutoff y" ),
128 		_( "Frequency cutoff y" ),
129 		VIPS_ARGUMENT_REQUIRED_INPUT,
130 		G_STRUCT_OFFSET( VipsMaskButterworthBand, frequency_cutoff_y ),
131 		0.0, 1000000.0, 0.5 );
132 
133 	VIPS_ARG_DOUBLE( class, "radius", 9,
134 		_( "radius" ),
135 		_( "radius of circle" ),
136 		VIPS_ARGUMENT_REQUIRED_INPUT,
137 		G_STRUCT_OFFSET( VipsMaskButterworthBand, radius ),
138 		0.0, 1000000.0, 0.1 );
139 
140 	VIPS_ARG_DOUBLE( class, "amplitude_cutoff", 10,
141 		_( "Amplitude cutoff" ),
142 		_( "Amplitude cutoff" ),
143 		VIPS_ARGUMENT_REQUIRED_INPUT,
144 		G_STRUCT_OFFSET( VipsMaskButterworthBand, amplitude_cutoff ),
145 		0.0, 1.0, 0.5 );
146 
147 }
148 
149 static void
vips_mask_butterworth_band_init(VipsMaskButterworthBand * butterworth_band)150 vips_mask_butterworth_band_init(
151 	VipsMaskButterworthBand *butterworth_band )
152 {
153 	butterworth_band->order = 1.0;
154 	butterworth_band->frequency_cutoff_x = 0.5;
155 	butterworth_band->frequency_cutoff_y = 0.5;
156 	butterworth_band->radius = 0.1;
157 	butterworth_band->amplitude_cutoff = 0.5;
158 }
159 
160 /**
161  * vips_mask_butterworth_band:
162  * @out: (out): output image
163  * @width: image size
164  * @height: image size
165  * @order: filter order
166  * @frequency_cutoff_x: band position
167  * @frequency_cutoff_y: band position
168  * @radius: band radius
169  * @amplitude_cutoff: amplitude threshold
170  * @...: %NULL-terminated list of optional named arguments
171  *
172  * Optional arguments:
173  *
174  * * @nodc: don't set the DC pixel
175  * * @reject: invert the filter sense
176  * * @optical: coordinates in optical space
177  * * @uchar: output a uchar image
178  *
179  * Make an butterworth band-pass or band-reject filter, that is, one with a
180  * variable, smooth transition positioned at @frequency_cutoff_x,
181  * @frequency_cutoff_y, of radius @radius.
182  * The shape of the curve is controlled by
183  * @order --- higher values give a sharper transition. See Gonzalez and Wintz,
184  * Digital Image Processing, 1987.
185  *
186  * See also: vips_mask_ideal().
187  *
188  * Returns: 0 on success, -1 on error
189  */
190 int
vips_mask_butterworth_band(VipsImage ** out,int width,int height,double order,double frequency_cutoff_x,double frequency_cutoff_y,double radius,double amplitude_cutoff,...)191 vips_mask_butterworth_band( VipsImage **out, int width, int height,
192 	double order, double frequency_cutoff_x, double frequency_cutoff_y,
193 	double radius, double amplitude_cutoff, ... )
194 {
195 	va_list ap;
196 	int result;
197 
198 	va_start( ap, amplitude_cutoff );
199 	result = vips_call_split( "mask_butterworth_band", ap,
200 		out, width, height,
201 		order, frequency_cutoff_x, frequency_cutoff_y, radius,
202 		amplitude_cutoff );
203 	va_end( ap );
204 
205 	return( result );
206 }
207