r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / denoisevideo / denoisevideo.C
blobd0d614171219928047a44a470620ca9c6e3fb44e
1 #include "clip.h"
2 #include "defaults.h"
3 #include "denoisevideo.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "keyframe.h"
7 #include "picon_png.h"
8 #include "vframe.h"
14 #include <stdint.h>
15 #include <string.h>
17 #include <libintl.h>
18 #define _(String) gettext(String)
19 #define gettext_noop(String) String
20 #define N_(String) gettext_noop (String)
24 REGISTER_PLUGIN(DenoiseVideo)
31 DenoiseVideoConfig::DenoiseVideoConfig()
33         frames = 2;
34         threshold = 0.1;
35         do_r = 1;
36         do_g = 1;
37         do_b = 1;
38         do_a = 1;
41 int DenoiseVideoConfig::equivalent(DenoiseVideoConfig &that)
43         return frames == that.frames && 
44                 EQUIV(threshold, that.threshold) &&
45                 do_r == that.do_r &&
46                 do_g == that.do_g &&
47                 do_b == that.do_b &&
48                 do_a == that.do_a;
51 void DenoiseVideoConfig::copy_from(DenoiseVideoConfig &that)
53         frames = that.frames;
54         threshold = that.threshold;
55         do_r = that.do_r;
56         do_g = that.do_g;
57         do_b = that.do_b;
58         do_a = that.do_a;
61 void DenoiseVideoConfig::interpolate(DenoiseVideoConfig &prev, 
62         DenoiseVideoConfig &next, 
63         long prev_frame, 
64         long next_frame, 
65         long current_frame)
67         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
68         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
70         this->frames = (int)(prev.frames * prev_scale + next.frames * next_scale);
71         this->threshold = prev.threshold * prev_scale + next.threshold * next_scale;
72         do_r = prev.do_r;
73         do_g = prev.do_g;
74         do_b = prev.do_b;
75         do_a = prev.do_a;
83 DenoiseVideoFrames::DenoiseVideoFrames(DenoiseVideo *plugin, int x, int y)
84  : BC_ISlider(x, 
85         y, 
86         0,
87         190, 
88         200, 
89         1, 
90         256, 
91         plugin->config.frames)
93         this->plugin = plugin;
96 int DenoiseVideoFrames::handle_event()
98         int result = get_value();
99         if(result < 1 || result > 256) result = 256;
100         plugin->config.frames = result;
101         plugin->send_configure_change();
102         return 1;
111 DenoiseVideoThreshold::DenoiseVideoThreshold(DenoiseVideo *plugin, int x, int y)
112  : BC_TextBox(x, y, 100, 1, plugin->config.threshold)
114         this->plugin = plugin;
117 int DenoiseVideoThreshold::handle_event()
119         plugin->config.threshold = atof(get_text());
120         plugin->send_configure_change();
121         return 1;
128 DenoiseVideoToggle::DenoiseVideoToggle(DenoiseVideo *plugin, 
129         DenoiseVideoWindow *gui, 
130         int x, 
131         int y, 
132         int *output,
133         char *text)
134  : BC_CheckBox(x, y, *output, text)
136         this->plugin = plugin;
137         this->output = output;
140 int DenoiseVideoToggle::handle_event()
142         *output = get_value();
143         plugin->send_configure_change();
155 DenoiseVideoWindow::DenoiseVideoWindow(DenoiseVideo *plugin, int x, int y)
156  : BC_Window(plugin->gui_string, 
157         x, 
158         y, 
159         210, 
160         240, 
161         200, 
162         240, 
163         0, 
164         0,
165         1)
167         this->plugin = plugin;
171 void DenoiseVideoWindow::create_objects()
173         int x = 10, y = 10;
174         add_subwindow(new BC_Title(x, y, _("Frames to accumulate:")));
175         y += 20;
176         add_subwindow(frames = new DenoiseVideoFrames(plugin, x, y));
177         y += 30;
178         add_subwindow(new BC_Title(x, y, _("Threshold:")));
179         y += 20;
180         add_subwindow(threshold = new DenoiseVideoThreshold(plugin, x, y));
181         y += 40;
182         add_subwindow(do_r = new DenoiseVideoToggle(plugin, this, x, y, &plugin->config.do_r, _("Red")));
183         y += 30;
184         add_subwindow(do_g = new DenoiseVideoToggle(plugin, this, x, y, &plugin->config.do_g, _("Green")));
185         y += 30;
186         add_subwindow(do_b = new DenoiseVideoToggle(plugin, this, x, y, &plugin->config.do_b, _("Blue")));
187         y += 30;
188         add_subwindow(do_a = new DenoiseVideoToggle(plugin, this, x, y, &plugin->config.do_a, _("Alpha")));
189         show_window();
190         flush();
193 int DenoiseVideoWindow::close_event()
195         set_done(1);
196         return 1;
204 PLUGIN_THREAD_OBJECT(DenoiseVideo, DenoiseVideoThread, DenoiseVideoWindow)
216 DenoiseVideo::DenoiseVideo(PluginServer *server)
217  : PluginVClient(server)
219         PLUGIN_CONSTRUCTOR_MACRO
220         accumulation = 0;
224 DenoiseVideo::~DenoiseVideo()
226         PLUGIN_DESTRUCTOR_MACRO
228         if(accumulation) delete [] accumulation;
231 int DenoiseVideo::process_realtime(VFrame *input, VFrame *output)
233         load_configuration();
235         int h = input->get_h();
236         int w = input->get_w();
237         int color_model = input->get_color_model();
239         if(!accumulation)
240         {
241                 accumulation = new float[w * h * cmodel_components(color_model)];
242                 bzero(accumulation, sizeof(float) * w * h * cmodel_components(color_model));
243         }
245         float *accumulation_ptr = accumulation;
246         float opacity = (float)1.0 / config.frames;
247         float transparency = 1 - opacity;
248         float threshold = (float)config.threshold * 
249                 cmodel_calculate_max(color_model);
250         int do_it[4] = { config.do_r, config.do_g, config.do_b, config.do_a };
252 #define DENOISE_MACRO(type, components, max) \
253 { \
254         for(int i = 0; i < h; i++) \
255         { \
256                 type *output_row = (type*)output->get_rows()[i]; \
257                 type *input_row = (type*)input->get_rows()[i]; \
259                 for(int k = 0; k < w * components; k++) \
260                 { \
261                         if(do_it[k % components]) \
262                         { \
263                                 float input_pixel = *input_row; \
264                                 (*accumulation_ptr) = \
265                                         transparency * (*accumulation_ptr) + \
266                                         opacity * input_pixel; \
268                                 if(fabs((*accumulation_ptr) - input_pixel) > threshold) \
269                                 { \
270                                         (*accumulation_ptr) = input_pixel; \
271                                         *output_row = (type)(*accumulation_ptr); \
272                                 } \
273                                 else \
274                                         *output_row = (type)CLIP((*accumulation_ptr), 0, max); \
275                         } \
276                         else \
277                         { \
278                                 *output_row = *input_row; \
279                         } \
281                         output_row++; \
282                         input_row++; \
283                         accumulation_ptr++; \
284                 } \
285         } \
293         switch(color_model)
294         {
295                 case BC_RGB888:
296                 case BC_YUV888:
297                         DENOISE_MACRO(unsigned char, 3, 0xff);
298                         break;
300                 case BC_RGBA8888:
301                 case BC_YUVA8888:
302                         DENOISE_MACRO(unsigned char, 4, 0xff);
303                         break;
305                 case BC_RGB161616:
306                 case BC_YUV161616:
307                         DENOISE_MACRO(uint16_t, 3, 0xffff);
308                         break;
310                 case BC_RGBA16161616:
311                 case BC_YUVA16161616:
312                         DENOISE_MACRO(uint16_t, 4, 0xffff);
313                         break;
314         }
317 int DenoiseVideo::is_realtime()
319         return 1;
322 char* DenoiseVideo::plugin_title()
324         return _("Denoise video");
327 NEW_PICON_MACRO(DenoiseVideo)
329 SHOW_GUI_MACRO(DenoiseVideo, DenoiseVideoThread)
331 RAISE_WINDOW_MACRO(DenoiseVideo)
333 SET_STRING_MACRO(DenoiseVideo);
335 LOAD_CONFIGURATION_MACRO(DenoiseVideo, DenoiseVideoConfig)
337 void DenoiseVideo::update_gui()
339         if(thread)
340         {
341                 load_configuration();
342                 thread->window->lock_window();
343                 thread->window->frames->update(config.frames);
344                 thread->window->threshold->update(config.threshold);
345                 thread->window->unlock_window();
346         }
351 int DenoiseVideo::load_defaults()
353         char directory[BCTEXTLEN];
354 // set the default directory
355         sprintf(directory, "%sdenoisevideo.rc", BCASTDIR);
357 // load the defaults
358         defaults = new Defaults(directory);
359         defaults->load();
361         config.frames = defaults->get("FRAMES", config.frames);
362         config.threshold = defaults->get("THRESHOLD", config.threshold);
363         config.do_r = defaults->get("DO_R", config.do_r);
364         config.do_g = defaults->get("DO_G", config.do_g);
365         config.do_b = defaults->get("DO_B", config.do_b);
366         config.do_a = defaults->get("DO_A", config.do_a);
367         return 0;
370 int DenoiseVideo::save_defaults()
372         defaults->update("THRESHOLD", config.threshold);
373         defaults->update("FRAMES", config.frames);
374         defaults->update("DO_R", config.do_r);
375         defaults->update("DO_G", config.do_g);
376         defaults->update("DO_B", config.do_b);
377         defaults->update("DO_A", config.do_a);
378         defaults->save();
379         return 0;
382 void DenoiseVideo::save_data(KeyFrame *keyframe)
384         FileXML output;
386 // cause data to be stored directly in text
387         output.set_shared_string(keyframe->data, MESSAGESIZE);
388         output.tag.set_title("DENOISE_VIDEO");
389         output.tag.set_property("FRAMES", config.frames);
390         output.tag.set_property("THRESHOLD", config.threshold);
391         output.tag.set_property("DO_R", config.do_r);
392         output.tag.set_property("DO_G", config.do_g);
393         output.tag.set_property("DO_B", config.do_b);
394         output.tag.set_property("DO_A", config.do_a);
395         output.append_tag();
396         output.terminate_string();
399 void DenoiseVideo::read_data(KeyFrame *keyframe)
401         FileXML input;
403         input.set_shared_string(keyframe->data, strlen(keyframe->data));
405         int result = 0;
407         while(!input.read_tag())
408         {
409                 if(input.tag.title_is("DENOISE_VIDEO"))
410                 {
411                         config.frames = input.tag.get_property("FRAMES", config.frames);
412                         config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
413                         config.do_r = input.tag.get_property("DO_R", config.do_r);
414                         config.do_g = input.tag.get_property("DO_G", config.do_g);
415                         config.do_b = input.tag.get_property("DO_B", config.do_b);
416                         config.do_a = input.tag.get_property("DO_A", config.do_a);
417                 }
418         }