/src/libvips/libvips/convolution/gaussblur.c
Line | Count | Source (jump to first uncovered line) |
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 <glib/gi18n-lib.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 |
71 | | vips_gaussblur_build(VipsObject *object) |
72 | 0 | { |
73 | 0 | VipsGaussblur *gaussblur = (VipsGaussblur *) object; |
74 | 0 | VipsImage **t = (VipsImage **) vips_object_local_array(object, 2); |
75 | |
|
76 | 0 | if (VIPS_OBJECT_CLASS(vips_gaussblur_parent_class)->build(object)) |
77 | 0 | return -1; |
78 | | |
79 | | /* vips_gaussmat() will make a 1x1 pixel mask for anything smaller than |
80 | | * this. |
81 | | */ |
82 | 0 | if (gaussblur->sigma < 0.2) { |
83 | 0 | if (vips_copy(gaussblur->in, &t[1], NULL)) |
84 | 0 | return -1; |
85 | 0 | } |
86 | 0 | else { |
87 | 0 | if (vips_gaussmat(&t[0], |
88 | 0 | gaussblur->sigma, gaussblur->min_ampl, |
89 | 0 | "separable", TRUE, |
90 | 0 | "precision", gaussblur->precision, |
91 | 0 | NULL)) |
92 | 0 | return -1; |
93 | | |
94 | | #ifdef DEBUG |
95 | | printf("gaussblur: blurring with:\n"); |
96 | | vips_matrixprint(t[0], NULL); |
97 | | #endif /*DEBUG*/ |
98 | | |
99 | 0 | g_info("gaussblur mask width %d", t[0]->Xsize); |
100 | |
|
101 | 0 | if (vips_convsep(gaussblur->in, &t[1], t[0], |
102 | 0 | "precision", gaussblur->precision, |
103 | 0 | NULL)) |
104 | 0 | return -1; |
105 | 0 | } |
106 | | |
107 | 0 | g_object_set(object, "out", vips_image_new(), NULL); |
108 | |
|
109 | 0 | if (vips_image_write(t[1], gaussblur->out)) |
110 | 0 | return -1; |
111 | | |
112 | 0 | return 0; |
113 | 0 | } |
114 | | |
115 | | static void |
116 | | vips_gaussblur_class_init(VipsGaussblurClass *class) |
117 | 1 | { |
118 | 1 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
119 | 1 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
120 | 1 | VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); |
121 | | |
122 | 1 | gobject_class->set_property = vips_object_set_property; |
123 | 1 | gobject_class->get_property = vips_object_get_property; |
124 | | |
125 | 1 | object_class->nickname = "gaussblur"; |
126 | 1 | object_class->description = _("gaussian blur"); |
127 | 1 | object_class->build = vips_gaussblur_build; |
128 | | |
129 | 1 | operation_class->flags = VIPS_OPERATION_SEQUENTIAL; |
130 | | |
131 | 1 | VIPS_ARG_IMAGE(class, "in", 1, |
132 | 1 | _("Input"), |
133 | 1 | _("Input image"), |
134 | 1 | VIPS_ARGUMENT_REQUIRED_INPUT, |
135 | 1 | G_STRUCT_OFFSET(VipsGaussblur, in)); |
136 | | |
137 | 1 | VIPS_ARG_IMAGE(class, "out", 2, |
138 | 1 | _("Output"), |
139 | 1 | _("Output image"), |
140 | 1 | VIPS_ARGUMENT_REQUIRED_OUTPUT, |
141 | 1 | G_STRUCT_OFFSET(VipsGaussblur, out)); |
142 | | |
143 | 1 | VIPS_ARG_DOUBLE(class, "sigma", 3, |
144 | 1 | _("Sigma"), |
145 | 1 | _("Sigma of Gaussian"), |
146 | 1 | VIPS_ARGUMENT_REQUIRED_INPUT, |
147 | 1 | G_STRUCT_OFFSET(VipsGaussblur, sigma), |
148 | 1 | 0.0, 1000, 1.5); |
149 | | |
150 | 1 | VIPS_ARG_DOUBLE(class, "min_ampl", 3, |
151 | 1 | _("Minimum amplitude"), |
152 | 1 | _("Minimum amplitude of Gaussian"), |
153 | 1 | VIPS_ARGUMENT_OPTIONAL_INPUT, |
154 | 1 | G_STRUCT_OFFSET(VipsGaussblur, min_ampl), |
155 | 1 | 0.001, 1.0, 0.2); |
156 | | |
157 | 1 | VIPS_ARG_ENUM(class, "precision", 4, |
158 | 1 | _("Precision"), |
159 | 1 | _("Convolve with this precision"), |
160 | 1 | VIPS_ARGUMENT_OPTIONAL_INPUT, |
161 | 1 | G_STRUCT_OFFSET(VipsGaussblur, precision), |
162 | 1 | VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER); |
163 | 1 | } |
164 | | |
165 | | static void |
166 | | vips_gaussblur_init(VipsGaussblur *gaussblur) |
167 | 0 | { |
168 | 0 | gaussblur->sigma = 1.5; |
169 | 0 | gaussblur->min_ampl = 0.2; |
170 | 0 | gaussblur->precision = VIPS_PRECISION_INTEGER; |
171 | 0 | } |
172 | | |
173 | | /** |
174 | | * vips_gaussblur: (method) |
175 | | * @in: input image |
176 | | * @out: (out): output image |
177 | | * @sigma: how large a mask to use |
178 | | * @...: %NULL-terminated list of optional named arguments |
179 | | * |
180 | | * Optional arguments: |
181 | | * |
182 | | * * @precision: #VipsPrecision, precision for blur, default int |
183 | | * * @min_ampl: minimum amplitude, default 0.2 |
184 | | * |
185 | | * This operator runs vips_gaussmat() and vips_convsep() for you on an image. |
186 | | * Set @min_ampl smaller to generate a larger, more accurate mask. Set @sigma |
187 | | * larger to make the blur more blurry. |
188 | | * |
189 | | * See also: vips_gaussmat(), vips_convsep(). |
190 | | * |
191 | | * Returns: 0 on success, -1 on error. |
192 | | */ |
193 | | int |
194 | | vips_gaussblur(VipsImage *in, VipsImage **out, double sigma, ...) |
195 | 0 | { |
196 | 0 | va_list ap; |
197 | 0 | int result; |
198 | |
|
199 | 0 | va_start(ap, sigma); |
200 | 0 | result = vips_call_split("gaussblur", ap, in, out, sigma); |
201 | 0 | va_end(ap); |
202 | |
|
203 | 0 | return result; |
204 | 0 | } |