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