From c4e21438a1da2e880f6e041669b993225a3f7e2f Mon Sep 17 00:00:00 2001 From: rfranke Date: Fri, 3 Jan 2020 10:37:22 +0100 Subject: [PATCH 01/33] Open inspector fullscreen and exploit monitor resolution, see #1474, #5591 - filecatalog.cc: add shortcuts 'f' for image on full screen 'Shift' 'f' for 100% crop on full screen (synchronization with mouse move as before with dual monitors) - filepanel.cc: don't create inspector tab - inspector.cc, inspector.h: create separate window for inspector scale image if requested exploit device scaling for full monitor resolution under macOS --- rtgui/filecatalog.cc | 10 +++++++ rtgui/filepanel.cc | 8 +++--- rtgui/inspector.cc | 68 ++++++++++++++++++++++++++++++++++++++------ rtgui/inspector.h | 10 ++++++- 4 files changed, 83 insertions(+), 13 deletions(-) diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 109a1bb57..a283398ee 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -42,6 +42,7 @@ #include "pathutils.h" #include "thumbnail.h" #include "toolbar.h" +#include "inspector.h" using namespace std; @@ -2503,6 +2504,15 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) } } + if (!ctrl && !alt) { + switch (event->keyval) { + case GDK_KEY_f: + case GDK_KEY_F: + fileBrowser->getInspector()->showWindow(!shift); + return true; + } + } + return fileBrowser->keyPressed(event); } diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 1a66aed7c..983a0840c 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -115,9 +115,9 @@ FilePanel::FilePanel () : parent(nullptr), error(0) Gtk::Label* devLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_DEVELOP")) ); devLab->set_name ("LabelRightNotebook"); devLab->set_angle (90); - Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) ); - inspectLab->set_name ("LabelRightNotebook"); - inspectLab->set_angle (90); + //Gtk::Label* inspectLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_INSPECT")) ); + //inspectLab->set_name ("LabelRightNotebook"); + //inspectLab->set_angle (90); Gtk::Label* filtLab = Gtk::manage ( new Gtk::Label (M("MAIN_TAB_FILTER")) ); filtLab->set_name ("LabelRightNotebook"); filtLab->set_angle (90); @@ -132,7 +132,7 @@ FilePanel::FilePanel () : parent(nullptr), error(0) tpcPaned->pack2 (*history, true, false); rightNotebook->append_page (*sFilterPanel, *filtLab); - rightNotebook->append_page (*inspectorPanel, *inspectLab); + //rightNotebook->append_page (*inspectorPanel, *inspectLab); rightNotebook->append_page (*tpcPaned, *devLab); //rightNotebook->append_page (*taggingBox, *tagLab); commented out: currently the tab is empty ... rightNotebook->append_page (*sExportPanel, *exportLab); diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 9002cc389..d27dd8d08 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -82,9 +82,16 @@ InspectorBuffer::~InspectorBuffer() { // return deg; //} -Inspector::Inspector () : currImage(nullptr), zoom(0.0), active(false) +Inspector::Inspector () : currImage(nullptr), scaled(false), active(false) { set_name("Inspector"); + window.add_events(Gdk::KEY_PRESS_MASK); + window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release)); + window.set_title("RawTherapee Inspector"); + window.add(*this); + window.show_all(); + window.set_visible(false); + active = true; // always track inspected thumbnails } Inspector::~Inspector() @@ -92,6 +99,19 @@ Inspector::~Inspector() deleteBuffers(); } +void Inspector::showWindow(bool scaled) +{ + this->scaled = scaled; + window.fullscreen(); + window.set_visible(true); +} + +bool Inspector::on_key_release(GdkEventKey *event) +{ + window.set_visible(false); + return true; +} + bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) { @@ -116,10 +136,18 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) rtengine::Coord availableSize; rtengine::Coord topLeft; rtengine::Coord dest(0, 0); - availableSize.x = win->get_width(); - availableSize.y = win->get_height(); + int deviceScale = get_scale_factor(); + availableSize.x = win->get_width() * deviceScale; + availableSize.y = win->get_height() * deviceScale; int imW = currImage->imgBuffer.getWidth(); int imH = currImage->imgBuffer.getHeight(); + double scale = 1.0; + if (scaled) { + // reduce size of image to fit into window + scale = rtengine::min(1.0, rtengine::min((double)availableSize.x/imW, (double)availableSize.y/imH)); + availableSize.x /= scale; + availableSize.y /= scale; + } if (imW < availableSize.x) { // center the image in the available space along X @@ -163,24 +191,48 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) Glib::RefPtr style = get_style_context(); // draw the background - style->render_background(cr, 0, 0, get_width(), get_height()); + //style->render_background(cr, 0, 0, get_width(), get_height()); - /* --- old method + ///* --- old method (the new method does not seem to work) c = style->get_background_color (Gtk::STATE_FLAG_NORMAL); cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue()); cr->set_line_width (0); cr->rectangle (0, 0, availableSize.x, availableSize.y); cr->fill (); - */ + //*/ - currImage->imgBuffer.copySurface(win); + bool scaledImage = scaled && (imW > win->get_width() || imH > win->get_height()); + if (deviceScale == 1 && !scaledImage) { + // standard drawing + currImage->imgBuffer.copySurface(win); + } + else { + // consider device scale and image scale + if (deviceScale > 1) { + // use full device resolution and let it scale the image (macOS) + cairo_surface_set_device_scale(cr->get_target()->cobj(), scale, scale); + scaledImage = false; + } + Glib::RefPtr crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeft.x, topLeft.y, rtengine::min(imW, availableSize.x), rtengine::min(imH, availableSize.y)); + if (!scaledImage) { + Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x, dest.y); + } + else { + // assume that the device does not support scaling (Linux) + crop = crop->scale_simple(imW*scale, imH*scale, Gdk::INTERP_BILINEAR); + Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x*scale, dest.y*scale); + } + cr->paint(); + } + /* --- not for separate window // draw the frame c = style->get_border_color (Gtk::STATE_FLAG_NORMAL); cr->set_source_rgb (c.get_red(), c.get_green(), c.get_blue()); cr->set_line_width (1); cr->rectangle (0.5, 0.5, availableSize.x - 1, availableSize.y - 1); cr->stroke (); + */ } return true; @@ -309,7 +361,7 @@ void Inspector::setActive(bool state) flushBuffers(); } - active = state; + //active = state; } diff --git a/rtgui/inspector.h b/rtgui/inspector.h index 8338259bf..2844b55ac 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -47,12 +47,15 @@ private: rtengine::Coord center; std::vector images; InspectorBuffer* currImage; - double zoom; + bool scaled; bool active; sigc::connection delayconn; Glib::ustring next_image_path; + Gtk::Window window; + bool on_key_release(GdkEventKey *event); + bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; void deleteBuffers(); @@ -62,6 +65,11 @@ public: Inspector(); ~Inspector() override; + /** @brief Show or hide window + * @param scaled fit image into window + */ + void showWindow(bool scaled); + /** @brief Mouse movement to a new position * @param pos Location of the mouse, in percentage (i.e. [0;1] range) relative to the full size image ; -1,-1 == out of the image * @param transform H/V flip and coarse rotation transformation From 3deff849efd09f4d8fa0c9fbb2eec0b192443d63 Mon Sep 17 00:00:00 2001 From: rfranke Date: Fri, 3 Jan 2020 16:46:00 +0100 Subject: [PATCH 02/33] Hide inspector window during initialization, thanks to @heckflosse --- rtgui/inspector.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index d27dd8d08..aa0a9c4ad 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -85,6 +85,7 @@ InspectorBuffer::~InspectorBuffer() { Inspector::Inspector () : currImage(nullptr), scaled(false), active(false) { set_name("Inspector"); + window.set_visible(false); window.add_events(Gdk::KEY_PRESS_MASK); window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release)); window.set_title("RawTherapee Inspector"); From 6604ab1b7c6f72782d7f9827b710ef4889981d3e Mon Sep 17 00:00:00 2001 From: rfranke Date: Sat, 4 Jan 2020 18:35:15 +0100 Subject: [PATCH 03/33] Enhance inspector window with scrolling and pinning - 2D scrolling during 1:1 view (tested with mac trackpad) - click to pin inspector window - another click or ESC to hide inspector window - 'z' or 'F' to switch to 1:1 view, 'f' to switch to scaled view --- rtgui/inspector.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++-- rtgui/inspector.h | 4 +++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index aa0a9c4ad..9cda065fc 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -82,12 +82,19 @@ InspectorBuffer::~InspectorBuffer() { // return deg; //} -Inspector::Inspector () : currImage(nullptr), scaled(false), active(false) +Inspector::Inspector () : currImage(nullptr), scaled(false), active(false), pinned(false) { set_name("Inspector"); window.set_visible(false); + window.add_events(Gdk::KEY_PRESS_MASK); + window.add_events(Gdk::BUTTON_PRESS_MASK); + window.add_events(Gdk::SCROLL_MASK); window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release)); + window.signal_button_press_event().connect(sigc::mem_fun(*this, &Inspector::on_button_press)); + window.signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press)); + window.signal_scroll_event().connect(sigc::mem_fun(*this, &Inspector::on_scroll)); + window.set_title("RawTherapee Inspector"); window.add(*this); window.show_all(); @@ -105,11 +112,73 @@ void Inspector::showWindow(bool scaled) this->scaled = scaled; window.fullscreen(); window.set_visible(true); + pinned = false; } bool Inspector::on_key_release(GdkEventKey *event) { - window.set_visible(false); + if (!pinned) { + switch (event->keyval) { + case GDK_KEY_f: + case GDK_KEY_F: + window.set_visible(false); + return true; + } + } + return false; +} + +bool Inspector::on_button_press(GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_PRESS) { + if (!pinned) + // pin window with mouse click + pinned = true; + else + // release window with another mouse click + window.set_visible(false); + return true; + } + return false; +} + +bool Inspector::on_key_press(GdkEventKey *event) +{ + switch (event->keyval) { + case GDK_KEY_z: + case GDK_KEY_F: + scaled = false; + queue_draw(); + return true; + case GDK_KEY_f: + scaled = true; + queue_draw(); + return true; + case GDK_KEY_Escape: + window.set_visible(false); + return true; + } + + return false; +} + +bool Inspector::on_scroll(GdkEventScroll *event) +{ + if (!currImage) + return false; + + rtengine::Coord margin; // limit for scroll area + int deviceScale = get_scale_factor(); + int imW = currImage->imgBuffer.getWidth(); + int imH = currImage->imgBuffer.getHeight(); + margin.x = (window.get_width() * deviceScale) / 2; + margin.y = (window.get_height() * deviceScale) / 2; + int new_x = rtengine::min(center.x + event->delta_x * deviceScale, imW - margin.x); + int new_y = rtengine::min(center.y + event->delta_y * deviceScale, imH - margin.y); + + center.set(rtengine::max(margin.x, new_x), rtengine::max(margin.y, new_y)); + queue_draw(); + return true; } diff --git a/rtgui/inspector.h b/rtgui/inspector.h index 2844b55ac..5f916ae81 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -49,12 +49,16 @@ private: InspectorBuffer* currImage; bool scaled; bool active; + bool pinned; sigc::connection delayconn; Glib::ustring next_image_path; Gtk::Window window; bool on_key_release(GdkEventKey *event); + bool on_button_press(GdkEventButton *event); + bool on_key_press(GdkEventKey *event); + bool on_scroll(GdkEventScroll *event); bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; void deleteBuffers(); From a064a225e0fd0726fa3faaf70a993efec7d8d48b Mon Sep 17 00:00:00 2001 From: rfranke Date: Sun, 5 Jan 2020 17:48:24 +0100 Subject: [PATCH 04/33] Support more scroll devices for inspector window - introduce step increment for non-mac - don't close pinned window on button press anymore --- rtgui/inspector.cc | 85 +++++++++++++++++++++++++++++++--------------- rtgui/inspector.h | 5 +-- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 9cda065fc..4624bab50 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -86,16 +86,14 @@ Inspector::Inspector () : currImage(nullptr), scaled(false), active(false), pinn { set_name("Inspector"); window.set_visible(false); + window.set_title("RawTherapee Inspector"); window.add_events(Gdk::KEY_PRESS_MASK); - window.add_events(Gdk::BUTTON_PRESS_MASK); - window.add_events(Gdk::SCROLL_MASK); window.signal_key_release_event().connect(sigc::mem_fun(*this, &Inspector::on_key_release)); - window.signal_button_press_event().connect(sigc::mem_fun(*this, &Inspector::on_button_press)); window.signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press)); - window.signal_scroll_event().connect(sigc::mem_fun(*this, &Inspector::on_scroll)); - window.set_title("RawTherapee Inspector"); + add_events(Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); + window.add(*this); window.show_all(); window.set_visible(false); @@ -128,20 +126,6 @@ bool Inspector::on_key_release(GdkEventKey *event) return false; } -bool Inspector::on_button_press(GdkEventButton *event) -{ - if (event->type == GDK_BUTTON_PRESS) { - if (!pinned) - // pin window with mouse click - pinned = true; - else - // release window with another mouse click - window.set_visible(false); - return true; - } - return false; -} - bool Inspector::on_key_press(GdkEventKey *event) { switch (event->keyval) { @@ -162,7 +146,18 @@ bool Inspector::on_key_press(GdkEventKey *event) return false; } -bool Inspector::on_scroll(GdkEventScroll *event) +bool Inspector::on_button_press_event(GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_PRESS) { + if (!pinned) + // pin window with mouse click + pinned = true; + return true; + } + return false; +} + +bool Inspector::on_scroll_event(GdkEventScroll *event) { if (!currImage) return false; @@ -173,10 +168,46 @@ bool Inspector::on_scroll(GdkEventScroll *event) int imH = currImage->imgBuffer.getHeight(); margin.x = (window.get_width() * deviceScale) / 2; margin.y = (window.get_height() * deviceScale) / 2; - int new_x = rtengine::min(center.x + event->delta_x * deviceScale, imW - margin.x); - int new_y = rtengine::min(center.y + event->delta_y * deviceScale, imH - margin.y); - center.set(rtengine::max(margin.x, new_x), rtengine::max(margin.y, new_y)); +#ifdef GDK_WINDOWING_QUARTZ + // event reports speed of scroll wheel + double step_x = -event->delta_x; + double step_y = event->delta_y; +#else + // assume fixed step of 5% + double step_x = 5; + double step_y = 5; +#endif + int delta_x = 0; + int delta_y = 0; + switch (event->direction) { + case GDK_SCROLL_SMOOTH: +#ifdef GDK_WINDOWING_QUARTZ + // no additional step for smooth scrolling + delta_x = event->delta_x * deviceScale; + delta_y = event->delta_y * deviceScale; +#else + // apply step to smooth scrolling as well + delta_x = event->delta_x * deviceScale * step_x * imW / 100; + delta_y = event->delta_y * deviceScale * step_y * imH / 100; +#endif + break; + case GDK_SCROLL_DOWN: + delta_y = step_y * deviceScale * imH / 100; + break; + case GDK_SCROLL_UP: + delta_y = -step_y * deviceScale * imH / 100; + break; + case GDK_SCROLL_LEFT: + delta_x = step_x * deviceScale * imW / 100; + break; + case GDK_SCROLL_RIGHT: + delta_x = -step_x * deviceScale * imW / 100; + break; + } + + center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x), + rtengine::LIM(center.y + delta_y, margin.y, imH - margin.y)); queue_draw(); return true; @@ -272,11 +303,11 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) //*/ bool scaledImage = scaled && (imW > win->get_width() || imH > win->get_height()); - if (deviceScale == 1 && !scaledImage) { + if (deviceScale == 1 && !scaledImage) { // standard drawing currImage->imgBuffer.copySurface(win); - } - else { + } + else { // consider device scale and image scale if (deviceScale > 1) { // use full device resolution and let it scale the image (macOS) @@ -293,7 +324,7 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x*scale, dest.y*scale); } cr->paint(); - } + } /* --- not for separate window // draw the frame diff --git a/rtgui/inspector.h b/rtgui/inspector.h index 5f916ae81..5262ccc8f 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -56,9 +56,10 @@ private: Gtk::Window window; bool on_key_release(GdkEventKey *event); - bool on_button_press(GdkEventButton *event); bool on_key_press(GdkEventKey *event); - bool on_scroll(GdkEventScroll *event); + + bool on_button_press_event(GdkEventButton *event) override; + bool on_scroll_event(GdkEventScroll *event) override; bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; void deleteBuffers(); From 134aa407c079fe18c664600bdf3516fc053d876c Mon Sep 17 00:00:00 2001 From: rfranke Date: Sun, 19 Jan 2020 16:01:29 +0100 Subject: [PATCH 05/33] Enhance inspector window with zooming - support zoom gesture and Alt scroll --- rtgui/inspector.cc | 99 ++++++++++++++++++++++++++++++++++++++-------- rtgui/inspector.h | 11 +++++- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 4624bab50..471f08e95 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -82,7 +82,7 @@ InspectorBuffer::~InspectorBuffer() { // return deg; //} -Inspector::Inspector () : currImage(nullptr), scaled(false), active(false), pinned(false) +Inspector::Inspector () : currImage(nullptr), scaled(false), scale(1.0), zoomScale(1.0), zoomScaleBegin(1.0), active(false), pinned(false), dirty(false) { set_name("Inspector"); window.set_visible(false); @@ -93,6 +93,9 @@ Inspector::Inspector () : currImage(nullptr), scaled(false), active(false), pinn window.signal_key_press_event().connect(sigc::mem_fun(*this, &Inspector::on_key_press)); add_events(Gdk::BUTTON_PRESS_MASK | Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); + gestureZoom = Gtk::GestureZoom::create(*this); + gestureZoom->signal_begin().connect(sigc::mem_fun(*this, &Inspector::on_zoom_begin)); + gestureZoom->signal_scale_changed().connect(sigc::mem_fun(*this, &Inspector::on_zoom_scale_changed)); window.add(*this); window.show_all(); @@ -119,6 +122,7 @@ bool Inspector::on_key_release(GdkEventKey *event) switch (event->keyval) { case GDK_KEY_f: case GDK_KEY_F: + zoomScale = 1.0; window.set_visible(false); return true; } @@ -131,14 +135,19 @@ bool Inspector::on_key_press(GdkEventKey *event) switch (event->keyval) { case GDK_KEY_z: case GDK_KEY_F: + if (pinned || scaled) + zoomScale = 1.0; // reset if not key hold scaled = false; queue_draw(); return true; case GDK_KEY_f: + if (pinned || !scaled) + zoomScale = 1.0; // reset if not key hold scaled = true; queue_draw(); return true; case GDK_KEY_Escape: + zoomScale = 1.0; window.set_visible(false); return true; } @@ -162,12 +171,10 @@ bool Inspector::on_scroll_event(GdkEventScroll *event) if (!currImage) return false; - rtengine::Coord margin; // limit for scroll area + bool alt = event->state & GDK_MOD1_MASK; int deviceScale = get_scale_factor(); int imW = currImage->imgBuffer.getWidth(); int imH = currImage->imgBuffer.getHeight(); - margin.x = (window.get_width() * deviceScale) / 2; - margin.y = (window.get_height() * deviceScale) / 2; #ifdef GDK_WINDOWING_QUARTZ // event reports speed of scroll wheel @@ -206,15 +213,66 @@ bool Inspector::on_scroll_event(GdkEventScroll *event) break; } + if (alt) { + // zoom + beginZoom(event->x, event->y); + if (std::fabs(delta_y) > std::fabs(delta_x)) + on_zoom_scale_changed(1.0 + (double)delta_y / imH / deviceScale); + else + on_zoom_scale_changed(1.0 + (double)delta_x / imW / deviceScale); + return true; + } + + // scroll + rtengine::Coord margin; // limit for scroll area + margin.x = rtengine::min(window.get_width() * deviceScale / scale, imW) / 2; + margin.y = rtengine::min(window.get_height() * deviceScale / scale, imH) / 2; center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x), rtengine::LIM(center.y + delta_y, margin.y, imH - margin.y)); - queue_draw(); + + if (!dirty) { + dirty = true; + queue_draw(); + } return true; } +void Inspector::beginZoom(double x, double y) +{ + int deviceScale = get_scale_factor(); + dcenterBegin.x = (x - window.get_width()/2) / scale * deviceScale; + dcenterBegin.y = (y - window.get_height()/2) / scale * deviceScale; + centerBegin = center; + zoomScaleBegin = zoomScale; +} + +void Inspector::on_zoom_begin(GdkEventSequence *s) +{ + double x, y; + if (gestureZoom->get_point(s, x, y)) + beginZoom(x, y); +} + +void Inspector::on_zoom_scale_changed(double zscale) +{ + if (!currImage) + return; + + zoomScale = rtengine::LIM(zoomScaleBegin * zscale, 0.01, 16.0); + double dcenterRatio = 1.0 - zoomScaleBegin / zoomScale; + center.x = centerBegin.x + dcenterBegin.x * dcenterRatio; + center.y = centerBegin.y + dcenterBegin.y * dcenterRatio; + + if (!dirty) { + dirty = true; + queue_draw(); + } +} + bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) { + dirty = false; Glib::RefPtr win = get_window(); @@ -240,15 +298,21 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) int deviceScale = get_scale_factor(); availableSize.x = win->get_width() * deviceScale; availableSize.y = win->get_height() * deviceScale; - int imW = currImage->imgBuffer.getWidth(); - int imH = currImage->imgBuffer.getHeight(); - double scale = 1.0; + int imW = rtengine::max(currImage->imgBuffer.getWidth(), 1); + int imH = rtengine::max(currImage->imgBuffer.getHeight(), 1); + scale = rtengine::min((double)availableSize.x / imW, (double)availableSize.y / imH); if (scaled) { - // reduce size of image to fit into window - scale = rtengine::min(1.0, rtengine::min((double)availableSize.x/imW, (double)availableSize.y/imH)); - availableSize.x /= scale; - availableSize.y /= scale; + // reduce size of image to fit into window, no further zoom down + zoomScale = rtengine::max(zoomScale, 1.0); + scale *= zoomScale; } + else { + // limit zoom to fill at least complete window or 1:1 + zoomScale = rtengine::max(zoomScale, rtengine::min(1.0, scale)); + scale = zoomScale; + } + availableSize.x /= scale; + availableSize.y /= scale; if (imW < availableSize.x) { // center the image in the available space along X @@ -275,7 +339,6 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) topLeft.y -= availableSize.y; topLeft.y = rtengine::max(topLeft.y, 0); } - //printf("center: %d, %d (img: %d, %d) (availableSize: %d, %d) (topLeft: %d, %d)\n", center.x, center.y, imW, imH, availableSize.x, availableSize.y, topLeft.x, topLeft.y); // define the destination area @@ -302,7 +365,7 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) cr->fill (); //*/ - bool scaledImage = scaled && (imW > win->get_width() || imH > win->get_height()); + bool scaledImage = scale != 1.0; if (deviceScale == 1 && !scaledImage) { // standard drawing currImage->imgBuffer.copySurface(win); @@ -314,13 +377,15 @@ bool Inspector::on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) cairo_surface_set_device_scale(cr->get_target()->cobj(), scale, scale); scaledImage = false; } - Glib::RefPtr crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeft.x, topLeft.y, rtengine::min(imW, availableSize.x), rtengine::min(imH, availableSize.y)); + int viewW = rtengine::min(imW, availableSize.x); + int viewH = rtengine::min(imH, availableSize.y); + Glib::RefPtr crop = Gdk::Pixbuf::create(currImage->imgBuffer.getSurface(), topLeft.x, topLeft.y, viewW, viewH); if (!scaledImage) { Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x, dest.y); } else { - // assume that the device does not support scaling (Linux) - crop = crop->scale_simple(imW*scale, imH*scale, Gdk::INTERP_BILINEAR); + // scale crop as the device does not seem to support it (Linux) + crop = crop->scale_simple(viewW*scale, viewH*scale, Gdk::INTERP_BILINEAR); Gdk::Cairo::set_source_pixbuf(cr, crop, dest.x*scale, dest.y*scale); } cr->paint(); diff --git a/rtgui/inspector.h b/rtgui/inspector.h index 5262ccc8f..18e285b39 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -47,9 +47,13 @@ private: rtengine::Coord center; std::vector images; InspectorBuffer* currImage; - bool scaled; + bool scaled; // fit image into window + double scale; // current scale + double zoomScale, zoomScaleBegin; // scale during zoom + rtengine::Coord centerBegin, dcenterBegin; // center during zoom bool active; bool pinned; + bool dirty; sigc::connection delayconn; Glib::ustring next_image_path; @@ -61,6 +65,11 @@ private: bool on_button_press_event(GdkEventButton *event) override; bool on_scroll_event(GdkEventScroll *event) override; + Glib::RefPtr gestureZoom; + void beginZoom(double x, double y); + void on_zoom_begin(GdkEventSequence *); + void on_zoom_scale_changed(double zscale); + bool on_draw(const ::Cairo::RefPtr< Cairo::Context> &cr) override; void deleteBuffers(); From 38c898884d0afe5968a5e1875978dd97ddebff15 Mon Sep 17 00:00:00 2001 From: rfranke Date: Thu, 23 Jan 2020 07:15:29 +0100 Subject: [PATCH 06/33] Change direction and center when zooming inspector with scroll wheel --- rtgui/inspector.cc | 27 ++++++++++++++++++++------- rtgui/inspector.h | 1 + 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 471f08e95..7d5d44e44 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -217,18 +217,14 @@ bool Inspector::on_scroll_event(GdkEventScroll *event) // zoom beginZoom(event->x, event->y); if (std::fabs(delta_y) > std::fabs(delta_x)) - on_zoom_scale_changed(1.0 + (double)delta_y / imH / deviceScale); + on_zoom_scale_changed(1.0 - (double)delta_y / imH / deviceScale); else - on_zoom_scale_changed(1.0 + (double)delta_x / imW / deviceScale); + on_zoom_scale_changed(1.0 - (double)delta_x / imW / deviceScale); return true; } // scroll - rtengine::Coord margin; // limit for scroll area - margin.x = rtengine::min(window.get_width() * deviceScale / scale, imW) / 2; - margin.y = rtengine::min(window.get_height() * deviceScale / scale, imH) / 2; - center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x), - rtengine::LIM(center.y + delta_y, margin.y, imH - margin.y)); + moveCenter(delta_x, delta_y, imW, imH, deviceScale); if (!dirty) { dirty = true; @@ -238,13 +234,30 @@ bool Inspector::on_scroll_event(GdkEventScroll *event) return true; } +void Inspector::moveCenter(int delta_x, int delta_y, int imW, int imH, int deviceScale) +{ + rtengine::Coord margin; // limit to image size + margin.x = rtengine::min(window.get_width() * deviceScale / scale, imW) / 2; + margin.y = rtengine::min(window.get_height() * deviceScale / scale, imH) / 2; + center.set(rtengine::LIM(center.x + delta_x, margin.x, imW - margin.x), + rtengine::LIM(center.y + delta_y, margin.y, imH - margin.y)); +} + void Inspector::beginZoom(double x, double y) { int deviceScale = get_scale_factor(); + int imW = currImage->imgBuffer.getWidth(); + int imH = currImage->imgBuffer.getHeight(); + + // limit center to image size + moveCenter(0, 0, imW, imH, deviceScale); + + // store center and current position for zooming dcenterBegin.x = (x - window.get_width()/2) / scale * deviceScale; dcenterBegin.y = (y - window.get_height()/2) / scale * deviceScale; centerBegin = center; zoomScaleBegin = zoomScale; + } void Inspector::on_zoom_begin(GdkEventSequence *s) diff --git a/rtgui/inspector.h b/rtgui/inspector.h index 18e285b39..4cb0cb8df 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -64,6 +64,7 @@ private: bool on_button_press_event(GdkEventButton *event) override; bool on_scroll_event(GdkEventScroll *event) override; + void moveCenter(int delta_x, int delta_y, int imW, int imH, int deviceScale); Glib::RefPtr gestureZoom; void beginZoom(double x, double y); From 746be1816460cf73c23336f42577fed93f483d37 Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 19 Jul 2020 11:48:55 +0200 Subject: [PATCH 07/33] Added histogram lab adjustments LC CL --- rtgui/labcurve.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc index 5f4febc0a..27a8bee52 100644 --- a/rtgui/labcurve.cc +++ b/rtgui/labcurve.cc @@ -663,6 +663,8 @@ void LCurve::updateCurveBackgroundHistogram( { lshape->updateBackgroundHistogram (histLCurve); ccshape->updateBackgroundHistogram (histCCurve); + lcshape->updateBackgroundHistogram (histCCurve); + clshape->updateBackgroundHistogram (histLCurve); } void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) From 6b749bcbff88b392cd4e5d757dea7354b0be04c3 Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 20 Jul 2020 06:40:18 +0200 Subject: [PATCH 08/33] Wavecrash - fixed crash in wavelet specially when using "edge sharpening" (#5854) * Add epsil to all log calculation * add another epsil to log * Another eps value in koeli calculation * Avoid negative L values after reconstruct * Suppress all changes except negatives values reconstruct --- rtengine/ipwavelet.cc | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 9b9a9612e..499ee7812 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -1579,10 +1579,16 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const if (numtiles > 1) { float factor = Vmask[i1] * Hmask[j1]; + if(L <= 0.f) { + L= 1.f; + } dsttmp->L[i][j] += factor * L; dsttmp->a[i][j] += factor * a; dsttmp->b[i][j] += factor * b; } else { + if(L <= 0.f) { + L= 1.f; + } dsttmp->L[i][j] = L; dsttmp->a[i][j] = a; dsttmp->b[i][j] = b; @@ -2208,9 +2214,9 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * for (int lvl = 0; lvl < 4; lvl++) { for (int dir = 1; dir < 4; dir++) { const float* const* WavCoeffs_LL = WaveletCoeffs_L.level_coeffs(lvl); - float tempkoeli; + float tempkoeli = 0.f; calckoe (WavCoeffs_LL, gradw, tloww, koeLi, lvl , dir, W_L, H_L, edd, tempkoeli, tmC); - maxkoeLi[lvl * 3 + dir - 1] = tempkoeli; + maxkoeLi[lvl * 3 + dir - 1] = tempkoeli ; // return convolution KoeLi and maxkoeLi of level 0 1 2 3 and Dir Horiz, Vert, Diag } } @@ -2766,7 +2772,6 @@ void ImProcFunctions::calckoe (const float* const* WavCoeffs_LL, float gradw, fl if (koeLi[level * 3 + dir - 1][i * W_L + j] > maxkoeLi) { maxkoeLi = koeLi[level * 3 + dir - 1][i * W_L + j]; } - float diff = maxkoeLi - koeLi[level * 3 + dir - 1][i * W_L + j]; diff *= diffFactor; koeLi[level * 3 + dir - 1][i * W_L + j] = maxkoeLi - diff; @@ -2781,13 +2786,13 @@ void ImProcFunctions::finalContAllL(float* const* WavCoeffs_L, float * WavCoeffs if (cp.diagcurv && cp.finena && MaxP[level] > 0.f && mean[level] != 0.f && sigma[level] != 0.f) { //curve float insigma = 0.666f; //SD float logmax = log(MaxP[level]); //log Max - float rapX = (mean[level] + cp.sigmafin * sigma[level]) / MaxP[level]; //rapport between sD / max + float rapX = (mean[level] + cp.sigmafin * sigma[level]) / (MaxP[level]); //rapport between sD / max float inx = log(insigma); float iny = log(rapX); float rap = inx / iny; //koef float asig = 0.166f / (sigma[level] * cp.sigmafin); float bsig = 0.5f - asig * mean[level]; - float amean = 0.5f / mean[level]; + float amean = 0.5f / (mean[level]); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic, W_L * 16) num_threads(wavNestedLevels) if (wavNestedLevels>1) @@ -3058,7 +3063,6 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, koe[i * W_L + j] = rtengine::min(thr2, std::fabs(tmC[i][j] / temp)); maxkoe = rtengine::max(maxkoe, koe[i * W_L + j]); - float diff = maxkoe - koe[i * W_L + j]; diff *= (cp.eddet / 100.f); float interm = maxkoe - diff; @@ -3158,13 +3162,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, // if (exa) {//curve float insigma = 0.666f; //SD float logmax = log(MaxP[level]); //log Max - float rapX = (mean[level] + sigma[level]) / MaxP[level]; //rapport between sD / max + float rapX = (mean[level] + sigma[level]) / (MaxP[level]); //rapport between sD / max float inx = log(insigma); float iny = log(rapX); float rap = inx / iny; //koef - float asig = 0.166f / sigma[level]; + float asig = 0.166f / (sigma[level]); float bsig = 0.5f - asig * mean[level]; - float amean = 0.5f / mean[level]; + float amean = 0.5f / (mean[level]); float absciss = 0.f; float kinterm; float kmul; From 999a4f3257fc11f12299a8b81012adf03ae4719b Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 20 Jul 2020 08:40:06 +0200 Subject: [PATCH 09/33] Added in option edghi edglo limrad --- rtengine/ipwavelet.cc | 19 +++++++++++-------- rtengine/settings.h | 4 ++++ rtgui/options.cc | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 499ee7812..651884e34 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -3093,10 +3093,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, float atten01234 = 0.80f; value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!! } - + float edghig = settings->edghi;//increase or reduce "reinforce" + float edglow = settings->edglo;//increase or reduce "reduce" + float limrad = settings->limrad;//threshold action in function radius (rad) + printf("edghi=%f edglo=%f limrad=%f\n", edghig, edglow, limrad); // value *= beta; float edge = 1.f; - float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi + float lim0 = limrad; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi float lev = float (level); float repart = (float)cp.til; @@ -3104,15 +3107,14 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, if (cp.reinforce != 2) { const float brepart = cp.reinforce == 1 - ? 3.f - : 0.5f; + ? edghig + : edglow; const float arepart = -(brepart - 1.f) / (lim0 / 60.f); - if (rad < lim0 / 60.f) { + if (rad < (lim0 / 60.f)) { repart *= (arepart * rad + brepart); //linear repartition of repart } } - float al0 = 1.f + (repart) / 50.f; float al10 = 1.0f; //arbitrary value ==> less = take into account high levels // float ak =-(al0-al10)/10.f;//10 = maximum levels @@ -3120,15 +3122,16 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, float bk = al0; float koef = ak * level + bk; //modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels float expkoef = -std::pow(std::fabs(rad - lev), koef); //reduce effect for high levels + printf("repart=%f\n", repart); if (cp.reinforce == 3) { - if (rad < lim0 / 60.f && level == 0) { + if (rad < (lim0 / 60.f) && level == 0) { expkoef *= abs(repart); //reduce effect for low values of rad and level=0==> quasi only level 1 is effective } } if (cp.reinforce == 1) { - if (rad < lim0 / 60.f && level == 1) { + if (rad < (lim0 / 60.f) && level == 1) { expkoef /= repart; //increase effect for low values of rad and level=1==> quasi only level 0 is effective } } diff --git a/rtengine/settings.h b/rtengine/settings.h index fde6fa132..0fb4996df 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -99,6 +99,10 @@ public: int itcwb_delta; bool itcwb_stdobserver10; int itcwb_precis; +//wavelet levels + double edghi; + double edglo; + double limrad; enum class ThumbnailInspectorMode { diff --git a/rtgui/options.cc b/rtgui/options.cc index cc49f1fcd..04914e748 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -617,6 +617,12 @@ void Options::setDefaults() rtSettings.itcwb_precis = 5;//3 or 5 or 9 // end locallab +//wavelet + rtSettings.edghi = 3.0;//1.1 and 5. + rtSettings.edglo = 0.5;//0.1 and 0.95 + rtSettings.limrad = 20.;//1 and 60 + + rtSettings.protectred = 60; rtSettings.protectredh = 0.3; rtSettings.CRI_color = 0; @@ -1704,6 +1710,22 @@ void Options::readFromFile(Glib::ustring fname) } + if (keyFile.has_group("Wavelet")) { + if (keyFile.has_key("Wavelet", "Edghi")) { + rtSettings.edghi = keyFile.get_double("Wavelet", "Edghi"); + } + + if (keyFile.has_key("Wavelet", "Edglo")) { + rtSettings.edglo = keyFile.get_double("Wavelet", "Edglo"); + } + + if (keyFile.has_key("Wavelet", "Limrad")) { + rtSettings.limrad = keyFile.get_double("Wavelet", "Limrad"); + } + + } + + if (keyFile.has_group("ICC Profile Creator")) { if (keyFile.has_key("ICC Profile Creator", "PimariesPreset")) { ICCPC_primariesPreset = keyFile.get_string("ICC Profile Creator", "PimariesPreset"); @@ -2302,6 +2324,11 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_integer("Color Management", "Previewselection", rtSettings.previewselection); keyFile.set_double("Color Management", "Cbdlsensi", rtSettings.cbdlsensi); + keyFile.set_double("Wavelet", "Edghi", rtSettings.edghi); + keyFile.set_double("Wavelet", "Edglo", rtSettings.edglo); + keyFile.set_double("Wavelet", "Limrad", rtSettings.limrad); + + keyFile.set_string("ICC Profile Creator", "PimariesPreset", ICCPC_primariesPreset); keyFile.set_double("ICC Profile Creator", "RedPrimaryX", ICCPC_redPrimaryX); keyFile.set_double("ICC Profile Creator", "RedPrimaryY", ICCPC_redPrimaryY); From 0fcca629057f70521ae1f42773b46a1b3d60fd18 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 21 Jul 2020 15:41:47 +0200 Subject: [PATCH 10/33] enable -ftree-loop-vectorize for gcc >= 10.2, #5749 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b7cf35099..6de75e748 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION endif() # Warning for GCC 10, which causes problems #5749: -if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "10.0") +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL "10.1") message(STATUS "WARNING: gcc ${CMAKE_CXX_COMPILER_VERSION} is known to miscompile RawTherapee when using -ftree-loop-vectorize, forcing the option to be off") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-tree-loop-vectorize") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-tree-loop-vectorize") From 932e0beea957672775d07e2cefc6ddecf88c53f4 Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 26 Jul 2020 07:17:39 +0200 Subject: [PATCH 11/33] Hide choice edgesharpness slider curve --- rtengine/ipwavelet.cc | 6 +++--- rtgui/wavelet.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 651884e34..b2ae5fc1d 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -323,14 +323,14 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const } cp.CHSLmet = 1; - cp.EDmet = 1; - + cp.EDmet = 2; +/* if (params->wavelet.EDmethod == "SL") { cp.EDmet = 1; } else if (params->wavelet.EDmethod == "CU") { cp.EDmet = 2; } - +*/ cp.cbena = params->wavelet.cbenab; cp.blhigh = (float)params->wavelet.bluehigh; cp.grhigh = (float)params->wavelet.greenhigh; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index ac8c6100b..9d7bf583a 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -674,7 +674,7 @@ Wavelet::Wavelet() : EDmethod->append(M("TP_WAVELET_EDCU")); EDmethodconn = EDmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::EDmethodChanged)); ctboxED->pack_start(*EDmethod); - edgBox->pack_start(*ctboxED); + // edgBox->pack_start(*ctboxED); edgcont->setAdjusterListener(this); edgcont->setBgGradient(milestones2); From b55312140b2e9fe6eac13888e15e4f6cc30d483c Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Sun, 26 Jul 2020 13:28:21 +0200 Subject: [PATCH 12/33] Fix wrong const usage --- rtengine/CA_correct_RT.cc | 6 +++--- rtengine/array2D.h | 4 ++-- rtengine/color.cc | 2 +- rtengine/color.h | 2 +- rtengine/ipdehaze.cc | 4 ++-- rtengine/rawimagesource.h | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rtengine/CA_correct_RT.cc b/rtengine/CA_correct_RT.cc index fa9788af0..c17826623 100644 --- a/rtengine/CA_correct_RT.cc +++ b/rtengine/CA_correct_RT.cc @@ -123,7 +123,7 @@ float* RawImageSource::CA_correct_RT( double cared, double cablue, bool avoidColourshift, - const array2D &rawData, + array2D &rawData, double* fitParamsTransfer, bool fitParamsIn, bool fitParamsOut, @@ -1291,7 +1291,7 @@ float* RawImageSource::CA_correct_RT( for (int i = 0; i < H - 2 * cb; ++i) { const int firstCol = fc(cfa, i, 0) & 1; const int colour = fc(cfa, i, firstCol); - const array2D* nonGreen = colour == 0 ? redFactor : blueFactor; + array2D* nonGreen = colour == 0 ? redFactor : blueFactor; int j = firstCol; #ifdef __SSE2__ for (; j < W - 7 - 2 * cb; j += 8) { @@ -1325,7 +1325,7 @@ float* RawImageSource::CA_correct_RT( const int ngRow = 1 - (fc(cfa, 0, 0) & 1); const int ngCol = fc(cfa, ngRow, 0) & 1; const int colour = fc(cfa, ngRow, ngCol); - const array2D* nonGreen = colour == 0 ? redFactor : blueFactor; + array2D* nonGreen = colour == 0 ? redFactor : blueFactor; for (int i = 0; i < (H + 1 - 2 * cb) / 2; ++i) { (*nonGreen)[i][(W - 2 * cb + 1) / 2 - 1] = (*nonGreen)[i][(W - 2* cb + 1) / 2 - 2]; } diff --git a/rtengine/array2D.h b/rtengine/array2D.h index de6381aeb..4b301383b 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -212,7 +212,7 @@ public: } // use with indices - T * operator[](int index) const + T * operator[](int index) { assert((index >= 0) && (index < y)); return ptr[index]; @@ -225,7 +225,7 @@ public: } // use as pointer to T** - operator const T* const *() + operator const T* const *() const { return ptr; } diff --git a/rtengine/color.cc b/rtengine/color.cc index 61009c81f..5761733f0 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -1772,7 +1772,7 @@ void Color::RGB2Lab(float *R, float *G, float *B, float *L, float *a, float *b, } } -void Color::RGB2L(float *R, float *G, float *B, float *L, const float wp[3][3], int width) +void Color::RGB2L(const float *R, const float *G, const float *B, float *L, const float wp[3][3], int width) { #ifdef __SSE2__ diff --git a/rtengine/color.h b/rtengine/color.h index 76edae6a1..704871d39 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -623,7 +623,7 @@ public: static void XYZ2Lab(float x, float y, float z, float &L, float &a, float &b); static void RGB2Lab(float *X, float *Y, float *Z, float *L, float *a, float *b, const float wp[3][3], int width); static void Lab2RGBLimit(float *L, float *a, float *b, float *R, float *G, float *B, const float wp[3][3], float limit, float afactor, float bfactor, int width); - static void RGB2L(float *X, float *Y, float *Z, float *L, const float wp[3][3], int width); + static void RGB2L(const float *R, const float *G, const float *B, float *L, const float wp[3][3], int width); /** * @brief Convert Lab in Yuv diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 7d715a9b0..4376808f8 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -103,7 +103,7 @@ void restore(Imagefloat *rgb, float maxval, bool multithread) } } -int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength) +int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength) { const int W = R.width(); const int H = R.height(); @@ -162,7 +162,7 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr return (W / patchsize + ((W % patchsize) > 0)) * (H / patchsize + ((H % patchsize) > 0)); } -int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, const array2D &dst, int patchsize, bool multithread) +int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, bool multithread) { const int W = R.width(); const int H = R.height(); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 3c19efd67..75aac923c 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -247,7 +247,7 @@ protected: double cared, double cablue, bool avoidColourshift, - const array2D &rawData, + array2D &rawData, double* fitParamsTransfer, bool fitParamsIn, bool fitParamsOut, From 65a258837f200e83cef6c54a00231c053a73b6ed Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 27 Jul 2020 09:23:39 +0200 Subject: [PATCH 13/33] First normal expert --- rtdata/languages/default | 5 ++ rtengine/procparams.cc | 4 ++ rtengine/procparams.h | 1 + rtgui/paramsedited.cc | 6 ++ rtgui/paramsedited.h | 1 + rtgui/wavelet.cc | 122 ++++++++++++++++++++++++++++++++++++++- rtgui/wavelet.h | 9 ++- 7 files changed, 144 insertions(+), 4 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index a5f77403e..9dc49102a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1215,6 +1215,7 @@ HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope +HISTORY_MSG_COMPLEX;Wavelet complexity HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only @@ -3280,6 +3281,10 @@ TP_WAVELET_COLORT;Opacity Red-Green TP_WAVELET_COMPCONT;Contrast TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. +TP_WAVELET_COMPLEXLAB;Complexity +TP_WAVELET_COMPLEX_TOOLTIP;Allows treatment +TP_WAVELET_COMPNORMAL;Normal +TP_WAVELET_COMPEXPERT;Expert TP_WAVELET_COMPTM;Tone mapping TP_WAVELET_CONTEDIT;'After' contrast curve TP_WAVELET_CONTFRAME;Contrast - Compression diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 863c7fc79..a12ab4ba4 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2395,6 +2395,7 @@ WaveletParams::WaveletParams() : CLmethod("all"), Backmethod("grey"), Tilesmethod("full"), + complexmethod("normal"), daubcoeffmethod("4_"), CHmethod("without"), Medgreinf("less"), @@ -2527,6 +2528,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && CLmethod == other.CLmethod && Backmethod == other.Backmethod && Tilesmethod == other.Tilesmethod + && complexmethod == other.complexmethod && daubcoeffmethod == other.daubcoeffmethod && CHmethod == other.CHmethod && Medgreinf == other.Medgreinf @@ -5988,6 +5990,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.iter, "Wavelet", "Iter", wavelet.iter, keyFile); saveToKeyfile(!pedited || pedited->wavelet.thres, "Wavelet", "MaxLev", wavelet.thres, keyFile); saveToKeyfile(!pedited || pedited->wavelet.Tilesmethod, "Wavelet", "TilesMethod", wavelet.Tilesmethod, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.complexmethod, "Wavelet", "complexMethod", wavelet.complexmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.daubcoeffmethod, "Wavelet", "DaubMethod", wavelet.daubcoeffmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.CLmethod, "Wavelet", "ChoiceLevMethod", wavelet.CLmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.Backmethod, "Wavelet", "BackMethod", wavelet.Backmethod, keyFile); @@ -7858,6 +7861,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "ChoiceLevMethod", pedited, wavelet.CLmethod, pedited->wavelet.CLmethod); assignFromKeyfile(keyFile, "Wavelet", "BackMethod", pedited, wavelet.Backmethod, pedited->wavelet.Backmethod); assignFromKeyfile(keyFile, "Wavelet", "TilesMethod", pedited, wavelet.Tilesmethod, pedited->wavelet.Tilesmethod); + assignFromKeyfile(keyFile, "Wavelet", "complexMethod", pedited, wavelet.complexmethod, pedited->wavelet.complexmethod); assignFromKeyfile(keyFile, "Wavelet", "DaubMethod", pedited, wavelet.daubcoeffmethod, pedited->wavelet.daubcoeffmethod); assignFromKeyfile(keyFile, "Wavelet", "CHromaMethod", pedited, wavelet.CHmethod, pedited->wavelet.CHmethod); assignFromKeyfile(keyFile, "Wavelet", "Medgreinf", pedited, wavelet.Medgreinf, pedited->wavelet.Medgreinf); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 7d609494e..048fe1ee5 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1790,6 +1790,7 @@ struct WaveletParams { Glib::ustring CLmethod; Glib::ustring Backmethod; Glib::ustring Tilesmethod; + Glib::ustring complexmethod; Glib::ustring daubcoeffmethod; Glib::ustring CHmethod; Glib::ustring Medgreinf; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index db830c6c1..070e31316 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -531,6 +531,7 @@ void ParamsEdited::set(bool v) wavelet.CLmethod = v; wavelet.Backmethod = v; wavelet.Tilesmethod = v; + wavelet.complexmethod = v; wavelet.daubcoeffmethod = v; wavelet.CHmethod = v; wavelet.CHSLmethod = v; @@ -1679,6 +1680,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.CLmethod = wavelet.CLmethod && p.wavelet.CLmethod == other.wavelet.CLmethod; wavelet.Backmethod = wavelet.Backmethod && p.wavelet.Backmethod == other.wavelet.Backmethod; wavelet.Tilesmethod = wavelet.Tilesmethod && p.wavelet.Tilesmethod == other.wavelet.Tilesmethod; + wavelet.complexmethod = wavelet.complexmethod && p.wavelet.complexmethod == other.wavelet.complexmethod; wavelet.daubcoeffmethod = wavelet.daubcoeffmethod && p.wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod; wavelet.CHmethod = wavelet.CHmethod && p.wavelet.CHmethod == other.wavelet.CHmethod; wavelet.CHSLmethod = wavelet.CHSLmethod && p.wavelet.CHSLmethod == other.wavelet.CHSLmethod; @@ -5574,6 +5576,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; } + if (wavelet.complexmethod) { + toEdit.wavelet.complexmethod = mods.wavelet.complexmethod; + } + if (wavelet.daubcoeffmethod) { toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 98a427796..57b6458b9 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1039,6 +1039,7 @@ struct WaveletParamsEdited { bool CLmethod; bool Backmethod; bool Tilesmethod; + bool complexmethod; bool daubcoeffmethod; bool Dirmethod; bool sigma; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 9d7bf583a..0fd153d40 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -158,6 +158,7 @@ Wavelet::Wavelet() : HSmethod(Gtk::manage(new MyComboBoxText())), CLmethod(Gtk::manage(new MyComboBoxText())), Backmethod(Gtk::manage(new MyComboBoxText())), + complexmethod(Gtk::manage(new MyComboBoxText())), Tilesmethod(Gtk::manage(new MyComboBoxText())), daubcoeffmethod(Gtk::manage(new MyComboBoxText())), Dirmethod(Gtk::manage(new MyComboBoxText())), @@ -190,7 +191,9 @@ Wavelet::Wavelet() : expclari(Gtk::manage(new MyExpander(true, M("TP_WAVELET_CLARI")))), expbl(Gtk::manage(new MyExpander(true, M("TP_WAVELET_BL")))), neutrHBox(Gtk::manage(new Gtk::HBox())), - usharpHBox(Gtk::manage(new Gtk::HBox())) + usharpHBox(Gtk::manage(new Gtk::HBox())), + ctboxch(Gtk::manage(new Gtk::HBox())) + { CurveListener::setMulti(true); auto m = ProcEventMapper::getInstance(); @@ -227,6 +230,7 @@ Wavelet::Wavelet() : EvWavrangeab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_RANGEAB"); EvWavprotab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_PROTAB"); EvWavlevelshc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_LEVELSHC"); + EvWavcomplexmet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_COMPLEX"); labgrid = Gtk::manage(new LabGrid(EvWavLabGridValue, M("TP_WAVELET_LABGRID_VALUES"))); @@ -269,6 +273,16 @@ Wavelet::Wavelet() : thres->set_tooltip_text(M("TP_WAVELET_LEVELS_TOOLTIP")); thres->setAdjusterListener(this); + complexmethod->append(M("TP_WAVELET_COMPNORMAL")); + complexmethod->append(M("TP_WAVELET_COMPEXPERT")); + complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::complexmethodChanged)); + complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP")); + Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":")); + complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4); + complexHBox->pack_start(*complexmethod); + + Tilesmethod->append(M("TP_WAVELET_TILESFULL")); Tilesmethod->append(M("TP_WAVELET_TILESBIG")); // Tilesmethod->append(M("TP_WAVELET_TILESLIT")); @@ -335,6 +349,7 @@ Wavelet::Wavelet() : levdirSubHBox->pack_start(*Lmethod); levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4? + settingsBox->pack_start(*complexHBox); settingsBox->pack_start(*strength); settingsBox->pack_start(*thres); settingsBox->pack_start(*tilesizeHBox); @@ -452,7 +467,7 @@ Wavelet::Wavelet() : ToolParamBlock* const chBox = Gtk::manage(new ToolParamBlock()); Gtk::Label* const labmch = Gtk::manage(new Gtk::Label(M("TP_WAVELET_CHTYPE") + ":")); - Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox()); +// Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox()); ctboxch->pack_start(*labmch, Gtk::PACK_SHRINK, 1); CHmethod->append(M("TP_WAVELET_CH1")); @@ -1236,6 +1251,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) CLmethodconn.block(true); Backmethodconn.block(true); Tilesmethodconn.block(true); + complexmethodconn.block(true); daubcoeffmethodconn.block(true); Dirmethodconn.block(true); CHmethodconn.block(true); @@ -1357,6 +1373,12 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) } else if (pp->wavelet.CLmethod == "all") { CLmethod->set_active(3); } + if (pp->wavelet.complexmethod == "normal") { + complexmethod->set_active(0); + } else if (pp->wavelet.complexmethod == "expert") { + complexmethod->set_active(1); + } + //Tilesmethod->set_active (2); if (pp->wavelet.Tilesmethod == "full") { @@ -1558,6 +1580,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) Backmethod->set_active_text(M("GENERAL_UNCHANGED")); } + if (!pedited->wavelet.complexmethod) { + complexmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.Tilesmethod) { Tilesmethod->set_active_text(M("GENERAL_UNCHANGED")); } @@ -1774,6 +1801,15 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) } else { sup->hide(); } + + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + } /***************************************************************************************************** @@ -1786,6 +1822,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) CLmethodconn.block(false); Backmethodconn.block(false); Tilesmethodconn.block(false); + complexmethodconn.block(false); daubcoeffmethodconn.block(false); CHmethodconn.block(false); CHSLmethodconn.block(false); @@ -1965,6 +2002,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.CLmethod = CLmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.complexmethod = complexmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED"); @@ -2168,6 +2206,12 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) // pp->wavelet.Tilesmethod = "lit"; } + if (complexmethod->get_active_row_number() == 0) { + pp->wavelet.complexmethod = "normal"; + } else if (complexmethod->get_active_row_number() == 1) { + pp->wavelet.complexmethod = "expert"; + } + if (daubcoeffmethod->get_active_row_number() == 0) { pp->wavelet.daubcoeffmethod = "2_"; } else if (daubcoeffmethod->get_active_row_number() == 1) { @@ -2835,6 +2879,79 @@ void Wavelet::ushamethodChanged() } + +void Wavelet::convertParamToNormal() +{ + const WaveletParams def_params; + disableListener(); + //contrast + offset->setValue(def_params.offset); + //chroma + expchroma->setEnabled(def_params.expchroma); + CHmethod->set_active(2); + //denoise + chromfi->setValue(def_params.chromfi); + chromco->setValue(def_params.chromco); + //toning + exptoning->setEnabled(def_params.exptoning); + //gamut + median->set_active(def_params.median); + avoid->set_active(def_params.avoid); + hueskin->setValue(def_params.hueskin); + skinprotect->setValue(def_params.skinprotect); + //blur + expbl->setEnabled(def_params.expbl); + //edge sharpness + lipst->set_active(def_params.lipst); + lipstUpdateUI(); + edgesensi->setValue(def_params.edgesensi); + edgeampli->setValue(def_params.edgeampli); + NPmethod->set_active(0); + enableListener(); + + // Update GUI based on converted widget parameters: +} + +void Wavelet::updateGUIToMode(int mode) +{ + if(mode ==0) { + offset->hide(); + ctboxch->hide(); + expgamut->hide(); + exptoning->hide(); + chroFrame->hide(); + expbl->hide(); + lipst->hide(); + } else { + offset->show(); + ctboxch->show(); + expgamut->show(); + exptoning->show(); + chroFrame->show(); + expbl->show(); + lipst->show(); + } + +} + + +void Wavelet::complexmethodChanged() +{ + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavcomplexmet, complexmethod->get_active_text()); + } +} + + + void Wavelet::TilesmethodChanged() { //TilesmethodUpdateUI(); @@ -2916,6 +3033,7 @@ void Wavelet::setBatchMode(bool batchMode) CLmethod->append(M("GENERAL_UNCHANGED")); Backmethod->append(M("GENERAL_UNCHANGED")); Tilesmethod->append(M("GENERAL_UNCHANGED")); + complexmethod->append(M("GENERAL_UNCHANGED")); daubcoeffmethod->append(M("GENERAL_UNCHANGED")); CHmethod->append(M("GENERAL_UNCHANGED")); Medgreinf->append(M("GENERAL_UNCHANGED")); diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 6daabcd67..127be0efa 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -47,7 +47,6 @@ class Wavelet final : public: Wavelet(); ~Wavelet() override; - bool wavComputed_(); void adjusterChanged(Adjuster* a, double newval) override; void autoOpenCurve() override; @@ -102,6 +101,7 @@ private: rtengine::ProcEvent EvWavrangeab; rtengine::ProcEvent EvWavprotab; rtengine::ProcEvent EvWavlevelshc; + rtengine::ProcEvent EvWavcomplexmet; LabGrid *labgrid; @@ -121,6 +121,7 @@ private: void LmethodChanged(); void MedgreinfChanged(); void TMmethodChanged(); + void complexmethodChanged(); void TilesmethodChanged(); void avoidToggled(); void showmaskToggled (); @@ -143,7 +144,8 @@ private: void ushamethodChanged(); void updateGUI(); void updateGUImaxlev(); - + void convertParamToNormal(); + void updateGUIToMode(int mode); void HSmethodUpdateUI(); void CHmethodUpdateUI(); // void CHSLmethodChangedUI(); @@ -297,6 +299,8 @@ private: sigc::connection CLmethodconn; MyComboBoxText* const Backmethod; sigc::connection Backmethodconn; + MyComboBoxText* const complexmethod; + sigc::connection complexmethodconn; MyComboBoxText* const Tilesmethod; sigc::connection Tilesmethodconn; MyComboBoxText* const daubcoeffmethod; @@ -338,6 +342,7 @@ private: Gtk::HBox* const neutrHBox; Gtk::HBox* const usharpHBox; + Gtk::HBox* const ctboxch; sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn; sigc::connection enableNoiseConn, enableResidConn, enableToningConn; From 05830912f78436fc916bf459fbec9977198f5f20 Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 27 Jul 2020 11:09:21 +0200 Subject: [PATCH 14/33] Second normal expert --- rtgui/wavelet.cc | 21 +++++++++++++++++++-- rtgui/wavelet.h | 1 + 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 0fd153d40..ee251f35f 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -192,7 +192,8 @@ Wavelet::Wavelet() : expbl(Gtk::manage(new MyExpander(true, M("TP_WAVELET_BL")))), neutrHBox(Gtk::manage(new Gtk::HBox())), usharpHBox(Gtk::manage(new Gtk::HBox())), - ctboxch(Gtk::manage(new Gtk::HBox())) + ctboxch(Gtk::manage(new Gtk::HBox())), + ctboxBA(Gtk::manage(new Gtk::VBox())) { CurveListener::setMulti(true); @@ -1022,7 +1023,7 @@ Wavelet::Wavelet() : resBox->pack_start(*neutrHBox); // Final Touchup - Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox()); + // Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox()); ctboxBA->set_spacing(2); @@ -2907,6 +2908,14 @@ void Wavelet::convertParamToNormal() edgesensi->setValue(def_params.edgesensi); edgeampli->setValue(def_params.edgeampli); NPmethod->set_active(0); + //resid + oldsh->set_active(true); + resblur->setValue(def_params.resblur); + resblurc->setValue(def_params.resblurc); + cbenab->set_active(false); + + //final touchup + BAmethod->set_active(0); enableListener(); // Update GUI based on converted widget parameters: @@ -2922,6 +2931,10 @@ void Wavelet::updateGUIToMode(int mode) chroFrame->hide(); expbl->hide(); lipst->hide(); + dirFrame->hide(); + oldsh->hide(); + blurFrame->hide(); + cbenab->hide(); } else { offset->show(); ctboxch->show(); @@ -2930,6 +2943,10 @@ void Wavelet::updateGUIToMode(int mode) chroFrame->show(); expbl->show(); lipst->show(); + dirFrame->show(); + oldsh->show(); + blurFrame->show(); + cbenab->show(); } } diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 127be0efa..a497d2c4f 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -343,6 +343,7 @@ private: Gtk::HBox* const neutrHBox; Gtk::HBox* const usharpHBox; Gtk::HBox* const ctboxch; + Gtk::VBox* const ctboxBA;// = Gtk::manage(new Gtk::VBox()); sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn; sigc::connection enableNoiseConn, enableResidConn, enableToningConn; From f08da7b99940597a72f7e106b692c7b3f8d64eef Mon Sep 17 00:00:00 2001 From: Desmis Date: Mon, 27 Jul 2020 16:41:28 +0200 Subject: [PATCH 15/33] Changes in normal expert contrast chroma residual --- rtengine/ipwavelet.cc | 6 ++++-- rtgui/wavelet.cc | 18 +++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index b2ae5fc1d..c2798af77 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -2079,7 +2079,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * ContrastResid(WavCoeffs_L0, cp, W_L, H_L, maxp); } - if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + // if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step const std::unique_ptr temp(new LabImage(W_L, H_L)); #ifdef _OPENMP #pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1) @@ -2104,7 +2105,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * } } - if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + // if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + if ((cp.conres < 0.f || cp.conresH < 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step #ifdef _OPENMP #pragma omp parallel for #endif diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index ee251f35f..79f4f4e25 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -854,7 +854,7 @@ Wavelet::Wavelet() : thrH->setAdjusterListener(this); radius->setAdjusterListener(this); - radius->hide(); +// radius->hide(); shFrame->set_label_align(0.025, 0.5); ToolParamBlock* const shBox = Gtk::manage(new ToolParamBlock()); @@ -2887,8 +2887,11 @@ void Wavelet::convertParamToNormal() disableListener(); //contrast offset->setValue(def_params.offset); + sigma->setValue(def_params.sigma); + lowthr->setValue(def_params.lowthr); //chroma expchroma->setEnabled(def_params.expchroma); + sigmacol->setValue(def_params.sigmacol); CHmethod->set_active(2); //denoise chromfi->setValue(def_params.chromfi); @@ -2909,7 +2912,8 @@ void Wavelet::convertParamToNormal() edgeampli->setValue(def_params.edgeampli); NPmethod->set_active(0); //resid - oldsh->set_active(true); + // oldsh->set_active(true); + radius->setValue(def_params.radius); resblur->setValue(def_params.resblur); resblurc->setValue(def_params.resblurc); cbenab->set_active(false); @@ -2925,7 +2929,10 @@ void Wavelet::updateGUIToMode(int mode) { if(mode ==0) { offset->hide(); + sigma->hide(); + lowthr->hide(); ctboxch->hide(); + sigmacol->hide(); expgamut->hide(); exptoning->hide(); chroFrame->hide(); @@ -2933,18 +2940,23 @@ void Wavelet::updateGUIToMode(int mode) lipst->hide(); dirFrame->hide(); oldsh->hide(); + radius->hide(); blurFrame->hide(); cbenab->hide(); } else { offset->show(); + sigma->show(); + lowthr->show(); ctboxch->show(); + sigmacol->show(); expgamut->show(); exptoning->show(); chroFrame->show(); expbl->show(); lipst->show(); dirFrame->show(); - oldsh->show(); + oldsh->hide(); + radius->show(); blurFrame->show(); cbenab->show(); } From bb88f4ad96878186476a05454ccd6cfe8fe965ed Mon Sep 17 00:00:00 2001 From: rfranke Date: Tue, 28 Jul 2020 18:11:36 +0200 Subject: [PATCH 16/33] Update AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 227390faa..ba31af23a 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -14,6 +14,7 @@ Development contributors, in last name alphabetical order: Maciek Dworak Michael Ezra Flössie + Rüdiger Franke Jean-Christophe Frisch Ilias Giarimis Alberto Griggio From 3101fb2b56848c7156ddfa15424e177e9f0c4117 Mon Sep 17 00:00:00 2001 From: Desmis Date: Tue, 28 Jul 2020 20:45:06 +0200 Subject: [PATCH 17/33] Change label complexity wavelet --- rtdata/languages/default | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 9dc49102a..87b39be78 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -3283,8 +3283,8 @@ TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. TP_WAVELET_COMPLEXLAB;Complexity TP_WAVELET_COMPLEX_TOOLTIP;Allows treatment -TP_WAVELET_COMPNORMAL;Normal -TP_WAVELET_COMPEXPERT;Expert +TP_WAVELET_COMPNORMAL;Standard +TP_WAVELET_COMPEXPERT;Advanced TP_WAVELET_COMPTM;Tone mapping TP_WAVELET_CONTEDIT;'After' contrast curve TP_WAVELET_CONTFRAME;Contrast - Compression From 40e6614d59c55b52228f11fa32da6be9cd045862 Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 29 Jul 2020 07:05:05 +0200 Subject: [PATCH 18/33] French + hide sigmafin standard --- rtdata/languages/Francais | 1 + rtgui/wavelet.cc | 3 +++ 2 files changed, 4 insertions(+) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 52d25d85b..0e8635484 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -2653,6 +2653,7 @@ TP_WAVELET_CHR_TOOLTIP;Ajuste le chroma en fonction des "niveaux de contraste" e TP_WAVELET_CHSL;Curseurs TP_WAVELET_CHTYPE;Méthode de chrominance TP_WAVELET_COLORT;Opacité Rouge-Vert +TP_WAVELET_COMPEXPERT;Avancé TP_WAVELET_COMPCONT;Contraste TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Ajuster le gamma de l'image résiduelle vous permet d'équiilibrer les données de l'histogramme. diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 79f4f4e25..8bd074867 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -2921,6 +2921,7 @@ void Wavelet::convertParamToNormal() //final touchup BAmethod->set_active(0); enableListener(); + sigmafin->setValue(def_params.sigmafin); // Update GUI based on converted widget parameters: } @@ -2943,6 +2944,7 @@ void Wavelet::updateGUIToMode(int mode) radius->hide(); blurFrame->hide(); cbenab->hide(); + sigmafin->hide(); } else { offset->show(); sigma->show(); @@ -2959,6 +2961,7 @@ void Wavelet::updateGUIToMode(int mode) radius->show(); blurFrame->show(); cbenab->show(); + sigmafin->show(); } } From e77dac43d547499bbfb9606b9ccdc8444d35c885 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Wed, 29 Jul 2020 13:38:17 +0200 Subject: [PATCH 19/33] array2D.h: cleanup --- rtengine/array2D.h | 219 ++++++++++++++------------------------- rtengine/guidedfilter.cc | 36 +++---- rtengine/ipdehaze.cc | 12 +-- rtengine/iplocallab.cc | 4 +- rtengine/rescale.h | 20 ++-- rtengine/tmo_fattal02.cc | 4 +- 6 files changed, 114 insertions(+), 181 deletions(-) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 4b301383b..8d1351cbb 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -27,7 +27,7 @@ * * creates an array which is valid within the normal C/C++ scope "{ ... }" * - * access to elements is a simple as: + * access to elements is as simple as: * * array2D my_array (10,10); // creates 10x10 array of floats * value = my_array[3][5]; @@ -48,25 +48,18 @@ * array2D my_array ; // empty container. * my_array(10,10) ; // resize to 10x10 array * my_array(10,10,ARRAY2D_CLEAR_DATA) ; // resize to 10x10 and clear data - * my_array(10,10,ARRAY2D_CLEAR_DATA|ARRAY2D_LOCK_DATA) ; same but set a lock on changes * - * !! locked arrays cannot be resized and cannot be unlocked again !! */ #pragma once -#include // for raise() #include +#include +#include "noncopyable.h" // flags for use -#define ARRAY2D_LOCK_DATA 1 -#define ARRAY2D_CLEAR_DATA 2 -#define ARRAY2D_BYREFERENCE 4 -#define ARRAY2D_VERBOSE 8 +constexpr unsigned int ARRAY2D_CLEAR_DATA = 1; +constexpr unsigned int ARRAY2D_BYREFERENCE = 2; -#include -#include - -#include "noncopyable.h" template class array2D : @@ -74,99 +67,80 @@ class array2D : { private: - int x, y, owner; - unsigned int flags; - T ** ptr; - T * data; - bool lock; // useful lock to ensure data is not changed anymore. - void ar_realloc(int w, int h, int offset = 0) + ssize_t width, height; + T** rows; + T* data; + void ar_realloc(ssize_t w, ssize_t h, int offset = 0) { - if ((ptr) && ((h > y) || (4 * h < y))) { - delete[] ptr; - ptr = nullptr; + if (rows && (h > height || 4 * h < height)) { + delete[] rows; + rows = nullptr; + } + if (!rows) { + rows = new T*[h]; } - if ((data) && (((h * w) > (x * y)) || ((h * w) < ((x * y) / 4)))) { + if (data && ((h * w > width * height) || (h * w < (width * height / 4)))) { delete[] data; data = nullptr; } - if (ptr == nullptr) { - ptr = new T*[h]; + width = w; + height = h; + + if (!data) { + data = new T[height * width + offset]; } - if (data == nullptr) { - data = new T[h * w + offset]; + for (ssize_t i = 0; i < height; i++) { + rows[i] = data + offset + width * i; } - - x = w; - y = h; - - for (int i = 0; i < h; i++) { - ptr[i] = data + offset + w * i; - } - - owner = 1; } public: // use as empty declaration, resize before use! // very useful as a member object array2D() : - x(0), y(0), owner(0), flags(0), ptr(nullptr), data(nullptr), lock(false) - { - //printf("got empty array2D init\n"); - } + width(0), height(0), rows(nullptr), data(nullptr) + { } // creator type1 - array2D(int w, int h, unsigned int flgs = 0) + array2D(int w, int h, unsigned int flags = 0) : + width(w), height(h) { - flags = flgs; - lock = flags & ARRAY2D_LOCK_DATA; - data = new T[h * w]; - owner = 1; - x = w; - y = h; - ptr = new T*[h]; + data = new T[height * width]; + rows = new T*[height]; - for (int i = 0; i < h; i++) { - ptr[i] = data + i * w; + for (ssize_t i = 0; i < height; ++i) { + rows[i] = data + i * width; } if (flags & ARRAY2D_CLEAR_DATA) { - memset(data, 0, w * h * sizeof(T)); + memset(data, 0, width * height * sizeof(T)); } } // creator type 2 - array2D(int w, int h, T ** source, unsigned int flgs = 0) + array2D(int w, int h, T ** source, unsigned int flags = 0) : + width(w), height(h) { - flags = flgs; - //if (lock) { printf("array2D attempt to overwrite data\n");raise(SIGSEGV);} - lock = flags & ARRAY2D_LOCK_DATA; - // when by reference - // TODO: improve this code with ar_realloc() - owner = (flags & ARRAY2D_BYREFERENCE) ? 0 : 1; - + const bool owner = !(flags & ARRAY2D_BYREFERENCE); if (owner) { - data = new T[h * w]; + data = new T[height * width]; } else { data = nullptr; } - x = w; - y = h; - ptr = new T*[h]; + rows = new T*[height]; - for (int i = 0; i < h; i++) { + for (ssize_t i = 0; i < height; ++i) { if (owner) { - ptr[i] = data + i * w; - - for (int j = 0; j < w; j++) { - ptr[i][j] = source[i][j]; + rows[i] = data + i * width; + for (ssize_t j = 0; j < width; ++j) { + rows[i][j] = source[i][j]; } } else { - ptr[i] = source[i]; + rows[i] = source[i]; } } } @@ -174,18 +148,8 @@ public: // destructor ~array2D() { - - if (flags & ARRAY2D_VERBOSE) { - printf(" deleting array2D size %dx%d \n", x, y); - } - - if ((owner) && (data)) { - delete[] data; - } - - if (ptr) { - delete[] ptr; - } + delete[] data; + delete[] rows; } void fill(const T val, bool multiThread = false) @@ -193,41 +157,43 @@ public: #ifdef _OPENMP #pragma omp parallel for if(multiThread) #endif - for (int i = 0; i < x * y; ++i) { + for (ssize_t i = 0; i < width * height; ++i) { data[i] = val; } } void free() { - if ((owner) && (data)) { - delete[] data; - data = nullptr; - } + delete[] data; + data = nullptr; - if (ptr) { - delete [] ptr; - ptr = nullptr; - } + delete [] rows; + rows = nullptr; } // use with indices T * operator[](int index) { - assert((index >= 0) && (index < y)); - return ptr[index]; + assert((index >= 0) && (index < height)); + return rows[index]; + } + + const T * operator[](int index) const + { + assert((index >= 0) && (index < height)); + return rows[index]; } // use as pointer to T** operator T**() { - return ptr; + return rows; } // use as pointer to T** operator const T* const *() const { - return ptr; + return rows; } // use as pointer to data @@ -237,86 +203,53 @@ public: return data; } + operator const T*() const + { + // only if owner this will return a valid pointer + return data; + } + // useful within init of parent object // or use as resize of 2D array - void operator()(int w, int h, unsigned int flgs = 0, int offset = 0) + void operator()(int w, int h, unsigned int flags = 0, int offset = 0) { - flags = flgs; - - if (flags & ARRAY2D_VERBOSE) { - printf("got init request %dx%d flags=%u\n", w, h, flags); - printf("previous was data %p ptr %p \n", data, ptr); - } - - if (lock) { // our object was locked so don't allow a change. - printf("got init request but object was locked!\n"); - raise( SIGSEGV); - } - - lock = flags & ARRAY2D_LOCK_DATA; - ar_realloc(w, h, offset); if (flags & ARRAY2D_CLEAR_DATA) { - memset(data + offset, 0, static_cast(w) * h * sizeof(T)); + memset(data + offset, 0, width * height * sizeof(T)); } } - // import from flat data - void operator()(int w, int h, T* copy, unsigned int flgs = 0) + int getWidth() const { - flags = flgs; - - if (flags & ARRAY2D_VERBOSE) { - printf("got init request %dx%d flags=%u\n", w, h, flags); - printf("previous was data %p ptr %p \n", data, ptr); - } - - if (lock) { // our object was locked so don't allow a change. - printf("got init request but object was locked!\n"); - raise( SIGSEGV); - } - - lock = flags & ARRAY2D_LOCK_DATA; - - ar_realloc(w, h); - memcpy(data, copy, w * h * sizeof(T)); + return width; } - int width() const + int getHeight() const { - return x; - } - int height() const - { - return y; + return height; } operator bool() { - return (x > 0 && y > 0); + return (width > 0 && height > 0); } }; template -class multi_array2D +class multi_array2D : public rtengine::NonCopyable { private: array2D list[num]; public: - multi_array2D(int x, int y, int flags = 0, int offset = 0) + multi_array2D(int width, int height, int flags = 0, int offset = 0) { - for (size_t i = 0; i < num; i++) { - list[i](x, y, flags, (i + 1) * offset); + for (size_t i = 0; i < num; ++i) { + list[i](width, height, flags, (i + 1) * offset); } } - ~multi_array2D() - { - //printf("trying to delete the list of array2D objects\n"); - } - array2D & operator[](int index) { assert(static_cast(index) < num); diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index b3f843bc1..3f5e00e05 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -82,8 +82,8 @@ int calculate_subsampling(int w, int h, int r) void guidedFilter(const array2D &guide, const array2D &src, array2D &dst, int r, float epsilon, bool multithread, int subsampling) { - const int W = src.width(); - const int H = src.height(); + const int W = src.getWidth(); + const int H = src.getHeight(); if (subsampling <= 0) { subsampling = calculate_subsampling(W, H, r); @@ -94,8 +94,8 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto apply = [=](Op op, array2D &res, const array2D &a, const array2D &b, const array2D &c=array2D()) -> void { - const int w = res.width(); - const int h = res.height(); + const int w = res.getWidth(); + const int h = res.getHeight(); #ifdef _OPENMP #pragma omp parallel for if (multithread) @@ -142,12 +142,12 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_subsample = [=](array2D &d, const array2D &s) -> void { - if (d.width() == s.width() && d.height() == s.height()) { + if (d.getWidth() == s.getWidth() && d.getHeight() == s.getHeight()) { #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < s.height(); ++y) { - for (int x = 0; x < s.width(); ++x) { + for (int y = 0; y < s.getHeight(); ++y) { + for (int x = 0; x < s.getWidth(); ++x) { d[y][x] = s[y][x]; } } @@ -164,9 +164,9 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_mean = [multithread](array2D &d, array2D &s, int rad) -> void { - rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1); - // boxblur(s, d, rad, s.width(), s.height(), multithread); - boxblur(static_cast(s), static_cast(d), rad, s.width(), s.height(), multithread); + rad = LIM(rad, 0, (min(s.getWidth(), s.getHeight()) - 1) / 2 - 1); + // boxblur(s, d, rad, s.getWidth(), s.getHeight(), multithread); + boxblur(static_cast(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread); }; array2D I1(w, h); @@ -225,10 +225,10 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 DEBUG_DUMP(meanb); // speedup by heckflosse67 - const int Ws = meana.width(); - const int Hs = meana.height(); - const int Wd = q.width(); - const int Hd = q.height(); + const int Ws = meana.getWidth(); + const int Hs = meana.getHeight(); + const int Wd = q.getWidth(); + const int Hd = q.getHeight(); const float col_scale = float(Ws) / float(Wd); const float row_scale = float(Hs) / float(Hd); @@ -249,8 +249,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < chan.height(); ++y) { - for (int x = 0; x < chan.width(); ++x) { + for (int y = 0; y < chan.getHeight(); ++y) { + for (int x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlin2log(max(chan[y][x], 0.f), base); } } @@ -260,8 +260,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < chan.height(); ++y) { - for (int x = 0; x < chan.width(); ++x) { + for (int y = 0; y < chan.getHeight(); ++y) { + for (int x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlog2lin(max(chan[y][x], 0.f), base); } } diff --git a/rtengine/ipdehaze.cc b/rtengine/ipdehaze.cc index 4376808f8..6526d0d1e 100644 --- a/rtengine/ipdehaze.cc +++ b/rtengine/ipdehaze.cc @@ -105,8 +105,8 @@ void restore(Imagefloat *rgb, float maxval, bool multithread) int get_dark_channel(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, const float ambient[3], bool clip, bool multithread, float strength) { - const int W = R.width(); - const int H = R.height(); + const int W = R.getWidth(); + const int H = R.getHeight(); #ifdef _OPENMP #pragma omp parallel for if (multithread) @@ -164,8 +164,8 @@ int get_dark_channel(const array2D &R, const array2D &G, const arr int get_dark_channel_downsized(const array2D &R, const array2D &G, const array2D &B, array2D &dst, int patchsize, bool multithread) { - const int W = R.width(); - const int H = R.height(); + const int W = R.getWidth(); + const int H = R.getHeight(); #ifdef _OPENMP #pragma omp parallel for if (multithread) @@ -195,8 +195,8 @@ int get_dark_channel_downsized(const array2D &R, const array2D &G, float estimate_ambient_light(const array2D &R, const array2D &G, const array2D &B, const array2D &dark, int patchsize, int npatches, float ambient[3]) { - const int W = R.width(); - const int H = R.height(); + const int W = R.getWidth(); + const int H = R.getHeight(); float darklim = RT_INFINITY_F; { diff --git a/rtengine/iplocallab.cc b/rtengine/iplocallab.cc index b349a454a..2c86db032 100644 --- a/rtengine/iplocallab.cc +++ b/rtengine/iplocallab.cc @@ -1840,8 +1840,8 @@ void tone_eq(array2D &R, array2D &G, array2D &B, const stru { BENCHFUN - const int W = R.width(); - const int H = R.height(); + const int W = R.getWidth(); + const int H = R.getHeight(); array2D Y(W, H); const auto log2 = diff --git a/rtengine/rescale.h b/rtengine/rescale.h index 2138cd8e8..3126a7c58 100644 --- a/rtengine/rescale.h +++ b/rtengine/rescale.h @@ -31,8 +31,8 @@ namespace rtengine inline float getBilinearValue(const array2D &src, float x, float y) { - const int W = src.width(); - const int H = src.height(); + const int W = src.getWidth(); + const int H = src.getHeight(); // Get integer and fractional parts of numbers int xi = x; @@ -57,10 +57,10 @@ inline float getBilinearValue(const array2D &src, float x, float y) inline void rescaleBilinear(const array2D &src, array2D &dst, bool multithread) { - const int Ws = src.width(); - const int Hs = src.height(); - const int Wd = dst.width(); - const int Hd = dst.height(); + const int Ws = src.getWidth(); + const int Hs = src.getHeight(); + const int Wd = dst.getWidth(); + const int Hd = dst.getHeight(); float col_scale = float (Ws) / float (Wd); float row_scale = float (Hs) / float (Hd); @@ -81,10 +81,10 @@ inline void rescaleBilinear(const array2D &src, array2D &dst, bool inline void rescaleNearest(const array2D &src, array2D &dst, bool multithread) { - const int width = src.width(); - const int height = src.height(); - const int nw = dst.width(); - const int nh = dst.height(); + const int width = src.getWidth(); + const int height = src.getHeight(); + const int nw = dst.getWidth(); + const int nh = dst.getHeight(); #ifdef _OPENMP #pragma omp parallel for if (multithread) diff --git a/rtengine/tmo_fattal02.cc b/rtengine/tmo_fattal02.cc index bef41d953..f49fe9c53 100644 --- a/rtengine/tmo_fattal02.cc +++ b/rtengine/tmo_fattal02.cc @@ -123,12 +123,12 @@ public: int getRows() const { - return const_cast(*this).height(); + return const_cast(*this).getHeight(); } int getCols() const { - return const_cast(*this).width(); + return const_cast(*this).getWidth(); } float *data() From afa62a2240f58bc0092e914b7118bf59a6bb24ac Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 29 Jul 2020 15:18:34 +0200 Subject: [PATCH 20/33] Added tooltip complexty wavelet --- rtdata/languages/Francais | 1 + rtdata/languages/default | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 0e8635484..d541234cf 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -2653,6 +2653,7 @@ TP_WAVELET_CHR_TOOLTIP;Ajuste le chroma en fonction des "niveaux de contraste" e TP_WAVELET_CHSL;Curseurs TP_WAVELET_CHTYPE;Méthode de chrominance TP_WAVELET_COLORT;Opacité Rouge-Vert +TP_WAVELET_COMPLEX_TOOLTIP;Standard: l’application dispose du nécessaire pour assurer les opérations courantes, l’interface graphique est simplifiée.\nAvancé: toutes les fonctionnalités sont présentes, certaines nécessitent un apprentissage important TP_WAVELET_COMPEXPERT;Avancé TP_WAVELET_COMPCONT;Contraste TP_WAVELET_COMPGAMMA;Compression gamma diff --git a/rtdata/languages/default b/rtdata/languages/default index 87b39be78..f00d9411e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -3282,7 +3282,7 @@ TP_WAVELET_COMPCONT;Contrast TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. TP_WAVELET_COMPLEXLAB;Complexity -TP_WAVELET_COMPLEX_TOOLTIP;Allows treatment +TP_WAVELET_COMPLEX_TOOLTIP;Standard: shows a reduced set of tools suitable for most processing operations.\nAdvanced: shows the complete set of tools for advanced processing operations TP_WAVELET_COMPNORMAL;Standard TP_WAVELET_COMPEXPERT;Advanced TP_WAVELET_COMPTM;Tone mapping From 57303d52b26b8e86ce3927486230eb2057f03c7d Mon Sep 17 00:00:00 2001 From: Thanatomanic <6567747+Thanatomanic@users.noreply.github.com> Date: Wed, 29 Jul 2020 20:07:24 +0200 Subject: [PATCH 21/33] Add white-levels for Fuji X-T3 and X-Pro3 (fixes #5839 and #5860) --- rtengine/camconst.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index de06f670f..01b73d0e7 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -1401,9 +1401,17 @@ Camera constants: "ranges": { "white": [ 16105, 16270, 16082 ] } // These values are the lowest pixel values >16000 for all ISOs. LENR has a negligble effect. // No aperture scaling data provided, but likely negligible }, - - { // Quality C, only raw crop - "make_model": [ "FUJIFILM X-T3", "FUJIFILM X-T30", "FUJIFILM X-PRO3", "FUJIFILM X100V", "FUJIFILM X-T4" ], + + { // Quality A, samples provided by Daniel Catalina (#5839) and pi99y (#5860) + "make_model": [ "FUJIFILM X-T3", "FUJIFILM X-PRO3" ], + "dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v11, standard_v2 d65 + "raw_crop": [ 0, 5, 6252, 4176], + "white": [ 16170, 16275, 16170 ] // typical safe-margins with LENR + // negligible aperture scaling effect + }, + + { // Quality B + "make_model": [ "FUJIFILM X-T30", "FUJIFILM X100V", "FUJIFILM X-T4" ], "dcraw_matrix": [ 13426,-6334,-1177,-4244,12136,2371,-580,1303,5980 ], // DNG_v11, standard_v2 d65 "raw_crop": [ 0, 5, 6252, 4176] }, From 584343fb36444c9fbf112e0ce121153acd0d9d41 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Thu, 30 Jul 2020 14:56:26 +0200 Subject: [PATCH 22/33] array2D: use size_t --- rtengine/array2D.h | 30 +++++++++++++++--------------- rtengine/guidedfilter.cc | 19 ++++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 8d1351cbb..f4e5ac596 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -67,10 +67,10 @@ class array2D : { private: - ssize_t width, height; + size_t width, height; T** rows; T* data; - void ar_realloc(ssize_t w, ssize_t h, int offset = 0) + void ar_realloc(size_t w, size_t h, int offset = 0) { if (rows && (h > height || 4 * h < height)) { delete[] rows; @@ -92,7 +92,7 @@ private: data = new T[height * width + offset]; } - for (ssize_t i = 0; i < height; i++) { + for (size_t i = 0; i < height; i++) { rows[i] = data + offset + width * i; } } @@ -105,13 +105,13 @@ public: { } // creator type1 - array2D(int w, int h, unsigned int flags = 0) : + array2D(size_t w, size_t h, unsigned int flags = 0) : width(w), height(h) { data = new T[height * width]; rows = new T*[height]; - for (ssize_t i = 0; i < height; ++i) { + for (size_t i = 0; i < height; ++i) { rows[i] = data + i * width; } @@ -121,7 +121,7 @@ public: } // creator type 2 - array2D(int w, int h, T ** source, unsigned int flags = 0) : + array2D(size_t w, size_t h, T ** source, unsigned int flags = 0) : width(w), height(h) { const bool owner = !(flags & ARRAY2D_BYREFERENCE); @@ -133,10 +133,10 @@ public: rows = new T*[height]; - for (ssize_t i = 0; i < height; ++i) { + for (size_t i = 0; i < height; ++i) { if (owner) { rows[i] = data + i * width; - for (ssize_t j = 0; j < width; ++j) { + for (size_t j = 0; j < width; ++j) { rows[i][j] = source[i][j]; } } else { @@ -157,7 +157,7 @@ public: #ifdef _OPENMP #pragma omp parallel for if(multiThread) #endif - for (ssize_t i = 0; i < width * height; ++i) { + for (size_t i = 0; i < width * height; ++i) { data[i] = val; } } @@ -172,13 +172,13 @@ public: } // use with indices - T * operator[](int index) + T * operator[](size_t index) { assert((index >= 0) && (index < height)); return rows[index]; } - const T * operator[](int index) const + const T * operator[](size_t index) const { assert((index >= 0) && (index < height)); return rows[index]; @@ -212,7 +212,7 @@ public: // useful within init of parent object // or use as resize of 2D array - void operator()(int w, int h, unsigned int flags = 0, int offset = 0) + void operator()(size_t w, size_t h, unsigned int flags = 0, int offset = 0) { ar_realloc(w, h, offset); @@ -221,11 +221,11 @@ public: } } - int getWidth() const + size_t getWidth() const { return width; } - int getHeight() const + size_t getHeight() const { return height; } @@ -243,7 +243,7 @@ private: array2D list[num]; public: - multi_array2D(int width, int height, int flags = 0, int offset = 0) + multi_array2D(size_t width, size_t height, int flags = 0, int offset = 0) { for (size_t i = 0; i < num; ++i) { list[i](width, height, flags, (i + 1) * offset); diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index 3f5e00e05..8429655dd 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -146,8 +146,8 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < s.getHeight(); ++y) { - for (int x = 0; x < s.getWidth(); ++x) { + for (size_t y = 0; y < s.getHeight(); ++y) { + for (size_t x = 0; x < s.getWidth(); ++x) { d[y][x] = s[y][x]; } } @@ -164,9 +164,10 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_mean = [multithread](array2D &d, array2D &s, int rad) -> void { - rad = LIM(rad, 0, (min(s.getWidth(), s.getHeight()) - 1) / 2 - 1); - // boxblur(s, d, rad, s.getWidth(), s.getHeight(), multithread); - boxblur(static_cast(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread); + if (rtengine::min(s.getWidth(), s.getHeight()) > 1) { + rad = LIM(rad, 0, (rtengine::min(s.getWidth(), s.getHeight()) - 1) / 2 - 1); + boxblur(static_cast(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread); + } }; array2D I1(w, h); @@ -249,8 +250,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < chan.getHeight(); ++y) { - for (int x = 0; x < chan.getWidth(); ++x) { + for (size_t y = 0; y < chan.getHeight(); ++y) { + for (size_t x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlin2log(max(chan[y][x], 0.f), base); } } @@ -260,8 +261,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (int y = 0; y < chan.getHeight(); ++y) { - for (int x = 0; x < chan.getWidth(); ++x) { + for (size_t y = 0; y < chan.getHeight(); ++y) { + for (size_t x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlog2lin(max(chan[y][x], 0.f), base); } } From 3346ee5eea7a3550f2944bbfc981009add03623a Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Thu, 30 Jul 2020 16:04:22 +0200 Subject: [PATCH 23/33] Revert "array2D: use size_t" This reverts commit 584343fb36444c9fbf112e0ce121153acd0d9d41. --- rtengine/array2D.h | 30 +++++++++++++++--------------- rtengine/guidedfilter.cc | 19 +++++++++---------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index f4e5ac596..8d1351cbb 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -67,10 +67,10 @@ class array2D : { private: - size_t width, height; + ssize_t width, height; T** rows; T* data; - void ar_realloc(size_t w, size_t h, int offset = 0) + void ar_realloc(ssize_t w, ssize_t h, int offset = 0) { if (rows && (h > height || 4 * h < height)) { delete[] rows; @@ -92,7 +92,7 @@ private: data = new T[height * width + offset]; } - for (size_t i = 0; i < height; i++) { + for (ssize_t i = 0; i < height; i++) { rows[i] = data + offset + width * i; } } @@ -105,13 +105,13 @@ public: { } // creator type1 - array2D(size_t w, size_t h, unsigned int flags = 0) : + array2D(int w, int h, unsigned int flags = 0) : width(w), height(h) { data = new T[height * width]; rows = new T*[height]; - for (size_t i = 0; i < height; ++i) { + for (ssize_t i = 0; i < height; ++i) { rows[i] = data + i * width; } @@ -121,7 +121,7 @@ public: } // creator type 2 - array2D(size_t w, size_t h, T ** source, unsigned int flags = 0) : + array2D(int w, int h, T ** source, unsigned int flags = 0) : width(w), height(h) { const bool owner = !(flags & ARRAY2D_BYREFERENCE); @@ -133,10 +133,10 @@ public: rows = new T*[height]; - for (size_t i = 0; i < height; ++i) { + for (ssize_t i = 0; i < height; ++i) { if (owner) { rows[i] = data + i * width; - for (size_t j = 0; j < width; ++j) { + for (ssize_t j = 0; j < width; ++j) { rows[i][j] = source[i][j]; } } else { @@ -157,7 +157,7 @@ public: #ifdef _OPENMP #pragma omp parallel for if(multiThread) #endif - for (size_t i = 0; i < width * height; ++i) { + for (ssize_t i = 0; i < width * height; ++i) { data[i] = val; } } @@ -172,13 +172,13 @@ public: } // use with indices - T * operator[](size_t index) + T * operator[](int index) { assert((index >= 0) && (index < height)); return rows[index]; } - const T * operator[](size_t index) const + const T * operator[](int index) const { assert((index >= 0) && (index < height)); return rows[index]; @@ -212,7 +212,7 @@ public: // useful within init of parent object // or use as resize of 2D array - void operator()(size_t w, size_t h, unsigned int flags = 0, int offset = 0) + void operator()(int w, int h, unsigned int flags = 0, int offset = 0) { ar_realloc(w, h, offset); @@ -221,11 +221,11 @@ public: } } - size_t getWidth() const + int getWidth() const { return width; } - size_t getHeight() const + int getHeight() const { return height; } @@ -243,7 +243,7 @@ private: array2D list[num]; public: - multi_array2D(size_t width, size_t height, int flags = 0, int offset = 0) + multi_array2D(int width, int height, int flags = 0, int offset = 0) { for (size_t i = 0; i < num; ++i) { list[i](width, height, flags, (i + 1) * offset); diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc index 8429655dd..3f5e00e05 100644 --- a/rtengine/guidedfilter.cc +++ b/rtengine/guidedfilter.cc @@ -146,8 +146,8 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (size_t y = 0; y < s.getHeight(); ++y) { - for (size_t x = 0; x < s.getWidth(); ++x) { + for (int y = 0; y < s.getHeight(); ++y) { + for (int x = 0; x < s.getWidth(); ++x) { d[y][x] = s[y][x]; } } @@ -164,10 +164,9 @@ void guidedFilter(const array2D &guide, const array2D &src, array2 const auto f_mean = [multithread](array2D &d, array2D &s, int rad) -> void { - if (rtengine::min(s.getWidth(), s.getHeight()) > 1) { - rad = LIM(rad, 0, (rtengine::min(s.getWidth(), s.getHeight()) - 1) / 2 - 1); - boxblur(static_cast(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread); - } + rad = LIM(rad, 0, (min(s.getWidth(), s.getHeight()) - 1) / 2 - 1); + // boxblur(s, d, rad, s.getWidth(), s.getHeight(), multithread); + boxblur(static_cast(s), static_cast(d), rad, s.getWidth(), s.getHeight(), multithread); }; array2D I1(w, h); @@ -250,8 +249,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (size_t y = 0; y < chan.getHeight(); ++y) { - for (size_t x = 0; x < chan.getWidth(); ++x) { + for (int y = 0; y < chan.getHeight(); ++y) { + for (int x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlin2log(max(chan[y][x], 0.f), base); } } @@ -261,8 +260,8 @@ void guidedFilterLog(const array2D &guide, float base, array2D &ch #ifdef _OPENMP # pragma omp parallel for if (multithread) #endif - for (size_t y = 0; y < chan.getHeight(); ++y) { - for (size_t x = 0; x < chan.getWidth(); ++x) { + for (int y = 0; y < chan.getHeight(); ++y) { + for (int x = 0; x < chan.getWidth(); ++x) { chan[y][x] = xlog2lin(max(chan[y][x], 0.f), base); } } From 03acf7680a208fa66111ce18afe0b9e794fb5053 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Thu, 30 Jul 2020 16:08:47 +0200 Subject: [PATCH 24/33] Add missing #include --- rtengine/array2D.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 8d1351cbb..0b624cf89 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -54,6 +54,7 @@ #include #include +#include #include "noncopyable.h" // flags for use From 04854518a3bc15697b996979726ef2d41f3e27c2 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Sat, 1 Aug 2020 15:29:05 +0200 Subject: [PATCH 25/33] array2D: use std::vector --- rtengine/array2D.h | 110 ++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 67 deletions(-) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 0b624cf89..f5f9b198b 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -55,6 +55,7 @@ #include #include #include +#include #include "noncopyable.h" // flags for use @@ -68,75 +69,59 @@ class array2D : { private: - ssize_t width, height; - T** rows; - T* data; + ssize_t width; + std::vector rows; + std::vector buffer; + + void initRows(ssize_t h, int offset = 0) + { + rows.resize(h); + T* start = buffer.data(); + for (ssize_t i = 0; i < h; i++) { + rows[i] = start + offset + width * i; + } + } + void ar_realloc(ssize_t w, ssize_t h, int offset = 0) { - if (rows && (h > height || 4 * h < height)) { - delete[] rows; - rows = nullptr; - } - if (!rows) { - rows = new T*[h]; - } - - if (data && ((h * w > width * height) || (h * w < (width * height / 4)))) { - delete[] data; - data = nullptr; - } - width = w; - height = h; - - if (!data) { - data = new T[height * width + offset]; - } - - for (ssize_t i = 0; i < height; i++) { - rows[i] = data + offset + width * i; - } + buffer.resize(h * width + offset); + initRows(h, offset); } public: // use as empty declaration, resize before use! // very useful as a member object - array2D() : - width(0), height(0), rows(nullptr), data(nullptr) - { } + array2D() : width(0) {} // creator type1 - array2D(int w, int h, unsigned int flags = 0) : - width(w), height(h) + array2D(int w, int h, unsigned int flags = 0) : width(w) { - data = new T[height * width]; - rows = new T*[height]; - - for (ssize_t i = 0; i < height; ++i) { - rows[i] = data + i * width; - } - if (flags & ARRAY2D_CLEAR_DATA) { - memset(data, 0, width * height * sizeof(T)); + buffer.resize(h * width, 0); + } else { + buffer.resize(h * width); } + initRows(h); } // creator type 2 array2D(int w, int h, T ** source, unsigned int flags = 0) : - width(w), height(h) + width(w) { const bool owner = !(flags & ARRAY2D_BYREFERENCE); if (owner) { - data = new T[height * width]; + buffer.resize(h * width); } else { - data = nullptr; + buffer.clear(); } - rows = new T*[height]; + rows.resize(h); - for (ssize_t i = 0; i < height; ++i) { + T* start = buffer.data(); + for (ssize_t i = 0; i < h; ++i) { if (owner) { - rows[i] = data + i * width; + rows[i] = start + i * width; for (ssize_t j = 0; j < width; ++j) { rows[i][j] = source[i][j]; } @@ -146,68 +131,59 @@ public: } } - // destructor - ~array2D() - { - delete[] data; - delete[] rows; - } - void fill(const T val, bool multiThread = false) { + const ssize_t height = rows.size(); #ifdef _OPENMP #pragma omp parallel for if(multiThread) #endif for (ssize_t i = 0; i < width * height; ++i) { - data[i] = val; + buffer[i] = val; } } void free() { - delete[] data; - data = nullptr; - - delete [] rows; - rows = nullptr; + buffer.clear(); + rows.clear(); } // use with indices T * operator[](int index) { - assert((index >= 0) && (index < height)); + assert((index >= 0) && (index < rows.size())); return rows[index]; } const T * operator[](int index) const { - assert((index >= 0) && (index < height)); + assert((index >= 0) && (index < rows.size())); return rows[index]; } // use as pointer to T** operator T**() { - return rows; + return rows.data(); } // use as pointer to T** operator const T* const *() const { - return rows; + return rows.data(); } - // use as pointer to data + // use as pointer to buffer operator T*() { // only if owner this will return a valid pointer - return data; + return buffer.data(); } operator const T*() const { // only if owner this will return a valid pointer - return data; + return buffer.data(); } @@ -218,7 +194,7 @@ public: ar_realloc(w, h, offset); if (flags & ARRAY2D_CLEAR_DATA) { - memset(data + offset, 0, width * height * sizeof(T)); + fill(0); } } @@ -228,12 +204,12 @@ public: } int getHeight() const { - return height; + return rows.size(); } operator bool() { - return (width > 0 && height > 0); + return (width > 0 && !rows.empty()); } }; From 5c932f66680a46df6f5dc905bdca809aed85874e Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Sat, 1 Aug 2020 17:23:24 +0200 Subject: [PATCH 26/33] array2D: further small changes --- rtengine/array2D.h | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/rtengine/array2D.h b/rtengine/array2D.h index f5f9b198b..512f7bcc1 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -76,9 +76,9 @@ private: void initRows(ssize_t h, int offset = 0) { rows.resize(h); - T* start = buffer.data(); - for (ssize_t i = 0; i < h; i++) { - rows[i] = start + offset + width * i; + T* start = buffer.data() + offset; + for (ssize_t i = 0; i < h; ++i) { + rows[i] = start + width * i; } } @@ -106,26 +106,20 @@ public: } // creator type 2 - array2D(int w, int h, T ** source, unsigned int flags = 0) : - width(w) + array2D(int w, int h, T ** source, unsigned int flags = 0) : width(w) { - const bool owner = !(flags & ARRAY2D_BYREFERENCE); - if (owner) { - buffer.resize(h * width); - } else { - buffer.clear(); - } - rows.resize(h); - - T* start = buffer.data(); - for (ssize_t i = 0; i < h; ++i) { - if (owner) { + if (!(flags & ARRAY2D_BYREFERENCE)) { + buffer.resize(h * width); + T* start = buffer.data(); + for (ssize_t i = 0; i < h; ++i) { rows[i] = start + i * width; for (ssize_t j = 0; j < width; ++j) { rows[i][j] = source[i][j]; } - } else { + } + } else { + for (ssize_t i = 0; i < h; ++i) { rows[i] = source[i]; } } From e0d3353d72d083412a36400579682d969ae234ad Mon Sep 17 00:00:00 2001 From: Desmis Date: Sun, 2 Aug 2020 15:52:01 +0200 Subject: [PATCH 27/33] Wavelet levels - choice complexity standard - advanced (#5869) * Added in option edghi edglo limrad * Hide choice edgesharpness slider curve * First normal expert * Second normal expert * Changes in normal expert contrast chroma residual * Change label complexity wavelet * French + hide sigmafin standard * Added tooltip complexty wavelet --- rtdata/languages/Francais | 2 + rtdata/languages/default | 5 ++ rtengine/ipwavelet.cc | 31 ++++---- rtengine/procparams.cc | 4 + rtengine/procparams.h | 1 + rtengine/settings.h | 4 + rtgui/options.cc | 27 +++++++ rtgui/paramsedited.cc | 6 ++ rtgui/paramsedited.h | 1 + rtgui/wavelet.cc | 160 ++++++++++++++++++++++++++++++++++++-- rtgui/wavelet.h | 10 ++- 11 files changed, 231 insertions(+), 20 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 52d25d85b..d541234cf 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -2653,6 +2653,8 @@ TP_WAVELET_CHR_TOOLTIP;Ajuste le chroma en fonction des "niveaux de contraste" e TP_WAVELET_CHSL;Curseurs TP_WAVELET_CHTYPE;Méthode de chrominance TP_WAVELET_COLORT;Opacité Rouge-Vert +TP_WAVELET_COMPLEX_TOOLTIP;Standard: l’application dispose du nécessaire pour assurer les opérations courantes, l’interface graphique est simplifiée.\nAvancé: toutes les fonctionnalités sont présentes, certaines nécessitent un apprentissage important +TP_WAVELET_COMPEXPERT;Avancé TP_WAVELET_COMPCONT;Contraste TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Ajuster le gamma de l'image résiduelle vous permet d'équiilibrer les données de l'histogramme. diff --git a/rtdata/languages/default b/rtdata/languages/default index a5f77403e..f00d9411e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1215,6 +1215,7 @@ HISTORY_MSG_COLORTONING_LABREGION_POWER;CT - region power HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope +HISTORY_MSG_COMPLEX;Wavelet complexity HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only @@ -3280,6 +3281,10 @@ TP_WAVELET_COLORT;Opacity Red-Green TP_WAVELET_COMPCONT;Contrast TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. +TP_WAVELET_COMPLEXLAB;Complexity +TP_WAVELET_COMPLEX_TOOLTIP;Standard: shows a reduced set of tools suitable for most processing operations.\nAdvanced: shows the complete set of tools for advanced processing operations +TP_WAVELET_COMPNORMAL;Standard +TP_WAVELET_COMPEXPERT;Advanced TP_WAVELET_COMPTM;Tone mapping TP_WAVELET_CONTEDIT;'After' contrast curve TP_WAVELET_CONTFRAME;Contrast - Compression diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index 499ee7812..c2798af77 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -323,14 +323,14 @@ void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int kall, const } cp.CHSLmet = 1; - cp.EDmet = 1; - + cp.EDmet = 2; +/* if (params->wavelet.EDmethod == "SL") { cp.EDmet = 1; } else if (params->wavelet.EDmethod == "CU") { cp.EDmet = 2; } - +*/ cp.cbena = params->wavelet.cbenab; cp.blhigh = (float)params->wavelet.bluehigh; cp.grhigh = (float)params->wavelet.greenhigh; @@ -2079,7 +2079,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * ContrastResid(WavCoeffs_L0, cp, W_L, H_L, maxp); } - if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + // if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena && !cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + if ((cp.conres >= 0.f || cp.conresH >= 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step const std::unique_ptr temp(new LabImage(W_L, H_L)); #ifdef _OPENMP #pragma omp parallel for num_threads(wavNestedLevels) if (wavNestedLevels>1) @@ -2104,7 +2105,8 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * } } - if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + // if ((cp.conres != 0.f || cp.conresH != 0.f) && cp.resena && cp.oldsh) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step + if ((cp.conres < 0.f || cp.conresH < 0.f) && cp.resena) { // cp.conres = 0.f and cp.comresH = 0.f means that all will be multiplied by 1.f, so we can skip this step #ifdef _OPENMP #pragma omp parallel for #endif @@ -3093,10 +3095,13 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, float atten01234 = 0.80f; value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!! } - + float edghig = settings->edghi;//increase or reduce "reinforce" + float edglow = settings->edglo;//increase or reduce "reduce" + float limrad = settings->limrad;//threshold action in function radius (rad) + printf("edghi=%f edglo=%f limrad=%f\n", edghig, edglow, limrad); // value *= beta; float edge = 1.f; - float lim0 = 20.f; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi + float lim0 = limrad; //arbitrary limit for low radius and level between 2 or 3 to 30 maxi float lev = float (level); float repart = (float)cp.til; @@ -3104,15 +3109,14 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, if (cp.reinforce != 2) { const float brepart = cp.reinforce == 1 - ? 3.f - : 0.5f; + ? edghig + : edglow; const float arepart = -(brepart - 1.f) / (lim0 / 60.f); - if (rad < lim0 / 60.f) { + if (rad < (lim0 / 60.f)) { repart *= (arepart * rad + brepart); //linear repartition of repart } } - float al0 = 1.f + (repart) / 50.f; float al10 = 1.0f; //arbitrary value ==> less = take into account high levels // float ak =-(al0-al10)/10.f;//10 = maximum levels @@ -3120,15 +3124,16 @@ void ImProcFunctions::ContAllL(float *koeLi[12], float maxkoeLi, bool lipschitz, float bk = al0; float koef = ak * level + bk; //modulate for levels : more levels high, more koef low ==> concentrated action on low levels, without or near for high levels float expkoef = -std::pow(std::fabs(rad - lev), koef); //reduce effect for high levels + printf("repart=%f\n", repart); if (cp.reinforce == 3) { - if (rad < lim0 / 60.f && level == 0) { + if (rad < (lim0 / 60.f) && level == 0) { expkoef *= abs(repart); //reduce effect for low values of rad and level=0==> quasi only level 1 is effective } } if (cp.reinforce == 1) { - if (rad < lim0 / 60.f && level == 1) { + if (rad < (lim0 / 60.f) && level == 1) { expkoef /= repart; //increase effect for low values of rad and level=1==> quasi only level 0 is effective } } diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 863c7fc79..a12ab4ba4 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -2395,6 +2395,7 @@ WaveletParams::WaveletParams() : CLmethod("all"), Backmethod("grey"), Tilesmethod("full"), + complexmethod("normal"), daubcoeffmethod("4_"), CHmethod("without"), Medgreinf("less"), @@ -2527,6 +2528,7 @@ bool WaveletParams::operator ==(const WaveletParams& other) const && CLmethod == other.CLmethod && Backmethod == other.Backmethod && Tilesmethod == other.Tilesmethod + && complexmethod == other.complexmethod && daubcoeffmethod == other.daubcoeffmethod && CHmethod == other.CHmethod && Medgreinf == other.Medgreinf @@ -5988,6 +5990,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->wavelet.iter, "Wavelet", "Iter", wavelet.iter, keyFile); saveToKeyfile(!pedited || pedited->wavelet.thres, "Wavelet", "MaxLev", wavelet.thres, keyFile); saveToKeyfile(!pedited || pedited->wavelet.Tilesmethod, "Wavelet", "TilesMethod", wavelet.Tilesmethod, keyFile); + saveToKeyfile(!pedited || pedited->wavelet.complexmethod, "Wavelet", "complexMethod", wavelet.complexmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.daubcoeffmethod, "Wavelet", "DaubMethod", wavelet.daubcoeffmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.CLmethod, "Wavelet", "ChoiceLevMethod", wavelet.CLmethod, keyFile); saveToKeyfile(!pedited || pedited->wavelet.Backmethod, "Wavelet", "BackMethod", wavelet.Backmethod, keyFile); @@ -7858,6 +7861,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Wavelet", "ChoiceLevMethod", pedited, wavelet.CLmethod, pedited->wavelet.CLmethod); assignFromKeyfile(keyFile, "Wavelet", "BackMethod", pedited, wavelet.Backmethod, pedited->wavelet.Backmethod); assignFromKeyfile(keyFile, "Wavelet", "TilesMethod", pedited, wavelet.Tilesmethod, pedited->wavelet.Tilesmethod); + assignFromKeyfile(keyFile, "Wavelet", "complexMethod", pedited, wavelet.complexmethod, pedited->wavelet.complexmethod); assignFromKeyfile(keyFile, "Wavelet", "DaubMethod", pedited, wavelet.daubcoeffmethod, pedited->wavelet.daubcoeffmethod); assignFromKeyfile(keyFile, "Wavelet", "CHromaMethod", pedited, wavelet.CHmethod, pedited->wavelet.CHmethod); assignFromKeyfile(keyFile, "Wavelet", "Medgreinf", pedited, wavelet.Medgreinf, pedited->wavelet.Medgreinf); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 7d609494e..048fe1ee5 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1790,6 +1790,7 @@ struct WaveletParams { Glib::ustring CLmethod; Glib::ustring Backmethod; Glib::ustring Tilesmethod; + Glib::ustring complexmethod; Glib::ustring daubcoeffmethod; Glib::ustring CHmethod; Glib::ustring Medgreinf; diff --git a/rtengine/settings.h b/rtengine/settings.h index fde6fa132..0fb4996df 100644 --- a/rtengine/settings.h +++ b/rtengine/settings.h @@ -99,6 +99,10 @@ public: int itcwb_delta; bool itcwb_stdobserver10; int itcwb_precis; +//wavelet levels + double edghi; + double edglo; + double limrad; enum class ThumbnailInspectorMode { diff --git a/rtgui/options.cc b/rtgui/options.cc index cc49f1fcd..04914e748 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -617,6 +617,12 @@ void Options::setDefaults() rtSettings.itcwb_precis = 5;//3 or 5 or 9 // end locallab +//wavelet + rtSettings.edghi = 3.0;//1.1 and 5. + rtSettings.edglo = 0.5;//0.1 and 0.95 + rtSettings.limrad = 20.;//1 and 60 + + rtSettings.protectred = 60; rtSettings.protectredh = 0.3; rtSettings.CRI_color = 0; @@ -1704,6 +1710,22 @@ void Options::readFromFile(Glib::ustring fname) } + if (keyFile.has_group("Wavelet")) { + if (keyFile.has_key("Wavelet", "Edghi")) { + rtSettings.edghi = keyFile.get_double("Wavelet", "Edghi"); + } + + if (keyFile.has_key("Wavelet", "Edglo")) { + rtSettings.edglo = keyFile.get_double("Wavelet", "Edglo"); + } + + if (keyFile.has_key("Wavelet", "Limrad")) { + rtSettings.limrad = keyFile.get_double("Wavelet", "Limrad"); + } + + } + + if (keyFile.has_group("ICC Profile Creator")) { if (keyFile.has_key("ICC Profile Creator", "PimariesPreset")) { ICCPC_primariesPreset = keyFile.get_string("ICC Profile Creator", "PimariesPreset"); @@ -2302,6 +2324,11 @@ void Options::saveToFile(Glib::ustring fname) keyFile.set_integer("Color Management", "Previewselection", rtSettings.previewselection); keyFile.set_double("Color Management", "Cbdlsensi", rtSettings.cbdlsensi); + keyFile.set_double("Wavelet", "Edghi", rtSettings.edghi); + keyFile.set_double("Wavelet", "Edglo", rtSettings.edglo); + keyFile.set_double("Wavelet", "Limrad", rtSettings.limrad); + + keyFile.set_string("ICC Profile Creator", "PimariesPreset", ICCPC_primariesPreset); keyFile.set_double("ICC Profile Creator", "RedPrimaryX", ICCPC_redPrimaryX); keyFile.set_double("ICC Profile Creator", "RedPrimaryY", ICCPC_redPrimaryY); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index db830c6c1..070e31316 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -531,6 +531,7 @@ void ParamsEdited::set(bool v) wavelet.CLmethod = v; wavelet.Backmethod = v; wavelet.Tilesmethod = v; + wavelet.complexmethod = v; wavelet.daubcoeffmethod = v; wavelet.CHmethod = v; wavelet.CHSLmethod = v; @@ -1679,6 +1680,7 @@ void ParamsEdited::initFrom(const std::vector& wavelet.CLmethod = wavelet.CLmethod && p.wavelet.CLmethod == other.wavelet.CLmethod; wavelet.Backmethod = wavelet.Backmethod && p.wavelet.Backmethod == other.wavelet.Backmethod; wavelet.Tilesmethod = wavelet.Tilesmethod && p.wavelet.Tilesmethod == other.wavelet.Tilesmethod; + wavelet.complexmethod = wavelet.complexmethod && p.wavelet.complexmethod == other.wavelet.complexmethod; wavelet.daubcoeffmethod = wavelet.daubcoeffmethod && p.wavelet.daubcoeffmethod == other.wavelet.daubcoeffmethod; wavelet.CHmethod = wavelet.CHmethod && p.wavelet.CHmethod == other.wavelet.CHmethod; wavelet.CHSLmethod = wavelet.CHSLmethod && p.wavelet.CHSLmethod == other.wavelet.CHSLmethod; @@ -5574,6 +5576,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.wavelet.Tilesmethod = mods.wavelet.Tilesmethod; } + if (wavelet.complexmethod) { + toEdit.wavelet.complexmethod = mods.wavelet.complexmethod; + } + if (wavelet.daubcoeffmethod) { toEdit.wavelet.daubcoeffmethod = mods.wavelet.daubcoeffmethod; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 98a427796..57b6458b9 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1039,6 +1039,7 @@ struct WaveletParamsEdited { bool CLmethod; bool Backmethod; bool Tilesmethod; + bool complexmethod; bool daubcoeffmethod; bool Dirmethod; bool sigma; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index ac8c6100b..8bd074867 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -158,6 +158,7 @@ Wavelet::Wavelet() : HSmethod(Gtk::manage(new MyComboBoxText())), CLmethod(Gtk::manage(new MyComboBoxText())), Backmethod(Gtk::manage(new MyComboBoxText())), + complexmethod(Gtk::manage(new MyComboBoxText())), Tilesmethod(Gtk::manage(new MyComboBoxText())), daubcoeffmethod(Gtk::manage(new MyComboBoxText())), Dirmethod(Gtk::manage(new MyComboBoxText())), @@ -190,7 +191,10 @@ Wavelet::Wavelet() : expclari(Gtk::manage(new MyExpander(true, M("TP_WAVELET_CLARI")))), expbl(Gtk::manage(new MyExpander(true, M("TP_WAVELET_BL")))), neutrHBox(Gtk::manage(new Gtk::HBox())), - usharpHBox(Gtk::manage(new Gtk::HBox())) + usharpHBox(Gtk::manage(new Gtk::HBox())), + ctboxch(Gtk::manage(new Gtk::HBox())), + ctboxBA(Gtk::manage(new Gtk::VBox())) + { CurveListener::setMulti(true); auto m = ProcEventMapper::getInstance(); @@ -227,6 +231,7 @@ Wavelet::Wavelet() : EvWavrangeab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_RANGEAB"); EvWavprotab = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_PROTAB"); EvWavlevelshc = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_LEVELSHC"); + EvWavcomplexmet = m->newEvent(DIRPYREQUALIZER, "HISTORY_MSG_COMPLEX"); labgrid = Gtk::manage(new LabGrid(EvWavLabGridValue, M("TP_WAVELET_LABGRID_VALUES"))); @@ -269,6 +274,16 @@ Wavelet::Wavelet() : thres->set_tooltip_text(M("TP_WAVELET_LEVELS_TOOLTIP")); thres->setAdjusterListener(this); + complexmethod->append(M("TP_WAVELET_COMPNORMAL")); + complexmethod->append(M("TP_WAVELET_COMPEXPERT")); + complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::complexmethodChanged)); + complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP")); + Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":")); + complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4); + complexHBox->pack_start(*complexmethod); + + Tilesmethod->append(M("TP_WAVELET_TILESFULL")); Tilesmethod->append(M("TP_WAVELET_TILESBIG")); // Tilesmethod->append(M("TP_WAVELET_TILESLIT")); @@ -335,6 +350,7 @@ Wavelet::Wavelet() : levdirSubHBox->pack_start(*Lmethod); levdirSubHBox->pack_start(*Dirmethod, Gtk::PACK_EXPAND_WIDGET, 2); // same, but 2 not 4? + settingsBox->pack_start(*complexHBox); settingsBox->pack_start(*strength); settingsBox->pack_start(*thres); settingsBox->pack_start(*tilesizeHBox); @@ -452,7 +468,7 @@ Wavelet::Wavelet() : ToolParamBlock* const chBox = Gtk::manage(new ToolParamBlock()); Gtk::Label* const labmch = Gtk::manage(new Gtk::Label(M("TP_WAVELET_CHTYPE") + ":")); - Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox()); +// Gtk::HBox* const ctboxch = Gtk::manage(new Gtk::HBox()); ctboxch->pack_start(*labmch, Gtk::PACK_SHRINK, 1); CHmethod->append(M("TP_WAVELET_CH1")); @@ -674,7 +690,7 @@ Wavelet::Wavelet() : EDmethod->append(M("TP_WAVELET_EDCU")); EDmethodconn = EDmethod->signal_changed().connect(sigc::mem_fun(*this, &Wavelet::EDmethodChanged)); ctboxED->pack_start(*EDmethod); - edgBox->pack_start(*ctboxED); + // edgBox->pack_start(*ctboxED); edgcont->setAdjusterListener(this); edgcont->setBgGradient(milestones2); @@ -838,7 +854,7 @@ Wavelet::Wavelet() : thrH->setAdjusterListener(this); radius->setAdjusterListener(this); - radius->hide(); +// radius->hide(); shFrame->set_label_align(0.025, 0.5); ToolParamBlock* const shBox = Gtk::manage(new ToolParamBlock()); @@ -1007,7 +1023,7 @@ Wavelet::Wavelet() : resBox->pack_start(*neutrHBox); // Final Touchup - Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox()); + // Gtk::VBox* const ctboxBA = Gtk::manage(new Gtk::VBox()); ctboxBA->set_spacing(2); @@ -1236,6 +1252,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) CLmethodconn.block(true); Backmethodconn.block(true); Tilesmethodconn.block(true); + complexmethodconn.block(true); daubcoeffmethodconn.block(true); Dirmethodconn.block(true); CHmethodconn.block(true); @@ -1357,6 +1374,12 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) } else if (pp->wavelet.CLmethod == "all") { CLmethod->set_active(3); } + if (pp->wavelet.complexmethod == "normal") { + complexmethod->set_active(0); + } else if (pp->wavelet.complexmethod == "expert") { + complexmethod->set_active(1); + } + //Tilesmethod->set_active (2); if (pp->wavelet.Tilesmethod == "full") { @@ -1558,6 +1581,11 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) Backmethod->set_active_text(M("GENERAL_UNCHANGED")); } + if (!pedited->wavelet.complexmethod) { + complexmethod->set_active_text(M("GENERAL_UNCHANGED")); + } + + if (!pedited->wavelet.Tilesmethod) { Tilesmethod->set_active_text(M("GENERAL_UNCHANGED")); } @@ -1774,6 +1802,15 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) } else { sup->hide(); } + + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + } /***************************************************************************************************** @@ -1786,6 +1823,7 @@ void Wavelet::read(const ProcParams* pp, const ParamsEdited* pedited) CLmethodconn.block(false); Backmethodconn.block(false); Tilesmethodconn.block(false); + complexmethodconn.block(false); daubcoeffmethodconn.block(false); CHmethodconn.block(false); CHSLmethodconn.block(false); @@ -1965,6 +2003,7 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) pedited->wavelet.CLmethod = CLmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Backmethod = Backmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.Tilesmethod = Tilesmethod->get_active_text() != M("GENERAL_UNCHANGED"); + pedited->wavelet.complexmethod = complexmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.daubcoeffmethod = daubcoeffmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHmethod = CHmethod->get_active_text() != M("GENERAL_UNCHANGED"); pedited->wavelet.CHSLmethod = CHSLmethod->get_active_text() != M("GENERAL_UNCHANGED"); @@ -2168,6 +2207,12 @@ void Wavelet::write(ProcParams* pp, ParamsEdited* pedited) // pp->wavelet.Tilesmethod = "lit"; } + if (complexmethod->get_active_row_number() == 0) { + pp->wavelet.complexmethod = "normal"; + } else if (complexmethod->get_active_row_number() == 1) { + pp->wavelet.complexmethod = "expert"; + } + if (daubcoeffmethod->get_active_row_number() == 0) { pp->wavelet.daubcoeffmethod = "2_"; } else if (daubcoeffmethod->get_active_row_number() == 1) { @@ -2835,6 +2880,110 @@ void Wavelet::ushamethodChanged() } + +void Wavelet::convertParamToNormal() +{ + const WaveletParams def_params; + disableListener(); + //contrast + offset->setValue(def_params.offset); + sigma->setValue(def_params.sigma); + lowthr->setValue(def_params.lowthr); + //chroma + expchroma->setEnabled(def_params.expchroma); + sigmacol->setValue(def_params.sigmacol); + CHmethod->set_active(2); + //denoise + chromfi->setValue(def_params.chromfi); + chromco->setValue(def_params.chromco); + //toning + exptoning->setEnabled(def_params.exptoning); + //gamut + median->set_active(def_params.median); + avoid->set_active(def_params.avoid); + hueskin->setValue(def_params.hueskin); + skinprotect->setValue(def_params.skinprotect); + //blur + expbl->setEnabled(def_params.expbl); + //edge sharpness + lipst->set_active(def_params.lipst); + lipstUpdateUI(); + edgesensi->setValue(def_params.edgesensi); + edgeampli->setValue(def_params.edgeampli); + NPmethod->set_active(0); + //resid + // oldsh->set_active(true); + radius->setValue(def_params.radius); + resblur->setValue(def_params.resblur); + resblurc->setValue(def_params.resblurc); + cbenab->set_active(false); + + //final touchup + BAmethod->set_active(0); + enableListener(); + sigmafin->setValue(def_params.sigmafin); + + // Update GUI based on converted widget parameters: +} + +void Wavelet::updateGUIToMode(int mode) +{ + if(mode ==0) { + offset->hide(); + sigma->hide(); + lowthr->hide(); + ctboxch->hide(); + sigmacol->hide(); + expgamut->hide(); + exptoning->hide(); + chroFrame->hide(); + expbl->hide(); + lipst->hide(); + dirFrame->hide(); + oldsh->hide(); + radius->hide(); + blurFrame->hide(); + cbenab->hide(); + sigmafin->hide(); + } else { + offset->show(); + sigma->show(); + lowthr->show(); + ctboxch->show(); + sigmacol->show(); + expgamut->show(); + exptoning->show(); + chroFrame->show(); + expbl->show(); + lipst->show(); + dirFrame->show(); + oldsh->hide(); + radius->show(); + blurFrame->show(); + cbenab->show(); + sigmafin->show(); + } + +} + + +void Wavelet::complexmethodChanged() +{ + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + + if (listener && (multiImage || getEnabled())) { + listener->panelChanged(EvWavcomplexmet, complexmethod->get_active_text()); + } +} + + + void Wavelet::TilesmethodChanged() { //TilesmethodUpdateUI(); @@ -2916,6 +3065,7 @@ void Wavelet::setBatchMode(bool batchMode) CLmethod->append(M("GENERAL_UNCHANGED")); Backmethod->append(M("GENERAL_UNCHANGED")); Tilesmethod->append(M("GENERAL_UNCHANGED")); + complexmethod->append(M("GENERAL_UNCHANGED")); daubcoeffmethod->append(M("GENERAL_UNCHANGED")); CHmethod->append(M("GENERAL_UNCHANGED")); Medgreinf->append(M("GENERAL_UNCHANGED")); diff --git a/rtgui/wavelet.h b/rtgui/wavelet.h index 6daabcd67..a497d2c4f 100644 --- a/rtgui/wavelet.h +++ b/rtgui/wavelet.h @@ -47,7 +47,6 @@ class Wavelet final : public: Wavelet(); ~Wavelet() override; - bool wavComputed_(); void adjusterChanged(Adjuster* a, double newval) override; void autoOpenCurve() override; @@ -102,6 +101,7 @@ private: rtengine::ProcEvent EvWavrangeab; rtengine::ProcEvent EvWavprotab; rtengine::ProcEvent EvWavlevelshc; + rtengine::ProcEvent EvWavcomplexmet; LabGrid *labgrid; @@ -121,6 +121,7 @@ private: void LmethodChanged(); void MedgreinfChanged(); void TMmethodChanged(); + void complexmethodChanged(); void TilesmethodChanged(); void avoidToggled(); void showmaskToggled (); @@ -143,7 +144,8 @@ private: void ushamethodChanged(); void updateGUI(); void updateGUImaxlev(); - + void convertParamToNormal(); + void updateGUIToMode(int mode); void HSmethodUpdateUI(); void CHmethodUpdateUI(); // void CHSLmethodChangedUI(); @@ -297,6 +299,8 @@ private: sigc::connection CLmethodconn; MyComboBoxText* const Backmethod; sigc::connection Backmethodconn; + MyComboBoxText* const complexmethod; + sigc::connection complexmethodconn; MyComboBoxText* const Tilesmethod; sigc::connection Tilesmethodconn; MyComboBoxText* const daubcoeffmethod; @@ -338,6 +342,8 @@ private: Gtk::HBox* const neutrHBox; Gtk::HBox* const usharpHBox; + Gtk::HBox* const ctboxch; + Gtk::VBox* const ctboxBA;// = Gtk::manage(new Gtk::VBox()); sigc::connection enableChromaConn, enableContrastConn, enableEdgeConn, enabletmConn, enableFinalConn, enableclariConn; sigc::connection enableNoiseConn, enableResidConn, enableToningConn; From c5001518d27bddd37ca93f514c907e9e6fd2bd91 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 4 Aug 2020 12:13:22 +0200 Subject: [PATCH 28/33] Hasselblad Lunar (NEX-7): black level and matrix --- rtengine/camconst.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 01b73d0e7..0e5c76afc 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2755,6 +2755,12 @@ Camera constants: "ranges": { "black": 0, "white": 64400 } }, + { // Quality B + "make_model": "HASSELBLAD NEX-7", + "dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 ], // adobe DNGv12.2 d65 + "ranges": { "black": 512 } + }, + { // Quality A for tested CFV, the other models have the same sensor (16 megapixel square sensor) "make_model": [ "Hasselblad V96C", "Hasselblad CFV", "Hasselblad CFV-II" ], "dcraw_matrix": [ 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809 ] // borrowed from Adobe's DNG converter From ab0c7aec5a687e450feb9cc54249eb22d88534f8 Mon Sep 17 00:00:00 2001 From: Ingo Weyrich Date: Tue, 4 Aug 2020 13:36:16 +0200 Subject: [PATCH 29/33] Added Sony Nex-7 to camconst.json --- rtengine/camconst.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 0e5c76afc..3518fa285 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2756,7 +2756,7 @@ Camera constants: }, { // Quality B - "make_model": "HASSELBLAD NEX-7", + "make_model": ["HASSELBLAD NEX-7", "SONY NEX-7"], // Hasselblad NEX-7 also known as Hasselblad Lunar "dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 ], // adobe DNGv12.2 d65 "ranges": { "black": 512 } }, From 2a31ed9dec08c452f4ee3362ff1e17e3699953e5 Mon Sep 17 00:00:00 2001 From: Thanatomanic <6567747+Thanatomanic@users.noreply.github.com> Date: Tue, 4 Aug 2020 18:00:45 +0200 Subject: [PATCH 30/33] Update white level for Sony NEX-7 --- rtengine/camconst.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 3518fa285..578ff1811 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2758,7 +2758,7 @@ Camera constants: { // Quality B "make_model": ["HASSELBLAD NEX-7", "SONY NEX-7"], // Hasselblad NEX-7 also known as Hasselblad Lunar "dcraw_matrix": [ 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 ], // adobe DNGv12.2 d65 - "ranges": { "black": 512 } + "ranges": { "black": 512, "white": 16372 } // Typical white level (samples provided by @ggc on Pixls, influence from LENR unknown }, { // Quality A for tested CFV, the other models have the same sensor (16 megapixel square sensor) From 6e4efb55c1ec3b03f7c8d66ff740c3773b83f247 Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 5 Aug 2020 07:13:49 +0200 Subject: [PATCH 31/33] Change labels and tooltip --- rtdata/languages/default | 110 +++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index f00d9411e..687e6cec0 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -568,10 +568,10 @@ HISTORY_MSG_314;W - Gamut - Reduce artifacts HISTORY_MSG_315;W - Residual - Contrast HISTORY_MSG_316;W - Gamut - Skin tar/prot HISTORY_MSG_317;W - Gamut - Skin hue -HISTORY_MSG_318;W - Contrast - Fine levels -HISTORY_MSG_319;W - Contrast - Fine range -HISTORY_MSG_320;W - Contrast - Coarse range -HISTORY_MSG_321;W - Contrast - Coarse levels +HISTORY_MSG_318;W - Contrast - Finer levels +HISTORY_MSG_319;W - Contrast - Finer range +HISTORY_MSG_320;W - Contrast - Coarser range +HISTORY_MSG_321;W - Contrast - Coarser levels HISTORY_MSG_322;W - Gamut - Avoid color shift HISTORY_MSG_323;W - ES - Local contrast HISTORY_MSG_324;W - Chroma - Pastel @@ -635,14 +635,14 @@ HISTORY_MSG_381;PRS RLD - Radius HISTORY_MSG_382;PRS RLD - Amount HISTORY_MSG_383;PRS RLD - Damping HISTORY_MSG_384;PRS RLD - Iterations -HISTORY_MSG_385;W - Residual - Color Balance +HISTORY_MSG_385;W - Residual - Color balance HISTORY_MSG_386;W - Residual - CB green high HISTORY_MSG_387;W - Residual - CB blue high HISTORY_MSG_388;W - Residual - CB green mid HISTORY_MSG_389;W - Residual - CB blue mid HISTORY_MSG_390;W - Residual - CB green low HISTORY_MSG_391;W - Residual - CB blue low -HISTORY_MSG_392;W - Residual - Color Balance +HISTORY_MSG_392;W - Residual - Color balance HISTORY_MSG_393;DCP - Look table HISTORY_MSG_394;DCP - Baseline exposure HISTORY_MSG_395;DCP - Base table @@ -1198,7 +1198,7 @@ HISTORY_MSG_956;Local - CH Curve HISTORY_MSG_BLSHAPE;Blur by level HISTORY_MSG_BLURCWAV;Blur chroma HISTORY_MSG_BLURWAV;Blur luminance -HISTORY_MSG_BLUWAV;Attenuation Response +HISTORY_MSG_BLUWAV;Attenuation response HISTORY_MSG_CAT02PRESET;Cat02 automatic preset HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction @@ -1223,7 +1223,7 @@ HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_STRENGTH;Dehaze - Strength HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;Dual demosaic - Auto threshold HISTORY_MSG_DUALDEMOSAIC_CONTRAST;Dual demosaic - Contrast threshold -HISTORY_MSG_EDGEFFECT;Edge Attenuation Response +HISTORY_MSG_EDGEFFECT;Edge Attenuation response HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative HISTORY_MSG_FILMNEGATIVE_FILMBASE;Film base color HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values @@ -1270,10 +1270,10 @@ HISTORY_MSG_RESIZE_ALLOWUPSCALING;Resize - Allow upscaling HISTORY_MSG_SHARPENING_BLUR;Sharpening - Blur radius HISTORY_MSG_SHARPENING_CONTRAST;Sharpening - Contrast threshold HISTORY_MSG_SH_COLORSPACE;S/H - Colorspace -HISTORY_MSG_SIGMACOL;Chroma Attenuation Response -HISTORY_MSG_SIGMADIR;Dir Attenuation Response -HISTORY_MSG_SIGMAFIN;Final contrast Attenuation Response -HISTORY_MSG_SIGMATON;Toning Attenuation Response +HISTORY_MSG_SIGMACOL;Chroma Attenuation response +HISTORY_MSG_SIGMADIR;Dir Attenuation response +HISTORY_MSG_SIGMAFIN;Final contrast Attenuation response +HISTORY_MSG_SIGMATON;Toning Attenuation response HISTORY_MSG_SOFTLIGHT_ENABLED;Soft light HISTORY_MSG_SOFTLIGHT_STRENGTH;Soft light - Strength HISTORY_MSG_TEMPOUT;CAM02 automatic temperature @@ -1292,10 +1292,10 @@ HISTORY_MSG_WAVMERGEC;Merge C HISTORY_MSG_WAVMERGEL;Merge L HISTORY_MSG_WAVOFFSET;Offset HISTORY_MSG_WAVOLDSH;Old algorithm -HISTORY_MSG_WAVRADIUS;Radius Shadows-Highlight +HISTORY_MSG_WAVRADIUS;Radius shadows-highlights HISTORY_MSG_WAVSCALE;Scale HISTORY_MSG_WAVSHOWMASK;Show wavelet mask -HISTORY_MSG_WAVSIGMA;Attenuation Response +HISTORY_MSG_WAVSIGMA;Attenuation response HISTORY_MSG_WAVSOFTRAD;Soft radius clarity HISTORY_MSG_WAVSOFTRADEND;Soft radius final HISTORY_MSG_WAVUSHAMET;Clarity method @@ -3237,18 +3237,18 @@ TP_WAVELET_6;Level 6 TP_WAVELET_7;Level 7 TP_WAVELET_8;Level 8 TP_WAVELET_9;Level 9 -TP_WAVELET_APPLYTO;Apply To +TP_WAVELET_APPLYTO;Apply to TP_WAVELET_AVOID;Avoid color shift TP_WAVELET_B0;Black -TP_WAVELET_B1;Grey +TP_WAVELET_B1;Gray TP_WAVELET_B2;Residual TP_WAVELET_BACKGROUND;Background TP_WAVELET_BACUR;Curve TP_WAVELET_BALANCE;Contrast balance d/v-h TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the wavelet directions: vertical-horizontal and diagonal.\nIf contrast, chroma or residual tone mapping are activated, the effect due to balance is amplified. -TP_WAVELET_BALCHRO;Chrominance balance -TP_WAVELET_BALCHROM;Denoise Equalizer Blue-yellow Red-green +TP_WAVELET_BALANCE_TOOLTIP;Alters the balance between the vertical, horizontal and diagonal wavelet directions: .\nActivating contrast, chroma or residual tone mapping amplifies the effect due to balance TP_WAVELET_BALCHRO_TOOLTIP;If enabled, the 'Contrast balance' curve or slider also modifies chroma balance. +TP_WAVELET_BALCHROM;Denoise equalizer blue-yellow red-green TP_WAVELET_BALLUM;Denoise Equalizer White-Black TP_WAVELET_BANONE;None TP_WAVELET_BASLI;Slider @@ -3256,9 +3256,9 @@ TP_WAVELET_BATYPE;Contrast balance method TP_WAVELET_BL;Blur levels TP_WAVELET_BLCURVE;Blur by levels TP_WAVELET_BLURFRAME;Blur -TP_WAVELET_BLUWAV;Attenuation Response -TP_WAVELET_CBENAB;Toning and Color Balance -TP_WAVELET_CB_TOOLTIP;For strong values product color-toning by combining it or not with levels decomposition 'toning'\nFor low values you can change the white balance of the background (sky, ...) without changing that of the front plane, generally more contrasted +TP_WAVELET_BLUWAV;Attenuation response +TP_WAVELET_CBENAB;Toning and Color balance +TP_WAVELET_CB_TOOLTIP;With high values you can create special effects, similar to those achieved with the Chroma Module, but focused on the residual image\nWith moderate values you can manually correct the white balance TP_WAVELET_CCURVE;Local contrast TP_WAVELET_CH1;Whole chroma range TP_WAVELET_CH2;Saturated/pastel @@ -3266,7 +3266,7 @@ TP_WAVELET_CH3;Link contrast levels TP_WAVELET_CHCU;Curve TP_WAVELET_CHR;Chroma-contrast link strength TP_WAVELET_CHRO;Saturated/pastel threshold -TP_WAVELET_CHROFRAME;Denoise Chrominance +TP_WAVELET_CHROFRAME;Denoise chrominance TP_WAVELET_CHROMAFRAME;Chroma TP_WAVELET_CHROMCO;Chrominance Coarse TP_WAVELET_CHROMFI;Chrominance Fine @@ -3277,7 +3277,7 @@ TP_WAVELET_CHSL;Sliders TP_WAVELET_CHTYPE;Chrominance method TP_WAVELET_CLA;Clarity TP_WAVELET_CLARI;Sharp-mask and Clarity -TP_WAVELET_COLORT;Opacity Red-Green +TP_WAVELET_COLORT;Opacity red-green TP_WAVELET_COMPCONT;Contrast TP_WAVELET_COMPGAMMA;Compression gamma TP_WAVELET_COMPGAMMA_TOOLTIP;Adjusting the gamma of the residual image allows you to equilibrate the data and histogram. @@ -3293,16 +3293,16 @@ TP_WAVELET_CONTRA;Contrast TP_WAVELET_CONTRASTEDIT;Finer - Coarser levels TP_WAVELET_CONTRAST_MINUS;Contrast - TP_WAVELET_CONTRAST_PLUS;Contrast + -TP_WAVELET_CONTRA_TOOLTIP;Changes contrast of the residual image. +TP_WAVELET_CONTRA_TOOLTIP;Changes the residual image contrast. TP_WAVELET_CTYPE;Chrominance control TP_WAVELET_CURVEEDITOR_BL_TOOLTIP;Disabled if zoom > about 300% TP_WAVELET_CURVEEDITOR_CC_TOOLTIP;Modifies local contrast as a function of the original local contrast (abscissa).\nLow abscissa values represent small local contrast (real values about 10..20).\n50% abscissa represents average local contrast (real value about 100..300).\n66% abscissa represents standard deviation of local contrast (real value about 300..800).\n100% abscissa represents maximum local contrast (real value about 3000..8000). TP_WAVELET_CURVEEDITOR_CH;Contrast levels=f(Hue) TP_WAVELET_CURVEEDITOR_CH_TOOLTIP;Modifies each level's contrast as a function of hue.\nTake care not to overwrite changes made with the Gamut sub-tool's hue controls.\nThe curve will only have an effect when wavelet contrast level sliders are non-zero. TP_WAVELET_CURVEEDITOR_CL;L -TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Applies a final contrast luminance curve at the end of the wavelet treatment. +TP_WAVELET_CURVEEDITOR_CL_TOOLTIP;Applies a final contrast-luminance curve at the end of the wavelet processing. TP_WAVELET_CURVEEDITOR_HH;HH -TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image's hue as a function of hue. +TP_WAVELET_CURVEEDITOR_HH_TOOLTIP;Modifies the residual image hue as a function of hue. TP_WAVELET_DALL;All directions TP_WAVELET_DAUB;Edge performance TP_WAVELET_DAUB2;D2 - low @@ -3311,34 +3311,34 @@ TP_WAVELET_DAUB6;D6 - standard plus TP_WAVELET_DAUB10;D10 - medium TP_WAVELET_DAUB14;D14 - high TP_WAVELET_DAUBLOCAL;Wavelet Edge performance -TP_WAVELET_DAUB_TOOLTIP;Changes Daubechies coefficients:\nD4 = Standard,\nD14 = Often best performance, 10% more time-intensive.\n\nAffects edge detection as well as the general quality of the firsts levels. However the quality is not strictly related to this coefficient and can vary with images and uses. +TP_WAVELET_DAUB_TOOLTIP;Changes Daubechies coefficients:\nD4 = Standard,\nD14 = Often best performance, 10% more time-intensive.\n\nAffects edge detection as well as the general quality of the first levels. However the quality is not strictly related to this coefficient and can vary depending on image and use. TP_WAVELET_DIRFRAME;Directional contrast TP_WAVELET_DONE;Vertical TP_WAVELET_DTHR;Diagonal TP_WAVELET_DTWO;Horizontal TP_WAVELET_EDCU;Curve -TP_WAVELET_EDEFFECT;Attenuation Response -TP_WAVELET_EDEFFECT_TOOLTIP;This slider controls how wide the range of contrast values are that receive the maximum effect from the tool.\nMaximum value (2.5) disabled the tool +TP_WAVELET_EDEFFECT;Attenuation response +TP_WAVELET_EDEFFECT_TOOLTIP;This slider selects the range of contrast values that will receive the full effect of any adjustment TP_WAVELET_EDGCONT;Local contrast -TP_WAVELET_EDGCONT_TOOLTIP;Adjusting the points to the left decreases contrast, and to the right increases it.\nBottom-left, top-left, top-right and bottom-right represent respectively local contrast for low values, mean, mean+stdev and maxima. +TP_WAVELET_EDGCONT_TOOLTIP;Adjusting the points to the left decreases contrast, and to the right increases it.\nBottom-left, top-left, top-right and bottom-right represent respectively local contrast for low values, mean, mean+std. dev. and maxima. TP_WAVELET_EDGE;Edge Sharpness TP_WAVELET_EDGEAMPLI;Base amplification TP_WAVELET_EDGEDETECT;Gradient sensitivity TP_WAVELET_EDGEDETECTTHR;Threshold low (noise) -TP_WAVELET_EDGEDETECTTHR2;Threshold high (detection) -TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This adjuster lets you target edge detection for example to avoid applying edge sharpness to fine details, such as noise in the sky. +TP_WAVELET_EDGEDETECTTHR2;Edge enhancement +TP_WAVELET_EDGEDETECTTHR_TOOLTIP;This slider sets a threshold below which finer details won't be considered as an edge TP_WAVELET_EDGEDETECT_TOOLTIP;Moving the slider to the right increases edge sensitivity. This affects local contrast, edge settings and noise. TP_WAVELET_EDGESENSI;Edge sensitivity TP_WAVELET_EDGREINF_TOOLTIP;Reinforce or reduce the action of the first level, do the opposite to the second level, and leave the rest unchanged. TP_WAVELET_EDGTHRESH;Detail TP_WAVELET_EDGTHRESH_TOOLTIP;Change the repartition between the first levels and the others. The higher the threshold the more the action is centered on the first levels. Be careful with negative values, they increase the action of high levels and can introduce artifacts. TP_WAVELET_EDRAD;Radius -TP_WAVELET_EDRAD_TOOLTIP;This radius adjustment is very different from those in other sharpening tools. Its value is compared to each level through a complex function. In this sense, a value of zero still has an effect. -TP_WAVELET_EDSL;Threshold Sliders +TP_WAVELET_EDRAD_TOOLTIP;This adjustment controls the local enhancement. A value of zero still has an effect +TP_WAVELET_EDSL;Threshold sliders TP_WAVELET_EDTYPE;Local contrast method TP_WAVELET_EDVAL;Strength TP_WAVELET_FINAL;Final Touchup -TP_WAVELET_FINCFRAME;Final Local Contrast +TP_WAVELET_FINCFRAME;Final local contrast TP_WAVELET_FINCOAR_TOOLTIP;The left (positive) part of the curve acts on the finer levels (increase).\nThe 2 points on the abscissa represent the respective action limits of finer and coarser levels 5 and 6 (default).\nThe right (negative) part of the curve acts on the coarser levels (increase).\nAvoid moving the left part of the curve with negative values. Avoid moving the right part of the curve with positives values TP_WAVELET_FINEST;Finest TP_WAVELET_HIGHLIGHT;Finer levels luminance range @@ -3346,7 +3346,7 @@ TP_WAVELET_HS1;Whole luminance range TP_WAVELET_HS2;Selective luminance range TP_WAVELET_HUESKIN;Skin hue TP_WAVELET_HUESKIN_TOOLTIP;The bottom points set the beginning of the transition zone, and the upper points the end of it, where the effect is at its maximum.\n\nIf you need to move the area significantly, or if there are artifacts, then the white balance is incorrect. -TP_WAVELET_HUESKY;Sky hue +TP_WAVELET_HUESKY;Hue range TP_WAVELET_HUESKY_TOOLTIP;The bottom points set the beginning of the transition zone, and the upper points the end of it, where the effect is at its maximum.\n\nIf you need to move the area significantly, or if there are artifacts, then the white balance is incorrect. TP_WAVELET_ITER;Delta balance levels TP_WAVELET_ITER_TOOLTIP;Left: increase low levels and reduce high levels,\nRight: reduce low levels and increase high levels. @@ -3354,18 +3354,18 @@ TP_WAVELET_LABEL;Wavelet Levels TP_WAVELET_LARGEST;Coarsest TP_WAVELET_LEVCH;Chroma TP_WAVELET_LEVDIR_ALL;All levels, in all directions -TP_WAVELET_LEVDIR_INF;Finer details levels, with selected level +TP_WAVELET_LEVDIR_INF;Finer detail levels, including selected level TP_WAVELET_LEVDIR_ONE;One level -TP_WAVELET_LEVDIR_SUP;Coarser details levels, without selected level +TP_WAVELET_LEVDIR_SUP;Coarser detail levels, excluding selected level TP_WAVELET_LEVELS;Wavelet levels -TP_WAVELET_LEVELS_TOOLTIP;Choose the number of detail levels the image is to be decomposed into. More levels require more RAM and require a longer processing time. +TP_WAVELET_LEVELS_TOOLTIP;Choose the number of wavelet decomposition levels for the image.\nMore levels require more RAM and require a longer processing time. TP_WAVELET_LEVF;Contrast TP_WAVELET_LEVLABEL;Preview maximum possible levels = %1 TP_WAVELET_LEVONE;Level 2 TP_WAVELET_LEVTHRE;Level 4 TP_WAVELET_LEVTWO;Level 3 TP_WAVELET_LEVZERO;Level 1 -TP_WAVELET_LINKEDG;Link with Edge Sharpness' Strength +TP_WAVELET_LINKEDG;Link to Edge Sharpness Strength TP_WAVELET_LIPST;Enhanced algoritm TP_WAVELET_LOWLIGHT;Coarser levels luminance range TP_WAVELET_LOWTHR_TOOLTIP;Prevents amplification of fine textures and noise @@ -3373,7 +3373,7 @@ TP_WAVELET_MEDGREINF;First level TP_WAVELET_MEDI;Reduce artifacts in blue sky TP_WAVELET_MEDILEV;Edge detection TP_WAVELET_MEDILEV_TOOLTIP;When you enable Edge Detection, it is recommanded:\n- to disabled low contrast levels to avoid artifacts,\n- to use high values of gradient sensitivity.\n\nYou can modulate the strength with 'refine' from Denoise and Refine. -TP_WAVELET_MERGEC;Merge Chroma +TP_WAVELET_MERGEC;Merge chroma TP_WAVELET_MERGEL;Merge Luma TP_WAVELET_NEUTRAL;Neutral TP_WAVELET_NOIS;Denoise @@ -3384,24 +3384,24 @@ TP_WAVELET_NPLOW;Low TP_WAVELET_NPNONE;None TP_WAVELET_NPTYPE;Neighboring pixels TP_WAVELET_NPTYPE_TOOLTIP;This algorithm uses the proximity of a pixel and eight of its neighbors. If less difference, edges are reinforced. -TP_WAVELET_OFFSET_TOOLTIP;Offset modifies the balance between shadows and highlights.\nHigh values here will amplify the contrast change of the highlights, whereas low values will amplify the contrast change of the shadows.\nAlong with a low Attenuation Response value you will able to select the contrasts that will be enhanced. +TP_WAVELET_OFFSET_TOOLTIP;Offset modifies the balance between low contrast and high contrast details.\nHigh values will amplify contrast changes to the higher contrast details, whereas low values will amplify contrast changes to low contrast details.\nBy using a low Attenuation response value you can select which contrast values will be enhanced. TP_WAVELET_OLDSH;Algorithm using negatives values -TP_WAVELET_OPACITY;Opacity Blue-Yellow +TP_WAVELET_OPACITY;Opacity blue-yellow TP_WAVELET_OPACITYW;Contrast balance d/v-h curve TP_WAVELET_OPACITYWL;Local contrast TP_WAVELET_OPACITYWL_TOOLTIP;Modify the final local contrast at the end of the wavelet treatment.\n\nThe left side represents the smallest local contrast, progressing to the largest local contrast on the right. TP_WAVELET_PASTEL;Pastel chroma TP_WAVELET_PROC;Process TP_WAVELET_PROTAB;Protection -TP_WAVELET_RADIUS;Radius Shadows - Highlight +TP_WAVELET_RADIUS;Radius shadows - highlight TP_WAVELET_RANGEAB;Range a and b % TP_WAVELET_RE1;Reinforced TP_WAVELET_RE2;Unchanged TP_WAVELET_RE3;Reduced -TP_WAVELET_RESBLUR;Blur Luminance -TP_WAVELET_RESBLURC;Blur Chroma +TP_WAVELET_RESBLUR;Blur luminance +TP_WAVELET_RESBLURC;Blur chroma TP_WAVELET_RESBLUR_TOOLTIP;Disabled if zoom > about 500% -TP_WAVELET_RESCHRO;Intensity +TP_WAVELET_RESCHRO;Strength TP_WAVELET_RESCON;Shadows TP_WAVELET_RESCONH;Highlights TP_WAVELET_RESID;Residual Image @@ -3410,14 +3410,14 @@ TP_WAVELET_SETTINGS;Wavelet Settings TP_WAVELET_SHA;Sharp mask TP_WAVELET_SHFRAME;Shadows/Highlights TP_WAVELET_SHOWMASK;Show wavelet 'mask' -TP_WAVELET_SIGMA;Attenuation Response -TP_WAVELET_SIGMAFIN;Attenuation Response +TP_WAVELET_SIGMA;Attenuation response +TP_WAVELET_SIGMAFIN;Attenuation response TP_WAVELET_SIGMA_TOOLTIP;The effect of the contrast sliders is stronger in medium contrast details, and weaker in high and low contrast details.\n With this slider you can control how quickly the effect dampens towards the extreme contrasts.\n The higher the slider is set, the wider the range of contrasts which will get a strong change, and the higher the risk to generate artifacts.\n .The lower it is, the more the effect will be pinpointed towards a narrow range of contrast values TP_WAVELET_SKIN;Skin targetting/protection TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 skin-tones are protected while all other tones are affected. -TP_WAVELET_SKY;Sky targetting/protection -TP_WAVELET_SKY_TOOLTIP;At -100 sky-tones are targetted.\nAt 0 all tones are treated equally.\nAt +100 sky-tones are protected while all other tones are affected. -TP_WAVELET_SOFTRAD;Soft Radius +TP_WAVELET_SKY;Hue targetting/protection +TP_WAVELET_SKY_TOOLTIP;Allows you to target or protect a range of hues.\nAt -100 selected hues are targetted.\nAt 0 all hues are treated equally.\nAt +100 selected hues are protected while all other hues are targetted. +TP_WAVELET_SOFTRAD;Soft radius TP_WAVELET_STREN;Strength TP_WAVELET_STRENGTH;Strength TP_WAVELET_SUPE;Extra @@ -3426,7 +3426,7 @@ TP_WAVELET_THRESHOLD;Finer levels TP_WAVELET_THRESHOLD2;Coarser levels TP_WAVELET_THRESHOLD2_TOOLTIP;Only levels from the chosen value to the selected number of ‘wavelet levels’ will be affected by the Shadow luminance range. TP_WAVELET_THRESHOLD_TOOLTIP;Only levels below and including the chosen value will be affected by the Highlight luminance range. -TP_WAVELET_THRESWAV;Balance Threshold +TP_WAVELET_THRESWAV;Balance threshold TP_WAVELET_THRH;Highlights threshold TP_WAVELET_TILESBIG;Tiles TP_WAVELET_TILESFULL;Full image @@ -3439,11 +3439,11 @@ TP_WAVELET_TMSTRENGTH;Compression strength TP_WAVELET_TMSTRENGTH_TOOLTIP;Control the strength of tone mapping or contrast compression of the residual image. TP_WAVELET_TMTYPE;Compression method TP_WAVELET_TON;Toning -TP_WAVELET_TONFRAME;Excluded Colors +TP_WAVELET_TONFRAME;Excluded colors TP_WAVELET_USH;None TP_WAVELET_USHARP;Clarity method TP_WAVELET_USHARP_TOOLTIP;Origin : the source file is the file before Wavelet.\nWavelet : the source file is the file including wavelet threatment -TP_WAVELET_USH_TOOLTIP;If you select Sharp-mask, wavelet settings will be automatically positioned :\nBackground=black, Process=below, level=3...you can change level between 1 and 4.\n\nIf you select Clarity, wavelet settings will be automatically positioned :\nBackground=residual, Process=above, level=7..you can change level between 5 and 10 and wavelet levels. +TP_WAVELET_USH_TOOLTIP;If you select Sharp-mask, you can choose any level (in Settings) from 1 to 4 for processing.\nIf you select Clarity, you can choose any level (in Settings) between 5 and Extra. TP_WAVELET_WAVLOWTHR;Low contrast threshold TP_WAVELET_WAVOFFSET;Offset TP_WBALANCE_AUTO;Auto From 2c3881f3a68821e98d70415a343f27eac412233a Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 5 Aug 2020 10:21:14 +0200 Subject: [PATCH 32/33] Retinex - Choice complexity Standard - Advanced (#5871) * Enabled standard advanced for Retinex * Added forgotten reset button --- rtdata/languages/default | 1 + rtengine/procparams.cc | 4 ++ rtengine/procparams.h | 1 + rtgui/paramsedited.cc | 6 ++ rtgui/paramsedited.h | 1 + rtgui/retinex.cc | 126 +++++++++++++++++++++++++++++++++++++-- rtgui/retinex.h | 8 +++ rtgui/wavelet.cc | 2 +- 8 files changed, 143 insertions(+), 6 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index f00d9411e..9fa208280 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1216,6 +1216,7 @@ HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - region show mask HISTORY_MSG_COLORTONING_LABREGION_SLOPE;CT - region slope HISTORY_MSG_COMPLEX;Wavelet complexity +HISTORY_MSG_COMPLEXRETI;Retinex complexity HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_LUMINANCE;Dehaze - Luminance only diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index a12ab4ba4..3d1f3e071 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -459,6 +459,7 @@ RetinexParams::RetinexParams() : shadows(0), stonalwidth(80), radius(40), + complexmethod("normal"), retinexMethod("high"), retinexcolorspace("Lab"), gammaretinex("none"), @@ -496,6 +497,7 @@ bool RetinexParams::operator ==(const RetinexParams& other) const && shadows == other.shadows && stonalwidth == other.stonalwidth && radius == other.radius + && complexmethod == other.complexmethod && retinexMethod == other.retinexMethod && retinexcolorspace == other.retinexcolorspace && gammaretinex == other.gammaretinex @@ -5027,6 +5029,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->retinex.limd, "Retinex", "Limd", retinex.limd, keyFile); saveToKeyfile(!pedited || pedited->retinex.highl, "Retinex", "highl", retinex.highl, keyFile); saveToKeyfile(!pedited || pedited->retinex.skal, "Retinex", "skal", retinex.skal, keyFile); + saveToKeyfile(!pedited || pedited->retinex.complexmethod, "Retinex", "complexMethod", retinex.complexmethod, keyFile); saveToKeyfile(!pedited || pedited->retinex.retinexMethod, "Retinex", "RetinexMethod", retinex.retinexMethod, keyFile); saveToKeyfile(!pedited || pedited->retinex.mapMethod, "Retinex", "mapMethod", retinex.mapMethod, keyFile); saveToKeyfile(!pedited || pedited->retinex.viewMethod, "Retinex", "viewMethod", retinex.viewMethod, keyFile); @@ -6497,6 +6500,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Retinex")) { assignFromKeyfile(keyFile, "Retinex", "Median", pedited, retinex.medianmap, pedited->retinex.medianmap); + assignFromKeyfile(keyFile, "Retinex", "complexMethod", pedited, retinex.complexmethod, pedited->retinex.complexmethod); assignFromKeyfile(keyFile, "Retinex", "RetinexMethod", pedited, retinex.retinexMethod, pedited->retinex.retinexMethod); assignFromKeyfile(keyFile, "Retinex", "mapMethod", pedited, retinex.mapMethod, pedited->retinex.mapMethod); assignFromKeyfile(keyFile, "Retinex", "viewMethod", pedited, retinex.viewMethod, pedited->retinex.viewMethod); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 048fe1ee5..0af03eaee 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -336,6 +336,7 @@ struct RetinexParams { int stonalwidth; int radius; + Glib::ustring complexmethod; Glib::ustring retinexMethod; Glib::ustring retinexcolorspace; Glib::ustring gammaretinex; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 070e31316..3cd93064e 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -60,6 +60,7 @@ void ParamsEdited::set(bool v) retinex.mapcurve = v; retinex.cdHcurve = v; retinex.lhcurve = v; + retinex.complexmethod = v; retinex.retinexMethod = v; retinex.mapMethod = v; retinex.viewMethod = v; @@ -711,6 +712,7 @@ void ParamsEdited::initFrom(const std::vector& retinex.lhcurve = retinex.lhcurve && p.retinex.lhcurve == other.retinex.lhcurve; retinex.transmissionCurve = retinex.transmissionCurve && p.retinex.transmissionCurve == other.retinex.transmissionCurve; retinex.gaintransmissionCurve = retinex.gaintransmissionCurve && p.retinex.gaintransmissionCurve == other.retinex.gaintransmissionCurve; + retinex.complexmethod = retinex.complexmethod && p.retinex.complexmethod == other.retinex.complexmethod; retinex.retinexMethod = retinex.retinexMethod && p.retinex.retinexMethod == other.retinex.retinexMethod; retinex.mapMethod = retinex.mapMethod && p.retinex.mapMethod == other.retinex.mapMethod; retinex.viewMethod = retinex.viewMethod && p.retinex.viewMethod == other.retinex.viewMethod; @@ -1917,6 +1919,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.retinex.gaintransmissionCurve = mods.retinex.gaintransmissionCurve; } + if (retinex.complexmethod) { + toEdit.retinex.complexmethod = mods.retinex.complexmethod; + } + if (retinex.retinexMethod) { toEdit.retinex.retinexMethod = mods.retinex.retinexMethod; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 57b6458b9..f8230a577 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -73,6 +73,7 @@ struct RetinexParamsEdited { bool slope; bool neigh; bool offs; + bool complexmethod; bool retinexMethod; bool mapMethod; bool viewMethod; diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index 2fdd8f319..feab8e6a5 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -9,6 +9,7 @@ #include "rtimage.h" #include "options.h" #include "../rtengine/color.h" +#include "eventmapper.h" using namespace rtengine; using namespace rtengine::procparams; @@ -25,13 +26,26 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL") nextsigma = 0.; nextminT = 0.; nextmaxT = 0.; + auto m = ProcEventMapper::getInstance(); + EvReticomplex = m->newEvent(DEMOSAIC, "HISTORY_MSG_COMPLEXRETI"); + const RetinexParams default_params; // MAIN Expander ================================================================== + complexmethod = Gtk::manage (new MyComboBoxText ()); + complexmethod->append(M("TP_WAVELET_COMPNORMAL")); + complexmethod->append(M("TP_WAVELET_COMPEXPERT")); + complexmethodconn = complexmethod->signal_changed().connect(sigc::mem_fun(*this, &Retinex::complexmethodChanged)); + complexmethod->set_tooltip_text(M("TP_WAVELET_COMPLEX_TOOLTIP")); + Gtk::HBox* const complexHBox = Gtk::manage(new Gtk::HBox()); + Gtk::Label* const complexLabel = Gtk::manage(new Gtk::Label(M("TP_WAVELET_COMPLEXLAB") + ":")); + complexHBox->pack_start(*complexLabel, Gtk::PACK_SHRINK, 4); + complexHBox->pack_start(*complexmethod); + pack_start(*complexHBox); Gtk::Grid *retinexGrid = Gtk::manage ( new Gtk::Grid()); @@ -116,7 +130,8 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL") // MAP (MASK) Frame --------------------------------------------------------------- - Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) ); + // Gtk::Frame *maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) ); + maskFrame = Gtk::manage (new Gtk::Frame (M ("TP_RETINEX_LABEL_MASK")) ); setExpandAlignProperties (maskFrame, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); Gtk::Grid *maskGrid = Gtk::manage ( new Gtk::Grid()); @@ -384,7 +399,6 @@ Retinex::Retinex () : FoldableToolPanel (this, "retinex", M ("TP_RETINEX_LABEL") Gtk::Grid *tranGrid = Gtk::manage (new Gtk::Grid()); setExpandAlignProperties (tranGrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START); - const RetinexParams default_params; // Transmission map curve transmissionCurveEditorG = new CurveEditorGroup (options.lastRetinexDir, M ("TP_RETINEX_TRANSMISSION")); @@ -628,12 +642,14 @@ void Retinex::neutral_pressed () limd->resetValue (false); highl->resetValue (false); gam->resetValue (false); + skal->resetValue (false); slope->resetValue (false); highlights->resetValue (false); h_tonalwidth->resetValue (false); shadows->resetValue (false); s_tonalwidth->resetValue (false); radius->resetValue (false); + medianmap->set_active (false); mapMethod->set_active (0); viewMethod->set_active (0); retinexMethod->set_active (2); @@ -742,7 +758,53 @@ void Retinex::updateTrans () } } +void Retinex::convertParamToNormal() +{ + const RetinexParams def_params; + disableListener(); + iter->setValue(def_params.iter); + viewMethod->set_active(0); + mapMethod->set_active(0); + cdshape->reset(); + cdshapeH->reset(); + lhshape->reset(); + transmissionShape->reset(); + medianmap->set_active(def_params.medianmap); + enableListener(); +} +void Retinex::updateGUIToMode(int mode) +{ + + if(mode ==0) { + iterFrame->hide(); + maskFrame->hide(); + equalFrame->hide(); + viewMethod->hide(); + mapMethod->hide(); + transmissionCurveEditorG->hide(); + medianmap->hide(); + } else { + iterFrame->show(); + maskFrame->show(); + equalFrame->show(); + viewMethod->show(); + transmissionCurveEditorG->show(); + medianmap->show(); + mapMethod->show(); + if (iter->getIntValue() > 1) { + grad->set_sensitive (true); + scal->set_sensitive (true); + grads->set_sensitive (true); + } else { + grad->set_sensitive (false); + scal->set_sensitive (false); + grads->set_sensitive (false); + } + + } + +} void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) { @@ -752,6 +814,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) gammaretinexConn.block (true); mapMethodConn.block (true); viewMethodConn.block (true); + complexmethodconn.block (true); if (pedited) { @@ -775,6 +838,9 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) shadows->setEditedState (pedited->retinex.shadows ? Edited : UnEdited); s_tonalwidth->setEditedState (pedited->retinex.stonalwidth ? Edited : UnEdited); + if (!pedited->retinex.complexmethod) { + complexmethod->set_active_text (M ("GENERAL_UNCHANGED")); + } if (!pedited->retinex.retinexMethod) { retinexMethod->set_active_text (M ("GENERAL_UNCHANGED")); @@ -844,6 +910,13 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) medianmapConn.block (false); lastmedianmap = pp->retinex.medianmap; + if (pp->retinex.complexmethod == "normal") { + complexmethod->set_active(0); + } else if (pp->retinex.complexmethod == "expert") { + complexmethod->set_active(1); + } + + if (pp->retinex.retinexMethod == "low") { retinexMethod->set_active (0); } else if (pp->retinex.retinexMethod == "uni") { @@ -906,6 +979,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) mapMethodChanged (); viewMethodChanged (); + medianmapConn.block (true); medianmapChanged (); medianmapConn.block (false); @@ -914,7 +988,7 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) cdshapeH->setCurve (pp->retinex.cdHcurve); lhshape->setCurve (pp->retinex.lhcurve); mapshape->setCurve (pp->retinex.mapcurve); - + retinexMethodConn.block (false); retinexColorSpaceConn.block (false); gammaretinexConn.block (false); @@ -923,8 +997,18 @@ void Retinex::read (const ProcParams* pp, const ParamsEdited* pedited) transmissionShape->setCurve (pp->retinex.transmissionCurve); gaintransmissionShape->setCurve (pp->retinex.gaintransmissionCurve); + complexmethodconn.block (false); enableListener (); + + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + // convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + } @@ -961,6 +1045,7 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) pp->retinex.stonalwidth = (int)s_tonalwidth->getValue (); if (pedited) { + pedited->retinex.complexmethod = complexmethod->get_active_text() != M ("GENERAL_UNCHANGED"); pedited->retinex.retinexMethod = retinexMethod->get_active_text() != M ("GENERAL_UNCHANGED"); pedited->retinex.retinexcolorspace = retinexcolorspace->get_active_text() != M ("GENERAL_UNCHANGED"); pedited->retinex.gammaretinex = gammaretinex->get_active_text() != M ("GENERAL_UNCHANGED"); @@ -998,6 +1083,12 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) } + if (complexmethod->get_active_row_number() == 0) { + pp->retinex.complexmethod = "normal"; + } else if (complexmethod->get_active_row_number() == 1) { + pp->retinex.complexmethod = "expert"; + } + if (retinexMethod->get_active_row_number() == 0) { pp->retinex.retinexMethod = "low"; } else if (retinexMethod->get_active_row_number() == 1) { @@ -1056,6 +1147,27 @@ void Retinex::write (ProcParams* pp, ParamsEdited* pedited) } +void Retinex::complexmethodChanged() +{ + + if (!batchMode) { + if (complexmethod->get_active_row_number() == 0) { + updateGUIToMode(0); + convertParamToNormal(); + + } else { + updateGUIToMode(1); + } + } + + if (listener) { + listener->panelChanged(EvReticomplex, complexmethod->get_active_text()); + } + +} + + + void Retinex::retinexMethodChanged() { @@ -1138,8 +1250,11 @@ void Retinex::viewMethodChanged() limd->show(); transmissionCurveEditorG->show(); medianmap->show(); - - iterFrame->show(); + if (complexmethod->get_active_row_number() == 0) { + iterFrame->hide(); + } else { + iterFrame->show(); + } /* iter->show(); scal->show(); @@ -1522,6 +1637,7 @@ void Retinex::setBatchMode (bool batchMode) h_tonalwidth->showEditedCB (); shadows->showEditedCB (); s_tonalwidth->showEditedCB (); + // complexmethod->append(M("GENERAL_UNCHANGED")); skal->showEditedCB (); curveEditorGD->setBatchMode (batchMode); diff --git a/rtgui/retinex.h b/rtgui/retinex.h index dea65daab..bf480c9cc 100644 --- a/rtgui/retinex.h +++ b/rtgui/retinex.h @@ -28,6 +28,7 @@ class Retinex final : { private: IdleRegister idle_register; + rtengine::ProcEvent EvReticomplex; protected: CurveEditorGroup* curveEditorGD; @@ -72,6 +73,9 @@ protected: MyComboBoxText* mapMethod; MyComboBoxText* viewMethod; Gtk::CheckButton* medianmap; + MyComboBoxText* complexmethod; + sigc::connection complexmethodconn; + double nextmin; double nextmax; double nextminiT; @@ -87,6 +91,7 @@ protected: Gtk::Frame *gainFrame; Gtk::Frame *tranFrame; Gtk::Frame *iterFrame; + Gtk::Frame *maskFrame; Gtk::Frame *equalFrame; DiagonalCurveEditor* cdshape; @@ -148,4 +153,7 @@ public: private: void foldAllButMe(GdkEventButton* event, MyExpander *expander); + void convertParamToNormal(); + void updateGUIToMode(int mode); + void complexmethodChanged(); }; diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc index 8bd074867..19d458dad 100644 --- a/rtgui/wavelet.cc +++ b/rtgui/wavelet.cc @@ -2920,8 +2920,8 @@ void Wavelet::convertParamToNormal() //final touchup BAmethod->set_active(0); - enableListener(); sigmafin->setValue(def_params.sigmafin); + enableListener(); // Update GUI based on converted widget parameters: } From d939ffafdc88ad6e4e29b41a225e1d02a1327506 Mon Sep 17 00:00:00 2001 From: Desmis Date: Wed, 5 Aug 2020 13:13:18 +0200 Subject: [PATCH 33/33] Change label strength refine --- rtdata/languages/default | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 97d5203da..db2bb7cc8 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -3419,7 +3419,7 @@ TP_WAVELET_SKIN_TOOLTIP;At -100 skin-tones are targetted.\nAt 0 all tones are tr TP_WAVELET_SKY;Hue targetting/protection TP_WAVELET_SKY_TOOLTIP;Allows you to target or protect a range of hues.\nAt -100 selected hues are targetted.\nAt 0 all hues are treated equally.\nAt +100 selected hues are protected while all other hues are targetted. TP_WAVELET_SOFTRAD;Soft radius -TP_WAVELET_STREN;Strength +TP_WAVELET_STREN;Refine TP_WAVELET_STRENGTH;Strength TP_WAVELET_SUPE;Extra TP_WAVELET_THR;Shadows threshold