loaders: JPG: Fix bussy loop on corrupted file.
[gfxprim.git] / libs / filters / GP_GaussianNoise.gen.c.t
blob770610fb1e7190ec58fb74737de20f37dee4d546
1 @ include source.t
2 /*
3  * Gaussian Noise
4  *
5  * Copyright (C) 2009-2014 Cyril Hrubis <metan@ucw.cz>
6  */
8 #include <errno.h>
10 #include "core/GP_Pixmap.h"
11 #include "core/GP_GetPutPixel.h"
12 #include "core/GP_TempAlloc.h"
13 //#include "core/GP_Gamma.h"
14 #include "core/GP_Clamp.h"
15 #include "core/GP_Debug.h"
17 #include "GP_Rand.h"
18 #include "GP_GaussianNoise.h"
20 @ for pt in pixeltypes:
21 @     if not pt.is_unknown() and not pt.is_palette():
22 static int GP_FilterGaussianNoiseAdd_{{ pt.name }}_Raw(const GP_Pixmap *src,
23                                 GP_Coord x_src, GP_Coord y_src,
24                                 GP_Size w_src, GP_Size h_src,
25                                 GP_Pixmap *dst,
26                                 GP_Coord x_dst, GP_Coord y_dst,
27                                 float sigma, float mu,
28                                 GP_ProgressCallback *callback)
30         GP_DEBUG(1, "Additive Gaussian noise filter %ux%u sigma=%f mu=%f",
31                  w_src, h_src, sigma, mu);
33 @         for c in pt.chanslist:
34         int sigma_{{ c.name }} = {{ c.max }} * sigma;
35         int mu_{{ c.name }} = {{ c.max }} * mu;
36 @         end
38         unsigned int size = w_src + w_src%2;
40         /* Create temporary buffers */
41         GP_TempAllocCreate(temp, sizeof(int) * size * {{ len(pt.chanslist) }});
43 @         for c in pt.chanslist:
44         int *{{ c.name }} = GP_TempAllocGet(temp, size * sizeof(int));
45 @         end
47         /* Apply the additive noise filter */
48         unsigned int x, y;
50         for (y = 0; y < h_src; y++) {
51 @         for c in pt.chanslist:
52                 GP_NormInt({{ c.name }}, size, sigma_{{ c.name }}, mu_{{ c.name }});
53 @         end
55                 for (x = 0; x < w_src; x++) {
56                         GP_Pixel pix = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, x + x_src, y + y_src);
58 @         for c in pt.chanslist:
59                         {{ c.name }}[x] += GP_Pixel_GET_{{ c.name }}_{{ pt.name }}(pix);
60                         {{ c.name }}[x] = GP_CLAMP({{ c.name }}[x], 0, {{ c.max }});
61 @         end
63                         pix = GP_Pixel_CREATE_{{ pt.name }}({{ arr_to_params(pt.chan_names, '', '[x]') }});
64                         GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x + x_dst, y + y_dst, pix);
65                 }
67                 if (GP_ProgressCallbackReport(callback, y, h_src, w_src)) {
68                         GP_TempAllocFree(temp);
69                         errno = ECANCELED;
70                         return 1;
71                 }
72         }
74         GP_TempAllocFree(temp);
75         GP_ProgressCallbackDone(callback);
77         return 0;
80 @ end
82 int GP_FilterGaussianNoiseAdd_Raw(const GP_Pixmap *src,
83                                   GP_Coord x_src, GP_Coord y_src,
84                                   GP_Size w_src, GP_Size h_src,
85                                   GP_Pixmap *dst,
86                                   GP_Coord x_dst, GP_Coord y_dst,
87                                   float sigma, float mu,
88                                   GP_ProgressCallback *callback)
90         switch (src->pixel_type) {
91 @ for pt in pixeltypes:
92 @     if not pt.is_unknown() and not pt.is_palette():
93         case GP_PIXEL_{{ pt.name }}:
94                 return GP_FilterGaussianNoiseAdd_{{ pt.name }}_Raw(src, x_src,
95                                 y_src, w_src, h_src, dst, x_dst, y_dst,
96                                 sigma, mu, callback);
97         break;
98 @ end
99         default:
100                 errno = EINVAL;
101                 return -1;
102         }
105 int GP_FilterGaussianNoiseAddEx(const GP_Pixmap *src,
106                                 GP_Coord x_src, GP_Coord y_src,
107                                 GP_Size w_src, GP_Size h_src,
108                                 GP_Pixmap *dst,
109                                 GP_Coord x_dst, GP_Coord y_dst,
110                                 float sigma, float mu,
111                                 GP_ProgressCallback *callback)
113         GP_CHECK(src->pixel_type == dst->pixel_type);
115         /* Check that destination is large enough */
116         GP_CHECK(x_dst + (GP_Coord)w_src <= (GP_Coord)dst->w);
117         GP_CHECK(y_dst + (GP_Coord)h_src <= (GP_Coord)dst->h);
119         /* Source is large enough */
120         GP_CHECK(x_src + w_src <= src->w);
121         GP_CHECK(y_src + h_src <= src->h);
123         return GP_FilterGaussianNoiseAdd_Raw(src, x_src, y_src, w_src, h_src,
124                                              dst, x_dst, y_dst,
125                                              sigma, mu, callback);
128 GP_Pixmap *GP_FilterGaussianNoiseAddExAlloc(const GP_Pixmap *src,
129                                              GP_Coord x_src, GP_Coord y_src,
130                                              GP_Size w_src, GP_Size h_src,
131                                              float sigma, float mu,
132                                              GP_ProgressCallback *callback)
134         int ret, err;
136         GP_Pixmap *dst = GP_PixmapAlloc(w_src, h_src, src->pixel_type);
138         if (dst == NULL)
139                 return NULL;
141         ret = GP_FilterGaussianNoiseAdd_Raw(src, x_src, y_src, w_src, h_src,
142                                             dst, 0, 0, sigma, mu, callback);
144         if (ret) {
145                 err = errno;
146                 GP_PixmapFree(dst);
147                 errno = err;
148                 return NULL;
149         }
151         return dst;