Coverage Report

Created: 2025-01-28 06:34

/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
}