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