diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc index 6d8856958..8b506432d 100644 --- a/rtengine/histmatching.cc +++ b/rtengine/histmatching.cc @@ -25,6 +25,7 @@ #include "rt_math.h" #include "iccstore.h" #include "../rtgui/mydiagonalcurve.h" +#include "improcfun.h" namespace rtengine { @@ -54,7 +55,7 @@ std::vector getCdf(const IImage8 &img) int findMatch(int val, const std::vector &cdf, int j) { if (cdf[j] <= val) { - for (; j < cdf.size(); ++j) { + for (; j < int(cdf.size()); ++j) { if (cdf[j] == val) { return j; } else if (cdf[j] > val) { @@ -123,27 +124,39 @@ void mappingToCurve(const std::vector &mapping, std::vector &curve) void RawImageSource::getAutoMatchedToneCurve(std::vector &outCurve) { const int rheight = 200; - RawMetaDataLocation rml; - eSensorType sensor_type; - int w, h; ProcParams neutral; + std::unique_ptr target; + { + int tr = TR_NONE; + int fw, fh; + getFullSize(fw, fh, tr); + int skip = fh / rheight; + PreviewProps pp(0, 0, fw, fh, skip); + ColorTemp currWB = getWB(); + std::unique_ptr image(new Imagefloat(int(fw / skip), int(fh / skip))); + neutral.raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::FAST); + neutral.raw.xtranssensor.method = procparams::RAWParams::XTransSensor::getMethodString(procparams::RAWParams::XTransSensor::Method::FAST); + getImage(currWB, tr, image.get(), pp, neutral.toneCurve, neutral.raw); + + // this could probably be made faster -- ideally we would need to just + // perform the transformation from camera space to the output space + // (taking gamma into account), but I couldn't find anything + // ready-made, so for now this will do. Remember the famous quote: + // "premature optimization is the root of all evil" :-) + convertColorSpace(image.get(), neutral.icm, currWB); + ImProcFunctions ipf(&neutral); + LabImage tmplab(image->getWidth(), image->getHeight()); + ipf.rgb2lab(*image, tmplab, neutral.icm.working); + image.reset(ipf.lab2rgbOut(&tmplab, 0, 0, tmplab.W, tmplab.H, neutral.icm)); + target.reset(image->to8()); + } std::unique_ptr source; { + RawMetaDataLocation rml; + eSensorType sensor_type; + int w, h; std::unique_ptr thumb(Thumbnail::loadQuickFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, true)); - source.reset(thumb->quickProcessImage(neutral, rheight, TI_Nearest)); - } - std::unique_ptr target; - if (true) { - neutral.icm.working = "RT_sRGB"; - // faster, but has problems likely due to color space transformations that I do not properly understand... - double scale; - std::unique_ptr thumb(Thumbnail::loadFromRaw(getFileName(), rml, sensor_type, w, h, 1, 0.0, false)); - target.reset(thumb->processImage(neutral, sensor_type, rheight, TI_Nearest, getMetaData(), scale, false)); - } else { - ProcessingJob *job = ProcessingJob::create(this, neutral, true); - int err = 0; - std::unique_ptr tmp(processImage(job, err, nullptr, false)); - target.reset(static_cast(tmp.get())->to8()); + source.reset(thumb->quickProcessImage(neutral, target->getHeight(), TI_Nearest)); } if (target->getWidth() != source->getWidth() || target->getHeight() != source->getHeight()) { Image8 *tmp = new Image8(source->getWidth(), source->getHeight()); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index c3f00300b..b4edab549 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -466,7 +466,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) params.toneCurve.black, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, params.toneCurve.hrenabled); } else if (params.toneCurve.histmatching) { imgsrc->getAutoMatchedToneCurve(params.toneCurve.curve); - + + params.toneCurve.histmatching = false; params.toneCurve.curveMode = ToneCurveParams::TcMode::FILMLIKE; params.toneCurve.curve2 = { 0 }; params.toneCurve.expcomp = 0.0; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 01d4922f5..7b636797e 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -751,7 +751,8 @@ private: ipf.getAutoExp (aehist, aehistcompr, params.toneCurve.clip, expcomp, bright, contr, black, hlcompr, hlcomprthresh); } else if (params.toneCurve.histmatching) { imgsrc->getAutoMatchedToneCurve(params.toneCurve.curve); - + + params.toneCurve.histmatching = false; params.toneCurve.curveMode = ToneCurveParams::TcMode::FILMLIKE; params.toneCurve.curve2 = { 0 }; params.toneCurve.expcomp = 0.0; diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index 7b07fbb58..0d753dcbf 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -31,6 +31,7 @@ ToneCurve::ToneCurve () : FoldableToolPanel(this, "tonecurve", M("TP_EXPOSURE_LA { auto m = ProcEventMapper::getInstance(); EvHistMatching = m->newEvent(AUTOEXP, "HISTORY_MSG_HISTMATCHING"); + EvHistMatchingBatch = m->newEvent(M_VOID, "HISTORY_MSG_HISTMATCHING"); CurveListener::setMulti(true); @@ -901,11 +902,15 @@ void ToneCurve::setHistmatching(bool enabled) void ToneCurve::histmatchingToggled() { if (listener) { - if (histmatching->get_active()) { - listener->panelChanged(EvHistMatching, M("GENERAL_ENABLED")); - waitForAutoExp(); + if (!batchMode) { + if (histmatching->get_active()) { + listener->panelChanged(EvHistMatching, M("GENERAL_ENABLED")); + waitForAutoExp(); + } else { + listener->panelChanged(EvHistMatching, M("GENERAL_DISABLED")); + } } else { - listener->panelChanged(EvHistMatching, M("GENERAL_DISABLED")); + listener->panelChanged(EvHistMatchingBatch, histmatching->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); } } } @@ -948,6 +953,7 @@ bool ToneCurve::histmatchingComputed() autolevels->set_inconsistent(false); } + histmatching->set_active(false); toneCurveMode->set_active(rtengine::toUnderlying(nextToneCurveMode)); shape->setCurve(nextToneCurve); shape2->setCurve({ DCT_Linear }); diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h index 5aae5f015..e85fefa39 100644 --- a/rtgui/tonecurve.h +++ b/rtgui/tonecurve.h @@ -68,6 +68,7 @@ protected: DiagonalCurveEditor* shape2; rtengine::ProcEvent EvHistMatching; + rtengine::ProcEvent EvHistMatchingBatch; // used temporarily in eventing double nextExpcomp;