5 * Copyright (C) 2009-2014 Cyril Hrubis <metan@ucw.cz>
10 #include <core/GP_Pixmap.h>
11 #include <core/GP_GetPutPixel.h>
12 #include <core/GP_TempAlloc.h>
13 #include <core/GP_Clamp.h>
14 #include <core/GP_Debug.h>
16 #include <filters/GP_Rand.h>
17 #include <filters/GP_GaussianNoise.h>
19 @ for pt in pixeltypes:
20 @ if not pt.is_unknown() and not pt.is_palette():
21 static int gaussian_noise_add_{{ pt.name }}(const gp_pixmap *src,
22 gp_coord x_src, gp_coord y_src,
23 gp_size w_src, gp_size h_src,
25 gp_coord x_dst, gp_coord y_dst,
26 float sigma, float mu,
27 gp_progress_cb *callback)
29 GP_DEBUG(1, "Additive Gaussian noise filter %ux%u sigma=%f mu=%f",
30 w_src, h_src, sigma, mu);
32 @ for c in pt.chanslist:
33 int sigma_{{ c.name }} = {{ c.max }} * sigma;
34 int mu_{{ c.name }} = {{ c.max }} * mu;
37 unsigned int size = w_src + w_src%2;
39 /* Create temporary buffers */
40 gp_temp_alloc_create(temp, sizeof(int) * size * {{ len(pt.chanslist) }});
42 @ for c in pt.chanslist:
43 int *{{ c.name }} = gp_temp_alloc_get(temp, size * sizeof(int));
46 /* Apply the additive noise filter */
49 for (y = 0; y < h_src; y++) {
50 @ for c in pt.chanslist:
51 gp_norm_int({{ c.name }}, size, sigma_{{ c.name }}, mu_{{ c.name }});
54 for (x = 0; x < w_src; x++) {
55 gp_pixel pix = gp_getpixel_raw_{{ pt.pixelsize.suffix }}(src, x + x_src, y + y_src);
57 @ for c in pt.chanslist:
58 {{ c.name }}[x] += GP_PIXEL_GET_{{ c.name }}_{{ pt.name }}(pix);
59 {{ c.name }}[x] = GP_CLAMP({{ c.name }}[x], 0, {{ c.max }});
62 pix = GP_PIXEL_CREATE_{{ pt.name }}({{ arr_to_params(pt.chan_names, '', '[x]') }});
63 gp_putpixel_raw_{{ pt.pixelsize.suffix }}(dst, x + x_dst, y + y_dst, pix);
66 if (gp_progress_cb_report(callback, y, h_src, w_src)) {
67 gp_temp_alloc_free(temp);
73 gp_temp_alloc_free(temp);
74 gp_progress_cb_done(callback);
81 int gp_filter_gaussian_noise_add_raw(const gp_pixmap *src,
82 gp_coord x_src, gp_coord y_src,
83 gp_size w_src, gp_size h_src,
85 gp_coord x_dst, gp_coord y_dst,
86 float sigma, float mu,
87 gp_progress_cb *callback)
89 switch (src->pixel_type) {
90 @ for pt in pixeltypes:
91 @ if not pt.is_unknown() and not pt.is_palette():
92 case GP_PIXEL_{{ pt.name }}:
93 return gaussian_noise_add_{{ pt.name }}(src, x_src,
94 y_src, w_src, h_src, dst, x_dst, y_dst,
104 int gp_filter_gaussian_noise_add_ex(const gp_pixmap *src,
105 gp_coord x_src, gp_coord y_src,
106 gp_size w_src, gp_size h_src,
108 gp_coord x_dst, gp_coord y_dst,
109 float sigma, float mu,
110 gp_progress_cb *callback)
112 GP_CHECK(src->pixel_type == dst->pixel_type);
114 /* Check that destination is large enough */
115 GP_CHECK(x_dst + (gp_coord)w_src <= (gp_coord)dst->w);
116 GP_CHECK(y_dst + (gp_coord)h_src <= (gp_coord)dst->h);
118 /* Source is large enough */
119 GP_CHECK(x_src + w_src <= src->w);
120 GP_CHECK(y_src + h_src <= src->h);
122 return gp_filter_gaussian_noise_add_raw(src, x_src, y_src, w_src, h_src,
124 sigma, mu, callback);
127 gp_pixmap *gp_filter_gaussian_noise_add_ex_alloc(const gp_pixmap *src,
128 gp_coord x_src, gp_coord y_src,
129 gp_size w_src, gp_size h_src,
130 float sigma, float mu,
131 gp_progress_cb *callback)
135 gp_pixmap *dst = gp_pixmap_alloc(w_src, h_src, src->pixel_type);
140 ret = gp_filter_gaussian_noise_add_raw(src, x_src, y_src, w_src, h_src,
141 dst, 0, 0, sigma, mu, callback);