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