From 041990d2167ea7df15e58c0f1106ea4fb04e34f3 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 8 Jan 2018 00:19:36 +0100 Subject: [PATCH 01/21] Added new color toning mode "L*a*b* color correction grid", adapted from DT's color correction module --- rtdata/languages/default | 2 + rtengine/improcfun.cc | 43 +++++- rtengine/improcfun.h | 2 +- rtengine/procparams.cc | 21 ++- rtengine/procparams.h | 7 + rtgui/colortoning.cc | 298 +++++++++++++++++++++++++++++++++++++++ rtgui/colortoning.h | 5 + rtgui/paramsedited.cc | 24 ++++ rtgui/paramsedited.h | 5 + 9 files changed, 403 insertions(+), 4 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index dd0a63fc6..7d95b85d2 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -723,6 +723,7 @@ HISTORY_MSG_490;HDR TM - Amount HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments +HISTORY_MSG_COLORTONING_LABGRID_VALUE;L*a*b* color correction HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast @@ -1405,6 +1406,7 @@ TP_COLORTONING_HIGHLIGHT;Highlights TP_COLORTONING_HUE;Hue TP_COLORTONING_LAB;L*a*b* blending TP_COLORTONING_LABEL;Color Toning +TP_COLORTONING_LABGRID;L*a*b* color correction grid TP_COLORTONING_LUMA;Luminance TP_COLORTONING_LUMAMODE;Preserve luminance TP_COLORTONING_LUMAMODE_TOOLTIP;If enabled, when you change color (red, green, cyan, blue, etc.) the luminance of each pixel is preserved. diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 7e8e153b1..42cbb6f20 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3477,7 +3477,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer userToneCurve.initApplyState (ptc2ApplyState, params->icm.working); } - bool hasColorToning = params->colorToning.enabled && bool (ctOpacityCurve) && bool (ctColorCurve); + bool hasColorToning = params->colorToning.enabled && bool (ctOpacityCurve) && bool (ctColorCurve) && params->colorToning.method != "LabGrid"; // float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; // float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); float strProtect = (float (params->colorToning.strength) / 100.f); @@ -4952,6 +4952,10 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer delete vCurve; } + if (params->colorToning.enabled && params->colorToning.method == "LabGrid") { + colorToningLabGrid(lab); + } + if (params->localContrast.enabled) { // Alberto's local contrast localContrast(lab); @@ -7175,4 +7179,41 @@ SSEFUNCTION void ImProcFunctions::lab2rgb (const LabImage &src, Imagefloat &dst, //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +// adapted from the "color correction" module of Darktable. Original copyright follows +/* + copyright (c) 2009--2010 johannes hanika. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ +void ImProcFunctions::colorToningLabGrid(LabImage *lab) +{ + const float factor = ColorToningParams::LABGRID_CORR_MAX * 1.6f; + float a_scale = (params->colorToning.labgridAHigh - params->colorToning.labgridALow) / factor; + float a_base = params->colorToning.labgridALow; + float b_scale = (params->colorToning.labgridBHigh - params->colorToning.labgridBLow) / factor; + float b_base = params->colorToning.labgridBLow; + +#ifdef _OPENMP + #pragma omp parallel for if (multiThread) +#endif + for (int y = 0; y < lab->H; ++y) { + for (int x = 0; x < lab->W; ++x) { + lab->a[y][x] += lab->L[y][x] * a_scale + a_base; + lab->b[y][x] += lab->L[y][x] * b_scale + b_base; + } + } +} + } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index b7e7a7545..1adc2fc5f 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -345,8 +345,8 @@ public: void BadpixelsLab (LabImage * src, LabImage * dst, double radius, int thresh, int mode, float skinprot, float chrom); void ToneMapFattal02(Imagefloat *rgb); - //void localContrast(float *r, float *g, float *b, int width, int height); void localContrast(LabImage *lab); + void colorToningLabGrid(LabImage *lab); Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 8fbab7a8d..336f32379 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -688,7 +688,11 @@ ColorToningParams::ColorToningParams() : bluehigh(0.0), satlow(0.0), sathigh(0.0), - lumamode(true) + lumamode(true), + labgridALow(0.0), + labgridBLow(0.0), + labgridAHigh(0.0), + labgridBHigh(0.0) { } @@ -720,7 +724,11 @@ bool ColorToningParams::operator ==(const ColorToningParams& other) const && bluehigh == other.bluehigh && satlow == other.satlow && sathigh == other.sathigh - && lumamode == other.lumamode; + && lumamode == other.lumamode + && labgridALow == other.labgridALow + && labgridBLow == other.labgridBLow + && labgridAHigh == other.labgridAHigh + && labgridBHigh == other.labgridBHigh; } bool ColorToningParams::operator !=(const ColorToningParams& other) const @@ -3337,6 +3345,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->colorToning.shadowsColSat, "ColorToning", "ShadowsColorSaturation", colorToning.shadowsColSat.toVector(), keyFile); saveToKeyfile(!pedited || pedited->colorToning.clcurve, "ColorToning", "ClCurve", colorToning.clcurve, keyFile); saveToKeyfile(!pedited || pedited->colorToning.cl2curve, "ColorToning", "Cl2Curve", colorToning.cl2curve, keyFile); + saveToKeyfile(!pedited || pedited->colorToning.labgridALow, "ColorToning", "LabGridALow", colorToning.labgridALow, keyFile); + saveToKeyfile(!pedited || pedited->colorToning.labgridBLow, "ColorToning", "LabGridBLow", colorToning.labgridBLow, keyFile); + saveToKeyfile(!pedited || pedited->colorToning.labgridAHigh, "ColorToning", "LabGridAHigh", colorToning.labgridAHigh, keyFile); + saveToKeyfile(!pedited || pedited->colorToning.labgridBHigh, "ColorToning", "LabGridBHigh", colorToning.labgridBHigh, keyFile); // Raw saveToKeyfile(!pedited || pedited->raw.darkFrame, "RAW", "DarkFrame", relativePathIfInside (fname, fnameAbsolute, raw.dark_frame), keyFile); @@ -4585,6 +4597,11 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "ColorToning", "Redhigh", pedited, colorToning.redhigh, pedited->colorToning.redhigh); assignFromKeyfile(keyFile, "ColorToning", "Greenhigh", pedited, colorToning.greenhigh, pedited->colorToning.greenhigh); assignFromKeyfile(keyFile, "ColorToning", "Bluehigh", pedited, colorToning.bluehigh, pedited->colorToning.bluehigh); + + assignFromKeyfile(keyFile, "ColorToning", "LabGridALow", pedited, colorToning.labgridALow, pedited->colorToning.labgridALow); + assignFromKeyfile(keyFile, "ColorToning", "LabGridBLow", pedited, colorToning.labgridBLow, pedited->colorToning.labgridBLow); + assignFromKeyfile(keyFile, "ColorToning", "LabGridAHigh", pedited, colorToning.labgridAHigh, pedited->colorToning.labgridAHigh); + assignFromKeyfile(keyFile, "ColorToning", "LabGridBHigh", pedited, colorToning.labgridBHigh, pedited->colorToning.labgridBHigh); } if (keyFile.has_group ("RAW")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 58cc2cdfc..7aed263ea 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -424,6 +424,7 @@ struct ColorToningParams { * Lch : * RGBSliders : * RGBCurves : + * LabGrid : */ Glib::ustring method; @@ -447,6 +448,12 @@ struct ColorToningParams { double sathigh; bool lumamode; + double labgridALow; + double labgridBLow; + double labgridAHigh; + double labgridBHigh; + static constexpr double LABGRID_CORR_MAX = 8000.f; + ColorToningParams(); bool operator ==(const ColorToningParams& other) const; diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 180b4235a..38e0630d4 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -4,10 +4,258 @@ #include "colortoning.h" #include "mycurve.h" #include "rtimage.h" +#include "eventmapper.h" using namespace rtengine; using namespace rtengine::procparams; +namespace { + +// adapted from the "color correction" module of Darktable. Original copyright follows +/* + copyright (c) 2009--2010 johannes hanika. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ +class LabGrid: public Gtk::DrawingArea { +private: + rtengine::ProcEvent evt_; + enum State { OFF, HIGH, LOW }; + State selected_; + float low_a_; + float high_a_; + float low_b_; + float high_b_; + float saturation_; + ToolPanelListener *listener_; + bool edited_; + static const int inset = 2; + + void notify_listener() + { + if (listener_) { + auto fmt = [](float f) -> Glib::ustring + { + return Glib::ustring::format(std::setw(4), std::fixed, std::setprecision(3), f); + }; + listener_->panelChanged(evt_, Glib::ustring::compose("%1, %2, %3, %4", fmt(low_a_), fmt(low_b_), fmt(high_a_), fmt(high_b_))); + } + } + +public: + LabGrid(rtengine::ProcEvent evt): + Gtk::DrawingArea(), + evt_(evt), selected_(OFF), + low_a_(0.f), high_a_(0.f), low_b_(0.f), high_b_(0.f), + listener_(nullptr), + edited_(false) + { + set_can_focus(true); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); + } + + void get_params(double &la, double &lb, double &ha, double &hb) const + { + la = low_a_; + ha = high_a_; + lb = low_b_; + hb = high_b_; + } + + void set_params(double la, double lb, double ha, double hb) + { + low_a_ = la; + low_b_ = lb; + high_a_ = ha; + high_b_ = hb; + queue_draw(); + } + + void set_edited(bool yes) + { + edited_ = yes; + } + + + bool get_edited() const + { + return edited_; + } + + void set_listener(ToolPanelListener *l) + { + listener_ = l; + } + + bool on_draw(const ::Cairo::RefPtr &crf) + { + int width = get_allocated_width(); + int height = get_allocated_height(); + Cairo::RefPtr cst = + Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height); + Cairo::RefPtr cr = Cairo::Context::create(cst); + // clear bg + cr->set_source_rgb(.2, .2, .2); + cr->paint(); + + cr->translate(inset, inset); + cr->set_antialias(Cairo::ANTIALIAS_NONE); + width -= 2 * inset; + height -= 2 * inset; + // flip y: + cr->translate(0, height); + cr->scale(1., -1.); + const int cells = 8; + float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); + for (int j = 0; j < cells; j++) { + for(int i = 0; i < cells; i++) { + float R, G, B; + float x, y, z; + int ii = i - cells/2; + int jj = j - cells/2; + float a = step * (ii + 0.5) * 1.5; + float b = step * (jj + 0.5) * 1.5; + Color::Lab2XYZ(25000.f, a, b, x, y, z); + Color::xyz2srgb(x, y, z, R, G, B); + cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); + cr->rectangle(width * i / (float)cells, height * j / (float)cells, + width / (float)cells - 1, + height / (float)cells - 1); + cr->fill(); + } + } + cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); + float loa, hia, lob, hib; + loa = .5f * (width + width * low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hia = .5f * (width + width * high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + lob = .5f * (height + height * low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hib = .5f * (height + height * high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + cr->set_line_width(2.); + cr->set_source_rgb(0.6, 0.6, 0.6); + cr->move_to(loa, lob); + cr->line_to(hia, hib); + cr->stroke(); + + cr->set_source_rgb(0.1, 0.1, 0.1); + if (selected_ == LOW) { + cr->arc(loa, lob, 5, 0, 2. * M_PI); + } else { + cr->arc(loa, lob, 3, 0, 2. * M_PI); + } + cr->fill(); + + cr->set_source_rgb(0.9, 0.9, 0.9); + if (selected_ == HIGH) { + cr->arc(hia, hib, 5, 0, 2. * M_PI); + } else { + cr->arc(hia, hib, 3, 0, 2. * M_PI); + } + cr->fill(); + + crf->set_source(cst, 0, 0); + crf->paint(); + + return true; + } + + bool on_button_release_event(GdkEventButton *event) + { + if (selected_ != OFF) { + edited_ = true; + notify_listener(); + } + return true; + } + + bool on_button_press_event(GdkEventButton *event) + { + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { + switch (selected_) { + case OFF: + low_a_ = low_b_ = high_a_ = high_b_ = 0.f; + break; + case LOW: + low_a_ = low_b_ = 0.f; + break; + case HIGH: + high_a_ = high_b_ = 0.f; + break; + } + edited_ = true; + notify_listener(); + } + return true; + } + + bool on_motion_notify_event(GdkEventMotion *event) + { + int width = get_allocated_width() - 2 * inset, height = get_allocated_height() - 2 * inset; + const float mouse_x = std::min(std::max(event->x - inset, 0.), double(width)); + const float mouse_y = std::min(std::max(height - 1 - event->y + inset, 0.), double(height)); + const float ma = (2.0 * mouse_x - width) / (float)width; + const float mb = (2.0 * mouse_y - height) / (float)height; + if (event->state & GDK_BUTTON1_MASK) { + if (selected_ == LOW) { + low_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + low_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + } else if (selected_ == HIGH) { + high_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + high_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + } + } else { + selected_ = OFF; + float la = low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float lb = low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float ha = high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float hb = high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + const float thrs = 0.05f; + const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); + const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); + if (distlo < thrs * thrs && distlo < disthi) { + selected_ = LOW; + } else if (disthi < thrs * thrs && disthi <= distlo) { + selected_ = HIGH; + } + } + if (selected_ != OFF) { + grab_focus(); + } + queue_draw(); + return true; + } + + Gtk::SizeRequestMode get_request_mode_vfunc() const + { + return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; + } + + void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const + { + minimum_width = 100; + natural_width = 200; + } + + void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const + { + minimum_height = natural_height = width; + } +}; + + +} // namespace + + ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true) { nextbw = 0; @@ -21,6 +269,7 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR method->append (M("TP_COLORTONING_RGBCURVES")); method->append (M("TP_COLORTONING_SPLITCOCO")); method->append (M("TP_COLORTONING_SPLITLR")); + method->append(M("TP_COLORTONING_LABGRID")); method->set_active (0); method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP")); @@ -312,6 +561,14 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR greenhigh->setAdjusterListener (this); bluehigh->setAdjusterListener (this); + //------------------------------------------------------------------------ + // LAB grid + auto m = ProcEventMapper::getInstance(); + EvColorToningLabGridValue = m->newEvent(RGBCURVE, "HISTORY_MSG_COLORTONING_LABGRID_VALUE"); + labgridArea = Gtk::manage(new LabGrid(EvColorToningLabGridValue)); + pack_start(*labgridArea, Gtk::PACK_EXPAND_WIDGET, 4); + //------------------------------------------------------------------------ + show_all(); disableListener(); @@ -329,6 +586,13 @@ ColorToning::~ColorToning() delete cl2CurveEditorG; } + +void ColorToning::setListener(ToolPanelListener *tpl) +{ + ToolPanel::setListener(tpl); + static_cast(labgridArea)->set_listener(tpl); +} + /* void ColorToning::neutralCurves_pressed () { disableListener(); @@ -400,6 +664,8 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) clshape->setUnChanged (!pedited->colorToning.clcurve); cl2shape->setUnChanged (!pedited->colorToning.cl2curve); lumamode->set_inconsistent (!pedited->colorToning.lumamode); + + static_cast(labgridArea)->set_edited(pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh); } redlow->setValue (pp->colorToning.redlow); @@ -431,6 +697,8 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) lastLumamode = pp->colorToning.lumamode; + static_cast(labgridArea)->set_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); + if (pedited && !pedited->colorToning.method) { method->set_active (5); } else if (pp->colorToning.method == "Lab") { @@ -443,6 +711,8 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) method->set_active (3); } else if (pp->colorToning.method == "Splitlr") { method->set_active (4); + } else if (pp->colorToning.method == "LabGrid") { + method->set_active(5); } methodChanged(); @@ -495,6 +765,8 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); pp->colorToning.strength = strength->getIntValue(); + static_cast(labgridArea)->get_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); + if (pedited) { pedited->colorToning.redlow = redlow->getEditedState (); pedited->colorToning.greenlow = greenlow->getEditedState (); @@ -519,6 +791,8 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pedited->colorToning.hlColSat = hlColSat->getEditedState (); pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); + + pedited->colorToning.labgridALow = pedited->colorToning.labgridBLow = pedited->colorToning.labgridAHigh = pedited->colorToning.labgridBHigh = static_cast(labgridArea)->get_edited(); } if (method->get_active_row_number() == 0) { @@ -531,6 +805,8 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pp->colorToning.method = "Splitco"; } else if (method->get_active_row_number() == 4) { pp->colorToning.method = "Splitlr"; + } else if (method->get_active_row_number() == 5) { + pp->colorToning.method = "LabGrid"; } if (twocolor->get_active_row_number() == 0) { @@ -782,6 +1058,8 @@ void ColorToning::methodChanged () { if (!batchMode) { + labgridArea->hide(); + if (method->get_active_row_number() == 0) { // Lab colorSep->show(); colorCurveEditorG->show(); @@ -929,6 +1207,26 @@ void ColorToning::methodChanged () chanMixerBox->hide(); neutrHBox->hide(); lumamode->show(); + } else if (method->get_active_row_number() == 5) { // Lab Grid + colorSep->hide(); + colorCurveEditorG->hide(); + twocolor->hide(); + opacityCurveEditorG->hide(); + clCurveEditorG->hide(); + cl2CurveEditorG->hide(); + hlColSat->hide(); + shadowsColSat->hide(); + balance->hide(); + p1Frame->hide(); + autosat->hide(); + satProtectionThreshold->hide(); + saturatedOpacity->hide(); + strength->hide(); + chanMixerBox->hide(); + neutrHBox->hide(); + lumamode->hide(); + + labgridArea->show(); } } diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index 347cfd126..31c1650cf 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -49,6 +49,8 @@ public: void colorForValue (double valX, double valY, enum ColorCaller::ElemType elemType, int callerId, ColorCaller* caller); + void setListener(ToolPanelListener *tpl); + private: //Gtk::HSeparator* satLimiterSep; Gtk::HSeparator* colorSep; @@ -101,6 +103,9 @@ private: bool lastLumamode; sigc::connection lumamodeConn; + rtengine::ProcEvent EvColorToningLabGridValue; + Gtk::DrawingArea *labgridArea; + IdleRegister idle_register; }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index fc302299c..5355c88da 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -134,6 +134,10 @@ void ParamsEdited::set (bool v) colorToning.greenhigh = v; colorToning.bluehigh = v; colorToning.lumamode = v; + colorToning.labgridALow = v; + colorToning.labgridBLow = v; + colorToning.labgridAHigh = v; + colorToning.labgridBHigh = v; sharpening.enabled = v; sharpening.radius = v; @@ -687,6 +691,10 @@ void ParamsEdited::initFrom (const std::vector colorToning.greenhigh = colorToning.greenhigh && p.colorToning.greenhigh == other.colorToning.greenhigh; colorToning.bluehigh = colorToning.bluehigh && p.colorToning.bluehigh == other.colorToning.bluehigh; colorToning.lumamode = colorToning.lumamode && p.colorToning.lumamode == other.colorToning.lumamode; + colorToning.labgridALow = colorToning.labgridALow && p.colorToning.labgridALow == other.colorToning.labgridALow; + colorToning.labgridBLow = colorToning.labgridBLow && p.colorToning.labgridBLow == other.colorToning.labgridBLow; + colorToning.labgridAHigh = colorToning.labgridAHigh && p.colorToning.labgridAHigh == other.colorToning.labgridAHigh; + colorToning.labgridBHigh = colorToning.labgridBHigh && p.colorToning.labgridBHigh == other.colorToning.labgridBHigh; sharpenEdge.enabled = sharpenEdge.enabled && p.sharpenEdge.enabled == other.sharpenEdge.enabled; sharpenEdge.passes = sharpenEdge.passes && p.sharpenEdge.passes == other.sharpenEdge.passes; sharpenEdge.amount = sharpenEdge.amount && p.sharpenEdge.amount == other.sharpenEdge.amount; @@ -1532,6 +1540,22 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; } + if (colorToning.labgridALow) { + toEdit.colorToning.labgridALow = mods.colorToning.labgridALow; + } + if (colorToning.labgridALow) { + toEdit.colorToning.labgridALow = mods.colorToning.labgridALow; + } + if (colorToning.labgridBLow) { + toEdit.colorToning.labgridBLow = mods.colorToning.labgridBLow; + } + if (colorToning.labgridAHigh) { + toEdit.colorToning.labgridAHigh = mods.colorToning.labgridAHigh; + } + if (colorToning.labgridBHigh) { + toEdit.colorToning.labgridBHigh = mods.colorToning.labgridBHigh; + } + if (sharpenEdge.enabled) { toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 5a835bf05..c49b60eaa 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -170,6 +170,11 @@ public: bool satlow; bool sathigh; bool lumamode; + bool labgridALow; + bool labgridBLow; + bool labgridAHigh; + bool labgridBHigh; + bool labgridSaturation; }; class SharpenEdgeParamsEdited From 7353ff864b4401da944deca93d41a92bc4c0cf40 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 8 Jan 2018 14:34:54 +0100 Subject: [PATCH 02/21] some tweaks to the L*a*b* correction grid module --- rtengine/improcfun.cc | 2 +- rtengine/procparams.cc | 2 ++ rtengine/procparams.h | 2 +- rtgui/colortoning.cc | 10 ++++------ rtgui/paramsedited.h | 1 - 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 42cbb6f20..052f13d08 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -7199,7 +7199,7 @@ SSEFUNCTION void ImProcFunctions::lab2rgb (const LabImage &src, Imagefloat &dst, */ void ImProcFunctions::colorToningLabGrid(LabImage *lab) { - const float factor = ColorToningParams::LABGRID_CORR_MAX * 1.6f; + const float factor = ColorToningParams::LABGRID_CORR_MAX * 3.f; float a_scale = (params->colorToning.labgridAHigh - params->colorToning.labgridALow) / factor; float a_base = params->colorToning.labgridALow; float b_scale = (params->colorToning.labgridBHigh - params->colorToning.labgridBLow) / factor; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 336f32379..4b8ccf71a 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -618,6 +618,8 @@ bool LocalContrastParams::operator!=(const LocalContrastParams &other) const } +const double ColorToningParams::LABGRID_CORR_MAX = 12000.f; + ColorToningParams::ColorToningParams() : enabled(false), autosat(true), diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 7aed263ea..7cc80b313 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -452,7 +452,7 @@ struct ColorToningParams { double labgridBLow; double labgridAHigh; double labgridBHigh; - static constexpr double LABGRID_CORR_MAX = 8000.f; + static const double LABGRID_CORR_MAX; ColorToningParams(); diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 38e0630d4..9a50c0730 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -119,19 +119,17 @@ public: const int cells = 8; float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); for (int j = 0; j < cells; j++) { - for(int i = 0; i < cells; i++) { + for (int i = 0; i < cells; i++) { float R, G, B; float x, y, z; int ii = i - cells/2; int jj = j - cells/2; - float a = step * (ii + 0.5) * 1.5; - float b = step * (jj + 0.5) * 1.5; + float a = step * (ii + 0.5); + float b = step * (jj + 0.5); Color::Lab2XYZ(25000.f, a, b, x, y, z); Color::xyz2srgb(x, y, z, R, G, B); cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); - cr->rectangle(width * i / (float)cells, height * j / (float)cells, - width / (float)cells - 1, - height / (float)cells - 1); + cr->rectangle(width * i / float(cells), height * j / float(cells), width / float(cells) - 1, height / float(cells) - 1); cr->fill(); } } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index c49b60eaa..6de5d52e4 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -174,7 +174,6 @@ public: bool labgridBLow; bool labgridAHigh; bool labgridBHigh; - bool labgridSaturation; }; class SharpenEdgeParamsEdited From 93ac6e01051cad5c5e927ad63dd2494041d60d0b Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 8 Jan 2018 22:31:48 +0100 Subject: [PATCH 03/21] added reset button for the L*a*b* grid in color toning --- rtgui/colortoning.cc | 33 +++++++++++++++++++++++---------- rtgui/colortoning.h | 1 + 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 9a50c0730..8a0ec75c2 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -37,7 +37,6 @@ private: float high_a_; float low_b_; float high_b_; - float saturation_; ToolPanelListener *listener_; bool edited_; static const int inset = 2; @@ -45,11 +44,7 @@ private: void notify_listener() { if (listener_) { - auto fmt = [](float f) -> Glib::ustring - { - return Glib::ustring::format(std::setw(4), std::fixed, std::setprecision(3), f); - }; - listener_->panelChanged(evt_, Glib::ustring::compose("%1, %2, %3, %4", fmt(low_a_), fmt(low_b_), fmt(high_a_), fmt(high_b_))); + listener_->panelChanged(evt_, Glib::ustring::compose("%1 %2 %3 %4", int(low_a_), int(low_b_), int(high_a_), int(high_b_))); } } @@ -73,13 +68,16 @@ public: hb = high_b_; } - void set_params(double la, double lb, double ha, double hb) + void set_params(double la, double lb, double ha, double hb, bool notify) { low_a_ = la; low_b_ = lb; high_a_ = ha; high_b_ = hb; queue_draw(); + if (notify) { + notify_listener(); + } } void set_edited(bool yes) @@ -191,6 +189,7 @@ public: break; } edited_ = true; + queue_draw(); notify_listener(); } return true; @@ -240,7 +239,7 @@ public: void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const { - minimum_width = 100; + minimum_width = 50; natural_width = 200; } @@ -563,8 +562,20 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR // LAB grid auto m = ProcEventMapper::getInstance(); EvColorToningLabGridValue = m->newEvent(RGBCURVE, "HISTORY_MSG_COLORTONING_LABGRID_VALUE"); + Gtk::HBox *labgridBox = Gtk::manage(new Gtk::HBox()); labgridArea = Gtk::manage(new LabGrid(EvColorToningLabGridValue)); - pack_start(*labgridArea, Gtk::PACK_EXPAND_WIDGET, 4); + labgridBox->pack_start(*labgridArea, true, true); + labgridReset = Gtk::manage(new Gtk::Button ()); + labgridReset->add (*Gtk::manage(new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); + setExpandAlignProperties(labgridReset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); + labgridReset->set_relief(Gtk::RELIEF_NONE); + labgridReset->set_tooltip_text(M("ADJUSTER_RESET_TO_DEFAULT")); + labgridReset->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT); + labgridReset->set_can_focus(false); + labgridReset->set_size_request(-1, 20); + labgridReset->signal_pressed().connect([=]() { static_cast(labgridArea)->set_params(0.0, 0.0, 0.0, 0.0, true); }); + labgridBox->pack_start(*labgridReset, false, false); + pack_start(*labgridBox, Gtk::PACK_EXPAND_WIDGET, 4); //------------------------------------------------------------------------ show_all(); @@ -695,7 +706,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) lastLumamode = pp->colorToning.lumamode; - static_cast(labgridArea)->set_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); + static_cast(labgridArea)->set_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, false); if (pedited && !pedited->colorToning.method) { method->set_active (5); @@ -1056,6 +1067,7 @@ void ColorToning::methodChanged () { if (!batchMode) { + labgridReset->hide(); labgridArea->hide(); if (method->get_active_row_number() == 0) { // Lab @@ -1224,6 +1236,7 @@ void ColorToning::methodChanged () neutrHBox->hide(); lumamode->hide(); + labgridReset->show(); labgridArea->show(); } } diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index 31c1650cf..9fd26e34c 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -104,6 +104,7 @@ private: sigc::connection lumamodeConn; rtengine::ProcEvent EvColorToningLabGridValue; + Gtk::Button *labgridReset; Gtk::DrawingArea *labgridArea; IdleRegister idle_register; From bfa3f786bad953f5dfba94ae4ad7e9c6f3b02ca0 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Mon, 8 Jan 2018 23:27:22 +0100 Subject: [PATCH 04/21] replace M_PI with rtengine::RT_PI --- rtgui/colortoning.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 8a0ec75c2..24193be97 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -145,17 +145,17 @@ public: cr->set_source_rgb(0.1, 0.1, 0.1); if (selected_ == LOW) { - cr->arc(loa, lob, 5, 0, 2. * M_PI); + cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); } else { - cr->arc(loa, lob, 3, 0, 2. * M_PI); + cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); } cr->fill(); cr->set_source_rgb(0.9, 0.9, 0.9); if (selected_ == HIGH) { - cr->arc(hia, hib, 5, 0, 2. * M_PI); + cr->arc(hia, hib, 5, 0, 2. * rtengine::RT_PI); } else { - cr->arc(hia, hib, 3, 0, 2. * M_PI); + cr->arc(hia, hib, 3, 0, 2. * rtengine::RT_PI); } cr->fill(); From 9e9d523fa34784cb32ba1c094b8a620d15ade490 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 9 Jan 2018 15:41:39 +0100 Subject: [PATCH 05/21] updated history msg for lab color correction --- rtdata/languages/default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 7d95b85d2..ec93fd41e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -723,7 +723,7 @@ HISTORY_MSG_490;HDR TM - Amount HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments -HISTORY_MSG_COLORTONING_LABGRID_VALUE;L*a*b* color correction +HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_LOCALCONTRAST_AMOUNT;Local Contrast - Amount HISTORY_MSG_LOCALCONTRAST_DARKNESS;Local Contrast - Darkness HISTORY_MSG_LOCALCONTRAST_ENABLED;Local Contrast From e5efc3a44ca5a33eadc354cb9f988b5136eb02dc Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 9 Jan 2018 18:02:58 +0100 Subject: [PATCH 06/21] do not perform unnecessary color toning computations when the method is "L*a*b* grid" (by heckflosse) --- rtengine/improccoordinator.cc | 2 +- rtengine/rtthumbnail.cc | 2 +- rtengine/simpleprocess.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 97e356f18..f79e173e9 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -509,7 +509,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) int satPR = 30; int indi = 0; - if (params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + if (params.colorToning.enabled && params.colorToning.autosat && params.colorToning.method != "LabGrid") { //for colortoning evaluation of saturation settings float moyS = 0.f; float eqty = 0.f; ipf.moyeqt (oprevi, moyS, eqty);//return image : mean saturation and standard dev of saturation diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index fcc039a81..e84214bd4 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1159,7 +1159,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT float satLimit = float (params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; float satLimitOpacity = 1.f - (float (params.colorToning.saturatedOpacity) / 100.f); - if (params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + if (params.colorToning.enabled && params.colorToning.autosat && params.colorToning.method != "LabGrid") { //for colortoning evaluation of saturation settings float moyS = 0.f; float eqty = 0.f; ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index e74c32a35..de0022e92 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -910,7 +910,7 @@ private: float satLimit = float (params.colorToning.satProtectionThreshold) / 100.f * 0.7f + 0.3f; float satLimitOpacity = 1.f - (float (params.colorToning.saturatedOpacity) / 100.f); - if (params.colorToning.enabled && params.colorToning.autosat) { //for colortoning evaluation of saturation settings + if (params.colorToning.enabled && params.colorToning.autosat && params.colorToning.method != "LabGrid") { //for colortoning evaluation of saturation settings float moyS = 0.f; float eqty = 0.f; ipf.moyeqt (baseImg, moyS, eqty);//return image : mean saturation and standard dev of saturation From 30e085d378a8abf5b39b5c9f34c3bf2b24ade55c Mon Sep 17 00:00:00 2001 From: heckflosse Date: Tue, 9 Jan 2018 19:41:34 +0100 Subject: [PATCH 07/21] colorToningLabGrid() : tiled/per row processing to make better use of cpu cache --- rtengine/improcfun.cc | 17 ++++++++++------- rtengine/improcfun.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 00c349323..7a9ac8b82 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -3479,6 +3479,7 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } bool hasColorToning = params->colorToning.enabled && bool (ctOpacityCurve) && bool (ctColorCurve) && params->colorToning.method != "LabGrid"; + bool hasColorToningLabGrid = params->colorToning.enabled && params->colorToning.method == "LabGrid"; // float satLimit = float(params->colorToning.satProtectionThreshold)/100.f*0.7f+0.3f; // float satLimitOpacity = 1.f-(float(params->colorToning.saturatedOpacity)/100.f); float strProtect = (float (params->colorToning.strength) / 100.f); @@ -4521,6 +4522,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer for (int i = istart, ti = 0; i < tH; i++, ti++) { Color::RGB2Lab(&rtemp[ti * TS], >emp[ti * TS], &btemp[ti * TS], &(lab->L[i][jstart]), &(lab->a[i][jstart]), &(lab->b[i][jstart]), toxyz, tW - jstart); } + if (hasColorToningLabGrid) { + colorToningLabGrid(lab, jstart, tW, istart, tH, false); + } } else { // black & white // Auto channel mixer needs whole image, so we now copy to tmpImage and close the tiled processing for (int i = istart, ti = 0; i < tH; i++, ti++) { @@ -4932,6 +4936,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer for (int i = 0; i < tH; i++) { Color::RGB2Lab(tmpImage->r(i), tmpImage->g(i), tmpImage->b(i), lab->L[i], lab->a[i], lab->b[i], toxyz, tW); + if (hasColorToningLabGrid) { + colorToningLabGrid(lab, 0, tW, i, i + 1, false); + } } @@ -4953,10 +4960,6 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer delete vCurve; } - if (params->colorToning.enabled && params->colorToning.method == "LabGrid") { - colorToningLabGrid(lab); - } - if (params->localContrast.enabled) { // Alberto's local contrast localContrast(lab); @@ -7198,7 +7201,7 @@ SSEFUNCTION void ImProcFunctions::lab2rgb (const LabImage &src, Imagefloat &dst, You should have received a copy of the GNU General Public License along with darktable. If not, see . */ -void ImProcFunctions::colorToningLabGrid(LabImage *lab) +void ImProcFunctions::colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread) { const float factor = ColorToningParams::LABGRID_CORR_MAX * 3.f; float a_scale = (params->colorToning.labgridAHigh - params->colorToning.labgridALow) / factor; @@ -7209,8 +7212,8 @@ void ImProcFunctions::colorToningLabGrid(LabImage *lab) #ifdef _OPENMP #pragma omp parallel for if (multiThread) #endif - for (int y = 0; y < lab->H; ++y) { - for (int x = 0; x < lab->W; ++x) { + for (int y = ystart; y < yend; ++y) { + for (int x = xstart; x < xend; ++x) { lab->a[y][x] += lab->L[y][x] * a_scale + a_base; lab->b[y][x] += lab->L[y][x] * b_scale + b_base; } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index c1b175ab6..83ffc12d6 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -346,7 +346,7 @@ public: void ToneMapFattal02(Imagefloat *rgb); void localContrast(LabImage *lab); - void colorToningLabGrid(LabImage *lab); + void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); Imagefloat* lab2rgbOut (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, GammaValues *ga = nullptr); From 68ba09fdd8976b68feadfdfa97af5e0f3f9e3107 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Wed, 10 Jan 2018 19:29:11 +0100 Subject: [PATCH 08/21] Speedup for Colour Toning Methods 'RGB sliders' and 'RGB curves' --- rtengine/color.cc | 63 +----------------------------- rtengine/color.h | 89 +++++++++++++++++++++++++++++++++++++++---- rtengine/improcfun.cc | 16 +++----- 3 files changed, 89 insertions(+), 79 deletions(-) diff --git a/rtengine/color.cc b/rtengine/color.cc index 706d0f36d..ee63720aa 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -553,44 +553,6 @@ void Color::rgb2hsl(float r, float g, float b, float &h, float &s, float &l) } } -void Color::rgb2hslfloat(float r, float g, float b, float &h, float &s, float &l) -{ - - float m = min(r, g, b); - float M = max(r, g, b); - float C = M - m; - - l = (M + m) * 7.6295109e-6f; // (0.5f / 65535.f) - - if (fabsf(C) < 0.65535f) { // 0.00001f * 65535.f - h = 0.f; - s = 0.f; - } else { - - if (l <= 0.5f) { - s = (M - m) / (M + m); - } else { - s = (M - m) / (131070.f - M - m); // 131070.f = 2.f * 65535.f - } - - if ( r == M ) { - h = (g - b); - } else if ( g == M ) { - h = (2.f * C) + (b - r); - } else { - h = (4.f * C) + (r - g); - } - - h /= (6.f * C); - - if ( h < 0.f ) { - h += 1.f; - } else if ( h > 1.f ) { - h -= 1.f; - } - } -} - #ifdef __SSE2__ void Color::rgb2hsl(vfloat r, vfloat g, vfloat b, vfloat &h, vfloat &s, vfloat &l) { @@ -609,9 +571,8 @@ void Color::rgb2hsl(vfloat r, vfloat g, vfloat b, vfloat &h, vfloat &s, vfloat & h /= (F2V(6.f) * C); vfloat onev = F2V(1.f); h = vself(vmaskf_lt(h, ZEROV), h + onev, h); - h = vself(vmaskf_gt(h, onev), h - onev, h); - vmask zeromask = vmaskf_lt(vabsf(C), F2V(0.65535f)); + vmask zeromask = vmaskf_lt(C, F2V(0.65535f)); h = vself(zeromask, ZEROV, h); s = vself(zeromask, ZEROV, s); } @@ -697,28 +658,6 @@ void Color::hsl2rgb (float h, float s, float l, float &r, float &g, float &b) } } -void Color::hsl2rgbfloat (float h, float s, float l, float &r, float &g, float &b) -{ - - if (s == 0.f) { - r = g = b = 65535.f * l; // achromatic - } else { - float m2; - - if (l <= 0.5f) { - m2 = l * (1.f + s); - } else { - m2 = l + s - l * s; - } - - float m1 = 2.f * l - m2; - - r = 65535.f * hue2rgbfloat (m1, m2, h * 6.f + 2.f); - g = 65535.f * hue2rgbfloat (m1, m2, h * 6.f); - b = 65535.f * hue2rgbfloat (m1, m2, h * 6.f - 2.f); - } -} - #ifdef __SSE2__ void Color::hsl2rgb (vfloat h, vfloat s, vfloat l, vfloat &r, vfloat &g, vfloat &b) { diff --git a/rtengine/color.h b/rtengine/color.h index 2b6d40174..d56b30e52 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -205,7 +205,64 @@ public: * @param l luminance channel [0; 1] (return value) */ static void rgb2hsl (float r, float g, float b, float &h, float &s, float &l); - static void rgb2hslfloat (float r, float g, float b, float &h, float &s, float &l); + + static inline void rgb2slfloat(float r, float g, float b, float &s, float &l) + { + + float m = min(r, g, b); + float M = max(r, g, b); + float C = M - m; + + l = (M + m) * 7.6295109e-6f; // (0.5f / 65535.f) + + if (C < 0.65535f) { // 0.00001f * 65535.f + s = 0.f; + } else { + + if (l <= 0.5f) { + s = C / (M + m); + } else { + s = C / (131070.f - (M + m)); // 131070.f = 2.f * 65535.f + } + } + } + + static inline void rgb2hslfloat(float r, float g, float b, float &h, float &s, float &l) + { + + float m = min(r, g, b); + float M = max(r, g, b); + float C = M - m; + + l = (M + m) * 7.6295109e-6f; // (0.5f / 65535.f) + + if (C < 0.65535f) { // 0.00001f * 65535.f + h = 0.f; + s = 0.f; + } else { + + if (l <= 0.5f) { + s = C / (M + m); + } else { + s = C / (131070.f - (M + m)); // 131070.f = 2.f * 65535.f + } + + if ( r == M ) { + h = (g - b); + } else if ( g == M ) { + h = (2.f * C) + (b - r); + } else { + h = (4.f * C) + (r - g); + } + + h /= (6.f * C); + + if ( h < 0.f ) { + h += 1.f; + } + } + } + #ifdef __SSE2__ static void rgb2hsl (vfloat r, vfloat g, vfloat b, vfloat &h, vfloat &s, vfloat &l); #endif @@ -220,7 +277,29 @@ public: * @param b blue channel [0 ; 65535] (return value) */ static void hsl2rgb (float h, float s, float l, float &r, float &g, float &b); - static void hsl2rgbfloat (float h, float s, float l, float &r, float &g, float &b); + + static inline void hsl2rgbfloat (float h, float s, float l, float &r, float &g, float &b) + { + + if (s == 0.f) { + r = g = b = 65535.f * l; // achromatic + } else { + float m2; + + if (l <= 0.5f) { + m2 = l * (1.f + s); + } else { + m2 = l + s - l * s; + } + + float m1 = 2.f * l - m2; + + r = 65535.f * hue2rgbfloat (m1, m2, h * 6.f + 2.f); + g = 65535.f * hue2rgbfloat (m1, m2, h * 6.f); + b = 65535.f * hue2rgbfloat (m1, m2, h * 6.f - 2.f); + } + } + #ifdef __SSE2__ static void hsl2rgb (vfloat h, vfloat s, vfloat l, vfloat &r, vfloat &g, vfloat &b); #endif @@ -254,11 +333,7 @@ public: float var_Max = max(r, g, b); float del_Max = var_Max - var_Min; - if (del_Max < 0.00001f) { - return 0.f; - } else { - return del_Max / var_Max; - } + return del_Max / (var_Max == 0.f ? 1.f : var_Max); } static inline bool rgb2hsvdcp(float r, float g, float b, float &h, float &s, float &v) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 569ba42f1..ceaed824d 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -4175,29 +4175,25 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) - float h, s, l; - Color::rgb2hsl (r, g, b, h, s, l); + float s, l; + Color::rgb2slfloat (r, g, b, s, l); - float l_ = Color::gamma_srgb (l * 65535.f) / 65535.f; + float l_ = Color::gammatab_srgb1[l * 65535.f]; // get the opacity and tweak it to preserve saturated colors - float opacity; + float opacity = 0.f; if (ctOpacityCurve) { opacity = (1.f - min (s / satLimit, 1.f) * (1.f - satLimitOpacity)) * ctOpacityCurve.lutOpacityCurve[l_ * 500.f]; } - if (!ctOpacityCurve) { - opacity = 0.f; - } - float r2, g2, b2; ctColorCurve.getVal (l_, r2, g2, b2); // get the color from the color curve float h2, s2, l2; - Color::rgb2hsl (r2, g2, b2, h2, s2, l2); // transform this new color to hsl + Color::rgb2hslfloat (r2, g2, b2, h2, s2, l2); // transform this new color to hsl - Color::hsl2rgb (h2, s + ((1.f - s) * (1.f - l) * 0.7f), l, r2, g2, b2); + Color::hsl2rgbfloat (h2, s + ((1.f - s) * (1.f - l) * 0.7f), l, r2, g2, b2); rtemp[ti * TS + tj] = r + (r2 - r) * opacity; // merge the color to the old color, depending on the opacity gtemp[ti * TS + tj] = g + (g2 - g) * opacity; From 840d3d1de4f659351f5b8434eda784670bb6fe16 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 11 Jan 2018 09:40:51 +0100 Subject: [PATCH 09/21] made L*a*b* color correction grid respect options.adjusterMinDelay for updating the preview --- rtgui/colortoning.cc | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 24193be97..5034f90cc 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -39,13 +39,15 @@ private: float high_b_; ToolPanelListener *listener_; bool edited_; + sigc::connection delay_conn_; static const int inset = 2; - void notify_listener() + bool notify_listener() { if (listener_) { listener_->panelChanged(evt_, Glib::ustring::compose("%1 %2 %3 %4", int(low_a_), int(low_b_), int(high_a_), int(high_b_))); - } + } + return false; } public: @@ -57,7 +59,7 @@ public: edited_(false) { set_can_focus(true); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK); } void get_params(double &la, double &lb, double &ha, double &hb) const @@ -165,15 +167,6 @@ public: return true; } - bool on_button_release_event(GdkEventButton *event) - { - if (selected_ != OFF) { - edited_ = true; - notify_listener(); - } - return true; - } - bool on_button_press_event(GdkEventButton *event) { if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { @@ -197,11 +190,16 @@ public: bool on_motion_notify_event(GdkEventMotion *event) { + if (delay_conn_.connected()) { + delay_conn_.disconnect(); + } + int width = get_allocated_width() - 2 * inset, height = get_allocated_height() - 2 * inset; const float mouse_x = std::min(std::max(event->x - inset, 0.), double(width)); const float mouse_y = std::min(std::max(height - 1 - event->y + inset, 0.), double(height)); const float ma = (2.0 * mouse_x - width) / (float)width; const float mb = (2.0 * mouse_y - height) / (float)height; + bool refresh = selected_ != OFF; if (event->state & GDK_BUTTON1_MASK) { if (selected_ == LOW) { low_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; @@ -227,8 +225,15 @@ public: } if (selected_ != OFF) { grab_focus(); + if (options.adjusterMinDelay == 0) { + notify_listener(); + } else { + delay_conn_ = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notify_listener), options.adjusterMinDelay); + } + } + if (refresh) { + queue_draw(); } - queue_draw(); return true; } From f0b73149bd5e9f5b8540e5f36556046984f40334 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Thu, 11 Jan 2018 13:30:57 +0100 Subject: [PATCH 10/21] Speedup for Colour Toning Methods 'RGB sliders' and 'RGB curves' in 'Black-and-White' mode --- rtengine/improcfun.cc | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index ceaed824d..49f85ba9c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -4869,31 +4869,31 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer for (int i = 0; i < tH; i++) { for (int j = 0; j < tW; j++) { - float r = tmpImage->r (i, j); - float g = tmpImage->g (i, j); - float b = tmpImage->b (i, j); + float r = tmpImage->r(i, j); + float g = tmpImage->g(i, j); + float b = tmpImage->b(i, j); // Luminance = (0.299f*r + 0.587f*g + 0.114f*b) - float h, s, l; - Color::rgb2hsl (r, g, b, h, s, l); + float s, l; + Color::rgb2slfloat(r, g, b, s, l); - float l_ = Color::gamma_srgb (l * 65535.f) / 65535.f; + float l_ = Color::gammatab_srgb1[l * 65535.f]; - // get the opacity and tweak it to preserve saturated colors + // get the opacity and tweak it to preserve saturated colours float opacity = ctOpacityCurve.lutOpacityCurve[l_ * 500.f] / 4.f; float r2, g2, b2; - ctColorCurve.getVal (l_, r2, g2, b2); // get the color from the color curve + ctColorCurve.getVal(l_, r2, g2, b2); // get the colour from the colour curve float h2, s2, l2; - Color::rgb2hsl (r2, g2, b2, h2, s2, l2); // transform this new color to hsl + Color::rgb2hslfloat(r2, g2, b2, h2, s2, l2); // transform this new colour to hsl - Color::hsl2rgb (h2, s2, l, r2, g2, b2); + Color::hsl2rgbfloat(h2, s2, l, r2, g2, b2); - tmpImage->r (i, j) = r + (r2 - r) * opacity; - tmpImage->g (i, j) = g + (g2 - g) * opacity; - tmpImage->b (i, j) = b + (b2 - b) * opacity; + tmpImage->r(i, j) = intp(opacity, r2, r); + tmpImage->g(i, j) = intp(opacity, g2, g); + tmpImage->b(i, j) = intp(opacity, b2, b); } } } From a748354b7bc99ee197390c86747d1051e2100c9a Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 11 Jan 2018 15:05:15 +0100 Subject: [PATCH 11/21] Fattal: do not consider clipped values when determining the luminance scaling factor This solves the issue with "color propagation" highlight reconstruction described in #4255 --- rtengine/tmo_fattal02.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index 7ef490807..b72f4e4d0 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -1119,6 +1119,12 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) const float epsilon = 1e-4f; const float luminance_noise_floor = 65.535f; const float min_luminance = 1.f; + const auto unclipped = + [=](int y, int x) -> bool + { + const float c = 65500.f; + return rgb->r(y, x) < c && rgb->g(y, x) < c && rgb->b(y, x) < c; + }; TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); float max_Y = 0.f; @@ -1136,7 +1142,7 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { Yr (x, y) = std::max (luminance (rgb->r (y, x), rgb->g (y, x), rgb->b (y, x), ws), min_luminance); // clip really black pixels - if (Yr(x, y) > max_YThr) { + if (Yr(x, y) > max_YThr && unclipped(y, x)) { max_YThr = Yr(x, y); max_xThr = x; max_yThr = y; From fa4e07b8bb550155acec143b5e6edf56f8723131 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Thu, 11 Jan 2018 19:17:06 +0100 Subject: [PATCH 12/21] Updated build-rawtherapee to 2018-01-06 --- tools/build-rawtherapee | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/tools/build-rawtherapee b/tools/build-rawtherapee index 8c86ed54d..5c13df061 100755 --- a/tools/build-rawtherapee +++ b/tools/build-rawtherapee @@ -1,6 +1,6 @@ #!/usr/bin/env bash # By Morgan Hardwood -# Version 2017-12-25 +# Version 2018-01-06 # This script gets the latest source code for the given program and compiles it. # The name of the program, used for the folder names: @@ -22,11 +22,14 @@ exe="${prog}" exeRelativePath="" # The path to the repository: -repo="git@github.com:Beep6581/RawTherapee.git" +repo="https://github.com/Beep6581/RawTherapee.git" # No touching below this line, with the exception of the "Compile" section # ----------------------------------------------------------------------------- +# The name of the project's standard branch, typically "master": +master="dev" + buildOnly="false" buildType="release" @@ -35,8 +38,6 @@ exeRelativePath="${exeRelativePath/%\/}" # Append forward-slash to exeRelativePath only if it is not empty. exePath="${exeRelativePath:+${exeRelativePath}/}${exe}" -printf '%s\n' "" "Program name: ${prog}" "Build type: ${buildType}" "Build without updating: ${buildOnly}" "" - # Command-line arguments OPTIND=1 while getopts "bdh?-" opt; do @@ -59,16 +60,18 @@ done shift $((OPTIND-1)) [ "$1" = "--" ] && shift +printf '%s\n' "" "Program name: ${prog}" "Build type: ${buildType}" "Build without updating: ${buildOnly}" "" + # Clone if needed cloned="false" updates="false" if [[ ! -d "$HOME/programs/code-${prog}" ]]; then mkdir -p "$HOME/programs" || exit 1 git clone "$repo" "$HOME/programs/code-${prog}" || exit 1 - pushd "$HOME/programs/code-${prog}" || exit 1 + pushd "$HOME/programs/code-${prog}" 1>/dev/null || exit 1 cloned="true" else - pushd "$HOME/programs/code-${prog}" || exit 1 + pushd "$HOME/programs/code-${prog}" 1>/dev/null || exit 1 git fetch if [[ $(git rev-parse HEAD) != $(git rev-parse '@{u}') ]]; then updates="true" @@ -80,8 +83,20 @@ if [[ "$updates" = "true" && "$buildOnly" = "false" ]]; then git pull || exit 1 fi +# Find out which branch git is on +branch="$(git rev-parse --abbrev-ref HEAD)" + +# Set build and install folder names +if [[ $branch = $master && $buildType = release ]]; then + buildDir="$HOME/programs/code-${prog}/build" + installDir="$HOME/programs/${prog}" +else + buildDir="$HOME/programs/code-${prog}/build-${branch}-${buildType}" + installDir="$HOME/programs/${prog}-${branch}-${buildType}" +fi + existsExe="false" -if [[ -e "$HOME/programs/${prog}/${exePath}" ]]; then +if [[ -e "${installDir}/${exePath}" ]]; then existsExe="true" fi @@ -101,9 +116,9 @@ if [[ ! ( $cpuCount -ge 1 && $cpuCount -le 64 ) ]]; then fi # Prepare folders -rm -rf "$HOME/programs/${prog}" "$HOME/programs/code-${prog}/build" -mkdir -p "$HOME/programs/${prog}" "$HOME/programs/code-${prog}/build" || exit 1 -cd "$HOME/programs/code-${prog}/build" || exit 1 +rm -rf "${installDir}" +mkdir -p "${buildDir}" "${installDir}" || exit 1 +cd "${buildDir}" || exit 1 # ----------------------------------------------------------------------------- # Compile @@ -116,7 +131,7 @@ cmake \ -DCACHE_NAME_SUFFIX="5-dev" \ -DPROC_TARGET_NUMBER="2" \ -DBUILD_BUNDLE="ON" \ - -DBUNDLE_BASE_INSTALL_DIR="$HOME/programs/${prog}" \ + -DBUNDLE_BASE_INSTALL_DIR="${installDir}" \ -DOPTION_OMP="ON" \ -DWITH_LTO="OFF" \ -DWITH_PROF="OFF" \ @@ -127,6 +142,6 @@ cmake \ make --jobs="$cpuCount" install || exit 1 # Finished -printf '%s\n' "" "To run ${prog} type:" "~/programs/${prog}/${exePath}" "" +printf '%s\n' "" "To run ${prog} type:" "${installDir}/${exePath}" "" popd 1>/dev/null From 9f17139bc1da09366f87579ae2305e541874a0ed Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 11 Jan 2018 23:43:27 +0100 Subject: [PATCH 13/21] sort directories before files in the processing profiles menus Fixes #4295 --- rtengine/profilestore.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc index 4d06b6f6b..e79c8e322 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -49,6 +49,7 @@ bool ProfileStore::init (bool loadAll) if ((storeState == STORESTATE_NOTINITIALIZED || storeState == STORESTATE_DIRTY) && loadAll) { storeState = STORESTATE_BEINGINITIALIZED; _parseProfiles (); + std::stable_partition(entries.begin(), entries.end(), [](const ProfileStoreEntry *e) { return e->type == PSET_FOLDER; }); storeState = STORESTATE_INITIALIZED; } From d6f1b3e6f6aa6a7057df00f8a65391616aa85255 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 12 Jan 2018 16:12:11 +0100 Subject: [PATCH 14/21] Fix resource leak reported by Coverity (CID 186465) --- rtengine/imageio.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 1b6a4ad20..0e404fa91 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -1439,16 +1439,16 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) } if (iptcdata) { - rtexif::Tag* iptcTag = new rtexif::Tag (nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData")); - iptcTag->initLongArray((char*)iptcdata, iptclen); + rtexif::Tag iptcTag(nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData")); + iptcTag.initLongArray((char*)iptcdata, iptclen); #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA; #else bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL; #endif if (needsReverse) { - unsigned char *ptr = iptcTag->getValue(); - for (int a = 0; a < iptcTag->getCount(); ++a) { + unsigned char *ptr = iptcTag.getValue(); + for (int a = 0; a < iptcTag.getCount(); ++a) { unsigned char cc; cc = ptr[3]; ptr[3] = ptr[0]; @@ -1459,7 +1459,7 @@ int ImageIO::saveTIFF (Glib::ustring fname, int bps, bool uncompressed) ptr += 4; } } - TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag->getCount(), (long*)iptcTag->getValue()); + TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag.getCount(), (long*)iptcTag.getValue()); iptc_data_free_buf (iptc, iptcdata); } From 187b278bc40e670b34e5b8a6a5a8dc79c50f0aa8 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 12 Jan 2018 16:43:35 +0100 Subject: [PATCH 15/21] Speedup for Colour Toning Method 'Saturation 2 colours' --- rtengine/improcfun.cc | 220 ++++++++++++++---------------------------- 1 file changed, 74 insertions(+), 146 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 89eb9cfbf..470164ea5 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -4003,23 +4003,21 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer if (hasColorToning && !blackwhite) { if (params->colorToning.method == "Splitlr") { - float balanS, balanH; - float reducac = 0.4f; + constexpr float reducac = 0.4f; int preser = 0; if (params->colorToning.lumamode) { preser = 1; } - balanS = 1.f + Balan / 100.f; //balan between 0 and 2 - balanH = 1.f - Balan / 100.f; + const float balanS = 1.f + Balan / 100.f; //balan between 0 and 2 + const float balanH = 1.f - Balan / 100.f; float rh, gh, bh; float rl, gl, bl; float xh, yh, zh; float xl, yl, zl; - float iplow, iphigh; - iplow = (float)ctColorCurve.low; - iphigh = (float)ctColorCurve.high; + const float iplow = (float)ctColorCurve.low; + const float iphigh = (float)ctColorCurve.high; //2 colours ctColorCurve.getVal (iphigh, xh, yh, zh); ctColorCurve.getVal (iplow, xl, yl, zl); @@ -4028,20 +4026,18 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer Color::xyz2rgb (xl, yl, zl, rl, gl, bl, wip); //reteave rgb value with s and l =1 retreavergb (rl, gl, bl); + const float krl = rl / (rl + gl + bl); + const float kgl = gl / (rl + gl + bl); + const float kbl = bl / (rl + gl + bl); retreavergb (rh, gh, bh); - //printf("rl=%f gl=%f bl=%f\n",rl,gl,bl); + const float krh = rh / (rh + gh + bh); + const float kgh = gh / (rh + gh + bh); + const float kbh = bh / (rh + gh + bh); for (int i = istart, ti = 0; i < tH; i++, ti++) { for (int j = jstart, tj = 0; j < tW; j++, tj++) { - float r = rtemp[ti * TS + tj]; - float g = gtemp[ti * TS + tj]; - float b = btemp[ti * TS + tj]; - float ro, go, bo; int mode = 0; - toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); - rtemp[ti * TS + tj] = ro; - gtemp[ti * TS + tj] = go; - btemp[ti * TS + tj] = bo; + toning2col(rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], rtemp[ti * TS + tj], gtemp[ti * TS + tj], btemp[ti * TS + tj], iplow, iphigh, krl, kgl, kbl, krh, kgh, kbh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); } } } @@ -4746,23 +4742,21 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer } else if (params->colorToning.method == "Splitlr") { - float balanS, balanH; - float reducac = 0.4f; + constexpr float reducac = 0.4f; int preser = 0; if (params->colorToning.lumamode) { preser = 1; } - balanS = 1.f + Balan / 100.f; //balan between 0 and 2 - balanH = 1.f - Balan / 100.f; + const float balanS = 1.f + Balan / 100.f; //balan between 0 and 2 + const float balanH = 1.f - Balan / 100.f; float rh, gh, bh; float rl, gl, bl; float xh, yh, zh; float xl, yl, zl; - float iplow, iphigh; - iplow = (float)ctColorCurve.low; - iphigh = (float)ctColorCurve.high; + const float iplow = ctColorCurve.low; + const float iphigh = ctColorCurve.high; //2 colours ctColorCurve.getVal (iphigh, xh, yh, zh); @@ -4773,23 +4767,23 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer //retrieve rgb value with s and l =1 retreavergb (rl, gl, bl); + const float krl = rl / (rl + gl + bl); + const float kgl = gl / (rl + gl + bl); + const float kbl = bl / (rl + gl + bl); + retreavergb (rh, gh, bh); + const float krh = rh / (rh + gh + bh); + const float kgh = gh / (rh + gh + bh); + const float kbh = bh / (rh + gh + bh); + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, 5) #endif for (int i = 0; i < tH; i++) { for (int j = 0; j < tW; j++) { - float r = tmpImage->r (i, j); - float g = tmpImage->g (i, j); - float b = tmpImage->b (i, j); - - float ro, go, bo; int mode = 1; - toning2col (r, g, b, ro, go, bo, iplow, iphigh, rl, gl, bl, rh, gh, bh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); - tmpImage->r (i, j) = ro; - tmpImage->g (i, j) = go; - tmpImage->b (i, j) = bo; + toning2col(tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j), tmpImage->r(i, j), tmpImage->g(i, j), tmpImage->b(i, j), iplow, iphigh, krl, kgl, kbl, krh, kgh, kbh, SatLow, SatHigh, balanS, balanH, reducac, mode, preser, strProtect); } } } @@ -5024,11 +5018,8 @@ void ImProcFunctions::secondeg_end (float reducac, float vinf, float &aa, float **/ void ImProcFunctions::secondeg_begin (float reducac, float vend, float &aam, float &bbm) { - float zrmd = reducac; //linear = 0.5 - float v0m = vend; - float mem = vend / 2.f; //(0. + 0.8)/2.f - aam = (1.f - zrmd * v0m / mem) / (v0m * v0m - mem * v0m); // - bbm = (1.f - aam * v0m * v0m) / v0m; + aam = (2.f - 4.f * reducac) / (vend * vend); + bbm = 1.f / vend - aam * vend; } @@ -5324,79 +5315,57 @@ void ImProcFunctions::toningsmh (float r, float g, float b, float &ro, float &go * @param balanH [0..1] balance for highlights (same slider than for balanS) * @param reducac value of the reduction in the middle of the range for second degree, increase or decrease action **/ -void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl, float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect) +void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float krl, float kgl, float kbl, float krh, float kgh, float kbh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect) { - float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; - float h, s, l; - Color::rgb2hsl (r, g, b, h, s, l); - float v; - Color::rgb2hsv (r, g, b, h, s, v); - float ksat = 1.f; - float ksatlow = 1.f; - /* - if(mode==0) {//color - if(s < s_0) ksat=SQR((1.f/s_0)*s); - if(s > s_1) ksat=SQR((1.f/(s_1-1.f))*s - (1.f/(s_1-1.f))); - } - */ - float kl = 1.f; - float rlo = 1.f; - float rlh = 2.2f; - rlo *= pow_F (strProtect, 0.4f); //0.5 ==> 0.75 transfered value for more action - rlh *= pow_F (strProtect, 0.4f); + const float lumbefore = 0.299f * r + 0.587f * g + 0.114f * b; + const float v = max(r, g, b) / 65535.f; + + const float rlo = pow_F (strProtect, 0.4f); //0.5 ==> 0.75 transfered value for more action + const float rlh = 2.2f * pow_F (strProtect, 0.4f); + //low tones //second degree float aa, bb, cc; //fixed value of reducac =0.4; secondeg_end (reducac, iplow, aa, bb, cc); - float aab, bbb; + float aab, bbb; secondeg_begin (0.7f, iplow, aab, bbb); - if (v > iplow) { - kl = aa * v * v + bb * v + cc; - } else if (mode == 0) { - kl = aab * v * v + bbb * v; - } - - if (SatLow > 0.f) { - //rl gl bl - float krl = rl / (rl + gl + bl); - float kgl = gl / (rl + gl + bl); - float kbl = bl / (rl + gl + bl); - float RedL, GreenL, BlueL; - - if (g < 20000.f || b < 20000.f || r < 20000.f) { - float kmgb = min (r, g, b); //I have tested ...0.85 compromise... - kl *= pow ((kmgb / 20000.f), 0.85f); + float kl = 1.f; + if (v > iplow) { + kl = aa * v * v + bb * v + cc; + } else if (mode == 0) { + kl = aab * v * v + bbb * v; + } + const float kmgb = min(r, g, b); + if (kmgb < 20000.f) { + //I have tested ...0.85 compromise... + kl *= pow_F ((kmgb / 20000.f), 0.85f); } - RedL = 1.f + (SatLow * krl) * kl * ksat * rlo * balanS; //0.4 + const float factor = 20000.f * SatLow * kl * rlo * balanS; if (krl > 0.f) { - g -= 20000.f * (RedL - 1.f) * ksatlow; - b -= 20000.f * (RedL - 1.f) * ksatlow; + g -= factor * krl; + b -= factor * krl; } g = CLIP (g); b = CLIP (b); - GreenL = 1.f + (SatLow * kgl) * kl * ksat * rlo * balanS; //0.4 - if (kgl > 0.f) { - r -= 20000.f * (GreenL - 1.f) * ksatlow; - b -= 20000.f * (GreenL - 1.f) * ksatlow; + r -= factor * kgl; + b -= factor * kgl; } r = CLIP (r); b = CLIP (b); - BlueL = 1.f + (SatLow * kbl) * kl * ksat * rlo * balanS; //0.4 - if (kbl > 0.f) { - r -= 20000.f * (BlueL - 1.f) * ksatlow; - g -= 20000.f * (BlueL - 1.f) * ksatlow; + r -= factor * kbl; + g -= factor * kbl; } r = CLIP (r); @@ -5404,84 +5373,43 @@ void ImProcFunctions::toning2col (float r, float g, float b, float &ro, float &g } //high tones - float kh = 1.f; float aa0, bb0; //fixed value of reducac ==0.4; secondeg_begin (reducac, iphigh, aa0, bb0); - if (v > iphigh) { - kh = (-1.f / (1.f - iphigh)) * v + (1.f) / (1.f - iphigh); //Low light ==> decrease action after iplow - } else { - kh = aa0 * v * v + bb0 * v; - } - - - if (g > 45535.f || b > 45535.f || r > 45535.f) { - float kmgb = max (r, g, b); - float cora = 1.f / (45535.f - 65535.f); - float corb = 1.f - cora * 45535.f; - float cor = kmgb * cora + corb; - kh *= cor; - /* best algo if necessary with non linear response...little differences and more time! - float aa=1.f /(pow(45535.f,0.65f) - pow(65535.f,0.65f)); - float bb=1.f-aa*pow(45535.f,0.65f); - float cor=aa*pow(kmbg,0.65f)+bb; - kh*=cor;*/ - } - - if (SatHigh > 0.f) { - float RedH, GreenH, BlueH; - float krh = rh / (rh + gh + bh); - float kgh = gh / (rh + gh + bh); - float kbh = bh / (rh + gh + bh); - RedH = 1.f + (SatHigh * krh) * kh * rlh * balanH; //1.2 - - if (krh > 0.f) { - r += 20000.f * (RedH - 1.f); - r = CLIP (r); + float kh = 1.f; + if (v > iphigh) { + kh = (1.f - v) / (1.f - iphigh); //Low light ==> decrease action after iplow + } else { + kh = aa0 * v * v + bb0 * v; } - g = CLIP (g); - b = CLIP (b); - - GreenH = 1.f + (SatHigh * kgh) * kh * rlh * balanH; //1.2 - - if (kgh > 0.f) { - g += 20000.f * (GreenH - 1.f); - g = CLIP (g); + const float kmgb = max(r, g, b); + if (kmgb > 45535.f) { + constexpr float cora = 1.f / (45535.f - 65535.f); + constexpr float corb = 1.f - cora * 45535.f; + kh *= kmgb * cora + corb; } + const float factor = 20000.f * SatHigh * kh * rlh * balanH; + r += factor * (krh > 0.f ? krh : 0.f); + g += factor * (kgh > 0.f ? kgh : 0.f); + b += factor * (kbh > 0.f ? kbh : 0.f); - r = CLIP (r); - b = CLIP (b); - BlueH = 1.f + (SatHigh * kbh) * kh * rlh * balanH; //1.2 - - if (kbh > 0.f) { - b += 20000.f * (BlueH - 1.f); - b = CLIP (b); - } - - r = CLIP (r); - g = CLIP (g); + r = CLIP(r); + g = CLIP(g); + b = CLIP(b); } - float lumafter = 0.299f * r + 0.587f * g + 0.114f * b; float preserv = 1.f; - if (preser == 1) { + float lumafter = 0.299f * r + 0.587f * g + 0.114f * b; preserv = lumbefore / lumafter; } - //float preserv=lumbefore/lumafter; - ro = r; - go = g; - bo = b; - ro *= preserv; - go *= preserv; - bo *= preserv; - ro = CLIP (ro); - go = CLIP (go); - bo = CLIP (bo); + ro = CLIP(r * preserv); + go = CLIP(g * preserv); + bo = CLIP(b * preserv); } /** From 3b6cc19ae9a43a66acde5240a01dcd4aaf77b20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Fri, 12 Jan 2018 18:20:21 +0100 Subject: [PATCH 16/21] Fix some Coverity warnings --- rtengine/imagesource.h | 2 +- rtengine/ipresize.cc | 2 +- rtengine/rawimagesource.cc | 2 +- rtengine/rawimagesource.h | 2 +- rtengine/simpleprocess.cc | 47 ++++++++++++++++++++++++++++++-------- rtengine/tmo_fattal02.cc | 16 ++++++------- 6 files changed, 50 insertions(+), 21 deletions(-) diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 261995f08..5a71bb532 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -69,7 +69,7 @@ public: virtual int load (const Glib::ustring &fname) = 0; virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true) {}; virtual void demosaic (const RAWParams &raw) {}; - virtual void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; + virtual void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, const ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; virtual void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI) {}; virtual void flushRawData () {}; diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 1a48e5c43..c62ff0bc9 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -105,7 +105,7 @@ void ImProcFunctions::Lanczos (const Imagefloat* src, Imagefloat* dst, float sca float y0 = (static_cast (i) + 0.5f) * delta - 0.5f; // weights for interpolation in y direction - float w[support]; + float w[support] = {}; // sum of weights used for normalization float ws = 0.0f; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index b948b8bdd..a8d94b638 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -2360,7 +2360,7 @@ void RawImageSource::retinexPrepareCurves(const RetinexParams &retinexParams, LU retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve); } -void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) +void RawImageSource::retinex(const ColorManagementParams& cmp, const RetinexParams &deh, const ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) { MyTime t4, t5; t4.set(); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index cdd7ca675..a374ef06e 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -119,7 +119,7 @@ public: int load (const Glib::ustring &fname); void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true); void demosaic (const RAWParams &raw); - void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, ToneCurveParams Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); + void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, const ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI); void retinexPrepareCurves (const RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI); void retinexPrepareBuffers (const ColorManagementParams& cmp, const RetinexParams &retinexParams, multi_array2D &conversionBuffer, LUTu &lhist16RETI); void flushRawData (); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 0c6576c48..027600302 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -49,19 +49,48 @@ void adjust_radius (const T &default_param, double scale_factor, T ¶m) class ImageProcessor { public: - ImageProcessor (ProcessingJob* pjob, int& errorCode, - ProgressListener* pl, bool flush): + ImageProcessor( + ProcessingJob* pjob, + int& errorCode, + ProgressListener* pl, + bool flush + ) : job (static_cast (pjob)), errorCode (errorCode), pl (pl), flush (flush), // internal state - ipf_p (nullptr), - ii (nullptr), - imgsrc (nullptr), - fw (-1), - fh (-1), - pp (0, 0, 0, 0, 0) + ii(nullptr), + imgsrc(nullptr), + fw(0), + fh(0), + tr(0), + pp(0, 0, 0, 0, 0), + calclum(nullptr), + autoNR(0.f), + autoNRmax(0.f), + tilesize(0), + overlap(0), + ch_M(nullptr), + max_r(nullptr), + max_b(nullptr), + min_b(nullptr), + min_r(nullptr), + lumL(nullptr), + chromC(nullptr), + ry(nullptr), + sk(nullptr), + pcsk(nullptr), + expcomp(0.0), + bright(0), + contr(0), + black(0), + hlcompr(0), + hlcomprthresh(0), + baseImg(nullptr), + labView(nullptr), + autili(false), + butili(false) { } @@ -814,7 +843,7 @@ private: if (params.fattal.enabled) { ipf.ToneMapFattal02(baseImg); } - + // perform transform (excepted resizing) if (ipf.needsTransform()) { Imagefloat* trImg = nullptr; diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index b72f4e4d0..055868344 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -1116,13 +1116,13 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) Array2Df Yr (w, h); - const float epsilon = 1e-4f; - const float luminance_noise_floor = 65.535f; - const float min_luminance = 1.f; + constexpr float epsilon = 1e-4f; + constexpr float luminance_noise_floor = 65.535f; + constexpr float min_luminance = 1.f; const auto unclipped = - [=](int y, int x) -> bool + [rgb](int y, int x) -> bool { - const float c = 65500.f; + constexpr float c = 65500.f; return rgb->r(y, x) < c && rgb->g(y, x) < c && rgb->b(y, x) < c; }; TMatrix ws = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); @@ -1200,16 +1200,16 @@ void ImProcFunctions::ToneMapFattal02 (Imagefloat *rgb) const float wr = float(w2) / float(w); const float scale = 65535.f / std::max(L(max_x * wr + 1, max_y * hr + 1), epsilon) * (65535.f / Yr(max_x, max_y)); - + #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) if(multiThread) #endif for (int y = 0; y < h; y++) { int yy = y * hr + 1; - + for (int x = 0; x < w; x++) { int xx = x * wr + 1; - + float Y = Yr (x, y); float l = std::max (L (xx, yy), epsilon) * (scale / Y); rgb->r (y, x) = std::max (rgb->r (y, x), 0.f) * l; From 0e52db3c7708893022c21a0a7006d70bcb8ef500 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 12 Jan 2018 21:58:10 +0100 Subject: [PATCH 17/21] moved LabGrid class to its own file --- rtgui/CMakeLists.txt | 1 + rtgui/colortoning.cc | 249 +--------------------------------------- rtgui/labgrid.cc | 263 +++++++++++++++++++++++++++++++++++++++++++ rtgui/labgrid.h | 78 +++++++++++++ 4 files changed, 343 insertions(+), 248 deletions(-) create mode 100644 rtgui/labgrid.cc create mode 100644 rtgui/labgrid.h diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index f5a20b88a..540b4d267 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -151,6 +151,7 @@ set(NONCLISOURCEFILES localcontrast.cc eventmapper.cc metadatapanel.cc + labgrid.cc ) include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 5034f90cc..396b4cb65 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -5,258 +5,11 @@ #include "mycurve.h" #include "rtimage.h" #include "eventmapper.h" +#include "labgrid.h" using namespace rtengine; using namespace rtengine::procparams; -namespace { - -// adapted from the "color correction" module of Darktable. Original copyright follows -/* - copyright (c) 2009--2010 johannes hanika. - - darktable 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. - - darktable 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 darktable. If not, see . -*/ -class LabGrid: public Gtk::DrawingArea { -private: - rtengine::ProcEvent evt_; - enum State { OFF, HIGH, LOW }; - State selected_; - float low_a_; - float high_a_; - float low_b_; - float high_b_; - ToolPanelListener *listener_; - bool edited_; - sigc::connection delay_conn_; - static const int inset = 2; - - bool notify_listener() - { - if (listener_) { - listener_->panelChanged(evt_, Glib::ustring::compose("%1 %2 %3 %4", int(low_a_), int(low_b_), int(high_a_), int(high_b_))); - } - return false; - } - -public: - LabGrid(rtengine::ProcEvent evt): - Gtk::DrawingArea(), - evt_(evt), selected_(OFF), - low_a_(0.f), high_a_(0.f), low_b_(0.f), high_b_(0.f), - listener_(nullptr), - edited_(false) - { - set_can_focus(true); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK); - } - - void get_params(double &la, double &lb, double &ha, double &hb) const - { - la = low_a_; - ha = high_a_; - lb = low_b_; - hb = high_b_; - } - - void set_params(double la, double lb, double ha, double hb, bool notify) - { - low_a_ = la; - low_b_ = lb; - high_a_ = ha; - high_b_ = hb; - queue_draw(); - if (notify) { - notify_listener(); - } - } - - void set_edited(bool yes) - { - edited_ = yes; - } - - - bool get_edited() const - { - return edited_; - } - - void set_listener(ToolPanelListener *l) - { - listener_ = l; - } - - bool on_draw(const ::Cairo::RefPtr &crf) - { - int width = get_allocated_width(); - int height = get_allocated_height(); - Cairo::RefPtr cst = - Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height); - Cairo::RefPtr cr = Cairo::Context::create(cst); - // clear bg - cr->set_source_rgb(.2, .2, .2); - cr->paint(); - - cr->translate(inset, inset); - cr->set_antialias(Cairo::ANTIALIAS_NONE); - width -= 2 * inset; - height -= 2 * inset; - // flip y: - cr->translate(0, height); - cr->scale(1., -1.); - const int cells = 8; - float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); - for (int j = 0; j < cells; j++) { - for (int i = 0; i < cells; i++) { - float R, G, B; - float x, y, z; - int ii = i - cells/2; - int jj = j - cells/2; - float a = step * (ii + 0.5); - float b = step * (jj + 0.5); - Color::Lab2XYZ(25000.f, a, b, x, y, z); - Color::xyz2srgb(x, y, z, R, G, B); - cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); - cr->rectangle(width * i / float(cells), height * j / float(cells), width / float(cells) - 1, height / float(cells) - 1); - cr->fill(); - } - } - cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); - float loa, hia, lob, hib; - loa = .5f * (width + width * low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - hia = .5f * (width + width * high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - lob = .5f * (height + height * low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - hib = .5f * (height + height * high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - cr->set_line_width(2.); - cr->set_source_rgb(0.6, 0.6, 0.6); - cr->move_to(loa, lob); - cr->line_to(hia, hib); - cr->stroke(); - - cr->set_source_rgb(0.1, 0.1, 0.1); - if (selected_ == LOW) { - cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); - } else { - cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); - } - cr->fill(); - - cr->set_source_rgb(0.9, 0.9, 0.9); - if (selected_ == HIGH) { - cr->arc(hia, hib, 5, 0, 2. * rtengine::RT_PI); - } else { - cr->arc(hia, hib, 3, 0, 2. * rtengine::RT_PI); - } - cr->fill(); - - crf->set_source(cst, 0, 0); - crf->paint(); - - return true; - } - - bool on_button_press_event(GdkEventButton *event) - { - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - switch (selected_) { - case OFF: - low_a_ = low_b_ = high_a_ = high_b_ = 0.f; - break; - case LOW: - low_a_ = low_b_ = 0.f; - break; - case HIGH: - high_a_ = high_b_ = 0.f; - break; - } - edited_ = true; - queue_draw(); - notify_listener(); - } - return true; - } - - bool on_motion_notify_event(GdkEventMotion *event) - { - if (delay_conn_.connected()) { - delay_conn_.disconnect(); - } - - int width = get_allocated_width() - 2 * inset, height = get_allocated_height() - 2 * inset; - const float mouse_x = std::min(std::max(event->x - inset, 0.), double(width)); - const float mouse_y = std::min(std::max(height - 1 - event->y + inset, 0.), double(height)); - const float ma = (2.0 * mouse_x - width) / (float)width; - const float mb = (2.0 * mouse_y - height) / (float)height; - bool refresh = selected_ != OFF; - if (event->state & GDK_BUTTON1_MASK) { - if (selected_ == LOW) { - low_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; - low_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; - } else if (selected_ == HIGH) { - high_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; - high_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; - } - } else { - selected_ = OFF; - float la = low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float lb = low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float ha = high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float hb = high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - const float thrs = 0.05f; - const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); - const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); - if (distlo < thrs * thrs && distlo < disthi) { - selected_ = LOW; - } else if (disthi < thrs * thrs && disthi <= distlo) { - selected_ = HIGH; - } - } - if (selected_ != OFF) { - grab_focus(); - if (options.adjusterMinDelay == 0) { - notify_listener(); - } else { - delay_conn_ = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notify_listener), options.adjusterMinDelay); - } - } - if (refresh) { - queue_draw(); - } - return true; - } - - Gtk::SizeRequestMode get_request_mode_vfunc() const - { - return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; - } - - void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const - { - minimum_width = 50; - natural_width = 200; - } - - void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const - { - minimum_height = natural_height = width; - } -}; - - -} // namespace - ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true) { diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc new file mode 100644 index 000000000..7cb752bb6 --- /dev/null +++ b/rtgui/labgrid.cc @@ -0,0 +1,263 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 . + */ + +// adapted from the "color correction" module of Darktable. Original copyright follows +/* + copyright (c) 2009--2010 johannes hanika. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +#include "labgrid.h" + +using rtengine::Color; + + +bool LabGrid::notify_listener() +{ + if (listener_) { + listener_->panelChanged(evt_, Glib::ustring::compose("%1 %2 %3 %4", int(low_a_), int(low_b_), int(high_a_), int(high_b_))); + } + return false; +} + + +LabGrid::LabGrid(rtengine::ProcEvent evt): + Gtk::DrawingArea(), + evt_(evt), selected_(OFF), + low_a_(0.f), high_a_(0.f), low_b_(0.f), high_b_(0.f), + listener_(nullptr), + edited_(false) +{ + set_can_focus(true); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK); +} + + +void LabGrid::get_params(double &la, double &lb, double &ha, double &hb) const +{ + la = low_a_; + ha = high_a_; + lb = low_b_; + hb = high_b_; +} + + +void LabGrid::set_params(double la, double lb, double ha, double hb, bool notify) +{ + low_a_ = la; + low_b_ = lb; + high_a_ = ha; + high_b_ = hb; + queue_draw(); + if (notify) { + notify_listener(); + } +} + + +void LabGrid::set_edited(bool yes) +{ + edited_ = yes; +} + + +bool LabGrid::get_edited() const +{ + return edited_; +} + + +void LabGrid::set_listener(ToolPanelListener *l) +{ + listener_ = l; +} + + +bool LabGrid::on_draw(const ::Cairo::RefPtr &crf) +{ + int width = get_allocated_width(); + int height = get_allocated_height(); + Cairo::RefPtr cst = + Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height); + Cairo::RefPtr cr = Cairo::Context::create(cst); + // clear bg + cr->set_source_rgb(.2, .2, .2); + cr->paint(); + + cr->translate(inset, inset); + cr->set_antialias(Cairo::ANTIALIAS_NONE); + width -= 2 * inset; + height -= 2 * inset; + // flip y: + cr->translate(0, height); + cr->scale(1., -1.); + const int cells = 8; + float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); + for (int j = 0; j < cells; j++) { + for (int i = 0; i < cells; i++) { + float R, G, B; + float x, y, z; + int ii = i - cells/2; + int jj = j - cells/2; + float a = step * (ii + 0.5); + float b = step * (jj + 0.5); + Color::Lab2XYZ(25000.f, a, b, x, y, z); + Color::xyz2srgb(x, y, z, R, G, B); + cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); + cr->rectangle(width * i / float(cells), height * j / float(cells), width / float(cells) - 1, height / float(cells) - 1); + cr->fill(); + } + } + cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); + float loa, hia, lob, hib; + loa = .5f * (width + width * low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hia = .5f * (width + width * high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + lob = .5f * (height + height * low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hib = .5f * (height + height * high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); + cr->set_line_width(2.); + cr->set_source_rgb(0.6, 0.6, 0.6); + cr->move_to(loa, lob); + cr->line_to(hia, hib); + cr->stroke(); + + cr->set_source_rgb(0.1, 0.1, 0.1); + if (selected_ == LOW) { + cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); + } else { + cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); + } + cr->fill(); + + cr->set_source_rgb(0.9, 0.9, 0.9); + if (selected_ == HIGH) { + cr->arc(hia, hib, 5, 0, 2. * rtengine::RT_PI); + } else { + cr->arc(hia, hib, 3, 0, 2. * rtengine::RT_PI); + } + cr->fill(); + + crf->set_source(cst, 0, 0); + crf->paint(); + + return true; +} + + +bool LabGrid::on_button_press_event(GdkEventButton *event) +{ + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { + switch (selected_) { + case OFF: + low_a_ = low_b_ = high_a_ = high_b_ = 0.f; + break; + case LOW: + low_a_ = low_b_ = 0.f; + break; + case HIGH: + high_a_ = high_b_ = 0.f; + break; + } + edited_ = true; + queue_draw(); + notify_listener(); + } + return true; +} + + +bool LabGrid::on_motion_notify_event(GdkEventMotion *event) +{ + if (delay_conn_.connected()) { + delay_conn_.disconnect(); + } + + int width = get_allocated_width() - 2 * inset, height = get_allocated_height() - 2 * inset; + const float mouse_x = std::min(std::max(event->x - inset, 0.), double(width)); + const float mouse_y = std::min(std::max(height - 1 - event->y + inset, 0.), double(height)); + const float ma = (2.0 * mouse_x - width) / (float)width; + const float mb = (2.0 * mouse_y - height) / (float)height; + bool refresh = selected_ != OFF; + if (event->state & GDK_BUTTON1_MASK) { + if (selected_ == LOW) { + low_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + low_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + } else if (selected_ == HIGH) { + high_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + high_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + } + } else { + selected_ = OFF; + float la = low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float lb = low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float ha = high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float hb = high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + const float thrs = 0.05f; + const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); + const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); + if (distlo < thrs * thrs && distlo < disthi) { + selected_ = LOW; + } else if (disthi < thrs * thrs && disthi <= distlo) { + selected_ = HIGH; + } + } + if (selected_ != OFF) { + grab_focus(); + if (options.adjusterMinDelay == 0) { + notify_listener(); + } else { + delay_conn_ = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notify_listener), options.adjusterMinDelay); + } + } + if (refresh) { + queue_draw(); + } + return true; +} + + +Gtk::SizeRequestMode LabGrid::get_request_mode_vfunc() const +{ + return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; +} + + +void LabGrid::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const +{ + minimum_width = 50; + natural_width = 200; +} + + +void LabGrid::get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const +{ + minimum_height = natural_height = width; +} diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h new file mode 100644 index 000000000..dcb34bcc3 --- /dev/null +++ b/rtgui/labgrid.h @@ -0,0 +1,78 @@ +/** -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2017 Alberto Griggio + * + * 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 . + */ + +// adapted from the "color correction" module of Darktable. Original copyright follows +/* + copyright (c) 2009--2010 johannes hanika. + + darktable 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. + + darktable 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 darktable. If not, see . +*/ + +#pragma once + +#include +#include "eventmapper.h" +#include "toolpanel.h" + + +class LabGrid: public Gtk::DrawingArea { +private: + rtengine::ProcEvent evt_; + enum State { OFF, HIGH, LOW }; + State selected_; + float low_a_; + float high_a_; + float low_b_; + float high_b_; + ToolPanelListener *listener_; + bool edited_; + sigc::connection delay_conn_; + static const int inset = 2; + + bool notify_listener(); + +public: + LabGrid(rtengine::ProcEvent evt); + + void get_params(double &la, double &lb, double &ha, double &hb) const; + void set_params(double la, double lb, double ha, double hb, bool notify); + void set_edited(bool yes); + bool get_edited() const; + void set_listener(ToolPanelListener *l); + + bool on_draw(const ::Cairo::RefPtr &crf); + bool on_button_press_event(GdkEventButton *event); + bool on_motion_notify_event(GdkEventMotion *event); + Gtk::SizeRequestMode get_request_mode_vfunc() const; + void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const; + void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const; +}; + From 0498048ca05078cfe07636bb636629a80e3890e9 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sat, 13 Jan 2018 12:23:46 +0100 Subject: [PATCH 18/21] Speedup for DCPProfile::apply(), closes #4294 --- rtengine/dcp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index f9cdd1c73..82ea35f0f 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -1074,7 +1074,7 @@ void DCPProfile::apply( float s; float v; - if(Color::rgb2hsvdcp(newr, newg, newb, h , s, v)) { + if (LIKELY(Color::rgb2hsvdcp(newr, newg, newb, h , s, v))) { hsdApply(delta_info, delta_base, h, s, v); From 52be618963845007575c4dff5bdb7e814568581c Mon Sep 17 00:00:00 2001 From: Hombre Date: Sat, 13 Jan 2018 20:26:19 +0100 Subject: [PATCH 19/21] Bugfix in LabGrid class + code refactoring - suppressed trailing `_` char for class' parameters - renamed function name (those not related to Gtk) to lowerCamelCase - changed the mecanism of dragging point, to avoid throwing unecessary `panelChange` event - added a `reset` function, with support of `toInitial` to get back the values at load time (CTRL+click on reset button) - `on_draw` optimisation: now LabGrid IS A BackBuffer --- rtdata/languages/Francais | 1 + rtdata/languages/default | 1 + rtgui/blackwhite.cc | 18 +- rtgui/colortoning.cc | 29 ++-- rtgui/colortoning.h | 4 +- rtgui/labgrid.cc | 334 ++++++++++++++++++++++---------------- rtgui/labgrid.h | 48 ++++-- rtgui/paramsedited.cc | 3 - 8 files changed, 257 insertions(+), 181 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 3def47d59..700691c7f 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1381,6 +1381,7 @@ TP_COLORTONING_HIGHLIGHT;Hautes lumières TP_COLORTONING_HUE;Teinte TP_COLORTONING_LAB;Mixage Lab TP_COLORTONING_LABEL;Virage Partiel +TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nO: a=%3 b=%4 TP_COLORTONING_LUMA;Luminance TP_COLORTONING_LUMAMODE;Préserver la luminance TP_COLORTONING_LUMAMODE_TOOLTIP;Si activé, lorsque vous changez la couleur (rouge, vert, cyan, bleu, etc.), la luminance de chaque pixel est préservé diff --git a/rtdata/languages/default b/rtdata/languages/default index ec93fd41e..38f357d5a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1407,6 +1407,7 @@ TP_COLORTONING_HUE;Hue TP_COLORTONING_LAB;L*a*b* blending TP_COLORTONING_LABEL;Color Toning TP_COLORTONING_LABGRID;L*a*b* color correction grid +TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nS: a=%3 b=%4 TP_COLORTONING_LUMA;Luminance TP_COLORTONING_LUMAMODE;Preserve luminance TP_COLORTONING_LUMAMODE_TOOLTIP;If enabled, when you change color (red, green, cyan, blue, etc.) the luminance of each pixel is preserved. diff --git a/rtgui/blackwhite.cc b/rtgui/blackwhite.cc index 2b410846f..0788a465d 100644 --- a/rtgui/blackwhite.cc +++ b/rtgui/blackwhite.cc @@ -1003,7 +1003,7 @@ void BlackWhite::autoch_toggled () bool wasEnabled = disableListener(); if (mixerRed->getAddMode()) { - mixerRed->resetValue(false); + mixerRed->resetValue(true); } if (mixerGreen->getAddMode()) { @@ -1053,14 +1053,14 @@ void BlackWhite::autoch_toggled () } else { if (autoch->get_active()) { bool wasEnabled = disableListener(); - mixerRed->setValue(33); - mixerGreen->setValue(33); - mixerBlue->setValue(33); - mixerOrange->setValue(33); - mixerYellow->setValue(33); - mixerMagenta->setValue(33); - mixerPurple->setValue(33); - mixerCyan->setValue(33); + mixerRed->resetValue(false); + mixerGreen->resetValue(false); + mixerBlue->resetValue(false); + mixerOrange->resetValue(false); + mixerYellow->resetValue(false); + mixerMagenta->resetValue(false); + mixerPurple->resetValue(false); + mixerCyan->resetValue(false); setting->set_active (11); filter->set_active (0); diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc index 396b4cb65..2ca099769 100644 --- a/rtgui/colortoning.cc +++ b/rtgui/colortoning.cc @@ -320,9 +320,9 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR // LAB grid auto m = ProcEventMapper::getInstance(); EvColorToningLabGridValue = m->newEvent(RGBCURVE, "HISTORY_MSG_COLORTONING_LABGRID_VALUE"); - Gtk::HBox *labgridBox = Gtk::manage(new Gtk::HBox()); - labgridArea = Gtk::manage(new LabGrid(EvColorToningLabGridValue)); - labgridBox->pack_start(*labgridArea, true, true); + labgridBox = Gtk::manage(new Gtk::HBox()); + labgrid = Gtk::manage(new LabGrid(EvColorToningLabGridValue)); + labgridBox->pack_start(*labgrid, true, true); labgridReset = Gtk::manage(new Gtk::Button ()); labgridReset->add (*Gtk::manage(new RTImage ("gtk-undo-ltr-small.png", "gtk-undo-rtl-small.png"))); setExpandAlignProperties(labgridReset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START); @@ -331,11 +331,11 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR labgridReset->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT); labgridReset->set_can_focus(false); labgridReset->set_size_request(-1, 20); - labgridReset->signal_pressed().connect([=]() { static_cast(labgridArea)->set_params(0.0, 0.0, 0.0, 0.0, true); }); + labgridReset->signal_button_release_event().connect([=](GdkEventButton* release_event) { labgrid->reset(release_event->state & GDK_CONTROL_MASK ? true : false); return false; }); labgridBox->pack_start(*labgridReset, false, false); pack_start(*labgridBox, Gtk::PACK_EXPAND_WIDGET, 4); //------------------------------------------------------------------------ - + show_all(); disableListener(); @@ -357,7 +357,7 @@ ColorToning::~ColorToning() void ColorToning::setListener(ToolPanelListener *tpl) { ToolPanel::setListener(tpl); - static_cast(labgridArea)->set_listener(tpl); + labgrid->setListener(tpl); } /* @@ -432,7 +432,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) cl2shape->setUnChanged (!pedited->colorToning.cl2curve); lumamode->set_inconsistent (!pedited->colorToning.lumamode); - static_cast(labgridArea)->set_edited(pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh); + labgrid->setEdited(pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh); } redlow->setValue (pp->colorToning.redlow); @@ -464,7 +464,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited) lastLumamode = pp->colorToning.lumamode; - static_cast(labgridArea)->set_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, false); + labgrid->setParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, false); if (pedited && !pedited->colorToning.method) { method->set_active (5); @@ -532,7 +532,7 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pp->colorToning.saturatedOpacity = saturatedOpacity->getIntValue(); pp->colorToning.strength = strength->getIntValue(); - static_cast(labgridArea)->get_params(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); + labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); if (pedited) { pedited->colorToning.redlow = redlow->getEditedState (); @@ -559,7 +559,7 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited) pedited->colorToning.hlColSat = hlColSat->getEditedState (); pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); - pedited->colorToning.labgridALow = pedited->colorToning.labgridBLow = pedited->colorToning.labgridAHigh = pedited->colorToning.labgridBHigh = static_cast(labgridArea)->get_edited(); + pedited->colorToning.labgridALow = pedited->colorToning.labgridBLow = pedited->colorToning.labgridAHigh = pedited->colorToning.labgridBHigh = labgrid->getEdited(); } if (method->get_active_row_number() == 0) { @@ -630,6 +630,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* hlColSat->setDefault (defParams->colorToning.hlColSat); shadowsColSat->setDefault (defParams->colorToning.shadowsColSat); strength->setDefault (defParams->colorToning.strength); + labgrid->setDefault(defParams->colorToning.labgridALow, defParams->colorToning.labgridBLow, defParams->colorToning.labgridAHigh, defParams->colorToning.labgridBHigh); if (pedited) { redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited); @@ -647,6 +648,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* hlColSat->setDefaultEditedState (pedited->colorToning.hlColSat ? Edited : UnEdited); shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); strength->setDefaultEditedState (pedited->colorToning.strength ? Edited : UnEdited); + labgrid->setEdited((pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh) ? Edited : UnEdited); } else { redlow->setDefaultEditedState (Irrelevant); greenlow->setDefaultEditedState (Irrelevant); @@ -663,6 +665,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited* hlColSat->setDefaultEditedState (Irrelevant); shadowsColSat->setDefaultEditedState (Irrelevant); strength->setDefaultEditedState (Irrelevant); + labgrid->setEdited(Edited); } } @@ -825,8 +828,7 @@ void ColorToning::methodChanged () { if (!batchMode) { - labgridReset->hide(); - labgridArea->hide(); + labgridBox->hide(); if (method->get_active_row_number() == 0) { // Lab colorSep->show(); @@ -994,8 +996,7 @@ void ColorToning::methodChanged () neutrHBox->hide(); lumamode->hide(); - labgridReset->show(); - labgridArea->show(); + labgridBox->show(); } } diff --git a/rtgui/colortoning.h b/rtgui/colortoning.h index 9fd26e34c..588e6ee3b 100644 --- a/rtgui/colortoning.h +++ b/rtgui/colortoning.h @@ -12,6 +12,7 @@ #include "curveeditorgroup.h" #include "thresholdadjuster.h" #include "colorprovider.h" +#include "labgrid.h" class ColorToning final : public ToolParamBlock, @@ -105,7 +106,8 @@ private: rtengine::ProcEvent EvColorToningLabGridValue; Gtk::Button *labgridReset; - Gtk::DrawingArea *labgridArea; + LabGrid *labgrid; + Gtk::HBox *labgridBox; IdleRegister idle_register; }; diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc index 7cb752bb6..079b3290f 100644 --- a/rtgui/labgrid.cc +++ b/rtgui/labgrid.cc @@ -41,208 +41,270 @@ using rtengine::Color; -bool LabGrid::notify_listener() +bool LabGrid::notifyListener() { - if (listener_) { - listener_->panelChanged(evt_, Glib::ustring::compose("%1 %2 %3 %4", int(low_a_), int(low_b_), int(high_a_), int(high_b_))); + if (listener) { + listener->panelChanged(evt, Glib::ustring::compose(M("TP_COLORTONING_LABGRID_VALUES"), int(low_a), int(low_b), int(high_a), int(high_b))); } return false; } - + LabGrid::LabGrid(rtengine::ProcEvent evt): Gtk::DrawingArea(), - evt_(evt), selected_(OFF), - low_a_(0.f), high_a_(0.f), low_b_(0.f), high_b_(0.f), - listener_(nullptr), - edited_(false) + evt(evt), litPoint(NONE), + low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), + defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), + listener(nullptr), + edited(false), + isDragged(false) { set_can_focus(true); - add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK); + add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); +} + +void LabGrid::getParams(double &la, double &lb, double &ha, double &hb) const +{ + la = low_a; + ha = high_a; + lb = low_b; + hb = high_b; } -void LabGrid::get_params(double &la, double &lb, double &ha, double &hb) const +void LabGrid::setParams(double la, double lb, double ha, double hb, bool notify) { - la = low_a_; - ha = high_a_; - lb = low_b_; - hb = high_b_; -} - - -void LabGrid::set_params(double la, double lb, double ha, double hb, bool notify) -{ - low_a_ = la; - low_b_ = lb; - high_a_ = ha; - high_b_ = hb; + low_a = la; + low_b = lb; + high_a = ha; + high_b = hb; queue_draw(); if (notify) { - notify_listener(); + notifyListener(); + } +} + +void LabGrid::setDefault (double la, double lb, double ha, double hb) +{ + defaultLow_a = la; + defaultLow_b = lb; + defaultHigh_a = ha; + defaultHigh_b = hb; +} + + +void LabGrid::reset(bool toInitial) +{ + if (toInitial) { + setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, true); + } else { + setParams(0., 0., 0., 0., true); } } -void LabGrid::set_edited(bool yes) +void LabGrid::setEdited(bool yes) { - edited_ = yes; + edited = yes; } -bool LabGrid::get_edited() const +bool LabGrid::getEdited() const { - return edited_; + return edited; } -void LabGrid::set_listener(ToolPanelListener *l) +void LabGrid::setListener(ToolPanelListener *l) { - listener_ = l; + listener = l; +} + + +void LabGrid::on_style_updated () +{ + setDirty(true); + queue_draw (); } bool LabGrid::on_draw(const ::Cairo::RefPtr &crf) { - int width = get_allocated_width(); - int height = get_allocated_height(); - Cairo::RefPtr cst = - Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, width, height); - Cairo::RefPtr cr = Cairo::Context::create(cst); - // clear bg - cr->set_source_rgb(.2, .2, .2); - cr->paint(); - - cr->translate(inset, inset); - cr->set_antialias(Cairo::ANTIALIAS_NONE); - width -= 2 * inset; - height -= 2 * inset; - // flip y: - cr->translate(0, height); - cr->scale(1., -1.); - const int cells = 8; - float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); - for (int j = 0; j < cells; j++) { - for (int i = 0; i < cells; i++) { - float R, G, B; - float x, y, z; - int ii = i - cells/2; - int jj = j - cells/2; - float a = step * (ii + 0.5); - float b = step * (jj + 0.5); - Color::Lab2XYZ(25000.f, a, b, x, y, z); - Color::xyz2srgb(x, y, z, R, G, B); - cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); - cr->rectangle(width * i / float(cells), height * j / float(cells), width / float(cells) - 1, height / float(cells) - 1); - cr->fill(); + Gtk::Allocation allocation = get_allocation(); + allocation.set_x(0); + allocation.set_y(0); + + // setDrawRectangle will allocate the backbuffer Surface + if (setDrawRectangle(Cairo::FORMAT_ARGB32, allocation)) { + setDirty(true); + } + + if (!isDirty() || !surfaceCreated()) { + return true; + } + + Glib::RefPtr style = get_style_context(); + Cairo::RefPtr cr = getContext(); + + if (isDirty()) { + int width = allocation.get_width(); + int height = allocation.get_height(); + + cr->set_line_cap(Cairo::LINE_CAP_SQUARE); + + // clear background + cr->set_source_rgba (0., 0., 0., 0.); + cr->set_operator (Cairo::OPERATOR_CLEAR); + cr->paint (); + cr->set_operator (Cairo::OPERATOR_OVER); + style->render_background(cr, 0, 0, width, height); + + // drawing the cells + cr->translate(inset, inset); + cr->set_antialias(Cairo::ANTIALIAS_NONE); + width -= 2 * inset; + height -= 2 * inset; + // flip y: + cr->translate(0, height); + cr->scale(1., -1.); + const int cells = 8; + float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); + for (int j = 0; j < cells; j++) { + for (int i = 0; i < cells; i++) { + float R, G, B; + float x, y, z; + int ii = i - cells/2; + int jj = j - cells/2; + float a = step * (ii + 0.5); + float b = step * (jj + 0.5); + Color::Lab2XYZ(25000.f, a, b, x, y, z); + Color::xyz2srgb(x, y, z, R, G, B); + cr->set_source_rgb(R / 65535.f, G / 65535.f, B / 65535.f); + cr->rectangle(width * i / float(cells), height * j / float(cells), width / float(cells) - 1, height / float(cells) - 1); + cr->fill(); + } } - } - cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); - float loa, hia, lob, hib; - loa = .5f * (width + width * low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - hia = .5f * (width + width * high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - lob = .5f * (height + height * low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - hib = .5f * (height + height * high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX); - cr->set_line_width(2.); - cr->set_source_rgb(0.6, 0.6, 0.6); - cr->move_to(loa, lob); - cr->line_to(hia, hib); - cr->stroke(); - cr->set_source_rgb(0.1, 0.1, 0.1); - if (selected_ == LOW) { - cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); - } else { - cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); - } - cr->fill(); + // drawing the connection line + cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); + float loa, hia, lob, hib; + loa = .5f * (width + width * low_a / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hia = .5f * (width + width * high_a / rtengine::ColorToningParams::LABGRID_CORR_MAX); + lob = .5f * (height + height * low_b / rtengine::ColorToningParams::LABGRID_CORR_MAX); + hib = .5f * (height + height * high_b / rtengine::ColorToningParams::LABGRID_CORR_MAX); + cr->set_line_width(2.); + cr->set_source_rgb(0.6, 0.6, 0.6); + cr->move_to(loa, lob); + cr->line_to(hia, hib); + cr->stroke(); - cr->set_source_rgb(0.9, 0.9, 0.9); - if (selected_ == HIGH) { - cr->arc(hia, hib, 5, 0, 2. * rtengine::RT_PI); - } else { - cr->arc(hia, hib, 3, 0, 2. * rtengine::RT_PI); - } - cr->fill(); + // drawing points + cr->set_source_rgb(0.1, 0.1, 0.1); + if (litPoint == LOW) { + cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); + } else { + cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); + } + cr->fill(); - crf->set_source(cst, 0, 0); - crf->paint(); - - return true; + cr->set_source_rgb(0.9, 0.9, 0.9); + if (litPoint == HIGH) { + cr->arc(hia, hib, 5, 0, 2. * rtengine::RT_PI); + } else { + cr->arc(hia, hib, 3, 0, 2. * rtengine::RT_PI); + } + cr->fill(); + } + + copySurface(crf); + return false; } bool LabGrid::on_button_press_event(GdkEventButton *event) { - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - switch (selected_) { - case OFF: - low_a_ = low_b_ = high_a_ = high_b_ = 0.f; - break; - case LOW: - low_a_ = low_b_ = 0.f; - break; - case HIGH: - high_a_ = high_b_ = 0.f; - break; + if (event->button == 1) { + if (event->type == GDK_2BUTTON_PRESS) { + switch (litPoint) { + case NONE: + low_a = low_b = high_a = high_b = 0.f; + break; + case LOW: + low_a = low_b = 0.f; + break; + case HIGH: + high_a = high_b = 0.f; + break; + } + edited = true; + } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { + isDragged = true; } - edited_ = true; - queue_draw(); - notify_listener(); + return false; } return true; } - + + +bool LabGrid::on_button_release_event(GdkEventButton *event) +{ + if (event->button == 1) { + isDragged = false; + return false; + } + return true; +} + bool LabGrid::on_motion_notify_event(GdkEventMotion *event) { - if (delay_conn_.connected()) { - delay_conn_.disconnect(); + if (isDragged && delayconn.connected()) { + delayconn.disconnect(); } - + + State oldLitPoint = litPoint; + int width = get_allocated_width() - 2 * inset, height = get_allocated_height() - 2 * inset; const float mouse_x = std::min(std::max(event->x - inset, 0.), double(width)); const float mouse_y = std::min(std::max(height - 1 - event->y + inset, 0.), double(height)); const float ma = (2.0 * mouse_x - width) / (float)width; const float mb = (2.0 * mouse_y - height) / (float)height; - bool refresh = selected_ != OFF; - if (event->state & GDK_BUTTON1_MASK) { - if (selected_ == LOW) { - low_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; - low_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; - } else if (selected_ == HIGH) { - high_a_ = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; - high_b_ = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + if (isDragged) { + if (litPoint == LOW) { + low_a = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + low_b = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; + } else if (litPoint == HIGH) { + high_a = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; + high_b = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; } + grab_focus(); + if (options.adjusterMinDelay == 0) { + notifyListener(); + } else { + delayconn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notifyListener), options.adjusterMinDelay); + } + queue_draw(); } else { - selected_ = OFF; - float la = low_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float lb = low_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float ha = high_a_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; - float hb = high_b_ / rtengine::ColorToningParams::LABGRID_CORR_MAX; + litPoint = NONE; + float la = low_a / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float lb = low_b / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float ha = high_a / rtengine::ColorToningParams::LABGRID_CORR_MAX; + float hb = high_b / rtengine::ColorToningParams::LABGRID_CORR_MAX; const float thrs = 0.05f; const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); if (distlo < thrs * thrs && distlo < disthi) { - selected_ = LOW; + litPoint = LOW; } else if (disthi < thrs * thrs && disthi <= distlo) { - selected_ = HIGH; + litPoint = HIGH; } - } - if (selected_ != OFF) { - grab_focus(); - if (options.adjusterMinDelay == 0) { - notify_listener(); - } else { - delay_conn_ = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notify_listener), options.adjusterMinDelay); + if ((oldLitPoint == NONE && litPoint != NONE) || (oldLitPoint != NONE && litPoint == NONE)) { + queue_draw(); } } - if (refresh) { - queue_draw(); - } return true; } - + Gtk::SizeRequestMode LabGrid::get_request_mode_vfunc() const { @@ -253,7 +315,7 @@ Gtk::SizeRequestMode LabGrid::get_request_mode_vfunc() const void LabGrid::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const { minimum_width = 50; - natural_width = 200; + natural_width = 150; // same as GRAPH_SIZE from mycurve.h } diff --git a/rtgui/labgrid.h b/rtgui/labgrid.h index dcb34bcc3..348ab2398 100644 --- a/rtgui/labgrid.h +++ b/rtgui/labgrid.h @@ -43,33 +43,45 @@ #include "toolpanel.h" -class LabGrid: public Gtk::DrawingArea { +class LabGrid: public Gtk::DrawingArea, public BackBuffer { private: - rtengine::ProcEvent evt_; - enum State { OFF, HIGH, LOW }; - State selected_; - float low_a_; - float high_a_; - float low_b_; - float high_b_; - ToolPanelListener *listener_; - bool edited_; - sigc::connection delay_conn_; + rtengine::ProcEvent evt; + enum State { NONE, HIGH, LOW }; + State litPoint; + float low_a; + float high_a; + float low_b; + float high_b; + + float defaultLow_a; + float defaultHigh_a; + float defaultLow_b; + float defaultHigh_b; + + ToolPanelListener *listener; + bool edited; + bool isDragged; + sigc::connection delayconn; static const int inset = 2; - bool notify_listener(); - + bool notifyListener(); + void getLitPoint(); + public: LabGrid(rtengine::ProcEvent evt); - void get_params(double &la, double &lb, double &ha, double &hb) const; - void set_params(double la, double lb, double ha, double hb, bool notify); - void set_edited(bool yes); - bool get_edited() const; - void set_listener(ToolPanelListener *l); + void getParams(double &la, double &lb, double &ha, double &hb) const; + void setParams(double la, double lb, double ha, double hb, bool notify); + void setDefault (double la, double lb, double ha, double hb); + void setEdited(bool yes); + bool getEdited() const; + void reset(bool toInitial); + void setListener(ToolPanelListener *l); bool on_draw(const ::Cairo::RefPtr &crf); + void on_style_updated (); bool on_button_press_event(GdkEventButton *event); + bool on_button_release_event(GdkEventButton *event); bool on_motion_notify_event(GdkEventMotion *event); Gtk::SizeRequestMode get_request_mode_vfunc() const; void get_preferred_width_vfunc(int &minimum_width, int &natural_width) const; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 5355c88da..b124eddfc 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -1540,9 +1540,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.colorToning.bluehigh = dontforceSet && options.baBehav[ADDSET_COLORTONING_SPLIT] ? toEdit.colorToning.bluehigh + mods.colorToning.bluehigh : mods.colorToning.bluehigh; } - if (colorToning.labgridALow) { - toEdit.colorToning.labgridALow = mods.colorToning.labgridALow; - } if (colorToning.labgridALow) { toEdit.colorToning.labgridALow = mods.colorToning.labgridALow; } From 2523983776085aeae1cbd86619d81134645f2fe8 Mon Sep 17 00:00:00 2001 From: Hombre Date: Sun, 14 Jan 2018 00:34:22 +0100 Subject: [PATCH 20/21] LabGrid was disfunctional in BatchEditing (reported in PR #4301) --- rtgui/labgrid.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rtgui/labgrid.cc b/rtgui/labgrid.cc index 079b3290f..945073221 100644 --- a/rtgui/labgrid.cc +++ b/rtgui/labgrid.cc @@ -237,6 +237,8 @@ bool LabGrid::on_button_press_event(GdkEventButton *event) break; } edited = true; + notifyListener(); + queue_draw(); } else if (event->type == GDK_BUTTON_PRESS && litPoint != NONE) { isDragged = true; } @@ -277,6 +279,7 @@ bool LabGrid::on_motion_notify_event(GdkEventMotion *event) high_a = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; high_b = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; } + edited = true; grab_focus(); if (options.adjusterMinDelay == 0) { notifyListener(); From b762804b809889e8e1fd81a244820d2e3d27cdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=B6ssie?= Date: Sun, 14 Jan 2018 10:32:48 +0100 Subject: [PATCH 21/21] Fix clang build (fixes #4303) --- rtengine/ipresize.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index c62ff0bc9..ba559b2a0 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -105,7 +105,10 @@ void ImProcFunctions::Lanczos (const Imagefloat* src, Imagefloat* dst, float sca float y0 = (static_cast (i) + 0.5f) * delta - 0.5f; // weights for interpolation in y direction - float w[support] = {}; + float w[support]; + for (auto& f : w) { + f = 0.f; + } // sum of weights used for normalization float ws = 0.0f;