filters: GaussianNoise: Set errno.
[gfxprim/pasky.git] / libs / filters / GP_GaussianNoise.gen.c.t
blob939533b41dac7267f1497ce9a1cd16a146026091
1 /*****************************************************************************
2  * This file is part of gfxprim library.                                     *
3  *                                                                           *
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.        *
8  *                                                                           *
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.                           *
13  *                                                                           *
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                                               *
18  *                                                                           *
19  * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz>                       *
20  *                                                                           *
21  *****************************************************************************/
23 %% extends "filter.c.t"
25 {% block descr %}Gaussian Noise{% endblock %}
27 %% block body
29 #include <errno.h>
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"
38 #include "GP_Rand.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,
46                                 GP_Context *dst,
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;
57         %% endfor
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));
66         %% endfor
68         /* Apply the additive noise filter */
69         unsigned int x, y;
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] }});
74                 %% endfor
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 }});
82                         %% endfor
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);
86                 }
88                 if (GP_ProgressCallbackReport(callback, y, h_src, w_src)) {
89                         GP_TempAllocFree(temp);
90                         errno = ECANCELED;
91                         return 1;
92                 }
93         }
95         GP_TempAllocFree(temp);
96         GP_ProgressCallbackDone(callback);
98         return 0;
101 %% endif
102 %% endfor
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,
107                                   GP_Context *dst,
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);
119         break;
120         %% endif
121         %% endfor
122         default:
123                 errno = EINVAL;
124                 return -1;
125         }
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,
131                                 GP_Context *dst,
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,
147                                              dst, x_dst, y_dst,
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)
157         int ret, err;
159         GP_Context *dst = GP_ContextAlloc(w_src, h_src, src->pixel_type);
161         if (dst == NULL)
162                 return NULL;
164         ret = GP_FilterGaussianNoiseAdd_Raw(src, x_src, y_src, w_src, h_src,
165                                             dst, 0, 0, sigma, mu, callback);
167         if (ret) {
168                 err = errno;
169                 GP_ContextFree(dst);
170                 errno = err;
171                 return NULL;
172         }
174         return dst;
177 %% endblock body