1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
23 %% extends "filter.c.t"
25 {% block descr %}Gaussian Noise{% endblock %}
31 #include "core/GP_Context.h"
32 #include "core/GP_GetPutPixel.h"
33 #include "core/GP_TempAlloc.h"
34 //#include "core/GP_Gamma.h"
35 #include "core/GP_Clamp.h"
36 #include "core/GP_Debug.h"
39 #include "GP_GaussianNoise.h"
41 %% for pt in pixeltypes
42 %% if not pt.is_unknown() and not pt.is_palette()
43 static int GP_FilterGaussianNoiseAdd_{{ pt.name }}_Raw(const GP_Context *src,
44 GP_Coord x_src, GP_Coord y_src,
45 GP_Size w_src, GP_Size h_src,
47 GP_Coord x_dst, GP_Coord y_dst,
48 float sigma, float mu,
49 GP_ProgressCallback *callback)
51 GP_DEBUG(1, "Additive Gaussian noise filter %ux%u sigma=%f mu=%f",
52 w_src, h_src, sigma, mu);
54 %% for c in pt.chanslist
55 int sigma_{{ c[0] }} = {{ 2 ** c[2] - 1 }} * sigma;
56 int mu_{{ c[0] }} = {{ 2 ** c[2] - 1 }} * mu;
59 unsigned int size = w_src + w_src%2;
61 /* Create temporary buffers */
62 GP_TempAllocCreate(temp, sizeof(int) * size * {{ len(pt.chanslist) }});
64 %% for c in pt.chanslist
65 int *{{ c[0] }} = GP_TempAllocGet(temp, size * sizeof(int));
68 /* Apply the additive noise filter */
71 for (y = 0; y < h_src; y++) {
72 %% for c in pt.chanslist
73 GP_NormInt({{ c[0] }}, size, sigma_{{ c[0] }}, mu_{{ c[0] }});
76 for (x = 0; x < w_src; x++) {
77 GP_Pixel pix = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, x + x_src, y + y_src);
79 %% for c in pt.chanslist
80 {{ c[0] }}[x] += GP_Pixel_GET_{{ c[0] }}_{{ pt.name }}(pix);
81 {{ c[0] }}[x] = GP_CLAMP({{ c[0] }}[x], 0, {{ 2 ** c[2] - 1 }});
84 pix = GP_Pixel_CREATE_{{ pt.name }}({{ expand_chanslist(pt, "", "[x]") }});
85 GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x + x_dst, y + y_dst, pix);
88 if (GP_ProgressCallbackReport(callback, y, h_src, w_src)) {
89 GP_TempAllocFree(temp);
95 GP_TempAllocFree(temp);
96 GP_ProgressCallbackDone(callback);
104 int GP_FilterGaussianNoiseAdd_Raw(const GP_Context *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_ProgressCallback *callback)
112 switch (src->pixel_type) {
113 %% for pt in pixeltypes
114 %% if not pt.is_unknown() and not pt.is_palette()
115 case GP_PIXEL_{{ pt.name }}:
116 return GP_FilterGaussianNoiseAdd_{{ pt.name }}_Raw(src, x_src,
117 y_src, w_src, h_src, dst, x_dst, y_dst,
118 sigma, mu, callback);
128 int GP_FilterGaussianNoiseAddEx(const GP_Context *src,
129 GP_Coord x_src, GP_Coord y_src,
130 GP_Size w_src, GP_Size h_src,
132 GP_Coord x_dst, GP_Coord y_dst,
133 float sigma, float mu,
134 GP_ProgressCallback *callback)
136 GP_CHECK(src->pixel_type == dst->pixel_type);
138 /* Check that destination is large enough */
139 GP_CHECK(x_dst + (GP_Coord)w_src <= (GP_Coord)dst->w);
140 GP_CHECK(y_dst + (GP_Coord)h_src <= (GP_Coord)dst->h);
142 /* Source is large enough */
143 GP_CHECK(x_src + w_src <= src->w);
144 GP_CHECK(y_src + h_src <= src->h);
146 return GP_FilterGaussianNoiseAdd_Raw(src, x_src, y_src, w_src, h_src,
148 sigma, mu, callback);
151 GP_Context *GP_FilterGaussianNoiseAddExAlloc(const GP_Context *src,
152 GP_Coord x_src, GP_Coord y_src,
153 GP_Size w_src, GP_Size h_src,
154 float sigma, float mu,
155 GP_ProgressCallback *callback)
159 GP_Context *dst = GP_ContextAlloc(w_src, h_src, src->pixel_type);
164 ret = GP_FilterGaussianNoiseAdd_Raw(src, x_src, y_src, w_src, h_src,
165 dst, 0, 0, sigma, mu, callback);