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