1 #include "bcdisplayinfo.h"
5 #include "histogramconfig.h"
6 #include "histogramwindow.h"
13 PLUGIN_THREAD_OBJECT(HistogramMain, HistogramThread, HistogramWindow)
17 HistogramWindow::HistogramWindow(HistogramMain *plugin, int x, int y)
18 : BC_Window(plugin->gui_string,
29 this->plugin = plugin;
32 HistogramWindow::~HistogramWindow()
36 #include "max_picon_png.h"
37 #include "mid_picon_png.h"
38 #include "min_picon_png.h"
39 static VFrame max_picon_image(max_picon_png);
40 static VFrame mid_picon_image(mid_picon_png);
41 static VFrame min_picon_image(min_picon_png);
43 int HistogramWindow::create_objects()
45 int x = 10, y = 10, x1 = 10;
48 max_picon = new BC_Pixmap(this, &max_picon_image);
49 mid_picon = new BC_Pixmap(this, &mid_picon_image);
50 min_picon = new BC_Pixmap(this, &min_picon_image);
51 add_subwindow(mode_v = new HistogramMode(plugin,
57 add_subwindow(mode_r = new HistogramMode(plugin,
63 add_subwindow(mode_g = new HistogramMode(plugin,
69 add_subwindow(mode_b = new HistogramMode(plugin,
75 // add_subwindow(mode_a = new HistogramMode(plugin,
83 add_subwindow(title = new BC_Title(x, y, _("Input X:")));
84 x += title->get_w() + 10;
85 input_x = new HistogramInputText(plugin,
90 input_x->create_objects();
92 x += input_x->get_w() + 10;
93 add_subwindow(title = new BC_Title(x, y, _("Input Y:")));
94 x += title->get_w() + 10;
95 input_y = new HistogramInputText(plugin,
100 input_y->create_objects();
105 canvas_w = get_w() - x - x;
106 canvas_h = get_h() - y - 170;
108 title2_x = x + (int)(canvas_w * -MIN_INPUT / FLOAT_RANGE);
109 title3_x = x + (int)(canvas_w * (1.0 - MIN_INPUT) / FLOAT_RANGE);
110 title4_x = x + (int)(canvas_w);
111 add_subwindow(canvas = new HistogramCanvas(plugin,
117 draw_canvas_overlay();
120 y += canvas->get_h() + 1;
121 add_subwindow(new BC_Title(title1_x,
124 add_subwindow(new BC_Title(title2_x,
127 add_subwindow(new BC_Title(title3_x - get_text_width(MEDIUMFONT, "100"),
130 add_subwindow(new BC_Title(title4_x - get_text_width(MEDIUMFONT, "110"),
135 add_subwindow(title = new BC_Title(x, y, _("Output min:")));
136 x += title->get_w() + 10;
137 output_min = new HistogramOutputText(plugin,
141 &plugin->config.output_min[plugin->mode]);
142 output_min->create_objects();
143 x += output_min->get_w() + 10;
144 add_subwindow(new BC_Title(x, y, _("Output Max:")));
145 x += title->get_w() + 10;
146 output_max = new HistogramOutputText(plugin,
150 &plugin->config.output_max[plugin->mode]);
151 output_max->create_objects();
156 add_subwindow(output = new HistogramSlider(plugin,
167 add_subwindow(automatic = new HistogramAuto(plugin,
172 add_subwindow(new HistogramReset(plugin,
176 add_subwindow(new BC_Title(x, y, _("Threshold:")));
178 threshold = new HistogramOutputText(plugin,
182 &plugin->config.threshold);
183 threshold->create_objects();
187 add_subwindow(split = new HistogramSplit(plugin, x, y));
194 WINDOW_CLOSE_EVENT(HistogramWindow)
196 int HistogramWindow::keypress_event()
199 if(get_keypress() == BACKSPACE ||
200 get_keypress() == DELETE)
202 if(plugin->current_point >= 0)
204 HistogramPoint *current =
205 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
207 plugin->current_point = -1;
210 plugin->send_configure_change();
217 void HistogramWindow::update(int do_input)
219 automatic->update(plugin->config.automatic);
220 threshold->update(plugin->config.threshold);
223 if(do_input) update_input();
227 void HistogramWindow::update_input()
233 void HistogramWindow::update_output()
236 output_min->update(plugin->config.output_min[plugin->mode]);
237 output_max->update(plugin->config.output_max[plugin->mode]);
240 void HistogramWindow::update_mode()
242 mode_v->update(plugin->mode == HISTOGRAM_VALUE ? 1 : 0);
243 mode_r->update(plugin->mode == HISTOGRAM_RED ? 1 : 0);
244 mode_g->update(plugin->mode == HISTOGRAM_GREEN ? 1 : 0);
245 mode_b->update(plugin->mode == HISTOGRAM_BLUE ? 1 : 0);
246 output_min->output = &plugin->config.output_min[plugin->mode];
247 output_max->output = &plugin->config.output_max[plugin->mode];
250 void HistogramWindow::draw_canvas_overlay()
252 canvas->set_color(0x00ff00);
255 // Calculate output curve
256 plugin->tabulate_curve(plugin->mode, 0);
259 for(int i = 0; i < canvas_w; i++)
261 float input = (float)i /
265 float output = plugin->calculate_smooth(input, plugin->mode);
267 int y2 = canvas_h - (int)(output * canvas_h);
270 canvas->draw_line(i - 1, y1, i, y2);
275 // Draw output points
276 HistogramPoint *current = plugin->config.points[plugin->mode].first;
280 int x = (int)((current->x - MIN_INPUT) * canvas_w / FLOAT_RANGE);
281 int y = (int)(canvas_h - current->y * canvas_h);
282 if(number == plugin->current_point)
283 canvas->draw_box(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
285 canvas->draw_rectangle(x - BOX_SIZE / 2, y - BOX_SIZE / 2, BOX_SIZE, BOX_SIZE);
291 // Draw 0 and 100% lines.
292 canvas->set_color(0xff0000);
293 canvas->draw_line(title2_x - canvas->get_x(),
295 title2_x - canvas->get_x(),
297 canvas->draw_line(title3_x - canvas->get_x(),
299 title3_x - canvas->get_x(),
303 void HistogramWindow::update_canvas()
305 int *accum = plugin->accum[plugin->mode];
306 int accum_per_canvas_i = HISTOGRAM_SLOTS / canvas_w + 1;
307 float accum_per_canvas_f = (float)HISTOGRAM_SLOTS / canvas_w;
311 for(int i = 0; i < HISTOGRAM_SLOTS; i++)
313 if(accum && accum[i] > normalize) normalize = accum[i];
319 for(int i = 0; i < canvas_w; i++)
321 int accum_start = (int)(accum_per_canvas_f * i);
322 int accum_end = accum_start + accum_per_canvas_i;
324 for(int j = accum_start; j < accum_end; j++)
326 max = MAX(accum[j], max);
329 // max = max * canvas_h / normalize;
330 max = (int)(log(max) / log(normalize) * canvas_h);
332 canvas->set_color(0xffffff);
333 canvas->draw_line(i, 0, i, canvas_h - max);
334 canvas->set_color(0x000000);
335 canvas->draw_line(i, canvas_h - max, i, canvas_h);
340 canvas->set_color(0xffffff);
341 canvas->draw_box(0, 0, canvas_w, canvas_h);
345 draw_canvas_overlay();
356 HistogramCanvas::HistogramCanvas(HistogramMain *plugin,
357 HistogramWindow *gui,
368 this->plugin = plugin;
372 int HistogramCanvas::button_press_event()
375 if(is_event_win() && cursor_inside())
377 if(!plugin->dragging_point)
379 HistogramPoint *new_point = 0;
381 // Search for existing point under cursor
382 HistogramPoint *current = plugin->config.points[plugin->mode].first;
383 plugin->current_point = -1;
386 int x = (int)((current->x - MIN_INPUT) * gui->canvas_w / FLOAT_RANGE);
387 int y = (int)(gui->canvas_h - current->y * gui->canvas_h);
389 if(get_cursor_x() >= x - BOX_SIZE / 2 &&
390 get_cursor_y() >= y - BOX_SIZE / 2 &&
391 get_cursor_x() < x + BOX_SIZE / 2 &&
392 get_cursor_y() < y + BOX_SIZE / 2)
394 plugin->current_point =
395 plugin->config.points[plugin->mode].number_of(current);
396 plugin->point_x_offset = get_cursor_x() - x;
397 plugin->point_y_offset = get_cursor_y() - y;
403 if(plugin->current_point < 0)
405 // Create new point under cursor
406 float current_x = (float)get_cursor_x() *
410 float current_y = 1.0 -
411 (float)get_cursor_y() /
414 plugin->config.points[plugin->mode].insert(current_x, current_y);
415 plugin->current_point =
416 plugin->config.points[plugin->mode].number_of(new_point);
417 plugin->point_x_offset = 0;
418 plugin->point_y_offset = 0;
421 plugin->dragging_point = 1;
424 plugin->config.boundaries();
426 gui->update_canvas();
429 plugin->send_configure_change();
436 int HistogramCanvas::cursor_motion_event()
438 if(plugin->dragging_point)
441 (float)(get_cursor_x() - plugin->point_x_offset) *
445 float current_y = 1.0 -
446 (float)(get_cursor_y() - plugin->point_y_offset) /
448 HistogramPoint *current_point =
449 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
450 current_point->x = current_x;
451 current_point->y = current_y;
452 plugin->config.boundaries();
454 gui->update_canvas();
455 plugin->send_configure_change();
461 int HistogramCanvas::button_release_event()
463 if(plugin->dragging_point)
465 // Test for out of order points to delete.
466 HistogramPoint *current =
467 plugin->config.points[plugin->mode].get_item_number(plugin->current_point);
468 HistogramPoint *prev = PREVIOUS;
469 HistogramPoint *next = NEXT;
471 if((prev && prev->x >= current->x) ||
472 (next && next->x <= current->x))
475 plugin->current_point = -1;
476 plugin->config.boundaries();
478 gui->update_canvas();
479 plugin->send_configure_change();
482 plugin->dragging_point = 0;
493 HistogramReset::HistogramReset(HistogramMain *plugin,
496 : BC_GenericButton(x, y, _("Reset"))
498 this->plugin = plugin;
500 int HistogramReset::handle_event()
502 plugin->config.reset(0);
503 plugin->thread->window->update(1);
504 plugin->thread->window->update_canvas();
505 plugin->send_configure_change();
517 HistogramSlider::HistogramSlider(HistogramMain *plugin,
518 HistogramWindow *gui,
524 : BC_SubWindow(x, y, w, h)
526 this->plugin = plugin;
528 this->is_input = is_input;
532 int HistogramSlider::input_to_pixel(float input)
534 return (int)((input - MIN_INPUT) / FLOAT_RANGE * get_w());
537 int HistogramSlider::button_press_event()
539 if(is_event_win() && cursor_inside())
545 int half_h = get_h() / 2;
549 if(operation == NONE)
551 int x1 = input_to_pixel(plugin->config.output_min[plugin->mode]) -
552 gui->mid_picon->get_w() / 2;
553 int x2 = x1 + gui->mid_picon->get_w();
554 if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
555 get_cursor_y() >= half_h && get_cursor_y() < h)
557 operation = DRAG_MIN_OUTPUT;
561 if(operation == NONE)
563 int x1 = input_to_pixel(plugin->config.output_max[plugin->mode]) -
564 gui->mid_picon->get_w() / 2;
565 int x2 = x1 + gui->mid_picon->get_w();
566 if(get_cursor_x() >= x1 && get_cursor_x() < x2 &&
567 get_cursor_y() >= half_h && get_cursor_y() < h)
569 operation = DRAG_MAX_OUTPUT;
577 int HistogramSlider::button_release_event()
579 if(operation != NONE)
587 int HistogramSlider::cursor_motion_event()
589 if(operation != NONE)
591 float value = (float)get_cursor_x() / get_w() * FLOAT_RANGE + MIN_INPUT;
592 CLAMP(value, MIN_INPUT, MAX_INPUT);
596 case DRAG_MIN_OUTPUT:
597 value = MIN(plugin->config.output_max[plugin->mode], value);
598 plugin->config.output_min[plugin->mode] = value;
600 case DRAG_MAX_OUTPUT:
601 value = MAX(plugin->config.output_min[plugin->mode], value);
602 plugin->config.output_max[plugin->mode] = value;
606 plugin->config.boundaries();
607 gui->update_output();
609 plugin->send_configure_change();
615 void HistogramSlider::update()
619 int half_h = get_h() / 2;
620 int quarter_h = get_h() / 4;
621 int mode = plugin->mode;
626 clear_box(0, 0, w, h);
633 case HISTOGRAM_GREEN:
641 for(int i = 0; i < w; i++)
643 int color = (int)(i * 0xff / w);
644 set_color(((r * color / 0xff) << 16) |
645 ((g * color / 0xff) << 8) |
648 draw_line(i, 0, i, half_h);
653 min = plugin->config.output_min[plugin->mode];
654 max = plugin->config.output_max[plugin->mode];
656 draw_pixmap(gui->min_picon,
657 input_to_pixel(min) - gui->min_picon->get_w() / 2,
659 draw_pixmap(gui->max_picon,
660 input_to_pixel(max) - gui->max_picon->get_w() / 2,
675 HistogramAuto::HistogramAuto(HistogramMain *plugin,
678 : BC_CheckBox(x, y, plugin->config.automatic, _("Automatic"))
680 this->plugin = plugin;
683 int HistogramAuto::handle_event()
685 plugin->config.automatic = get_value();
686 plugin->send_configure_change();
693 HistogramSplit::HistogramSplit(HistogramMain *plugin,
696 : BC_CheckBox(x, y, plugin->config.split, _("Split picture"))
698 this->plugin = plugin;
701 int HistogramSplit::handle_event()
703 plugin->config.split = get_value();
704 plugin->send_configure_change();
710 HistogramMode::HistogramMode(HistogramMain *plugin,
715 : BC_Radial(x, y, plugin->mode == value, text)
717 this->plugin = plugin;
720 int HistogramMode::handle_event()
722 plugin->mode = value;
723 plugin->current_point= -1;
724 plugin->thread->window->update_canvas();
725 plugin->thread->window->update_mode();
726 plugin->thread->window->update_input();
727 plugin->thread->window->update_canvas();
728 plugin->thread->window->update_output();
729 plugin->thread->window->output->update();
730 // plugin->send_configure_change();
742 HistogramOutputText::HistogramOutputText(HistogramMain *plugin,
743 HistogramWindow *gui,
747 : BC_TumbleTextBox(gui,
748 output ? (float)*output : 0.0,
755 this->plugin = plugin;
756 this->output = output;
757 set_precision(DIGITS);
758 set_increment(PRECISION);
762 int HistogramOutputText::handle_event()
766 *output = atof(get_text());
769 plugin->thread->window->output->update();
770 plugin->send_configure_change();
781 HistogramInputText::HistogramInputText(HistogramMain *plugin,
782 HistogramWindow *gui,
786 : BC_TumbleTextBox(gui,
795 this->plugin = plugin;
797 set_precision(DIGITS);
798 set_increment(PRECISION);
802 int HistogramInputText::handle_event()
804 if(plugin->current_point >= 0 &&
805 plugin->current_point < plugin->config.points[plugin->mode].total())
807 HistogramPoint *point =
808 plugin->config.points[plugin->mode].get_item_number(
809 plugin->current_point);
814 point->x = atof(get_text());
816 point->y = atof(get_text());
818 plugin->config.boundaries();
819 gui->update_canvas();
821 plugin->thread->window->output->update();
822 plugin->send_configure_change();
828 void HistogramInputText::update()
830 if(plugin->current_point >= 0 &&
831 plugin->current_point < plugin->config.points[plugin->mode].total())
833 HistogramPoint *point =
835 plugin->config.points[plugin->mode].get_item_number(
836 plugin->current_point);
841 BC_TumbleTextBox::update(point->x);
843 BC_TumbleTextBox::update(point->y);
847 BC_TumbleTextBox::update((float)0.0);
852 BC_TumbleTextBox::update((float)0.0);