Pipette and "On Preview Widgets" branch. See issue 227
The pipette part is already working quite nice but need to be finished. The widgets part needs more work...
This commit is contained in:
835
rtgui/histogrampanel.cc
Normal file
835
rtgui/histogrampanel.cc
Normal file
@@ -0,0 +1,835 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "histogrampanel.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "guiutils.h"
|
||||
#include "options.h"
|
||||
#include <cstring>
|
||||
#include "../rtengine/LUT.h"
|
||||
#include "rtimage.h"
|
||||
#include "../rtengine/improccoordinator.h"
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
extern Options options;
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
// HistogramPanel
|
||||
HistogramPanel::HistogramPanel () {
|
||||
|
||||
histogramArea = Gtk::manage (new HistogramArea (this));
|
||||
histogramRGBArea = Gtk::manage (new HistogramRGBArea ());
|
||||
histogramRGBArea->show();
|
||||
|
||||
gfxVBox = Gtk::manage (new Gtk::VBox (false, 2));
|
||||
histogramRGBArea->setParent(gfxVBox);
|
||||
gfxVBox->pack_start (*histogramArea, Gtk::PACK_EXPAND_WIDGET, 0);
|
||||
if (options.histogramBar)
|
||||
gfxVBox->pack_start (*histogramRGBArea, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
redImage = new RTImage ("histRed.png");
|
||||
greenImage = new RTImage ("histGreen.png");
|
||||
blueImage = new RTImage ("histBlue.png");
|
||||
valueImage = new RTImage ("histValue.png");
|
||||
chroImage = new RTImage ("histChro.png");
|
||||
rawImage = new RTImage ("histRaw.png");
|
||||
fullImage = new RTImage ("histFull.png");
|
||||
barImage = new RTImage ("histBar.png");
|
||||
|
||||
redImage_g = new RTImage ("histRedg.png");
|
||||
greenImage_g = new RTImage ("histGreeng.png");
|
||||
blueImage_g = new RTImage ("histBlueg.png");
|
||||
valueImage_g = new RTImage ("histValueg.png");
|
||||
chroImage_g = new RTImage ("histChrog.png");
|
||||
rawImage_g = new RTImage ("histRawg.png");
|
||||
fullImage_g = new RTImage ("histFullg.png");
|
||||
barImage_g = new RTImage ("histBarg.png");
|
||||
|
||||
showRed = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showGreen = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showBlue = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showValue = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showChro = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showRAW = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showFull = Gtk::manage (new Gtk::ToggleButton ());
|
||||
showBAR = Gtk::manage (new Gtk::ToggleButton ());
|
||||
|
||||
showRed->set_name("histButton"); showRed->set_can_focus(false);
|
||||
showGreen->set_name("histButton"); showGreen->set_can_focus(false);
|
||||
showBlue->set_name("histButton"); showBlue->set_can_focus(false);
|
||||
showValue->set_name("histButton"); showValue->set_can_focus(false);
|
||||
showChro->set_name("histButton"); showChro->set_can_focus(false);
|
||||
showRAW->set_name("histButton"); showRAW->set_can_focus(false);
|
||||
showFull->set_name("fullButton"); showFull->set_can_focus(false);
|
||||
showBAR->set_name("histButton"); showBAR->set_can_focus(false);
|
||||
|
||||
showRed->set_relief (Gtk::RELIEF_NONE);
|
||||
showGreen->set_relief (Gtk::RELIEF_NONE);
|
||||
showBlue->set_relief (Gtk::RELIEF_NONE);
|
||||
showValue->set_relief (Gtk::RELIEF_NONE);
|
||||
showChro->set_relief (Gtk::RELIEF_NONE);
|
||||
showRAW->set_relief (Gtk::RELIEF_NONE);
|
||||
showFull->set_relief (Gtk::RELIEF_NONE);
|
||||
showBAR->set_relief (Gtk::RELIEF_NONE);
|
||||
|
||||
showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R"));
|
||||
showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G"));
|
||||
showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B"));
|
||||
showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L"));
|
||||
showChro->set_tooltip_text (M("HISTOGRAM_TOOLTIP_CHRO"));
|
||||
showRAW->set_tooltip_text (M("HISTOGRAM_TOOLTIP_RAW"));
|
||||
showFull->set_tooltip_text (M("HISTOGRAM_TOOLTIP_FULL"));
|
||||
showBAR->set_tooltip_text (M("HISTOGRAM_TOOLTIP_BAR"));
|
||||
|
||||
buttonVBox = Gtk::manage (new Gtk::VBox (false, 2));
|
||||
showRed->set_active (true);
|
||||
showGreen->set_active (true);
|
||||
showBlue->set_active (true);
|
||||
showValue->set_active (true);
|
||||
showChro->set_active (false);//unactive by default
|
||||
|
||||
showRAW->set_active (false);
|
||||
showFull->set_active (!options.histogramFullMode);
|
||||
showBAR->set_active (options.histogramBar);
|
||||
|
||||
showRed->set_image (showRed->get_active() ? *redImage : *redImage_g);
|
||||
showGreen->set_image (showGreen->get_active() ? *greenImage : *greenImage_g);
|
||||
showBlue->set_image (showBlue->get_active() ? *blueImage : *blueImage_g);
|
||||
showValue->set_image (showValue->get_active() ? *valueImage : *valueImage_g);
|
||||
showChro->set_image (showChro->get_active() ? *chroImage : *chroImage_g);
|
||||
showRAW->set_image (showRAW->get_active() ? *rawImage : *rawImage_g);
|
||||
showFull->set_image (showFull->get_active() ? *fullImage : *fullImage_g);
|
||||
showBAR->set_image (showBAR->get_active() ? *barImage : *barImage_g);
|
||||
|
||||
showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::red_toggled), showRed );
|
||||
showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::green_toggled), showGreen );
|
||||
showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::blue_toggled), showBlue );
|
||||
showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::value_toggled), showValue );
|
||||
showChro->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::chro_toggled), showChro );
|
||||
showRAW->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::raw_toggled), showRAW );
|
||||
showFull->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::full_toggled), showFull );
|
||||
showBAR->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::bar_toggled), showBAR );
|
||||
|
||||
buttonVBox->pack_start (*showRed, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showGreen, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showBlue, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showValue, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showChro, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showRAW, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showFull, Gtk::PACK_SHRINK, 0);
|
||||
buttonVBox->pack_start (*showBAR, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
// Put the button vbox next to the window's border to be less disturbing
|
||||
if (options.histogramPosition == 1) {
|
||||
pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2);
|
||||
pack_start (*gfxVBox,Gtk::PACK_EXPAND_WIDGET, 2);
|
||||
}
|
||||
else {
|
||||
pack_start (*gfxVBox,Gtk::PACK_EXPAND_WIDGET, 2);
|
||||
pack_start (*buttonVBox, Gtk::PACK_SHRINK, 2);
|
||||
}
|
||||
|
||||
show_all ();
|
||||
|
||||
rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) );
|
||||
}
|
||||
|
||||
HistogramPanel::~HistogramPanel () {
|
||||
delete redImage;
|
||||
delete greenImage;
|
||||
delete blueImage;
|
||||
delete valueImage;
|
||||
delete chroImage;
|
||||
delete rawImage;
|
||||
delete fullImage;
|
||||
delete barImage;
|
||||
|
||||
delete redImage_g;
|
||||
delete greenImage_g;
|
||||
delete blueImage_g;
|
||||
delete valueImage_g;
|
||||
delete chroImage_g;
|
||||
delete rawImage_g;
|
||||
delete fullImage_g;
|
||||
delete barImage_g;
|
||||
|
||||
}
|
||||
|
||||
void HistogramPanel::resized (Gtk::Allocation& req) {
|
||||
|
||||
rconn.block (true);
|
||||
|
||||
int gHeight = req.get_width()/2;
|
||||
if (gHeight > 150) gHeight = 150; else if (gHeight < 100) gHeight = 100;
|
||||
int bHeight = req.get_width()/30;
|
||||
if (bHeight > 10) bHeight = 10; else if (bHeight < 5 ) bHeight = 5;
|
||||
histogramArea->set_size_request (req.get_width(), gHeight);
|
||||
histogramRGBArea->set_size_request (req.get_width(), bHeight);
|
||||
|
||||
rconn.block (false);
|
||||
|
||||
histogramArea->renderHistogram ();
|
||||
histogramArea->queue_draw ();
|
||||
|
||||
if (histogramRGBArea->getFreeze()==true) {
|
||||
histogramRGBArea->updateFreeze(false);
|
||||
// set histogramRGBArea invalid;
|
||||
histogramRGBArea->renderRGBMarks(-1, -1, -1);
|
||||
// re-set freeze to old state
|
||||
histogramRGBArea->updateFreeze(true);
|
||||
histogramRGBArea->queue_draw ();
|
||||
}
|
||||
else {
|
||||
// set histogramRGBArea invalid;
|
||||
histogramRGBArea->renderRGBMarks(-1, -1, -1);
|
||||
histogramRGBArea->queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void HistogramPanel::red_toggled () {
|
||||
showRed->set_image(showRed->get_active() ? *redImage : *redImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::green_toggled () {
|
||||
showGreen->set_image(showGreen->get_active() ? *greenImage : *greenImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::blue_toggled () {
|
||||
showBlue->set_image(showBlue->get_active() ? *blueImage : *blueImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::value_toggled () {
|
||||
removeIfThere(showValue, valueImage, false);
|
||||
removeIfThere(showValue, valueImage_g, false);
|
||||
showValue->set_image(showValue->get_active() ? *valueImage : *valueImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::chro_toggled () {
|
||||
removeIfThere(showChro, chroImage, false);
|
||||
removeIfThere(showChro, chroImage_g, false);
|
||||
showChro->set_image(showChro->get_active() ? *chroImage : *chroImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
|
||||
void HistogramPanel::raw_toggled () {
|
||||
if (showRAW->get_active()) {
|
||||
showRAW->set_image(*rawImage);
|
||||
showValue->set_sensitive(false);
|
||||
showChro->set_sensitive(false);
|
||||
}
|
||||
else {
|
||||
showRAW->set_image(*rawImage_g);
|
||||
showValue->set_sensitive(true);
|
||||
showChro->set_sensitive(true);
|
||||
}
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::full_toggled () {
|
||||
options.histogramFullMode = !showFull->get_active();
|
||||
showFull->set_image(showFull->get_active() ? *fullImage : *fullImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::bar_toggled () {
|
||||
showBAR->set_image(showBAR->get_active() ? *barImage : *barImage_g);
|
||||
rgbv_toggled();
|
||||
}
|
||||
void HistogramPanel::rgbv_toggled () {
|
||||
// Update Display
|
||||
histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showFull->get_active(), showChro->get_active());
|
||||
histogramArea->queue_draw ();
|
||||
|
||||
histogramRGBArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active(), showRAW->get_active(), showBAR->get_active(), showChro->get_active());
|
||||
histogramRGBArea->renderRGBMarks (0,0,0);
|
||||
histogramArea->queue_draw ();
|
||||
}
|
||||
|
||||
void HistogramPanel::setHistRGBInvalid () {
|
||||
// do something to un-show vertical bars
|
||||
histogramRGBArea->renderRGBMarks(-1, -1, -1);
|
||||
histogramRGBArea->queue_draw ();
|
||||
}
|
||||
|
||||
// "Freeze" is not a button, but a RMB-click, so this is not in the RGBV-Toggle method
|
||||
void HistogramPanel::toggleFreeze () {
|
||||
if (histogramRGBArea->getFreeze()==true) {
|
||||
histogramRGBArea->updateFreeze(false);
|
||||
}
|
||||
else if (histogramRGBArea->getShow()==true) {
|
||||
histogramRGBArea->updateFreeze(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void HistogramPanel::pointerMoved (bool validPos, Glib::ustring profile, int x, int y, int r, int g, int b) {
|
||||
|
||||
if (!validPos) {
|
||||
// do something to un-show vertical bars
|
||||
histogramRGBArea->renderRGBMarks(-1, -1, -1);
|
||||
histogramRGBArea->queue_draw ();
|
||||
}
|
||||
else {
|
||||
// do something to show vertical bars
|
||||
histogramRGBArea->renderRGBMarks(r, g, b);
|
||||
histogramRGBArea->queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the vertical button bar to the right side
|
||||
* only allowed values for align are Gtk::ALIGN_LEFT and Gtk::ALIGN_RIGHT
|
||||
*/
|
||||
void HistogramPanel::reorder (Gtk::AlignmentEnum align) {
|
||||
if (align == Gtk::ALIGN_LEFT)
|
||||
reorder_child(*buttonVBox, 0);
|
||||
else
|
||||
reorder_child(*buttonVBox, 1);
|
||||
}
|
||||
|
||||
// FullModeListener interface:
|
||||
void HistogramPanel::toggle_button_full () {
|
||||
showFull->set_active (!showFull->get_active ());
|
||||
showFull->set_image(showFull->get_active() ? *fullImage : *fullImage_g);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// HistogramRGBArea
|
||||
HistogramRGBArea::HistogramRGBArea () ://needChroma unactive by default
|
||||
frozen(false), valid(false), needRed(true), needGreen(true), needBlue(true), needLuma(true), rawMode(false), showMode(options.histogramBar), barDisplayed(options.histogramBar), needChroma(false){
|
||||
|
||||
harih = new HistogramRGBAreaIdleHelper;
|
||||
harih->harea = this;
|
||||
harih->destroyed = false;
|
||||
harih->pending = 0;
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &HistogramRGBArea::styleChanged) );
|
||||
}
|
||||
|
||||
HistogramRGBArea::~HistogramRGBArea () {
|
||||
|
||||
if (harih->pending)
|
||||
harih->destroyed = true;
|
||||
else
|
||||
delete harih;
|
||||
}
|
||||
|
||||
bool HistogramRGBArea::getFreeze() {
|
||||
return(frozen);
|
||||
}
|
||||
|
||||
bool HistogramRGBArea::getShow() {
|
||||
return(showMode);
|
||||
}
|
||||
|
||||
void HistogramRGBArea::updateFreeze (bool f) {
|
||||
frozen = f;
|
||||
return;
|
||||
}
|
||||
|
||||
void HistogramRGBArea::renderRGBMarks (int r, int g, int b) {
|
||||
|
||||
if (!is_realized ())
|
||||
return;
|
||||
|
||||
if (frozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mostly not necessary, but should be in some case
|
||||
GThreadLock lock; // All GUI acces from idle_add callbacks or separate thread HAVE to be protected
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
int winx, winy, winw, winh, wind;
|
||||
window->get_geometry(winx, winy, winw, winh, wind);
|
||||
|
||||
overlay = Gdk::Pixmap::create (window, winw, winh, -1);
|
||||
Glib::RefPtr<Gdk::GC> ovrl = Gdk::GC::create(overlay);
|
||||
|
||||
Glib::RefPtr<Gtk::Style> style = get_style ();
|
||||
|
||||
if (!showMode) {
|
||||
ovrl->set_foreground (style->get_bg (Gtk::STATE_NORMAL));
|
||||
overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh);
|
||||
if (rgbgc_ && overlay) {
|
||||
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); }
|
||||
return; }
|
||||
else {
|
||||
ovrl->set_foreground (mgray);
|
||||
overlay->draw_rectangle (ovrl, true, 0, 0, winw, winh);
|
||||
if (rgbgc_ && overlay) {
|
||||
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1); }
|
||||
}
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> cr = overlay->create_cairo_context();
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
if ( r != -1 && g != -1 && b != -1 ) {
|
||||
if (needRed) {
|
||||
// Red
|
||||
cr->set_source_rgb(1.0, 0.0, 0.0);
|
||||
cr->move_to((int)(r*(winw/256.0)), 0);
|
||||
cr->line_to((int)(r*(winw/256.0)), winh-0);
|
||||
cr->stroke();
|
||||
}
|
||||
if (needGreen) {
|
||||
// Green
|
||||
cr->set_source_rgb(0.0, 1.0, 0.0);
|
||||
cr->move_to((int)(g*(winw/256.0)), 0);
|
||||
cr->line_to((int)(g*(winw/256.0)), winh-0);
|
||||
cr->stroke();
|
||||
}
|
||||
if (needBlue) {
|
||||
// Blue
|
||||
cr->set_source_rgb(0.0, 0.0, 1.0);
|
||||
cr->move_to((int)(b*(winw/256.0)), 0);
|
||||
cr->line_to((int)(b*(winw/256.0)), winh-0);
|
||||
cr->stroke();
|
||||
}
|
||||
if (needLuma) {
|
||||
// Luma
|
||||
cr->set_source_rgb(1.0, 1.0, 1.0);
|
||||
cr->move_to((int)((r+g+b)/3*(winw/256.0)), 0);
|
||||
cr->line_to((int)((r+g+b)/3*(winw/256.0)), winh-0);
|
||||
cr->stroke();
|
||||
}
|
||||
if (needChroma) {
|
||||
// Luma
|
||||
cr->set_source_rgb(1.0, 1.0, 1.0);
|
||||
cr->move_to((int)((r+g+b)/3*(winw/256.0)), 0);
|
||||
cr->line_to((int)((r+g+b)/3*(winw/256.0)), winh-0);
|
||||
cr->stroke();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int histrgbupdate (void* data) {
|
||||
|
||||
HistogramRGBAreaIdleHelper* harih = static_cast<HistogramRGBAreaIdleHelper*>(data);
|
||||
|
||||
if (harih->destroyed) {
|
||||
if (harih->pending == 1)
|
||||
delete harih;
|
||||
else
|
||||
harih->pending--;
|
||||
return 0;
|
||||
}
|
||||
|
||||
harih->harea->renderRGBMarks(-1,-1,-1);
|
||||
harih->harea->queue_draw ();
|
||||
|
||||
harih->pending--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HistogramRGBArea::update (int valh, int rh, int gh, int bh) {
|
||||
|
||||
if (valh) {
|
||||
val=valh;
|
||||
r=rh;
|
||||
g=gh;
|
||||
b=bh;
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
valid = false;
|
||||
|
||||
harih->pending++;
|
||||
g_idle_add (histrgbupdate, harih);
|
||||
}
|
||||
|
||||
void HistogramRGBArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool bar, bool c) {
|
||||
|
||||
needRed = r;
|
||||
needGreen = g;
|
||||
needBlue = b;
|
||||
needLuma = l;
|
||||
rawMode = raw;
|
||||
showMode = bar;
|
||||
needChroma = c;
|
||||
|
||||
// Histogram RGB BAR button logic goes here
|
||||
|
||||
if (bar && !barDisplayed) {
|
||||
// Toggled on, add (show) the widget
|
||||
parent->pack_start(*this, Gtk::PACK_SHRINK, 0);
|
||||
options.histogramBar = true;
|
||||
barDisplayed = true;
|
||||
}
|
||||
else if (!bar && barDisplayed){
|
||||
// Toggled off, remove (hide) the widget
|
||||
removeIfThere(parent, this, false);
|
||||
options.histogramBar = false;
|
||||
barDisplayed = false;
|
||||
// unfreeze
|
||||
updateFreeze(false);
|
||||
}
|
||||
|
||||
// Disable (but don't hide it) the bar button when RAW histogram is displayed
|
||||
if (rawMode) {
|
||||
showMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
void HistogramRGBArea::on_realize () {
|
||||
|
||||
Gtk::DrawingArea::on_realize();
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
rgbgc_ = Gdk::GC::create(window);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK);
|
||||
|
||||
Glib::RefPtr<Gdk::Colormap> rgbcolormap = get_default_colormap();
|
||||
black = Gdk::Color ("black");
|
||||
red = Gdk::Color ("red");
|
||||
green = Gdk::Color ("green");
|
||||
blue = Gdk::Color ("blue");
|
||||
lgray = Gdk::Color ("gray75");
|
||||
mgray = Gdk::Color ("gray50");
|
||||
dgray = Gdk::Color ("gray25");
|
||||
rgbcolormap->alloc_color(black);
|
||||
rgbcolormap->alloc_color(white);
|
||||
rgbcolormap->alloc_color(red);
|
||||
rgbcolormap->alloc_color(green);
|
||||
rgbcolormap->alloc_color(blue);
|
||||
rgbcolormap->alloc_color(lgray);
|
||||
rgbcolormap->alloc_color(mgray);
|
||||
rgbcolormap->alloc_color(dgray);
|
||||
|
||||
}
|
||||
|
||||
bool HistogramRGBArea::on_expose_event(GdkEventExpose* event) {
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
|
||||
// on_realize & RenderRGBMarks have to be called before
|
||||
if (rgbgc_ && overlay) {
|
||||
window->draw_drawable (rgbgc_, overlay, 0, 0, 0, 0, -1, -1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HistogramRGBArea::on_button_press_event (GdkEventButton* event) {
|
||||
|
||||
if (event->type==GDK_2BUTTON_PRESS && event->button==1) {
|
||||
// do something. Maybe un-freeze ?
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HistogramRGBArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
white = get_style()->get_base(Gtk::STATE_NORMAL);
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// HistogramArea
|
||||
HistogramArea::HistogramArea (FullModeListener *fml) : //needChroma unactive by default
|
||||
valid(false), fullMode(options.histogramFullMode), myFullModeListener(fml), oldwidth(-1), needLuma(true), needRed(true), needGreen(true), needBlue(true), rawMode(false), needChroma(false) {
|
||||
|
||||
lhist(256);
|
||||
rhist(256);
|
||||
ghist(256);
|
||||
bhist(256);
|
||||
chist(256);
|
||||
|
||||
haih = new HistogramAreaIdleHelper;
|
||||
haih->harea = this;
|
||||
haih->destroyed = false;
|
||||
haih->pending = 0;
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &HistogramArea::styleChanged) );
|
||||
}
|
||||
|
||||
HistogramArea::~HistogramArea () {
|
||||
|
||||
if (haih->pending)
|
||||
haih->destroyed = true;
|
||||
else
|
||||
delete haih;
|
||||
|
||||
}
|
||||
|
||||
void HistogramArea::updateOptions (bool r, bool g, bool b, bool l, bool raw, bool full, bool c) {
|
||||
|
||||
needRed = r;
|
||||
needGreen = g;
|
||||
needBlue = b;
|
||||
needLuma = l;
|
||||
rawMode = raw;
|
||||
fullMode = !full;
|
||||
needChroma = c;
|
||||
|
||||
renderHistogram ();
|
||||
}
|
||||
|
||||
int histupdateUI (void* data) {
|
||||
|
||||
HistogramAreaIdleHelper* haih = static_cast<HistogramAreaIdleHelper*>(data);
|
||||
|
||||
if (haih->destroyed) {
|
||||
if (haih->pending == 1)
|
||||
delete haih;
|
||||
else
|
||||
haih->pending--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
haih->harea->renderHistogram ();
|
||||
haih->harea->queue_draw ();
|
||||
|
||||
haih->pending--;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HistogramArea::update (LUTu &histRed, LUTu &histGreen, LUTu &histBlue, LUTu &histLuma, LUTu &histRedRaw, LUTu &histGreenRaw, LUTu &histBlueRaw, LUTu &histChroma) {
|
||||
|
||||
if (histRed) {
|
||||
lhist=histLuma;chist=histChroma;
|
||||
rhist=histRed; ghist=histGreen; bhist=histBlue;
|
||||
rhistRaw=histRedRaw; ghistRaw=histGreenRaw; bhistRaw=histBlueRaw;
|
||||
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
valid = false;
|
||||
|
||||
haih->pending++;
|
||||
// Can be done outside of the GUI thread
|
||||
g_idle_add (histupdateUI, haih);
|
||||
}
|
||||
|
||||
void HistogramArea::renderHistogram () {
|
||||
|
||||
if (!is_realized ())
|
||||
return;
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
int winx, winy, winw, winh, wind;
|
||||
window->get_geometry(winx, winy, winw, winh, wind);
|
||||
|
||||
backBuffer = Gdk::Pixmap::create (window, winw, winh, -1);
|
||||
|
||||
Glib::RefPtr<Gdk::GC> bgc = Gdk::GC::create(backBuffer);
|
||||
|
||||
bgc->set_foreground (white);
|
||||
backBuffer->draw_rectangle (bgc, true, 0, 0, winw, winh);
|
||||
|
||||
if (valid) {
|
||||
// For RAW mode use the other hists
|
||||
LUTu& rh = rawMode ? rhistRaw : rhist;
|
||||
LUTu& gh = rawMode ? ghistRaw : ghist;
|
||||
LUTu& bh = rawMode ? bhistRaw : bhist;
|
||||
|
||||
// compute height of the full histogram (realheight) and
|
||||
// does not take into account 0 and 255 values
|
||||
// them are handled separately
|
||||
|
||||
int fullhistheight = 0;
|
||||
for (int i=1; i<255; i++) {
|
||||
if (needLuma && lhist[i]>fullhistheight)
|
||||
fullhistheight = lhist[i];
|
||||
if (needChroma && chist[i]>fullhistheight)
|
||||
fullhistheight = chist[i];
|
||||
if (needRed && (rawMode?rhistRaw:rhist)[i]>fullhistheight)
|
||||
fullhistheight = rh[i];
|
||||
if (needGreen && (rawMode?ghistRaw:ghist)[i]>fullhistheight)
|
||||
fullhistheight = gh[i];
|
||||
if (needBlue && (rawMode?bhistRaw:bhist)[i]>fullhistheight)
|
||||
fullhistheight = bh[i];
|
||||
}
|
||||
|
||||
int realhistheight = fullhistheight;
|
||||
|
||||
if (!fullMode) {
|
||||
int area = 0;
|
||||
for (int i=0; i<fullhistheight; i++) {
|
||||
for (int j=0; j<256; j++)
|
||||
if ((needLuma && !rawMode && lhist[j]>i) || (needChroma && !rawMode && chist[j]>i) || (needRed && rh[j]>i) || (needGreen && gh[j]>i) || (needBlue && bh[j]>i))
|
||||
area++;
|
||||
if ((double)area / (256*(i+1)) < 0.3) {
|
||||
realhistheight = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (realhistheight<winh-2)
|
||||
realhistheight = winh-2;
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> cr = backBuffer->create_cairo_context();
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
int ui = 0, oi = 0;
|
||||
|
||||
if (needLuma && !rawMode) {
|
||||
drawCurve(cr, lhist, realhistheight, winw, winh);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
cr->fill_preserve ();
|
||||
cr->set_source_rgb (0.5, 0.5, 0.5);
|
||||
cr->stroke ();
|
||||
|
||||
drawMarks(cr, lhist, realhistheight, winw, ui, oi);
|
||||
}
|
||||
if (needChroma && !rawMode) {
|
||||
drawCurve(cr, chist, realhistheight, winw, winh);
|
||||
cr->set_source_rgb (0.6, 0.6, 0.6);
|
||||
// cr->fill_preserve ();
|
||||
// cr->set_source_rgb (0.2, 0.2, 0.1);
|
||||
cr->stroke ();
|
||||
|
||||
drawMarks(cr, lhist, realhistheight, winw, ui, oi);
|
||||
}
|
||||
|
||||
|
||||
if (needRed) {
|
||||
drawCurve(cr, rh, realhistheight, winw, winh);
|
||||
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||
cr->stroke ();
|
||||
|
||||
drawMarks(cr, rh, realhistheight, winw, ui, oi);
|
||||
}
|
||||
if (needGreen) {
|
||||
drawCurve(cr, gh, realhistheight, winw, winh);
|
||||
cr->set_source_rgb (0.0, 1.0, 0.0);
|
||||
cr->stroke ();
|
||||
|
||||
drawMarks(cr, gh, realhistheight, winw, ui, oi);
|
||||
}
|
||||
if (needBlue) {
|
||||
drawCurve(cr, bh, realhistheight, winw, winh);
|
||||
cr->set_source_rgb (0.0, 0.0, 1.0);
|
||||
cr->stroke ();
|
||||
|
||||
drawMarks(cr, bh, realhistheight, winw, ui, oi);
|
||||
}
|
||||
}
|
||||
|
||||
bgc->set_foreground (mgray);
|
||||
backBuffer->draw_rectangle (bgc, false, 0, 0, winw-1, winh-1);
|
||||
|
||||
bgc->set_line_attributes (1, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
|
||||
|
||||
backBuffer->draw_line (bgc, winw/4, 0, winw/4, winh);
|
||||
backBuffer->draw_line (bgc, 2*winw/4, 0, 2*winw/4, winh);
|
||||
backBuffer->draw_line (bgc, 3*winw/4, 0, 3*winw/4, winh);
|
||||
backBuffer->draw_line (bgc, 0, winh/4, winw, winh/4);
|
||||
backBuffer->draw_line (bgc, 0, 2*winh/4, winw, 2*winh/4);
|
||||
backBuffer->draw_line (bgc, 0, 3*winh/4, winw, 3*winh/4);
|
||||
|
||||
bgc->set_line_attributes (1, Gdk::LINE_SOLID, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
|
||||
|
||||
oldwidth = winw;
|
||||
oldheight = winh;
|
||||
}
|
||||
|
||||
void HistogramArea::on_realize () {
|
||||
|
||||
Gtk::DrawingArea::on_realize();
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
gc_ = Gdk::GC::create(window);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK);
|
||||
Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
|
||||
|
||||
black = Gdk::Color ("black");
|
||||
red = Gdk::Color ("red");
|
||||
green = Gdk::Color ("green");
|
||||
blue = Gdk::Color ("blue");
|
||||
lgray = Gdk::Color ("gray75");
|
||||
mgray = Gdk::Color ("gray50");
|
||||
dgray = Gdk::Color ("gray25");
|
||||
colormap->alloc_color(black);
|
||||
colormap->alloc_color(white);
|
||||
colormap->alloc_color(red);
|
||||
colormap->alloc_color(green);
|
||||
colormap->alloc_color(blue);
|
||||
colormap->alloc_color(lgray);
|
||||
colormap->alloc_color(mgray);
|
||||
colormap->alloc_color(dgray);
|
||||
|
||||
}
|
||||
|
||||
void HistogramArea::drawCurve(Cairo::RefPtr<Cairo::Context> &cr,
|
||||
LUTu & data, double scale, int hsize, int vsize)
|
||||
{
|
||||
cr->move_to (0, vsize-1);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
double val = data[i] * (double)(vsize-2) / scale;
|
||||
if (val > vsize - 1)
|
||||
val = vsize - 1;
|
||||
cr->line_to ((i/255.0)*(hsize - 1), vsize - 1 - val);
|
||||
}
|
||||
cr->line_to (hsize - 1, vsize - 1);
|
||||
}
|
||||
|
||||
void HistogramArea::drawMarks(Cairo::RefPtr<Cairo::Context> &cr,
|
||||
LUTu & data, double scale, int hsize, int & ui, int & oi)
|
||||
{
|
||||
int s = 8;
|
||||
|
||||
if(data[0] > scale) {
|
||||
cr->rectangle(0, (ui++)*s, s, s);
|
||||
}
|
||||
if(data[255] > scale) {
|
||||
cr->rectangle(hsize - s, (oi++)*s, s, s);
|
||||
}
|
||||
cr->fill();
|
||||
}
|
||||
|
||||
void HistogramArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
white = get_style()->get_base(Gtk::STATE_NORMAL);
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
bool HistogramArea::on_expose_event(GdkEventExpose* event) {
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
|
||||
int winx, winy, winw, winh, wind;
|
||||
window->get_geometry(winx, winy, winw, winh, wind);
|
||||
|
||||
if (winw!=oldwidth && winh!=oldheight)
|
||||
renderHistogram ();
|
||||
window->draw_drawable (gc_, backBuffer, 0, 0, 0, 0, -1, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HistogramArea::on_button_press_event (GdkEventButton* event) {
|
||||
|
||||
if (event->type==GDK_2BUTTON_PRESS && event->button==1) {
|
||||
fullMode = !fullMode;
|
||||
options.histogramFullMode = fullMode;
|
||||
if (myFullModeListener)
|
||||
myFullModeListener->toggle_button_full ();
|
||||
renderHistogram ();
|
||||
queue_draw ();
|
||||
}
|
||||
return true;
|
||||
}
|
Reference in New Issue
Block a user