1 #include "bcdisplayinfo.h"
4 #include "histogramconfig.h"
5 #include "histogramwindow.h"
12 PLUGIN_THREAD_OBJECT(HistogramMain, HistogramThread, HistogramWindow)
16 HistogramWindow::HistogramWindow(HistogramMain *plugin, int x, int y)
17 : BC_Window(plugin->gui_string,
28 this->plugin = plugin;
31 HistogramWindow::~HistogramWindow()
35 #include "max_picon_png.h"
36 #include "mid_picon_png.h"
37 #include "min_picon_png.h"
38 static VFrame max_picon_image(max_picon_png);
39 static VFrame mid_picon_image(mid_picon_png);
40 static VFrame min_picon_image(min_picon_png);
42 int HistogramWindow::create_objects()
44 int x = 10, y = 10, x1 = 10;
47 max_picon = new BC_Pixmap(this, &max_picon_image);
48 mid_picon = new BC_Pixmap(this, &mid_picon_image);
49 min_picon = new BC_Pixmap(this, &min_picon_image);
50 add_subwindow(mode_v = new HistogramMode(plugin,
56 add_subwindow(mode_r = new HistogramMode(plugin,
62 add_subwindow(mode_g = new HistogramMode(plugin,
68 add_subwindow(mode_b = new HistogramMode(plugin,
74 // add_subwindow(mode_a = new HistogramMode(plugin,
82 add_subwindow(title = new BC_Title(x, y, _("Input X:")));
83 x += title->get_w() + 10;
84 input_x = new HistogramInputText(plugin,
89 input_x->create_objects();
91 x += input_x->get_w() + 10;
92 add_subwindow(title = new BC_Title(x, y, _("Input Y:")));
93 x += title->get_w() + 10;
94 input_y = new HistogramInputText(plugin,
99 input_y->create_objects();
104 canvas_w = get_w() - x - x;
105 canvas_h = get_h() - y - 170;
107 title2_x = x + (int)(canvas_w * -MIN_INPUT / FLOAT_RANGE);
108 title3_x = x + (int)(canvas_w * (1.0 - MIN_INPUT) / FLOAT_RANGE);
109 title4_x = x + (int)(canvas_w);
110 add_subwindow(canvas = new HistogramCanvas(plugin,
116 draw_canvas_overlay();
119 y += canvas->get_h() + 1;
120 add_subwindow(new BC_Title(title1_x,
123 add_subwindow(new BC_Title(title2_x,
126 add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"),
129 add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"),
134 add_subwindow(title = new BC_Title(x, y, _("Output min:")));
135 x += title->get_w() + 10;
136 output_min = new HistogramOutputText(plugin,
140 &plugin->config.output_min[plugin->mode]);
141 output_min->create_objects();
142 x += output_min->get_w() + 10;
143 add_subwindow(new BC_Title(x, y, _("Output Max:")));
144 x += title->get_w() + 10;
145 output_max = new HistogramOutputText(plugin,
149 &plugin->config.output_max[plugin->mode]);
150 output_max->create_objects();
155 add_subwindow(output = new HistogramSlider(plugin,
166 add_subwindow(automatic = new HistogramAuto(plugin,
171 add_subwindow(new HistogramReset(plugin,
175 add_subwindow(new BC_Title(x, y, _("Threshold:")));
177 threshold = new HistogramOutputText(plugin,
181 &plugin->config.threshold);
182 threshold->create_objects();
190 WINDOW_CLOSE_EVENT(HistogramWindow)
192 int HistogramWindow::keypress_event()
195 if(get_keypress() == BACKSPACE ||
196 get_keypress() == DELETE)
198 if(plugin->current_point >= 0)
200 HistogramPoint *current =
201 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
203 plugin->current_point = -1;
206 plugin->send_configure_change();
213 void HistogramWindow::update(int do_input)
215 automatic->update(plugin->config.automatic);
216 threshold->update(plugin->config.threshold);
219 if(do_input) update_input();
223 void HistogramWindow::update_input()
229 void HistogramWindow::update_output()
232 output_min->update(plugin->config.output_min[plugin->mode]);
233 output_max->update(plugin->config.output_max[plugin->mode]);
236 void HistogramWindow::update_mode()
238 mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
239 mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
240 mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
241 mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
242 output_min->output = &plugin->config.output_min[plugin->mode];
243 output_max->output = &plugin->config.output_max[plugin->mode];
246 void HistogramWindow::draw_canvas_overlay()
248 canvas->set_color(0x00ff00);
251 // Calculate output curve
252 plugin->tabulate_curve(plugin->mode, 0);
255 for(int i = 0; i < canvas_w; i++)
257 float input = (float)i /
261 float output = plugin->calculate_smooth(input, plugin->mode);
263 int y2 = canvas_h - (int)(output * canvas_h);
266 canvas->draw_line(i - 1, y1, i, y2);
271 // Draw output points
272 HistogramPoint *current = plugin->config.points[plugin->mode].first;
276 int x = (int)((current->x - MIN_INPUT) * canvas_w / FLOAT_RANGE);
277 int y = (int)(canvas_h - current->y * canvas_h);
278 if(number == plugin->current_point)
279 canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
281 canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
287 // Draw 0 and 100% lines.
288 canvas->set_color(0xff0000);
289 canvas->draw_line(title2_x - canvas->get_x(),
291 title2_x - canvas->get_x(),
293 canvas->draw_line(title3_x - canvas->get_x(),
295 title3_x - canvas->get_x(),
299 void HistogramWindow::update_canvas()
301 int *accum = plugin->accum[plugin->mode];
302 int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
303 float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
307 for(int i = 0; i < HISTOGRAM_SLOTS; i++)
309 if(accum && accum[i] > normalize) normalize = accum[i];
315 for(int i = 0; i < canvas_w; i++)
317 int accum_start = (int)(accum_per_canvas_f * i);
318 int accum_end = accum_start + accum_per_canvas_i;
320 for(int j = accum_start; j < accum_end; j++)
322 max = MAX(accum[j], max);
325 // max = max * canvas_h / normalize;
326 max = (int)(log(max) / log(normalize) * canvas_h);
328 canvas->set_color(0xffffff);
329 canvas->draw_line(i, 0, i, canvas_h - max);
330 canvas->set_color(0x000000);
331 canvas->draw_line(i, canvas_h - max, i, canvas_h);
336 canvas->set_color(0xffffff);
337 canvas->draw_box(0, 0, canvas_w, canvas_h);
341 draw_canvas_overlay();
352 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
353 HistogramWindow *gui,
364 this->plugin = plugin;
368 int HistogramCanvas::button_press_event()
371 if(is_event_win() && cursor_inside())
373 if(!plugin->dragging_point)
375 HistogramPoint *new_point = 0;
377 // Search for existing point under cursor
378 HistogramPoint *current = plugin->config.points[plugin->mode].first;
379 plugin->current_point = -1;
382 int x = (int)((current->x - MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
383 int y = (int)(gui->canvas_h - current->y * gui->canvas_h);
385 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
386 get_cursor_y() >= y - BOX_SIZE / 2 &&
387 get_cursor_x() < x + BOX_SIZE / 2 &&
388 get_cursor_y() < y + BOX_SIZE / 2)
390 plugin->current_point =
391 plugin->config.points[plugin->mode].number_of(current);
392 plugin->point_x_offset = get_cursor_x() - x;
393 plugin->point_y_offset = get_cursor_y() - y;
399 if(plugin->current_point < 0)
401 // Create new point under cursor
402 float current_x = (float)get_cursor_x() *
406 float current_y = 1.0 -
407 (float)get_cursor_y() /
410 plugin->config.points[plugin->mode].insert(current_x, current_y);
411 plugin->current_point =
412 plugin->config.points[plugin->mode].number_of(new_point);
413 plugin->point_x_offset = 0;
414 plugin->point_y_offset = 0;
417 plugin->dragging_point = 1;
420 plugin->config.boundaries();
422 gui->update_canvas();
425 plugin->send_configure_change();
432 int HistogramCanvas::cursor_motion_event()
434 if(plugin->dragging_point)
437 (float)(get_cursor_x() - plugin->point_x_offset) *
441 float current_y = 1.0 -
442 (float)(get_cursor_y() - plugin->point_y_offset) /
444 HistogramPoint *current_point =
445 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
446 current_point->x = current_x;
447 current_point->y = current_y;
448 plugin->config.boundaries();
450 gui->update_canvas();
451 plugin->send_configure_change();
457 int HistogramCanvas::button_release_event()
459 if(plugin->dragging_point)
461 // Test for out of order points to delete.
462 HistogramPoint *current =
463 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
464 HistogramPoint *prev = PREVIOUS;
465 HistogramPoint *next = NEXT;
467 if((prev && prev->x >= current->x) ||
468 (next && next->x <= current->x))
471 plugin->current_point = -1;
472 plugin->config.boundaries();
474 gui->update_canvas();
475 plugin->send_configure_change();
478 plugin->dragging_point = 0;
489 HistogramReset::HistogramReset(HistogramMain *plugin,
492 : BC_GenericButton(x, y, _("Reset"))
494 this->plugin = plugin;
496 int HistogramReset::handle_event()
498 plugin->config.reset(0);
499 plugin->thread->window->update(1);
500 plugin->thread->window->update_canvas();
501 plugin->send_configure_change();
513 HistogramSlider::HistogramSlider(HistogramMain *plugin,
514 HistogramWindow *gui,
520 : BC_SubWindow(x, y, w, h)
522 this->plugin = plugin;
524 this->is_input = is_input;
528 int HistogramSlider::input_to_pixel(float input)
530 return (int)((input - MIN_INPUT) / FLOAT_RANGE * get_w());
533 int HistogramSlider::button_press_event()
535 if(is_event_win() && cursor_inside())
541 int half_h = get_h() / 2;
545 if(operation == NONE)
547 int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) -
548 gui->mid_picon->get_w() / 2;
549 int x2 = x1 + gui->mid_picon->get_w();
550 if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
551 get_cursor_y() >= half_h && get_cursor_y() < h)
553 operation = DRAG_MIN_OUTPUT;
557 if(operation == NONE)
559 int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) -
560 gui->mid_picon->get_w() / 2;
561 int x2 = x1 + gui->mid_picon->get_w();
562 if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
563 get_cursor_y() >= half_h && get_cursor_y() < h)
565 operation = DRAG_MAX_OUTPUT;
573 int HistogramSlider::button_release_event()
575 if(operation != NONE)
583 int HistogramSlider::cursor_motion_event()
585 if(operation != NONE)
587 float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + MIN_INPUT;
588 CLAMP(value, MIN_INPUT, MAX_INPUT);
592 case DRAG_MIN_OUTPUT:
593 value = MIN(plugin->config.output_max[plugin->mode], value);
594 plugin->config.output_min[plugin->mode] = value;
596 case DRAG_MAX_OUTPUT:
597 value = MAX(plugin->config.output_min[plugin->mode], value);
598 plugin->config.output_max[plugin->mode] = value;
602 plugin->config.boundaries();
603 gui->update_output();
605 plugin->send_configure_change();
611 void HistogramSlider::update()
615 int half_h = get_h() / 2;
616 int quarter_h = get_h() / 4;
617 int mode = plugin->mode;
622 clear_box(0, 0, w, h);
629 case HISTOGRAM_GREEN:
637 for(int i = 0; i < w; i++)
639 int color = (int)(i * 0xff / w);
640 set_color(((r * color / 0xff) << 16) |
641 ((g * color / 0xff) << 8) |
644 draw_line(i, 0, i, half_h);
649 min = plugin->config.output_min[plugin->mode];
650 max = plugin->config.output_max[plugin->mode];
652 draw_pixmap(gui->min_picon,
653 input_to_pixel(min) - gui->min_picon->get_w() / 2,
655 draw_pixmap(gui->max_picon,
656 input_to_pixel(max) - gui->max_picon->get_w() / 2,
671 HistogramAuto::HistogramAuto(HistogramMain *plugin,
674 : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
676 this->plugin = plugin;
679 int HistogramAuto::handle_event()
681 plugin->config.automatic = get_value();
682 plugin->send_configure_change();
689 HistogramMode::HistogramMode(HistogramMain *plugin,
694 : BC_Radial(x, y, plugin->mode == value, text)
696 this->plugin = plugin;
699 int HistogramMode::handle_event()
701 plugin->mode = value;
702 plugin->current_point= -1;
703 plugin->thread->window->update_canvas();
704 plugin->thread->window->update_mode();
705 plugin->thread->window->update_input();
706 plugin->thread->window->update_canvas();
707 plugin->thread->window->update_output();
708 plugin->thread->window->output->update();
709 // plugin->send_configure_change();
721 HistogramOutputText::HistogramOutputText(HistogramMain *plugin,
722 HistogramWindow *gui,
726 : BC_TumbleTextBox(gui,
727 output ? (float)*output : 0.0,
734 this->plugin = plugin;
735 this->output = output;
736 set_precision(DIGITS);
737 set_increment(PRECISION);
741 int HistogramOutputText::handle_event()
745 *output = atof(get_text());
748 plugin->thread->window->output->update();
749 plugin->send_configure_change();
760 HistogramInputText::HistogramInputText(HistogramMain *plugin,
761 HistogramWindow *gui,
765 : BC_TumbleTextBox(gui,
774 this->plugin = plugin;
776 set_precision(DIGITS);
777 set_increment(PRECISION);
781 int HistogramInputText::handle_event()
783 if(plugin->current_point >= 0 &&
784 plugin->current_point < plugin->config.points[plugin->mode].total())
786 HistogramPoint *point =
787 plugin->config.points[plugin->mode].get_item_number(
788 plugin->current_point);
793 point->x = atof(get_text());
795 point->y = atof(get_text());
797 plugin->config.boundaries();
798 gui->update_canvas();
800 plugin->thread->window->output->update();
801 plugin->send_configure_change();
807 void HistogramInputText::update()
809 if(plugin->current_point >= 0 &&
810 plugin->current_point < plugin->config.points[plugin->mode].total())
812 HistogramPoint *point =
814 plugin->config.points[plugin->mode].get_item_number(
815 plugin->current_point);
820 BC_TumbleTextBox::update(point->x);
822 BC_TumbleTextBox::update(point->y);
826 BC_TumbleTextBox::update((float)0.0);
831 BC_TumbleTextBox::update((float)0.0);