1 /* creates an ideal ringpass filter.
2  *
3  * 02/01/14
4  * 	- from ideal.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 _VipsMaskIdealRing {
55 	VipsMaskIdeal parent_instance;
56 
57 	double ringwidth;
58 
59 } VipsMaskIdealRing;
60 
61 typedef VipsMaskIdealClass VipsMaskIdealRingClass;
62 
63 G_DEFINE_TYPE( VipsMaskIdealRing, vips_mask_ideal_ring,
64 	VIPS_TYPE_MASK_IDEAL );
65 
66 static double
vips_mask_ideal_ring_point(VipsMask * mask,double dx,double dy)67 vips_mask_ideal_ring_point( VipsMask *mask, double dx, double dy )
68 {
69 	VipsMaskIdeal *ideal = (VipsMaskIdeal *) mask;
70 	VipsMaskIdealRing *ideal_ring = (VipsMaskIdealRing *) mask;
71 	double fc = ideal->frequency_cutoff;
72 	double ringwidth = ideal_ring->ringwidth;
73 
74 	double df = ringwidth / 2.0;
75 	double dist2 = dx * dx + dy * dy;
76 	double fc2_1 = (fc - df) * (fc - df);
77 	double fc2_2 = (fc + df) * (fc + df);
78 
79 	return( dist2 > fc2_1 && dist2 < fc2_2 ? 1.0 : 0.0 );
80 }
81 
82 static void
vips_mask_ideal_ring_class_init(VipsMaskIdealClass * class)83 vips_mask_ideal_ring_class_init( VipsMaskIdealClass *class )
84 {
85 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
86 	VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
87 	VipsMaskClass *mask_class = VIPS_MASK_CLASS( class );
88 
89 	gobject_class->set_property = vips_object_set_property;
90 	gobject_class->get_property = vips_object_get_property;
91 
92 	vobject_class->nickname = "mask_ideal_ring";
93 	vobject_class->description = _( "make an ideal ring filter" );
94 
95 	mask_class->point = vips_mask_ideal_ring_point;
96 
97 	VIPS_ARG_DOUBLE( class, "ringwidth", 20,
98 		_( "Ringwidth" ),
99 		_( "Ringwidth" ),
100 		VIPS_ARGUMENT_REQUIRED_INPUT,
101 		G_STRUCT_OFFSET( VipsMaskIdealRing, ringwidth ),
102 		0.0, 1000000.0, 0.5 );
103 
104 }
105 
106 static void
vips_mask_ideal_ring_init(VipsMaskIdealRing * ideal_ring)107 vips_mask_ideal_ring_init( VipsMaskIdealRing *ideal_ring )
108 {
109 	ideal_ring->ringwidth = 0.5;
110 }
111 
112 /**
113  * vips_mask_ideal_ring:
114  * @out: (out): output image
115  * @width: image size
116  * @height: image size
117  * @frequency_cutoff: threshold at which filter ends
118  * @ringwidth: ring width
119  * @...: %NULL-terminated list of optional named arguments
120  *
121  * Optional arguments:
122  *
123  * * @nodc: don't set the DC pixel
124  * * @reject: invert the filter sense
125  * * @optical: coordinates in optical space
126  * * @uchar: output a uchar image
127  *
128  * Make an ideal ring-pass or ring-reject filter, that is, one with a sharp
129  * ring positioned at @frequency_cutoff of width @width, where
130  * @frequency_cutoff and @width are expressed as the range 0 - 1.
131  *
132  * See also: vips_mask_ideal().
133  *
134  * Returns: 0 on success, -1 on error
135  */
136 int
vips_mask_ideal_ring(VipsImage ** out,int width,int height,double frequency_cutoff,double ringwidth,...)137 vips_mask_ideal_ring( VipsImage **out, int width, int height,
138 	double frequency_cutoff, double ringwidth, ... )
139 {
140 	va_list ap;
141 	int result;
142 
143 	va_start( ap, ringwidth );
144 	result = vips_call_split( "mask_ideal_ring", ap, out, width, height,
145 		frequency_cutoff, ringwidth );
146 	va_end( ap );
147 
148 	return( result );
149 }
150