no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / plugins / histogram / histogramwindow.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2011 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 "bcsignals.h"
24 #include "cursors.h"
25 #include "edl.h"
26 #include "histogram.h"
27 #include "histogramconfig.h"
28 #include "histogramwindow.h"
29 #include "keys.h"
30 #include "language.h"
31 #include "localsession.h"
32 #include "mwindow.h"
33 #include "pluginserver.h"
34 #include "theme.h"
35
36 #include <unistd.h>
37
38
39
40
41 HistogramWindow::HistogramWindow(HistogramMain *plugin)
42  : PluginClientWindow(plugin,
43         plugin->w,
44         plugin->h,
45         xS(440),
46         yS(500),
47         1)
48 {
49         this->plugin = plugin;
50         active_value = 0;
51 }
52
53 HistogramWindow::~HistogramWindow()
54 {
55 }
56
57
58 void HistogramWindow::create_objects()
59 {
60         int margin = plugin->get_theme()->widget_border;
61         int x = margin, y = margin, x1 = margin;
62
63         add_subwindow(mode_v = new HistogramMode(plugin, x, y,
64                 HISTOGRAM_VALUE, _("Value")));
65         x += mode_v->get_w() + margin;
66         add_subwindow(mode_r = new HistogramMode(plugin, x, y,
67                 HISTOGRAM_RED, _("Red")));
68         x += mode_r->get_w() + margin;
69         add_subwindow(mode_g = new HistogramMode(plugin, x, y,
70                 HISTOGRAM_GREEN, _("Green")));
71         x += mode_g->get_w() + margin;
72         add_subwindow(mode_b = new HistogramMode(plugin, x, y,
73                 HISTOGRAM_BLUE, _("Blue")));
74         x = get_w() - margin - plugin->get_theme()->get_image_set("histogram_rgb_toggle")[0]->get_w();
75         add_subwindow(parade_on = new HistogramParade(plugin, this,
76                 x, y, 1));
77         x -= parade_on->get_w() + margin;
78         add_subwindow(parade_off = new HistogramParade(plugin, this, x, y, 0));
79
80         x = x1;
81         y += parade_on->get_h() + margin;
82         add_subwindow(canvas_title1 = new BC_Title(margin, y, "-10%"));
83         x = get_w() - get_text_width(MEDIUMFONT, "110%") - margin;
84         add_subwindow(canvas_title2 = new BC_Title(x, y, "110%"));
85
86         y += canvas_title2->get_h() + margin;
87         x = x1;
88         canvas_h = get_h() - y - yS(210);
89
90         add_subwindow(low_input_carrot = new HistogramCarrot(plugin, this, x, y + canvas_h));
91
92         x = low_input_carrot->get_w() / 2 + x;
93         canvas_w = get_w() - x - x;
94
95         title1_x = x;
96         title2_x = x + (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
97         title3_x = x + (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
98         title4_x = x + (int)(canvas_w);
99
100         add_subwindow(canvas = new HistogramCanvas(plugin, this,
101                         x, y, canvas_w, canvas_h));
102
103 // Canvas border
104         draw_3d_border(x - 2, y - 2, canvas_w + 4, canvas_h + 4,
105                 get_bg_color(), BLACK, MDGREY, get_bg_color());
106
107 // Calculate output curve with no value function
108         plugin->tabulate_curve(plugin->preview_lookup, plugin->mode, 0x10000, 0);
109
110         y += canvas->get_h();
111         x = margin;
112
113         add_subwindow(gamma_carrot = new HistogramCarrot(plugin, this,
114                 canvas->get_x() + canvas->get_w() / 2 -
115                         low_input_carrot->get_w() / 2 , y));
116
117         add_subwindow(high_input_carrot = new HistogramCarrot(plugin, this,
118                 canvas->get_x() + canvas->get_w() -
119                         low_input_carrot->get_w() / 2, y));
120         y += low_input_carrot->get_h() + margin;
121
122 //      add_subwindow(title = new BC_Title(x, y, _("Input:")));
123 //      x += title->get_w() + margin;
124         low_input = new HistogramText(plugin, this, x, y);
125         low_input->create_objects();
126
127         x = get_w() / 2 - low_input->get_w() / 2;
128         gamma = new HistogramText(plugin, this, x, y, 0.01, 100.);
129         gamma->create_objects();
130
131         x = get_w() - low_input->get_w() - margin;
132         high_input = new HistogramText(plugin, this, x, y);
133         high_input->create_objects();
134
135         y += high_input->get_h() + margin;
136         x = x1;
137
138         add_subwindow(output = new HistogramSlider(plugin, this,
139                 canvas->get_x(), y, canvas->get_w(), yS(20), 0));
140         output->update();
141
142 // Output border
143         draw_3d_border(output->get_x() - 2, output->get_y() - 2,
144                 output->get_w() + 4, output->get_h() + 4,
145                 get_bg_color(), BLACK, MDGREY, get_bg_color());
146         y += output->get_h();
147
148         add_subwindow(low_output_carrot = new HistogramCarrot(plugin,
149                 this, margin, y));
150
151         add_subwindow(high_output_carrot = new HistogramCarrot(plugin,
152                 this, canvas->get_x() + canvas->get_w() -
153                         low_output_carrot->get_w() / 2, y));
154         y += high_output_carrot->get_h() + margin;
155
156
157 //      add_subwindow(title = new BC_Title(x, y, _("Output:")));
158 //      x += title->get_w() + margin;
159         low_output = new HistogramText(plugin, this, x, y);
160         low_output->create_objects();
161
162         const char *linear_text = _("Linear");
163         int xs = get_w()/2 - xS(50);
164         x = xs - BC_Title::calculate_w(this, linear_text) - margin;
165         add_subwindow(log_title1 = new BC_Title(x, y, linear_text));
166         add_subwindow(log_slider = new HistogramLogSlider(plugin, this, xs, y));
167         xs += log_slider->get_w() + margin;
168         add_subwindow(log_title2 = new BC_Title(xs, y, _("Log")));
169
170         high_output = new HistogramText(plugin, this,
171                 get_w() - low_output->get_w() - margin, y);
172         high_output->create_objects();
173
174         x = x1;
175         y += high_output->get_h() + margin;
176
177         add_subwindow(bar = new BC_Bar(x, y, get_w() - margin * 2));
178         y += bar->get_h() + margin;
179
180         add_subwindow(automatic = new HistogramAuto(plugin, x, y));
181         int x2 = xS(190);
182         add_subwindow(threshold_title = new BC_Title(x2, y, _("Threshold:")));
183         int x3 = xS(305);
184         threshold = new HistogramText(plugin, this, x3, y);
185         threshold->create_objects();
186         y += automatic->get_h() + margin;
187
188         add_subwindow(plot = new HistogramPlot(plugin, x1, y));
189         add_subwindow(select = new HistogramSelect(plugin, this, x2, y));
190         frames = new HistogramFrames(plugin, this, x3, y);
191         frames->create_objects();
192         x = x3 + frames->get_w() + margin;
193         add_subwindow(clear_frames = new HistogramClearFrames(plugin, this, x, y));
194         y += plot->get_h() + margin;
195
196         x = x1;
197         add_subwindow(split = new HistogramSplit(plugin, x, y));
198         x = xS(340);
199         add_subwindow(reset = new HistogramReset(plugin, x, y + yS(5)));
200
201         update(1, 1, 1, 1);
202
203         flash(0);
204         show_window();
205 }
206
207
208
209 int HistogramWindow::resize_event(int w, int h)
210 {
211         int xdiff = w - get_w();
212         int ydiff = h - get_h();
213
214         parade_on->reposition_window(parade_on->get_x() + xdiff,
215                 parade_on->get_y());
216         parade_off->reposition_window(parade_off->get_x() + xdiff,
217                 parade_on->get_y());
218         canvas_title2->reposition_window(canvas_title2->get_x() + xdiff,
219                 canvas_title2->get_y());
220
221 // Canvas follows window size
222         canvas_w = canvas_w + xdiff;
223         canvas_h = canvas_h + ydiff;
224         canvas->reposition_window(canvas->get_x(), canvas->get_y(),
225                 canvas_w, canvas_h);
226
227 // Canvas border
228         draw_3d_border(canvas->get_x() - 2, canvas->get_y() - 2,
229                 canvas_w + 4, canvas_h + 4,
230                 get_bg_color(), BLACK, MDGREY, get_bg_color());
231
232         low_input_carrot->reposition_window(low_input_carrot->get_x(),
233                 low_input_carrot->get_y() + ydiff);
234         gamma_carrot->reposition_window(gamma_carrot->get_x(),
235                 gamma_carrot->get_y() + ydiff);
236         high_input_carrot->reposition_window(high_input_carrot->get_x(),
237                 high_input_carrot->get_y() + ydiff);
238
239         low_input->reposition_window(low_input->get_x(),
240                 low_input->get_y() + ydiff);
241         gamma->reposition_window(w / 2 - gamma->get_w() / 2,
242                 gamma->get_y() + ydiff);
243         high_input->reposition_window(high_input->get_x() + xdiff,
244                 low_input->get_y() + ydiff);
245
246         output->reposition_window(output->get_x(),
247                 output->get_y() + ydiff,
248                 output->get_w() + xdiff,
249                 output->get_h());
250         output->update();
251
252 // Output border
253         draw_3d_border(output->get_x() - 2, output->get_y() - 2,
254                 output->get_w() + 4, output->get_h() + 4,
255                 get_bg_color(), BLACK, MDGREY, get_bg_color());
256
257         low_output_carrot->reposition_window(low_output_carrot->get_x(),
258                 low_output_carrot->get_y() + ydiff);
259         high_output_carrot->reposition_window(high_output_carrot->get_x(),
260                 high_output_carrot->get_y() + ydiff);
261
262         low_output->reposition_window(low_output->get_x(),
263                 low_output->get_y() + ydiff);
264         int xs = (w - log_slider->get_w()) / 2;
265         int margin = plugin->get_theme()->widget_border;
266         log_title1->reposition_window(xs - log_title1->get_w() - margin,
267                 log_title1->get_y() + ydiff);
268         log_slider->reposition_window(xs,
269                 log_slider->get_y() + ydiff);
270         log_title2->reposition_window(xs + log_slider->get_w() + margin,
271                 log_title2->get_y() + ydiff);
272         high_output->reposition_window(high_output->get_x() + xdiff,
273                 high_output->get_y() + ydiff);
274
275         bar->reposition_window(bar->get_x(),
276                 bar->get_y() + ydiff,
277                 bar->get_w() + xdiff);
278
279         automatic->reposition_window(automatic->get_x(),
280                 automatic->get_y() + ydiff);
281         threshold_title->reposition_window(threshold_title->get_x(),
282                 threshold_title->get_y() + ydiff);
283         threshold->reposition_window(threshold->get_x(),
284                 threshold->get_y() + ydiff);
285         plot->reposition_window(plot->get_x(),
286                 plot->get_y() + ydiff);
287
288         split->reposition_window(split->get_x(),
289                 split->get_y() + ydiff);
290         reset->reposition_window(reset->get_x(),
291                 reset->get_y() + ydiff);
292
293         frames->reposition_window(frames->get_x(),
294                 frames->get_y() + ydiff);
295         select->reposition_window(select->get_x(),
296                 select->get_y() + ydiff);
297         clear_frames->reposition_window(clear_frames->get_x(),
298                 clear_frames->get_y() + ydiff);
299
300         update(1, 1, 1, 1);
301
302         plugin->w = w;
303         plugin->h = h;
304         flash();
305         return 1;
306 }
307
308
309
310 int HistogramWindow::keypress_event()
311 {
312         int result = 0;
313
314         if(active_value)
315         {
316                 float sign = 1;
317                 for(int i = 0; i < HISTOGRAM_MODES; i++)
318                 {
319                         if(active_value == &plugin->config.gamma[i])
320                                 sign = -1;
321                 }
322
323                 if(get_keypress() == RIGHT || get_keypress() == UP)
324                 {
325                         *active_value += sign * PRECISION;
326                         plugin->config.boundaries();
327                         update(1, 1, 1, 0);
328                         plugin->send_configure_change();
329                         return 1;
330                 }
331                 else
332                 if(get_keypress() == LEFT || get_keypress() == DOWN)
333                 {
334                         *active_value -= sign * PRECISION;
335                         plugin->config.boundaries();
336                         update(1, 1, 1, 0);
337                         plugin->send_configure_change();
338                         return 1;
339                 }
340         }
341
342         return result;
343 }
344
345 void HistogramWindow::update(int do_canvases,
346         int do_carrots,
347         int do_text,
348         int do_toggles)
349 {
350         if(do_toggles)
351         {
352                 automatic->update(plugin->config.automatic);
353                 mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
354                 mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
355                 mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
356                 mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
357                 plot->update(plugin->config.plot);
358                 split->update(plugin->config.split);
359                 frames->update(plugin->config.frames);
360                 parade_on->update(plugin->parade ? 1 : 0);
361                 parade_off->update(plugin->parade ? 0 : 1);
362                 log_slider->update(plugin->config.log_slider);
363                 output->update();
364         }
365
366         if(do_canvases)
367         {
368                 update_canvas();
369         }
370
371         if(do_carrots)
372         {
373                 low_input_carrot->update();
374                 high_input_carrot->update();
375                 gamma_carrot->update();
376                 low_output_carrot->update();
377                 high_output_carrot->update();
378         }
379
380         if(do_text)
381         {
382                 low_input->update();
383                 gamma->update();
384                 high_input->update();
385                 low_output->update();
386                 high_output->update();
387                 threshold->update();
388         }
389
390
391 }
392
393
394 void HistogramWindow::draw_canvas_mode(int mode, int color, int y, int h)
395 {
396 // Draw histogram
397         int max = 0, *accum = plugin->accum[mode];
398         if( accum ) {
399                 for( int i=0,x=0; x<canvas_w; ++x ) {
400                         int m = 0;
401                         int i1 = (HISTOGRAM_SLOTS * (x+1)) / canvas_w;
402                         while( i < i1 ) m += accum[i++];
403                         if( max < m ) max = m;
404                 }
405         }
406
407         if( max > 0 ) {
408                 double log_slider = plugin->config.log_slider;
409                 double lin_slider = 1. - log_slider;
410                 double lin_scale = (lin_slider * h) / max;
411                 double log_scale = (log_slider * h) / log(max);
412                 for( int i=0,x=0; x<canvas_w; ++x ) {
413                         int m = 0, i0 = i;
414                         int i1 = (HISTOGRAM_SLOTS * (x+1)) / canvas_w;
415                         while( i < i1 ) m += accum[i++];
416                         double v = m > 0 && i1 > i0 ? (double)m : 0;
417                         m = v > 0 ? v*lin_scale + log(v)*log_scale : 0;
418
419                         canvas->set_color(BLACK);
420                         canvas->draw_line(x, y, x, y+h - m);
421                         canvas->set_color(color);
422                         canvas->draw_line(x, y+h - m, x, y+h);
423                 }
424         }
425         else {
426                 canvas->set_color(BLACK);
427                 canvas->draw_box(0, y, canvas_w, h);
428         }
429
430 // Draw overlays
431         canvas->set_color(WHITE);
432         canvas->set_line_width(2);
433         int y1 = 0;
434
435 // Draw output line
436         for( int x=0; x<canvas_w; ++x ) {
437                 float input = (float)x / canvas_w * FLOAT_RANGE + HIST_MIN_INPUT;
438                 float output = plugin->calculate_level(input, mode, 0);
439                 int y2 = h - (int)(output * h);
440                 if( x > 0 )
441                         canvas->draw_line(x-1, y+y1, x, y+y2);
442                 y1 = y2;
443         }
444
445         canvas->set_line_width(1);
446 }
447
448
449 void HistogramWindow::update_canvas()
450 {
451         if(plugin->parade)
452         {
453                 draw_canvas_mode(HISTOGRAM_RED, RED, 0, canvas_h / 3);
454                 draw_canvas_mode(HISTOGRAM_GREEN, GREEN, canvas_h / 3, canvas_h / 3);
455                 draw_canvas_mode(HISTOGRAM_BLUE, BLUE, canvas_h * 2 / 3, canvas_h - canvas_h * 2 / 3);
456         }
457         else
458         {
459                 draw_canvas_mode(plugin->mode, MEGREY, 0, canvas_h);
460         }
461
462
463 // Draw 0 and 100% lines.
464         canvas->set_color(RED);
465         int x = (int)(canvas_w * -HIST_MIN_INPUT / FLOAT_RANGE);
466         canvas->draw_line(x,
467                 0,
468                 x,
469                 canvas_h);
470         x = (int)(canvas_w * (1.0 - HIST_MIN_INPUT) / FLOAT_RANGE);
471         canvas->draw_line(x,
472                 0,
473                 x,
474                 canvas_h);
475         canvas->flash();
476 }
477
478
479
480
481 HistogramParade::HistogramParade(HistogramMain *plugin,
482         HistogramWindow *gui,
483         int x,
484         int y,
485         int value)
486  : BC_Toggle(x,
487         y,
488         value ? plugin->get_theme()->get_image_set("histogram_rgb_toggle") :
489                 plugin->get_theme()->get_image_set("histogram_toggle"),
490         0)
491 {
492         this->plugin = plugin;
493         this->gui = gui;
494         this->value = value;
495         if(value)
496                 set_tooltip(_("RGB Parade on"));
497         else
498                 set_tooltip(_("RGB Parade off"));
499 }
500
501 int HistogramParade::handle_event()
502 {
503         update(1);
504         plugin->parade = value;
505         gui->update(1,
506                 0,
507                 0,
508                 1);
509         return 1;
510 }
511
512
513
514
515
516
517
518 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
519         HistogramWindow *gui,
520         int x,
521         int y,
522         int w,
523         int h)
524  : BC_SubWindow(x,
525         y,
526         w,
527         h,
528         BLACK)
529 {
530         this->plugin = plugin;
531         this->gui = gui;
532 }
533
534 int HistogramCanvas::button_press_event()
535 {
536         int result = 0;
537         if(is_event_win() && cursor_inside())
538         {
539                 if(!plugin->dragging_point &&
540                         (!plugin->config.automatic || plugin->mode == HISTOGRAM_VALUE))
541                 {
542                         gui->deactivate();
543                 }
544         }
545         return result;
546 }
547
548 int HistogramCanvas::cursor_motion_event()
549 {
550         if(is_event_win() && cursor_inside())
551         {
552         }
553         return 0;
554 }
555
556 int HistogramCanvas::button_release_event()
557 {
558         return 0;
559 }
560
561
562 HistogramReset::HistogramReset(HistogramMain *plugin, int x, int y)
563  : BC_GenericButton(x, y, _("Reset"))
564 {
565         this->plugin = plugin;
566 }
567 int HistogramReset::handle_event()
568 {
569         plugin->config.reset(0);
570         ((HistogramWindow*)plugin->thread->window)->update(1, 1, 1, 1);
571         plugin->send_configure_change();
572         return 1;
573 }
574
575
576 HistogramSelect::HistogramSelect(HistogramMain *plugin, HistogramWindow *gui,
577                 int x, int y)
578  : BC_GenericButton(x, y, xS(100), _("Frames"))
579 {
580         this->plugin = plugin;
581         this->gui = gui;
582         set_tooltip(_("Set frames to selection duration"));
583 }
584 int HistogramSelect::handle_event()
585 {
586         MWindow *mwindow = plugin->server->mwindow;
587         if( mwindow ) {
588                 EDL *edl = mwindow->edl;
589                 double start = edl->local_session->get_selectionstart();
590                 int64_t start_pos = edl->get_frame_rate() * start;
591                 double end = edl->local_session->get_selectionend();
592                 int64_t end_pos = edl->get_frame_rate() * end;
593                 int64_t frames = end_pos - start_pos;
594                 gui->frames->update(frames);
595                 plugin->config.frames = frames;
596                 plugin->send_configure_change();
597         }
598         return 1;
599 }
600
601 HistogramClearFrames::HistogramClearFrames(HistogramMain *plugin, HistogramWindow *gui,
602                 int x, int y)
603  : BC_Button(x, y, plugin->get_theme()->get_image_set("reset_button"))
604 {
605         this->plugin = plugin;
606         this->gui = gui;
607         set_tooltip(_("Clear frames"));
608 }
609
610 int HistogramClearFrames::handle_event()
611 {
612         plugin->config.frames = 0;
613         gui->frames->update(0);
614         plugin->send_configure_change();
615         return 1;
616 }
617
618 HistogramLogSlider::HistogramLogSlider(HistogramMain *plugin, HistogramWindow *gui,
619                 int x, int y)
620 : BC_FSlider(x, y, 0, xS(100), xS(100), 0., 1., plugin->config.log_slider)
621
622 {
623         this->plugin = plugin;
624         this->gui = gui;
625 }
626
627 int HistogramLogSlider::handle_event()
628 {
629         plugin->config.log_slider = get_value();
630         plugin->send_configure_change();
631         return 1;
632 }
633
634 HistogramCarrot::HistogramCarrot(HistogramMain *plugin, HistogramWindow *gui, int x, int y)
635  : BC_Toggle(x, y, plugin->get_theme()->get_image_set("histogram_carrot"), 0)
636 {
637         this->plugin = plugin;
638         this->gui = gui;
639         drag_operation = 0;
640 }
641
642 HistogramCarrot::~HistogramCarrot()
643 {
644 }
645
646 float* HistogramCarrot::get_value()
647 {
648         if( this == gui->low_input_carrot )
649                 return &plugin->config.low_input[plugin->mode];
650         if( this == gui->high_input_carrot )
651                 return &plugin->config.high_input[plugin->mode];
652         if( this == gui->gamma_carrot )
653                 return &plugin->config.gamma[plugin->mode];
654         if( this == gui->low_output_carrot )
655                 return &plugin->config.low_output[plugin->mode];
656         if( this == gui->high_output_carrot )
657                 return &plugin->config.high_output[plugin->mode];
658         return 0;
659 }
660
661 void HistogramCarrot::update()
662 {
663         int new_x = 0;
664         float *value = get_value();
665
666         if(this != gui->gamma_carrot)
667         {
668                 new_x = (int)(gui->canvas->get_x() +
669                         (*value - HIST_MIN_INPUT) *
670                         gui->canvas->get_w() /
671                         (HIST_MAX_INPUT - HIST_MIN_INPUT) -
672                         get_w() / 2);
673         }
674         else
675         {
676                 float min = plugin->config.low_input[plugin->mode];
677                 float max = plugin->config.high_input[plugin->mode];
678                 float delta = (max - min) / 2.0;
679                 float mid = min + delta;
680                 float tmp = log10(1.0 / *value);
681                 tmp = mid + delta * tmp;
682
683 //printf("HistogramCarrot::update %d %f %f\n", __LINE__, *value, tmp);
684
685                         new_x = gui->canvas->get_x() -
686                                 get_w() / 2 +
687                                 (int)(gui->canvas->get_w() *
688                                 (tmp - HIST_MIN_INPUT) /
689                                 (HIST_MAX_INPUT - HIST_MIN_INPUT));
690         }
691
692         reposition_window(new_x, get_y());
693 }
694
695 int HistogramCarrot::button_press_event()
696 {
697         if(is_event_win() && get_buttonpress() == 1)
698         {
699                 //int w = get_w();
700                 gui->deactivate();
701                 set_status(BC_Toggle::TOGGLE_DOWN);
702
703                 BC_Toggle::update(0);
704                 gui->active_value = get_value();
705 // Disable the other toggles
706                 if(this != gui->low_input_carrot) gui->low_input_carrot->BC_Toggle::update(0);
707                 if(this != gui->high_input_carrot) gui->high_input_carrot->BC_Toggle::update(0);
708                 if(this != gui->gamma_carrot) gui->gamma_carrot->BC_Toggle::update(0);
709                 if(this != gui->low_output_carrot) gui->low_output_carrot->BC_Toggle::update(0);
710                 if(this != gui->high_output_carrot) gui->high_output_carrot->BC_Toggle::update(0);
711                 starting_x = get_x();
712                 offset_x = gui->get_relative_cursor_x();
713                 offset_y = gui->get_relative_cursor_y();
714 //printf("HistogramCarrot::button_press_event %d %d %d\n", __LINE__, starting_x, offset_x);
715                 drag_operation = 1;
716                 draw_face(1, 1);
717                 return 1;
718         }
719         return 0;
720 }
721
722 int HistogramCarrot::button_release_event()
723 {
724         int result = BC_Toggle::button_release_event();
725         handle_event();
726         drag_operation = 0;
727         return result;
728 }
729
730 int HistogramCarrot::cursor_motion_event()
731 {
732         int cursor_x = gui->get_relative_cursor_x();
733
734         if(drag_operation)
735         {
736 //printf("HistogramCarrot::cursor_motion_event %d %d\n", __LINE__, cursor_x);
737                 int new_x = starting_x + cursor_x - offset_x;
738
739 // Clamp x
740 // Get level from x
741                 float *value = get_value();
742                 if(this == gui->gamma_carrot)
743                 {
744                         float min = gui->low_input_carrot->get_x();
745                         float max = gui->high_input_carrot->get_x();
746                         float delta = (max - min) / 2.0;
747                         if(delta >= 0.5)
748                         {
749                                 float mid = min + delta;
750                                 float tmp = (float)(new_x - mid) /
751                                         delta;
752                                 tmp = 1.0 / pow(10, tmp);
753                                 CLAMP(tmp, MIN_GAMMA, MAX_GAMMA);
754                                 *value = tmp;
755 //printf("HistogramCarrot::update %d %f\n", __LINE__, tmp);
756                         }
757                 }
758                 else
759                 {
760                         int min_x = gui->canvas->get_x() - get_w() / 2;
761                         int max_x = gui->canvas->get_x() + gui->canvas->get_w() - get_w() / 2;
762                         CLAMP(new_x, min_x, max_x);
763                         *value = HIST_MIN_INPUT +
764                                 (HIST_MAX_INPUT - HIST_MIN_INPUT) *
765                                 (new_x - min_x) /
766                                 (max_x - min_x);
767                 }
768
769                 reposition_window(new_x, get_y());
770                 flush();
771
772                 gui->update(1,
773                         (this == gui->low_input_carrot || this == gui->high_input_carrot),
774                         1,
775                         0);
776                 plugin->send_configure_change();
777
778                 return 1;
779         }
780         return 0;
781 }
782
783
784
785
786
787
788
789
790 HistogramSlider::HistogramSlider(HistogramMain *plugin,
791         HistogramWindow *gui,
792         int x,
793         int y,
794         int w,
795         int h,
796         int is_input)
797  : BC_SubWindow(x, y, w, h)
798 {
799         this->plugin = plugin;
800         this->gui = gui;
801         this->is_input = is_input;
802         operation = NONE;
803 }
804
805 int HistogramSlider::input_to_pixel(float input)
806 {
807         return (int)((input - HIST_MIN_INPUT) / FLOAT_RANGE * get_w());
808 }
809
810 void HistogramSlider::update()
811 {
812         int w = get_w();
813         int h = get_h();
814         //int half_h = get_h() / 2;
815         //int quarter_h = get_h() / 4;
816         int mode = plugin->mode;
817         int r = 0xff;
818         int g = 0xff;
819         int b = 0xff;
820
821         clear_box(0, 0, w, h);
822
823         switch(mode)
824         {
825                 case HISTOGRAM_RED:
826                         g = b = 0x00;
827                         break;
828                 case HISTOGRAM_GREEN:
829                         r = b = 0x00;
830                         break;
831                 case HISTOGRAM_BLUE:
832                         r = g = 0x00;
833                         break;
834         }
835
836         for(int i = 0; i < w; i++)
837         {
838                 int color = (int)(i * 0xff / w);
839                 set_color(((r * color / 0xff) << 16) |
840                         ((g * color / 0xff) << 8) |
841                         (b * color / 0xff));
842
843                 draw_line(i, 0, i, h);
844         }
845
846
847         flash();
848 }
849
850
851
852
853
854
855
856
857
858 HistogramAuto::HistogramAuto(HistogramMain *plugin,
859         int x,
860         int y)
861  : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
862 {
863         this->plugin = plugin;
864 }
865
866 int HistogramAuto::handle_event()
867 {
868         plugin->config.automatic = get_value();
869         plugin->send_configure_change();
870         return 1;
871 }
872
873
874
875
876 HistogramPlot::HistogramPlot(HistogramMain *plugin,
877         int x,
878         int y)
879  : BC_CheckBox(x, y, plugin->config.plot, _("Plot histogram"))
880 {
881         this->plugin = plugin;
882 }
883
884 int HistogramPlot::handle_event()
885 {
886         plugin->config.plot = get_value();
887         plugin->send_configure_change();
888         return 1;
889 }
890
891
892
893
894 HistogramSplit::HistogramSplit(HistogramMain *plugin,
895         int x,
896         int y)
897  : BC_CheckBox(x, y, plugin->config.split, _("Split output"))
898 {
899         this->plugin = plugin;
900 }
901
902 int HistogramSplit::handle_event()
903 {
904         plugin->config.split = get_value();
905         plugin->send_configure_change();
906         return 1;
907 }
908
909
910 HistogramMode::HistogramMode(HistogramMain *plugin,
911         int x,
912         int y,
913         int value,
914         char *text)
915  : BC_Radial(x, y, plugin->mode == value, text)
916 {
917         this->plugin = plugin;
918         this->value = value;
919 }
920 int HistogramMode::handle_event()
921 {
922         HistogramWindow *gui = (HistogramWindow*)plugin->thread->window;
923         plugin->mode = value;
924         plugin->current_point= -1;
925         gui->active_value = 0;
926         gui->low_input_carrot->BC_Toggle::update(0);
927         gui->gamma_carrot->BC_Toggle::update(0);
928         gui->high_input_carrot->BC_Toggle::update(0);
929         gui->low_output_carrot->BC_Toggle::update(0);
930         gui->high_output_carrot->BC_Toggle::update(0);
931         gui->update(1, 1, 1, 1);
932 //      plugin->send_configure_change();
933         return 1;
934 }
935
936
937 HistogramFrames::HistogramFrames(HistogramMain *plugin, HistogramWindow *gui,
938                 int x, int y)
939  : BC_TumbleTextBox(gui, 0, 0, 65535, x, y, xS(80))
940 {
941         this->plugin = plugin;
942         this->gui = gui;
943 }
944
945 int HistogramFrames::handle_event()
946 {
947         plugin->config.frames = atoi(get_text());
948         plugin->send_configure_change();
949         return 1;
950 }
951
952 void HistogramFrames::update(int frames)
953 {
954         BC_TumbleTextBox::update((int64_t)frames);
955 }
956
957
958 HistogramText::HistogramText(HistogramMain *plugin,
959         HistogramWindow *gui, int x, int y, float hist_min, float hist_max)
960  : BC_TumbleTextBox(gui, 0.0, hist_min, hist_max, x, y, xS(80))
961 {
962         this->plugin = plugin;
963         this->gui = gui;
964         set_precision(DIGITS);
965         set_increment(PRECISION);
966 }
967
968 float* HistogramText::get_value()
969 {
970         if( this == gui->low_input )
971                 return &plugin->config.low_input[plugin->mode];
972         if( this == gui->high_input )
973                 return &plugin->config.high_input[plugin->mode];
974         if( this == gui->gamma )
975                 return &plugin->config.gamma[plugin->mode];
976         if( this == gui->low_output )
977                 return &plugin->config.low_output[plugin->mode];
978         if( this == gui->high_output )
979                 return &plugin->config.high_output[plugin->mode];
980         if( this == gui->threshold )
981                 return &plugin->config.threshold;
982         return 0;
983 }
984
985 int HistogramText::handle_event()
986 {
987         float *output = get_value();
988         if( output )
989                 *output = atof(get_text());
990
991         gui->update(1, 1, 0, 0);
992         plugin->send_configure_change();
993         return 1;
994 }
995
996 void HistogramText::update()
997 {
998         float *output = get_value();
999         if( output )
1000                 BC_TumbleTextBox::update(*output);
1001 }
1002