initial commit
[goodguy/history.git] / cinelerra-5.0 / plugins / denoisemjpeg / denoisemjpeg.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "clip.h"
23 #include "bchash.h"
24 #include "denoisemjpeg.h"
25 #include "filexml.h"
26 #include "guicast.h"
27 #include "keyframe.h"
28 #include "vframe.h"
29
30
31 #include <libintl.h>
32 #define _(String) gettext(String)
33 #define gettext_noop(String) String
34 #define N_(String) gettext_noop (String)
35
36
37
38
39 #include <stdint.h>
40 #include <string.h>
41
42
43
44 REGISTER_PLUGIN(DenoiseMJPEG)
45
46
47
48 DenoiseMJPEGConfig::DenoiseMJPEGConfig()
49 {
50         radius = 8;
51         threshold = 5;
52         threshold2 = 4;
53         sharpness = 125;
54         lcontrast = 100;
55         ccontrast = 100;
56         deinterlace = 0;
57         mode = 0;
58         delay = 3;
59 }
60
61 int DenoiseMJPEGConfig::equivalent(DenoiseMJPEGConfig &that)
62 {
63         return 
64                 that.radius == radius && 
65                 that.threshold == threshold && 
66                 that.threshold2 == threshold2 && 
67                 that.sharpness == sharpness && 
68                 that.lcontrast == lcontrast && 
69                 that.ccontrast == ccontrast && 
70                 that.deinterlace == deinterlace && 
71                 that.mode == mode && 
72                 that.delay == delay;
73 }
74
75 void DenoiseMJPEGConfig::copy_from(DenoiseMJPEGConfig &that)
76 {
77         radius = that.radius;
78         threshold = that.threshold;
79         threshold2 = that.threshold2;
80         sharpness = that.sharpness;
81         lcontrast = that.lcontrast;
82         ccontrast = that.ccontrast;
83         deinterlace = that.deinterlace;
84         mode = that.mode;
85         delay = that.delay;
86 }
87
88 void DenoiseMJPEGConfig::interpolate(DenoiseMJPEGConfig &prev, 
89         DenoiseMJPEGConfig &next, 
90         long prev_frame, 
91         long next_frame, 
92         long current_frame)
93 {
94         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
95         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
96
97         this->radius = (int)(prev.radius * prev_scale + next.radius * next_scale);
98         this->threshold = (int)(prev.threshold * prev_scale + next.threshold * next_scale);
99         this->threshold2 = (int)(prev.threshold2 * prev_scale + next.threshold2 * next_scale);
100         this->sharpness = (int)(prev.sharpness * prev_scale + next.sharpness * next_scale);
101         this->lcontrast = (int)(prev.lcontrast * prev_scale + next.lcontrast * next_scale);
102         this->ccontrast = (int)(prev.ccontrast * prev_scale + next.ccontrast * next_scale);
103         this->deinterlace = prev.deinterlace;
104         this->mode = prev.mode;
105         this->delay = (int)(prev.delay * prev_scale + next.delay * next_scale);
106 }
107
108
109
110
111
112
113 DenoiseMJPEGRadius::DenoiseMJPEGRadius(DenoiseMJPEG *plugin, int x, int y)
114  : BC_IPot(x, 
115         y, 
116         plugin->config.radius,
117         8,
118         24)
119 {
120         this->plugin = plugin;
121 }
122
123 int DenoiseMJPEGRadius::handle_event()
124 {
125         int result = get_value();
126         plugin->config.radius = result;
127         plugin->send_configure_change();
128         return 1;
129 }
130
131
132
133
134
135
136 DenoiseMJPEGThresh::DenoiseMJPEGThresh(DenoiseMJPEG *plugin, int x, int y)
137  : BC_IPot(x, 
138         y, 
139         plugin->config.threshold,
140         0,
141         255)
142 {
143         this->plugin = plugin;
144 }
145
146 int DenoiseMJPEGThresh::handle_event()
147 {
148         int result = get_value();
149         plugin->config.threshold = result;
150         plugin->send_configure_change();
151         return 1;
152 }
153
154
155
156
157
158
159 DenoiseMJPEGThresh2::DenoiseMJPEGThresh2(DenoiseMJPEG *plugin, int x, int y)
160  : BC_IPot(x, 
161         y, 
162         plugin->config.threshold2,
163         0,
164         255)
165 {
166         this->plugin = plugin;
167 }
168
169 int DenoiseMJPEGThresh2::handle_event()
170 {
171         int result = get_value();
172         plugin->config.threshold2 = result;
173         plugin->send_configure_change();
174         return 1;
175 }
176
177
178
179
180
181
182 DenoiseMJPEGSharp::DenoiseMJPEGSharp(DenoiseMJPEG *plugin, int x, int y)
183  : BC_IPot(x, 
184         y, 
185         plugin->config.sharpness,
186         0,
187         255)
188 {
189         this->plugin = plugin;
190 }
191
192 int DenoiseMJPEGSharp::handle_event()
193 {
194         int result = get_value();
195         plugin->config.sharpness = result;
196         plugin->send_configure_change();
197         return 1;
198 }
199
200
201
202
203
204
205 DenoiseMJPEGLContrast::DenoiseMJPEGLContrast(DenoiseMJPEG *plugin, int x, int y)
206  : BC_IPot(x, 
207         y, 
208         plugin->config.lcontrast,
209         0,
210         255)
211 {
212         this->plugin = plugin;
213 }
214
215 int DenoiseMJPEGLContrast::handle_event()
216 {
217         int result = get_value();
218         plugin->config.lcontrast = result;
219         plugin->send_configure_change();
220         return 1;
221 }
222
223
224
225
226
227
228 DenoiseMJPEGCContrast::DenoiseMJPEGCContrast(DenoiseMJPEG *plugin, int x, int y)
229  : BC_IPot(x, 
230         y, 
231         plugin->config.ccontrast,
232         0,
233         255)
234 {
235         this->plugin = plugin;
236 }
237
238 int DenoiseMJPEGCContrast::handle_event()
239 {
240         int result = get_value();
241         plugin->config.ccontrast = result;
242         plugin->send_configure_change();
243         return 1;
244 }
245
246
247
248
249
250
251 DenoiseMJPEGDeinterlace::DenoiseMJPEGDeinterlace(DenoiseMJPEG *plugin, int x, int y)
252  : BC_CheckBox(x, 
253         y, 
254         plugin->config.deinterlace,
255         _("Deinterlace"))
256 {
257         this->plugin = plugin;
258 }
259
260 int DenoiseMJPEGDeinterlace::handle_event()
261 {
262         int result = get_value();
263         plugin->config.deinterlace = result;
264         plugin->send_configure_change();
265         return 1;
266 }
267
268
269
270
271
272
273 DenoiseMJPEGModeProgressive::DenoiseMJPEGModeProgressive(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
274  : BC_Radial(x, 
275         y, 
276         plugin->config.mode == 0,
277         _("Progressive"))
278 {
279         this->plugin = plugin;
280         this->gui = gui;
281 }
282
283 int DenoiseMJPEGModeProgressive::handle_event()
284 {
285         int result = get_value();
286         if(result) gui->update_mode(0);
287         plugin->send_configure_change();
288         return 1;
289 }
290
291
292 DenoiseMJPEGModeInterlaced::DenoiseMJPEGModeInterlaced(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
293  : BC_Radial(x, 
294         y, 
295         plugin->config.mode == 1,
296         _("Interlaced"))
297 {
298         this->plugin = plugin;
299         this->gui = gui;
300 }
301
302 int DenoiseMJPEGModeInterlaced::handle_event()
303 {
304         int result = get_value();
305         if(result) gui->update_mode(1);
306         plugin->send_configure_change();
307         return 1;
308 }
309
310
311 DenoiseMJPEGModeFast::DenoiseMJPEGModeFast(DenoiseMJPEG *plugin, DenoiseMJPEGWindow *gui, int x, int y)
312  : BC_Radial(x, 
313         y, 
314         plugin->config.mode == 2,
315         _("Fast"))
316 {
317         this->plugin = plugin;
318         this->gui = gui;
319 }
320
321 int DenoiseMJPEGModeFast::handle_event()
322 {
323         int result = get_value();
324         if(result) gui->update_mode(2);
325         plugin->send_configure_change();
326         return 1;
327 }
328
329
330
331
332
333
334 DenoiseMJPEGDelay::DenoiseMJPEGDelay(DenoiseMJPEG *plugin, int x, int y)
335  : BC_IPot(x, 
336         y, 
337         plugin->config.delay,
338         1,
339         8)
340 {
341         this->plugin = plugin;
342 }
343
344 int DenoiseMJPEGDelay::handle_event()
345 {
346         int result = get_value();
347         plugin->config.delay = result;
348         plugin->send_configure_change();
349         return 1;
350 }
351
352
353
354
355
356
357
358
359
360
361
362 DenoiseMJPEGWindow::DenoiseMJPEGWindow(DenoiseMJPEG *plugin)
363  : PluginClientWindow(plugin, 250, 350, 0, 0, 1)
364 {
365         this->plugin = plugin;
366 }
367
368
369 void DenoiseMJPEGWindow::create_objects()
370 {
371         int x1 = 10, y1 = 20, x2 = 140, x3 = 180, y2 = 10, margin = 30, margin2 = 25;
372         add_subwindow(new BC_Title(x1, y1, _("Search radius:")));
373         add_subwindow(radius = new DenoiseMJPEGRadius(plugin, x2, y2));
374         y1 += margin;
375         y2 += margin;
376         add_subwindow(new BC_Title(x1, y1, _("Pass 1 threshold:")));
377         add_subwindow(threshold1 = new DenoiseMJPEGThresh(plugin, x3, y2));
378         y1 += margin;
379         y2 += margin;
380         add_subwindow(new BC_Title(x1, y1, _("Pass 2 threshold:")));
381         add_subwindow(threshold2 = new DenoiseMJPEGThresh2(plugin, x2, y2));
382         y1 += margin;
383         y2 += margin;
384         add_subwindow(new BC_Title(x1, y1, _("Sharpness:")));
385         add_subwindow(sharpness = new DenoiseMJPEGSharp(plugin, x3, y2));
386         y1 += margin;
387         y2 += margin;
388         add_subwindow(new BC_Title(x1, y1, _("Luma contrast:")));
389         add_subwindow(lcontrast = new DenoiseMJPEGLContrast(plugin, x2, y2));
390         y1 += margin;
391         y2 += margin;
392         add_subwindow(new BC_Title(x1, y1, _("Chroma contrast:")));
393         add_subwindow(ccontrast = new DenoiseMJPEGCContrast(plugin, x3, y2));
394         y1 += margin;
395         y2 += margin;
396         add_subwindow(new BC_Title(x1, y1, _("Delay frames:")));
397         add_subwindow(delay = new DenoiseMJPEGDelay(plugin, x2, y2));
398         y1 += margin;
399         y2 += margin;
400         add_subwindow(new BC_Title(x1, y1, _("Mode:")));
401         add_subwindow(interlaced = new DenoiseMJPEGModeInterlaced(plugin, this, x2, y1));
402         y1 += margin2;
403         y2 += margin2;
404         add_subwindow(progressive = new DenoiseMJPEGModeProgressive(plugin, this, x2, y1));
405         y1 += margin2;
406         y2 += margin2;
407         add_subwindow(fast = new DenoiseMJPEGModeFast(plugin, this, x2, y1));
408         y1 += margin;
409         y2 += margin;
410         add_subwindow(deinterlace = new DenoiseMJPEGDeinterlace(plugin, x1, y1));
411
412         show_window();
413         flush();
414 }
415
416 void DenoiseMJPEGWindow::update_mode(int value)
417 {
418         plugin->config.mode = value;
419         progressive->update(value == 0);
420         interlaced->update(value == 1);
421         fast->update(value == 2);
422 }
423
424 int DenoiseMJPEGWindow::close_event()
425 {
426         set_done(1);
427         return 1;
428 }
429
430
431
432
433 DenoiseMJPEG::DenoiseMJPEG(PluginServer *server)
434  : PluginVClient(server)
435 {
436         
437         accumulation = 0;
438 }
439
440
441 DenoiseMJPEG::~DenoiseMJPEG()
442 {
443         
444
445         if(accumulation) delete [] accumulation;
446 }
447
448 int DenoiseMJPEG::process_realtime(VFrame *input, VFrame *output)
449 {
450         load_configuration();
451         return 0;
452 }
453
454 const char* DenoiseMJPEG::plugin_title() { return N_("Denoise video2"); }
455 int DenoiseMJPEG::is_realtime() { return 1; }
456
457 void DenoiseMJPEG::update_gui()
458 {
459         if(thread) 
460         {
461                 load_configuration();
462                 DenoiseMJPEGWindow *window = (DenoiseMJPEGWindow *)thread->window;
463                 window->lock_window();
464                 window->delay->update(config.delay);
465                 window->threshold1->update(config.threshold);
466                 window->unlock_window();
467         }
468 }
469
470
471 NEW_WINDOW_MACRO(DenoiseMJPEG, DenoiseMJPEGWindow)
472 LOAD_CONFIGURATION_MACRO(DenoiseMJPEG, DenoiseMJPEGConfig)
473
474
475 void DenoiseMJPEG::save_data(KeyFrame *keyframe)
476 {
477         FileXML output;
478
479 // cause data to be stored directly in text
480         output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
481         output.tag.set_title("DENOISE_VIDEO2");
482         output.tag.set_property("RADIUS", config.radius);
483         output.tag.set_property("THRESHOLD", config.threshold);
484         output.tag.set_property("THRESHOLD2", config.threshold2);
485         output.tag.set_property("SHARPNESS", config.sharpness);
486         output.tag.set_property("LCONTRAST", config.lcontrast);
487         output.tag.set_property("CCONTRAST", config.ccontrast);
488         output.tag.set_property("DEINTERLACE", config.deinterlace);
489         output.tag.set_property("MODE", config.mode);
490         output.tag.set_property("DELAY", config.delay);
491         output.append_tag();
492         output.terminate_string();
493 }
494
495 void DenoiseMJPEG::read_data(KeyFrame *keyframe)
496 {
497         FileXML input;
498
499         input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
500
501         while(!input.read_tag())
502         {
503                 if(input.tag.title_is("DENOISE_VIDEO2"))
504                 {
505                         config.radius = input.tag.get_property("RADIUS", config.radius);
506                         config.threshold = input.tag.get_property("THRESHOLD", config.threshold);
507                         config.threshold2 = input.tag.get_property("THRESHOLD2", config.threshold2);
508                         config.sharpness = input.tag.get_property("SHARPNESS", config.sharpness);
509                         config.lcontrast = input.tag.get_property("LCONTRAST", config.lcontrast);
510                         config.ccontrast = input.tag.get_property("CCONTRAST", config.ccontrast);
511                         config.deinterlace = input.tag.get_property("DEINTERLACE", config.deinterlace);
512                         config.mode = input.tag.get_property("MODE", config.mode);
513                         config.delay = input.tag.get_property("DELAY", config.delay);
514                 }
515         }
516 }
517
518
519
520