1 /*
2 * This file is a modified port of RGB Noise plug-in from Gimp.
3 * It contains code from plug-ins/common/noise-rgb.c, see that for copyrights.
4 *
5 * rgbnoise.c
6 * Copyright 2012 Janne Liljeblad
7 *
8 * This file is a Frei0r plugin.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 */
24
25
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <math.h>
29 #include "frei0r.h"
30 #include "frei0r_math.h"
31
32 static int MY_MAX_RAND = 32767;// I assume RAND_MAX to be at least this big.
33 static double gaussian_lookup[32767];
34 static int TABLE_INITED = 0;
35 static int next_gaussian_index = 0;
36 static int last_in_range = 32766;
37
38 typedef struct rgbnoise_instance
39 {
40 unsigned int width;
41 unsigned int height;
42 double noise;
43 } rgbnoise_instance_t;
44
45
46
f0r_deinit()47 void f0r_deinit()
48 {}
49
f0r_get_plugin_info(f0r_plugin_info_t * rgbnoiseInfo)50 void f0r_get_plugin_info(f0r_plugin_info_t* rgbnoiseInfo)
51 {
52 rgbnoiseInfo->name = "rgbnoise";
53 rgbnoiseInfo->author = "Janne Liljeblad";
54 rgbnoiseInfo->plugin_type = F0R_PLUGIN_TYPE_FILTER;
55 rgbnoiseInfo->color_model = F0R_COLOR_MODEL_RGBA8888;
56 rgbnoiseInfo->frei0r_version = FREI0R_MAJOR_VERSION;
57 rgbnoiseInfo->major_version = 0;
58 rgbnoiseInfo->minor_version = 9;
59 rgbnoiseInfo->num_params = 1;
60 rgbnoiseInfo->explanation = "Adds RGB noise to image.";
61 }
62
f0r_get_param_info(f0r_param_info_t * info,int param_index)63 void f0r_get_param_info(f0r_param_info_t* info, int param_index)
64 {
65 switch ( param_index ) {
66 case 0:
67 info->name = "noise";
68 info->type = F0R_PARAM_DOUBLE;
69 info->explanation = "Amount of noise added";
70 break;
71 }
72 }
73
f0r_construct(unsigned int width,unsigned int height)74 f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
75 {
76 rgbnoise_instance_t* inst = (rgbnoise_instance_t*)calloc(1, sizeof(*inst));
77 inst->width = width;
78 inst->height = height;
79 inst->noise = 0.2;
80 return (f0r_instance_t)inst;
81 }
82
f0r_destruct(f0r_instance_t instance)83 void f0r_destruct(f0r_instance_t instance)
84 {
85 free(instance);
86 }
87
f0r_set_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)88 void f0r_set_param_value(f0r_instance_t instance,
89 f0r_param_t param, int param_index)
90 {
91 rgbnoise_instance_t* inst = (rgbnoise_instance_t*)instance;
92 switch (param_index)
93 {
94 case 0:
95 inst->noise = *((double*)param);
96 break;
97 }
98 }
99
f0r_get_param_value(f0r_instance_t instance,f0r_param_t param,int param_index)100 void f0r_get_param_value(f0r_instance_t instance,
101 f0r_param_t param, int param_index)
102 {
103 rgbnoise_instance_t* inst = (rgbnoise_instance_t*)instance;
104 switch (param_index)
105 {
106 case 0:
107 *((double*)param) = inst->noise;
108 break;
109 }
110 }
111
112 //-------------------------------------------------------- filter methods
nextDouble()113 static inline double nextDouble()
114 {
115 double val = ((double) rand()) / ((double) RAND_MAX);
116 return val;
117 }
118
gauss()119 static inline double gauss()
120 {
121 double u, v, x;
122 do
123 {
124 v = nextDouble();
125
126 do u = nextDouble();
127 while (u == 0);
128
129 x = 1.71552776992141359295 * (v - 0.5) / u;
130 }
131 while ( x * x > -4.0 * log(u) );
132
133 return x;
134 }
135
create_new_lookup_range()136 static void create_new_lookup_range()
137 {
138 int first, last, tmp;
139 first = rand() % (MY_MAX_RAND - 1);
140 last = rand() % (MY_MAX_RAND - 1);
141 if (first > last)
142 {
143 tmp = last;
144 last = first;
145 first = tmp;
146 }
147 next_gaussian_index = first;
148 last_in_range = last;
149 }
150
next_gauss()151 static inline double next_gauss()
152 {
153 next_gaussian_index++;
154 if (next_gaussian_index >= last_in_range)
155 {
156 create_new_lookup_range();
157 }
158 return gaussian_lookup[next_gaussian_index];
159 }
160
addNoise(int sample,double noise)161 static inline int addNoise(int sample, double noise)
162 {
163 int byteNoise = 0;
164 int noiseSample = 0;
165
166 byteNoise = (int) (noise * next_gauss());
167 noiseSample = sample + byteNoise;
168 noiseSample = CLAMP(noiseSample, 0, 255);
169 return noiseSample;
170 }
171
f0r_init()172 int f0r_init()
173 {
174 if (TABLE_INITED == 0)
175 {
176 int i;
177 for( i = 0; i < MY_MAX_RAND; i++)
178 {
179 gaussian_lookup[i] = gauss() * 127.0;
180 }
181 TABLE_INITED = 1;
182 }
183 return 1;
184 }
185
rgb_noise(f0r_instance_t instance,double time,const uint32_t * inframe,uint32_t * outframe)186 void rgb_noise(f0r_instance_t instance, double time,
187 const uint32_t* inframe, uint32_t* outframe)
188 {
189 rgbnoise_instance_t* inst = (rgbnoise_instance_t*)instance;
190 unsigned int len = inst->width * inst->height;
191
192 unsigned char* dst = (unsigned char*)outframe;
193 const unsigned char* src = (unsigned char*)inframe;
194
195 int sample;
196 double noise = inst->noise;
197 while (len--)
198 {
199 sample = *src++;
200 *dst++ = addNoise(sample, noise);
201 sample = *src++;
202 *dst++ = addNoise(sample, noise);
203 sample = *src++;
204 *dst++ = addNoise(sample, noise);
205 *dst++ = *src++;
206 }
207 }
208
209 //---------------------------------------------------- update
f0r_update(f0r_instance_t instance,double time,const uint32_t * inframe,uint32_t * outframe)210 void f0r_update(f0r_instance_t instance, double time,
211 const uint32_t* inframe, uint32_t* outframe)
212 {
213 assert(instance);
214 rgb_noise(instance, time, inframe, outframe);
215 }
216
217