1 /* Gaussian blur.
2 *
3 * 15/11/13
4 * - from vips_sharpen()
5 * 19/11/14
6 * - change parameters to be more imagemagick-like
7 * 21/9/20
8 * - allow sigma zero, meaning no blur
9 * - sigma < 0.2 is just copy
10 */
11
12 /*
13
14 This file is part of VIPS.
15
16 VIPS is free software; you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
29 02110-1301 USA
30
31 */
32
33 /*
34
35 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
36
37 */
38
39 /*
40 #define DEBUG
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif /*HAVE_CONFIG_H*/
46 #include <vips/intl.h>
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <math.h>
51
52 #include <vips/vips.h>
53
54 typedef struct _VipsGaussblur {
55 VipsOperation parent_instance;
56
57 VipsImage *in;
58 VipsImage *out;
59
60 gdouble sigma;
61 gdouble min_ampl;
62 VipsPrecision precision;
63
64 } VipsGaussblur;
65
66 typedef VipsOperationClass VipsGaussblurClass;
67
68 G_DEFINE_TYPE( VipsGaussblur, vips_gaussblur, VIPS_TYPE_OPERATION );
69
70 static int
vips_gaussblur_build(VipsObject * object)71 vips_gaussblur_build( VipsObject *object )
72 {
73 VipsGaussblur *gaussblur = (VipsGaussblur *) object;
74 VipsImage **t = (VipsImage **) vips_object_local_array( object, 2 );
75
76 if( VIPS_OBJECT_CLASS( vips_gaussblur_parent_class )->build( object ) )
77 return( -1 );
78
79 /* vips_gaussmat() will make a 1x1 pixel mask for anything smaller than
80 * this.
81 */
82 if( gaussblur->sigma < 0.2 ) {
83 if( vips_copy( gaussblur->in, &t[1], NULL ) )
84 return( -1 );
85 }
86 else {
87 if( vips_gaussmat( &t[0],
88 gaussblur->sigma, gaussblur->min_ampl,
89 "separable", TRUE,
90 "precision", gaussblur->precision,
91 NULL ) )
92 return( -1 );
93
94 #ifdef DEBUG
95 printf( "gaussblur: blurring with:\n" );
96 vips_matrixprint( t[0], NULL );
97 #endif /*DEBUG*/
98
99 g_info( "gaussblur mask width %d", t[0]->Xsize );
100
101 if( vips_convsep( gaussblur->in, &t[1], t[0],
102 "precision", gaussblur->precision,
103 NULL ) )
104 return( -1 );
105 }
106
107 g_object_set( object, "out", vips_image_new(), NULL );
108
109 if( vips_image_write( t[1], gaussblur->out ) )
110 return( -1 );
111
112 return( 0 );
113 }
114
115 static void
vips_gaussblur_class_init(VipsGaussblurClass * class)116 vips_gaussblur_class_init( VipsGaussblurClass *class )
117 {
118 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
119 VipsObjectClass *object_class = (VipsObjectClass *) class;
120 VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
121
122 gobject_class->set_property = vips_object_set_property;
123 gobject_class->get_property = vips_object_get_property;
124
125 object_class->nickname = "gaussblur";
126 object_class->description = _( "gaussian blur" );
127 object_class->build = vips_gaussblur_build;
128
129 operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
130
131 VIPS_ARG_IMAGE( class, "in", 1,
132 _( "Input" ),
133 _( "Input image" ),
134 VIPS_ARGUMENT_REQUIRED_INPUT,
135 G_STRUCT_OFFSET( VipsGaussblur, in ) );
136
137 VIPS_ARG_IMAGE( class, "out", 2,
138 _( "Output" ),
139 _( "Output image" ),
140 VIPS_ARGUMENT_REQUIRED_OUTPUT,
141 G_STRUCT_OFFSET( VipsGaussblur, out ) );
142
143 VIPS_ARG_DOUBLE( class, "sigma", 3,
144 _( "Sigma" ),
145 _( "Sigma of Gaussian" ),
146 VIPS_ARGUMENT_REQUIRED_INPUT,
147 G_STRUCT_OFFSET( VipsGaussblur, sigma ),
148 0.0, 1000, 1.5 );
149
150 VIPS_ARG_DOUBLE( class, "min_ampl", 3,
151 _( "Minimum amplitude" ),
152 _( "Minimum amplitude of Gaussian" ),
153 VIPS_ARGUMENT_OPTIONAL_INPUT,
154 G_STRUCT_OFFSET( VipsGaussblur, min_ampl ),
155 0.001, 1.0, 0.2 );
156
157 VIPS_ARG_ENUM( class, "precision", 4,
158 _( "Precision" ),
159 _( "Convolve with this precision" ),
160 VIPS_ARGUMENT_OPTIONAL_INPUT,
161 G_STRUCT_OFFSET( VipsGaussblur, precision ),
162 VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
163
164 }
165
166 static void
vips_gaussblur_init(VipsGaussblur * gaussblur)167 vips_gaussblur_init( VipsGaussblur *gaussblur )
168 {
169 gaussblur->sigma = 1.5;
170 gaussblur->min_ampl = 0.2;
171 gaussblur->precision = VIPS_PRECISION_INTEGER;
172 }
173
174 /**
175 * vips_gaussblur: (method)
176 * @in: input image
177 * @out: (out): output image
178 * @sigma: how large a mask to use
179 * @...: %NULL-terminated list of optional named arguments
180 *
181 * Optional arguments:
182 *
183 * * @precision: #VipsPrecision, precision for blur, default int
184 * * @min_ampl: minimum amplitude, default 0.2
185 *
186 * This operator runs vips_gaussmat() and vips_convsep() for you on an image.
187 * Set @min_ampl smaller to generate a larger, more accurate mask. Set @sigma
188 * larger to make the blur more blurry.
189 *
190 * See also: vips_gaussmat(), vips_convsep().
191 *
192 * Returns: 0 on success, -1 on error.
193 */
194 int
vips_gaussblur(VipsImage * in,VipsImage ** out,double sigma,...)195 vips_gaussblur( VipsImage *in, VipsImage **out, double sigma, ... )
196 {
197 va_list ap;
198 int result;
199
200 va_start( ap, sigma );
201 result = vips_call_split( "gaussblur", ap, in, out, sigma );
202 va_end( ap );
203
204 return( result );
205 }
206