remove whitespace at eol
[goodguy/history.git] / cinelerra-5.1 / plugins / threshold / thresholdwindow.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 "bcdisplayinfo.h"
23 #include "histogramengine.h"
24 #include "language.h"
25 #include "threshold.h"
26 #include "thresholdwindow.h"
27
28 #define COLOR_W 100
29 #define COLOR_H 30
30
31
32
33
34 ThresholdMin::ThresholdMin(ThresholdMain *plugin,
35         ThresholdWindow *gui,
36         int x,
37         int y,
38         int w)
39  : BC_TumbleTextBox(gui,
40         plugin->config.min,
41         HISTOGRAM_MIN,
42         HISTOGRAM_MAX,
43         x,
44         y,
45         w)
46 {
47         this->plugin = plugin;
48         this->gui = gui;
49 }
50
51
52 int ThresholdMin::handle_event()
53 {
54         plugin->config.min = atof(get_text());
55         gui->canvas->draw();
56         plugin->send_configure_change();
57         return 1;
58 }
59
60
61
62
63
64
65
66
67
68 ThresholdMax::ThresholdMax(ThresholdMain *plugin,
69         ThresholdWindow *gui,
70         int x,
71         int y,
72         int w)
73  : BC_TumbleTextBox(gui,
74         plugin->config.max,
75         HISTOGRAM_MIN,
76         HISTOGRAM_MAX,
77         x,
78         y,
79         w)
80 {
81         this->plugin = plugin;
82         this->gui = gui;
83 }
84
85 int ThresholdMax::handle_event()
86 {
87         plugin->config.max = atof(get_text());
88         gui->canvas->draw();
89         plugin->send_configure_change();
90         return 1;
91 }
92
93
94
95
96
97
98
99 ThresholdPlot::ThresholdPlot(ThresholdMain *plugin,
100         int x,
101         int y)
102  : BC_CheckBox(x, y, plugin->config.plot, _("Plot histogram"))
103 {
104         this->plugin = plugin;
105 }
106
107 int ThresholdPlot::handle_event()
108 {
109         plugin->config.plot = get_value();
110
111         plugin->send_configure_change();
112         return 1;
113 }
114
115
116
117
118
119
120 ThresholdCanvas::ThresholdCanvas(ThresholdMain *plugin,
121         ThresholdWindow *gui,
122         int x,
123         int y,
124         int w,
125         int h)
126  : BC_SubWindow(x, y, w, h)
127 {
128         this->plugin = plugin;
129         this->gui = gui;
130         state = NO_OPERATION;
131 }
132
133 int ThresholdCanvas::button_press_event()
134 {
135         if(is_event_win() && cursor_inside())
136         {
137                 activate();
138                 state = DRAG_SELECTION;
139                 if(shift_down())
140                 {
141                         x1 = (int)((plugin->config.min - HISTOGRAM_MIN) /
142                                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
143                                 get_w());
144                         x2 = (int)((plugin->config.max - HISTOGRAM_MIN) /
145                                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
146                                 get_w());
147                         center_x = (x2 + x1) / 2;
148                         if(abs(get_cursor_x() - x1) < abs(get_cursor_x() - x2))
149                         {
150                                 x1 = get_cursor_x();
151                                 center_x = x2;
152                         }
153                         else
154                         {
155                                 x2 = get_cursor_x();
156                                 center_x = x1;
157                         }
158                 }
159                 else
160                 {
161                         x1 = x2 = center_x = get_cursor_x();
162                 }
163
164                 plugin->config.min = x1 *
165                         (HISTOGRAM_MAX - HISTOGRAM_MIN) /
166                         get_w() +
167                         HISTOGRAM_MIN;
168                 plugin->config.max = x2 *
169                         (HISTOGRAM_MAX - HISTOGRAM_MIN) /
170                         get_w() +
171                         HISTOGRAM_MIN;
172
173                 draw();
174                 return 1;
175         }
176         return 0;
177 }
178
179 int ThresholdCanvas::button_release_event()
180 {
181         if(state == DRAG_SELECTION)
182         {
183                 state = NO_OPERATION;
184                 return 1;
185         }
186         return 0;
187 }
188
189 int ThresholdCanvas::cursor_motion_event()
190 {
191         if(state == DRAG_SELECTION)
192         {
193                 if(get_cursor_x() > center_x)
194                 {
195                         x1 = center_x;
196                         x2 = get_cursor_x();
197                 }
198                 else
199                 {
200                         x1 = get_cursor_x();
201                         x2 = center_x;
202                 }
203
204                 plugin->config.min = x1 *
205                         (HISTOGRAM_MAX - HISTOGRAM_MIN) /
206                         get_w() +
207                         HISTOGRAM_MIN;
208
209                 plugin->config.max = x2 *
210                         (HISTOGRAM_MAX - HISTOGRAM_MIN) /
211                         get_w() +
212                         HISTOGRAM_MIN;
213
214                 gui->min->update(plugin->config.min);
215                 gui->max->update(plugin->config.max);
216                 draw();
217                 plugin->send_configure_change();
218                 return 1;
219         }
220         return 0;
221 }
222
223 void ThresholdCanvas::draw()
224 {
225         int max = 0;
226         set_color(WHITE);
227         draw_box(0, 0, get_w(), get_h());
228         int border_x1 = (int)((0 - HISTOGRAM_MIN) /
229                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
230                 get_w());
231         int border_x2 = (int)((1.0 - HISTOGRAM_MIN) /
232                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
233                 get_w());
234
235         int x1 = (int)((plugin->config.min - HISTOGRAM_MIN) /
236                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
237                 get_w());
238         int x2 = (int)((plugin->config.max - HISTOGRAM_MIN) /
239                 (HISTOGRAM_MAX - HISTOGRAM_MIN) *
240                 get_w());
241
242         if(plugin->engine)
243         {
244                 int64_t *array = plugin->engine->accum[HISTOGRAM_VALUE];
245
246
247 // Get normalizing factor
248                 for(int i = 0; i < get_w(); i++)
249                 {
250                         int division1 = i * HISTOGRAM_RANGE / get_w();
251                         int division2 = (i + 1) * HISTOGRAM_RANGE / get_w();
252                         int total = 0;
253                         for(int j = division1; j < division2; j++)
254                         {
255                                 total += array[j];
256                         }
257                         if(total > max) max = total;
258                 }
259
260                 for(int i = 0; i < get_w(); i++)
261                 {
262                         int division1 = i * HISTOGRAM_RANGE / get_w();
263                         int division2 = (i + 1) * HISTOGRAM_RANGE / get_w();
264                         int total = 0;
265                         for(int j = division1; j < division2; j++)
266                         {
267                                 total += array[j];
268                         }
269
270                         int pixels;
271                         if(max)
272                                 pixels = total * get_h() / max;
273                         else
274                                 pixels = 0;
275                         if(i >= x1 && i < x2)
276                         {
277                                 set_color(BLUE);
278                                 draw_line(i, 0, i, get_h() - pixels);
279                                 set_color(WHITE);
280                                 draw_line(i, get_h(), i, get_h() - pixels);
281                         }
282                         else
283                         {
284                                 set_color(BLACK);
285                                 draw_line(i, get_h(), i, get_h() - pixels);
286                         }
287                 }
288         }
289         else
290         {
291
292
293                 set_color(BLUE);
294                 draw_box(x1, 0, x2 - x1, get_h());
295         }
296
297         set_color(RED);
298         draw_line(border_x1, 0, border_x1, get_h());
299         draw_line(border_x2, 0, border_x2, get_h());
300
301         flash(1);
302 }
303
304
305
306
307
308
309 ThresholdLowColorButton::ThresholdLowColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
310  : BC_GenericButton(x, y, _("Low Color"))
311 {
312         this->plugin = plugin;
313         this->window = window;
314 }
315
316 int ThresholdLowColorButton::handle_event()
317 {
318         RGBA & color = plugin->config.low_color;
319         window->low_color_thread->start_window(
320                 color.getRGB(),
321                 color.a);
322         return 1;
323 }
324
325
326
327
328
329 ThresholdMidColorButton::ThresholdMidColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
330  : BC_GenericButton(x, y, _("Mid Color"))
331 {
332         this->plugin = plugin;
333         this->window = window;
334 }
335
336 int ThresholdMidColorButton::handle_event()
337 {
338         RGBA & color = plugin->config.mid_color;
339         window->mid_color_thread->start_window(
340                 color.getRGB(),
341                 color.a);
342         return 1;
343 }
344
345
346
347
348
349 ThresholdHighColorButton::ThresholdHighColorButton(ThresholdMain *plugin, ThresholdWindow *window, int x, int y)
350  : BC_GenericButton(x, y, _("High Color"))
351 {
352         this->plugin = plugin;
353         this->window = window;
354 }
355
356 int ThresholdHighColorButton::handle_event()
357 {
358         RGBA & color = plugin->config.high_color;
359         window->high_color_thread->start_window(
360                 color.getRGB(),
361                 color.a);
362         return 1;
363 }
364
365
366
367
368
369 ThresholdLowColorThread::ThresholdLowColorThread(ThresholdMain *plugin, ThresholdWindow *window)
370  : ColorThread(1, _("Low color"))
371 {
372         this->plugin = plugin;
373         this->window = window;
374 }
375
376 int ThresholdLowColorThread::handle_new_color(int output, int alpha)
377 {
378         plugin->config.low_color.set(output, alpha);
379         window->update_low_color();
380         window->flush();
381         plugin->send_configure_change();
382         return 1;
383 }
384
385
386
387
388
389 ThresholdMidColorThread::ThresholdMidColorThread(ThresholdMain *plugin, ThresholdWindow *window)
390  : ColorThread(1, _("Mid color"))
391 {
392         this->plugin = plugin;
393         this->window = window;
394 }
395
396 int ThresholdMidColorThread::handle_new_color(int output, int alpha)
397 {
398         plugin->config.mid_color.set(output, alpha);
399         window->update_mid_color();
400         window->flush();
401         plugin->send_configure_change();
402         return 1;
403 }
404
405
406
407
408
409 ThresholdHighColorThread::ThresholdHighColorThread(ThresholdMain *plugin, ThresholdWindow *window)
410  : ColorThread(1, _("High color"))
411 {
412         this->plugin = plugin;
413         this->window = window;
414 }
415
416 int ThresholdHighColorThread::handle_new_color(int output, int alpha)
417 {
418         plugin->config.high_color.set(output, alpha);
419         window->update_high_color();
420         window->flush();
421         plugin->send_configure_change();
422         return 1;
423 }
424
425
426
427
428
429
430 ThresholdWindow::ThresholdWindow(ThresholdMain *plugin)
431 : PluginClientWindow(plugin, 450, 450, 450, 450, 1)
432 {
433         this->plugin = plugin;
434         this->min = 0;
435         this->max = 0;
436         this->canvas = 0;
437         this->plot = 0;
438         this->low_color = 0;
439         this->mid_color = 0;
440         this->high_color = 0;
441         this->low_color_thread = 0;
442         this->mid_color_thread = 0;
443         this->high_color_thread = 0;
444 }
445
446 ThresholdWindow::~ThresholdWindow()
447 {
448 }
449
450 void ThresholdWindow::create_objects()
451 {
452         int x = 10;
453         int y = 10;
454         add_subwindow(canvas = new ThresholdCanvas(plugin,
455                 this,
456                 x,
457                 y,
458                 get_w() - x - 10,
459                 get_h() - 160));
460         canvas->draw();
461         y += canvas->get_h() + 10;
462
463         add_subwindow(plot = new ThresholdPlot(plugin, x, y));
464         y += plot->get_h() + 10;
465
466
467         add_subwindow(low_color = new ThresholdLowColorButton(plugin, this, x, y));
468         low_color_x = x + 10;
469         low_color_y = y + low_color->get_h() + 10;
470         x += low_color->get_w() + 10;
471
472         add_subwindow(mid_color = new ThresholdMidColorButton(plugin, this, x, y));
473         mid_color_x = x + 10;
474         mid_color_y = y + mid_color->get_h() + 10;
475         x += mid_color->get_w() + 10;
476
477         add_subwindow(high_color = new ThresholdHighColorButton(plugin, this, x, y));
478         high_color_x = x + 10;
479         high_color_y = y + high_color->get_h() + 10;
480
481         y += low_color->get_h() + COLOR_H + 10 + 10;
482
483         x = 30;
484         BC_Title * min_title;
485         add_subwindow(min_title = new BC_Title(x, y, _("Min:")));
486         x += min_title->get_w() + 10;
487         min = new ThresholdMin(plugin,
488                 this,
489                 x,
490                 y,
491                 100);
492         min->create_objects();
493         min->set_increment(0.1);
494
495
496         x = mid_color->get_x() + mid_color->get_w() / 2;
497         BC_Title * max_title;
498         add_subwindow(max_title = new BC_Title(x, y, _("Max:")));
499         x += max_title->get_w() + 10;
500         max = new ThresholdMax(plugin,
501                 this,
502                 x,
503                 y,
504                 100);
505         max->create_objects();
506         max->set_increment(0.1);
507
508
509         low_color_thread  = new ThresholdLowColorThread(plugin, this);
510         mid_color_thread  = new ThresholdMidColorThread(plugin, this);
511         high_color_thread = new ThresholdHighColorThread(plugin, this);
512         update_low_color();
513         update_mid_color();
514         update_high_color();
515
516         show_window(1);
517 }
518
519 void ThresholdWindow::update_low_color()
520 {
521         set_color(plugin->config.low_color.getRGB());
522         draw_box(low_color_x, low_color_y, COLOR_W, COLOR_H);
523         flash(low_color_x, low_color_y, COLOR_W, COLOR_H);
524 }
525
526 void ThresholdWindow::update_mid_color()
527 {
528         set_color(plugin->config.mid_color.getRGB());
529         draw_box(mid_color_x, mid_color_y, COLOR_W, COLOR_H);
530         flash(mid_color_x, mid_color_y, COLOR_W, COLOR_H);
531 }
532
533 void ThresholdWindow::update_high_color()
534 {
535         set_color(plugin->config.high_color.getRGB());
536         draw_box(high_color_x, high_color_y, COLOR_W, COLOR_H);
537         flash(high_color_x, high_color_y, COLOR_W, COLOR_H);
538 }
539
540
541