diff --git a/rtdata/languages/default b/rtdata/languages/default index 3eacc3429..bf7402629 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1404,6 +1404,8 @@ 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_DEHABLACK;Dehaze Bayer Black +HISTORY_MSG_DEHABLACKX;Dehaze X-Trans Black HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_SATURATION;Dehaze - Saturation @@ -3782,6 +3784,7 @@ TP_RAWEXPOS_BLACK_3;Green 2 TP_RAWEXPOS_BLACK_BLUE;Blue TP_RAWEXPOS_BLACK_GREEN;Green TP_RAWEXPOS_BLACK_RED;Red +TP_RAWEXPOS_DEHA;Dehaze TP_RAWEXPOS_LINEAR;White-point correction TP_RAWEXPOS_RGB;Red, Green, Blue TP_RAWEXPOS_TWOGREEN;Link greens diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 892fe61b4..b2ae94961 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -91,7 +91,7 @@ public: ~ImageSource () override {} virtual int load (const Glib::ustring &fname) = 0; - virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) {}; + virtual void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, float &reddeha, float &greendeha, float &bluedeha, bool prepareDenoise = true) {}; virtual void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) {}; virtual void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) {}; virtual void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) {}; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 127c65248..3e06ca144 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -153,6 +153,7 @@ ImProcCoordinator::ImProcCoordinator() : imageListener(nullptr), aeListener(nullptr), acListener(nullptr), + ablListener(nullptr), abwListener(nullptr), awbListener(nullptr), flatFieldAutoClipListener(nullptr), @@ -383,11 +384,26 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) } // raw auto CA is bypassed if no high detail is needed, so we have to compute it when high detail is needed + float reddeha = 0.f;//initialize black red, blue, green for dehaze + float greendeha = 0.f; + float bluedeha = 0.f; + if ((todo & M_PREPROC) || (!highDetailPreprocessComputed && highDetailNeeded)) { imgsrc->setCurrentFrame(params->raw.bayersensor.imageNum); - - imgsrc->preprocess(rp, params->lensProf, params->coarse); - + imgsrc->preprocess(rp, params->lensProf, params->coarse, reddeha, greendeha, bluedeha, true); + if(imgsrc->getSensorType() == ST_BAYER) {//Bayer + if (ablListener) { + if(rp.bayersensor.Dehablack) { + ablListener->autoBlackChanged(reddeha, greendeha, bluedeha); + } + } + } else if(imgsrc->getSensorType() == ST_FUJI_XTRANS) {//X trans + if (ablxListener) { + if(rp.xtranssensor.Dehablackx) { + ablxListener->autoBlackxChanged(reddeha, greendeha, bluedeha); + } + } + } if (flatFieldAutoClipListener && rp.ff_AutoClipControl) { flatFieldAutoClipListener->flatFieldAutoClipValueChanged(imgsrc->getFlatFieldAutoClipValue()); } @@ -3038,7 +3054,10 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a ppar.toneCurve.hrenabled = false; ppar.icm.inputProfile = "(none)"; Imagefloat* im = new Imagefloat(fW, fH); - imgsrc->preprocess(ppar.raw, ppar.lensProf, ppar.coarse); + float reddeha = 0.f; + float greendeha = 0.f; + float bluedeha = 0.f; + imgsrc->preprocess(ppar.raw, ppar.lensProf, ppar.coarse,reddeha, greendeha, bluedeha, true); double dummy = 0.0; imgsrc->demosaic(ppar.raw, false, dummy); ColorTemp currWB = ColorTemp(validParams->wb.temperature, validParams->wb.green, validParams->wb.equal, validParams->wb.method, validParams->wb.observer); diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index f276bc30a..f8d4424f1 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -182,6 +182,8 @@ protected: PreviewImageListener* imageListener; AutoExpListener* aeListener; AutoCamListener* acListener; + AutoBlackListener* ablListener; + AutoBlackxListener* ablxListener; AutoBWListener* abwListener; AutoWBListener* awbListener; FlatFieldAutoClipListener *flatFieldAutoClipListener; @@ -518,6 +520,15 @@ public: { acListener = acl; } + void setAutoBlackListener (AutoBlackListener* abl) override + { + ablListener = abl; + } + void setAutoBlackxListener (AutoBlackxListener* ablx) override + { + ablxListener = ablx; + } + void setAutoBWListener (AutoBWListener* abw) override { abwListener = abw; diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index b7e6ad9f8..327c83899 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -116,7 +116,10 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext params.raw.deadPixelFilter = false; params.raw.ca_autocorrect = false; params.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST); - rawImage.preprocess(params.raw, params.lensProf, params.coarse); + float reddeha = 0.f; + float greendeha = 0.f; + float bluedeha = 0.f; + rawImage.preprocess(params.raw, params.lensProf, params.coarse, reddeha, greendeha, bluedeha, true); double contrastThresholdDummy = 0.0; rawImage.demosaic(params.raw, false, contrastThresholdDummy); Imagefloat image(fw, fh); diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 8041ab298..69b17223e 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -5810,6 +5810,7 @@ RAWParams::BayerSensor::BayerSensor() : black2(0.0), black3(0.0), twogreen(true), + Dehablack(false), linenoise(0), linenoiseDirection(LineNoiseDirection::BOTH), greenthresh(0), @@ -5849,6 +5850,7 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const && black2 == other.black2 && black3 == other.black3 && twogreen == other.twogreen + && Dehablack == other.Dehablack && linenoise == other.linenoise && linenoiseDirection == other.linenoiseDirection && greenthresh == other.greenthresh @@ -5952,7 +5954,9 @@ RAWParams::XTransSensor::XTransSensor() : ccSteps(0), blackred(0.0), blackgreen(0.0), - blackblue(0.0) + blackblue(0.0), + Dehablackx(false) + { } @@ -5966,7 +5970,8 @@ bool RAWParams::XTransSensor::operator ==(const XTransSensor& other) const && ccSteps == other.ccSteps && blackred == other.blackred && blackgreen == other.blackgreen - && blackblue == other.blackblue; + && blackblue == other.blackblue + && Dehablackx == other.Dehablackx; } bool RAWParams::XTransSensor::operator !=(const XTransSensor& other) const @@ -8080,6 +8085,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.exBlack2, "RAW Bayer", "PreBlack2", raw.bayersensor.black2, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.exBlack3, "RAW Bayer", "PreBlack3", raw.bayersensor.black3, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.exTwoGreen, "RAW Bayer", "PreTwoGreen", raw.bayersensor.twogreen, keyFile); + saveToKeyfile(!pedited || pedited->raw.bayersensor.Dehablack, "RAW Bayer", "Dehablack", raw.bayersensor.Dehablack, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.linenoise, "RAW Bayer", "LineDenoise", raw.bayersensor.linenoise, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.linenoise, "RAW Bayer", "LineDenoiseDirection", toUnderlying(raw.bayersensor.linenoiseDirection), keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.greenEq, "RAW Bayer", "GreenEqThreshold", raw.bayersensor.greenthresh, keyFile); @@ -8112,6 +8118,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.xtranssensor.exBlackRed, "RAW X-Trans", "PreBlackRed", raw.xtranssensor.blackred, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.exBlackGreen, "RAW X-Trans", "PreBlackGreen", raw.xtranssensor.blackgreen, keyFile); saveToKeyfile(!pedited || pedited->raw.xtranssensor.exBlackBlue, "RAW X-Trans", "PreBlackBlue", raw.xtranssensor.blackblue, keyFile); + saveToKeyfile(!pedited || pedited->raw.xtranssensor.Dehablackx, "RAW X-Trans", "Dehablackx", raw.xtranssensor.Dehablackx, keyFile); // Raw exposition saveToKeyfile(!pedited || pedited->raw.exPos, "RAW", "PreExposure", raw.expos, keyFile); @@ -11099,6 +11106,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW Bayer", "PreBlack2", raw.bayersensor.black2, pedited->raw.bayersensor.exBlack2); assignFromKeyfile(keyFile, "RAW Bayer", "PreBlack3", raw.bayersensor.black3, pedited->raw.bayersensor.exBlack3); assignFromKeyfile(keyFile, "RAW Bayer", "PreTwoGreen", raw.bayersensor.twogreen, pedited->raw.bayersensor.exTwoGreen); + assignFromKeyfile(keyFile, "RAW Bayer", "Dehablack", raw.bayersensor.Dehablack, pedited->raw.bayersensor.Dehablack); assignFromKeyfile(keyFile, "RAW Bayer", "LineDenoise", raw.bayersensor.linenoise, pedited->raw.bayersensor.linenoise); if (keyFile.has_key("RAW Bayer", "LineDenoiseDirection")) { @@ -11185,6 +11193,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackRed", raw.xtranssensor.blackred, pedited->raw.xtranssensor.exBlackRed); assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackGreen", raw.xtranssensor.blackgreen, pedited->raw.xtranssensor.exBlackGreen); assignFromKeyfile(keyFile, "RAW X-Trans", "PreBlackBlue", raw.xtranssensor.blackblue, pedited->raw.xtranssensor.exBlackBlue); + assignFromKeyfile(keyFile, "RAW X-Trans", "Dehablackx", raw.xtranssensor.Dehablackx, pedited->raw.xtranssensor.Dehablackx); } if (keyFile.has_group("Film Negative")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index e6945cfbd..9ac023d17 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -2517,6 +2517,7 @@ struct RAWParams { double black2; double black3; bool twogreen; + bool Dehablack; int linenoise; enum class LineNoiseDirection { HORIZONTAL = 1, @@ -2584,6 +2585,7 @@ struct RAWParams { double blackred; double blackgreen; double blackblue; + bool Dehablackx; XTransSensor(); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index ab2ee58e6..6f4db62a9 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1432,7 +1432,7 @@ int RawImageSource::load(const Glib::ustring &fname, bool firstFrameOnly) //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise) +void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, float &reddeha, float &greendeha, float &bluedeha, bool prepareDenoise) { // BENCHFUN MyTime t1, t2; @@ -1510,7 +1510,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens for (unsigned int i = 0; i < 4; ++i) { if (i == currFrame) { - copyOriginalPixels(raw, ri, rid, rif, rawData); + copyOriginalPixels(raw, ri, rid, rif, rawData, reddeha, greendeha, bluedeha); rawDataFrames[i] = &rawData; } else { if (!rawDataBuffer[bufferNumber]) { @@ -1519,7 +1519,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens rawDataFrames[i] = rawDataBuffer[bufferNumber]; ++bufferNumber; - copyOriginalPixels(raw, riFrames[i], rid, rif, *rawDataFrames[i]); + copyOriginalPixels(raw, riFrames[i], rid, rif, *rawDataFrames[i], reddeha, greendeha, bluedeha); } } } else if (numFrames == 2 && currFrame == 2) { // average the frames @@ -1528,8 +1528,8 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens } rawDataFrames[1] = rawDataBuffer[0]; - copyOriginalPixels(raw, riFrames[1], rid, rif, *rawDataFrames[1]); - copyOriginalPixels(raw, ri, rid, rif, rawData); + copyOriginalPixels(raw, riFrames[1], rid, rif, *rawDataFrames[1], reddeha, greendeha, bluedeha); + copyOriginalPixels(raw, ri, rid, rif, rawData, reddeha, greendeha, bluedeha); for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { @@ -1537,7 +1537,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens } } } else { - copyOriginalPixels(raw, ri, rid, rif, rawData); + copyOriginalPixels(raw, ri, rid, rif, rawData, reddeha, greendeha, bluedeha); } //FLATFIELD end @@ -2634,8 +2634,9 @@ void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp) /* Copy original pixel data and * subtract dark frame (if present) from current image and apply flat field correction (if present) */ -void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData) +void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData, float &reddeha, float &greendeha, float &bluedeha) { + minVals[0] = minVals[1] = minVals[2] = std::numeric_limits::max(); const auto tmpfilters = ri->get_filters(); ri->set_filters(ri->prefilters); // we need 4 blacks for bayer processing float black[4]; @@ -2681,8 +2682,19 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, con } } } - - +/* + Copyright (c) Ingo Weyrich 2020 (heckflosse67@gmx.de) +*/ + + if (ri->getSensorType() == ST_BAYER) { + getMinValsBayer(ri->zeroIsBad()); + } else { + getMinValsXtrans(); + } + // + reddeha = minVals[0]; + greendeha = minVals[1]; + bluedeha = minVals[2]; if (riFlatFile && W == riFlatFile->get_width() && H == riFlatFile->get_height()) { processFlatField(raw, riFlatFile, rawData, black); } // flatfield @@ -2749,19 +2761,33 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R if (getSensorType() == ST_BAYER || getSensorType() == ST_FOVEON) { - black_lev[0] = raw.bayersensor.black1; //R - black_lev[1] = raw.bayersensor.black0; //G1 - black_lev[2] = raw.bayersensor.black2; //B - black_lev[3] = raw.bayersensor.black3; //G2 + if (raw.bayersensor.Dehablack) { + black_lev[0] = minVals[0]; + black_lev[1] = minVals[1]; + black_lev[2] = minVals[2]; + black_lev[3] = minVals[1]; + } else { + black_lev[0] = raw.bayersensor.black1; //R + black_lev[1] = raw.bayersensor.black0; //G1 + black_lev[2] = raw.bayersensor.black2; //B + black_lev[3] = raw.bayersensor.black3; //G2 + } isMono = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::MONO) == raw.bayersensor.method; } else if (getSensorType() == ST_FUJI_XTRANS) { - black_lev[0] = raw.xtranssensor.blackred; //R - black_lev[1] = raw.xtranssensor.blackgreen; //G1 - black_lev[2] = raw.xtranssensor.blackblue; //B - black_lev[3] = raw.xtranssensor.blackgreen; //G2 (set, only used with a Bayer filter) - + if (raw.xtranssensor.Dehablackx) { + black_lev[0] = minVals[0]; + black_lev[1] = minVals[1]; + black_lev[2] = minVals[2]; + black_lev[3] = minVals[1]; + } else { + black_lev[0] = raw.xtranssensor.blackred; //R + black_lev[1] = raw.xtranssensor.blackgreen; //G1 + black_lev[2] = raw.xtranssensor.blackblue; //B + black_lev[3] = raw.xtranssensor.blackgreen; //G2 (set, only used with a Bayer filter) + } + isMono = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO) == raw.xtranssensor.method; } @@ -8352,6 +8378,54 @@ void RawImageSource::getRawValues(int x, int y, int rotate, int &R, int &G, int B = 0; } } +/* + Copyright (c) Ingo Weyrich 2020 (heckflosse67@gmx.de) +*/ +void RawImageSource::getMinValsXtrans() { +#ifdef _OPENMP + #pragma omp parallel for reduction (min:minVals) +#endif + for (int row = 0; row < H; ++row) { + const int c0 = ri->XTRANSFC(row, 0); + const int c1 = ri->XTRANSFC(row, 1); + const int c2 = ri->XTRANSFC(row, 2); + const int c3 = ri->XTRANSFC(row, 3); + const int c4 = ri->XTRANSFC(row, 4); + const int c5 = ri->XTRANSFC(row, 5); + const float cb0 = c_black[c0]; + const float cb1 = c_black[c1]; + const float cb2 = c_black[c2]; + const float cb3 = c_black[c3]; + const float cb4 = c_black[c4]; + const float cb5 = c_black[c5]; + float m0 = minVals[c0]; + float m1 = minVals[c1]; + float m2 = minVals[c2]; + float m3 = minVals[c3]; + float m4 = minVals[c4]; + float m5 = minVals[c5]; + int col = 0; + for (; col < W - 5; col += 6) { + m0 = rtengine::min(m0, rawData[row][col] - cb0); + m1 = rtengine::min(m1, rawData[row][col + 1] - cb1); + m2 = rtengine::min(m2, rawData[row][col + 2] - cb2); + m3 = rtengine::min(m3, rawData[row][col + 3] - cb3); + m4 = rtengine::min(m4, rawData[row][col + 4] - cb4); + m5 = rtengine::min(m5, rawData[row][col + 5] - cb5); + } + for (; col < W; ++col) { + const int c = ri->XTRANSFC(row,col); + minVals[c] = rtengine::min(minVals[c], rawData[row][col] - c_black[c]); + } + minVals[c0] = rtengine::min(m0, minVals[c0]); + minVals[c1] = rtengine::min(m1, minVals[c1]); + minVals[c2] = rtengine::min(m2, minVals[c2]); + minVals[c3] = rtengine::min(m3, minVals[c3]); + minVals[c4] = rtengine::min(m4, minVals[c4]); + minVals[c5] = rtengine::min(m5, minVals[c5]); + + } +} bool RawImageSource::isGainMapSupported() const { @@ -8450,6 +8524,61 @@ void RawImageSource::applyDngGainMap(const float black[4], const std::vector 0.f)) { + m0 = rtengine::min(m0, rawData[row][col] - cb0); + } + if (LIKELY(rawData[row][col + 1] > 0.f)) { + m1 = rtengine::min(m1, rawData[row][col + 1] - cb1); + } + } + if (col < W && LIKELY(rawData[row][col] > 0.f)) { + m0 = rtengine::min(m0, rawData[row][col] - cb0); + } + minVals[c0] = m0; + minVals[c1] = m1; + } + } +} void RawImageSource::cleanup() { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 7296b830f..1fef1a5cf 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -107,6 +107,7 @@ protected: std::vector histMatchingCache; const std::unique_ptr histMatchingParams; + float minVals[3]; void processFalseColorCorrectionThread(Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to); void hlRecovery(const std::string &method, float* red, float* green, float* blue, int width, float* hlmax); @@ -124,7 +125,7 @@ public: int load(const Glib::ustring &fname) override { return load(fname, false); } int load(const Glib::ustring &fname, bool firstFrameOnly); - void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, bool prepareDenoise = true) override; + void preprocess (const procparams::RAWParams &raw, const procparams::LensProfParams &lensProf, const procparams::CoarseTransformParams& coarse, float &reddeha, float &greendeha, float &bluedeha, bool prepareDenoise = true) override; void demosaic (const procparams::RAWParams &raw, bool autoContrast, double &contrastThreshold, bool cache = false) override; void retinex (const procparams::ColorManagementParams& cmp, const procparams::RetinexParams &deh, const procparams::ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI) override; void retinexPrepareCurves (const procparams::RetinexParams &retinexParams, LUTf &cdcurve, LUTf &mapcurve, RetinextransmissionCurve &retinextransmissionCurve, RetinexgaintransmissionCurve &retinexgaintransmissionCurve, bool &retinexcontlutili, bool &mapcontlutili, bool &useHsl, LUTu & lhist16RETI, LUTu & histLRETI) override; @@ -139,7 +140,7 @@ public: } void processFlatField(const procparams::RAWParams &raw, RawImage *riFlatFile, array2D &rawData, const float black[4]); - void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData ); + void copyOriginalPixels(const procparams::RAWParams &raw, RawImage *ri, const RawImage *riDark, RawImage *riFlatFile, array2D &rawData, float &reddeha, float &greendeha, float &bluedeha); void scaleColors (int winx, int winy, int winw, int winh, const procparams::RAWParams &raw, array2D &rawData); // raw for cblack void WBauto(bool extra, double &tempref, double &greenref, array2D &redloc, array2D &greenloc, array2D &blueloc, int bfw, int bfh, double &avg_rm, double &avg_gm, double &avg_bm, double &tempitc, double &greenitc, float &temp0, float &delta, int &bia, int &dread, int &kcam, int &nocam, float &studgood, float &minchrom, int &kmin, float &minhist, float &maxhist, bool &twotimes, const procparams::WBParams & wbpar, int begx, int begy, int yEn, int xEn, int cx, int cy, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; void getAutoWBMultipliersitc(bool extra, double &tempref, double &greenref, double &tempitc, double &greenitc, float &temp0, float &delta, int &bia, int &dread, int &kcam, int &nocam, float &studgood, float &minchrom, int &kmin, float &minhist, float &maxhist, int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, double &rm, double &gm, double &bm, const procparams::WBParams & wbpar, const procparams::ColorManagementParams &cmp, const procparams::RAWParams &raw, const procparams::ToneCurveParams &hrp) override; @@ -308,6 +309,8 @@ protected: void vflip (Imagefloat* im); void getRawValues(int x, int y, int rotate, int &R, int &G, int &B) override; void captureSharpening(const procparams::CaptureSharpeningParams &sharpeningParams, bool showMask, double &conrastThreshold, double &radius) override; + void getMinValsXtrans(); + void getMinValsBayer(bool zeroIsBad); void applyDngGainMap(const float black[4], const std::vector &gainMaps); public: void wbMul2Camera(double &rm, double &gm, double &bm) override; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 569bcca25..cb4dc36c5 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -383,6 +383,23 @@ public : }; +class AutoBlackListener +{ +public : + virtual ~AutoBlackListener() = default; + virtual void autoBlackChanged(double reddeha, double greendeha, double bluedeha) = 0; + +}; + +class AutoBlackxListener +{ +public : + virtual ~AutoBlackxListener() = default; + virtual void autoBlackxChanged(double reddeha, double greendeha, double bluedeha) = 0; + +}; + + class AutoChromaListener { public : @@ -696,6 +713,8 @@ public: virtual void setHistogramListener (HistogramListener *l) = 0; virtual void setPreviewImageListener (PreviewImageListener* l) = 0; virtual void setAutoCamListener (AutoCamListener* l) = 0; + virtual void setAutoBlackListener (AutoBlackListener* l) = 0; + virtual void setAutoBlackxListener (AutoBlackxListener* l) = 0; virtual void setFlatFieldAutoClipListener (FlatFieldAutoClipListener* l) = 0; virtual void setFrameCountListener (FrameCountListener* l) = 0; virtual void setBayerAutoContrastListener (AutoContrastListener* l) = 0; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index bf5e48f59..b0543fc79 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -422,8 +422,10 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, eSensorType &sensorType, neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST); neutral.icm.inputProfile = "(camera)"; neutral.icm.workingProfile = settings->srgb; - - src.preprocess(neutral.raw, neutral.lensProf, neutral.coarse, false); + float reddeha = 0.f; + float greendeha = 0.f; + float bluedeha = 0.f; + src.preprocess(neutral.raw, neutral.lensProf, neutral.coarse, reddeha, greendeha, bluedeha, false); double thresholdDummy = 0.f; src.demosaic(neutral.raw, false, thresholdDummy); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 06194e437..f72e7b211 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -222,7 +222,10 @@ private: ImProcFunctions &ipf = * (ipf_p.get()); imgsrc->setCurrentFrame(params.raw.bayersensor.imageNum); - imgsrc->preprocess(params.raw, params.lensProf, params.coarse, params.dirpyrDenoise.enabled); + float reddeha = 0.f; + float greendeha = 0.f; + float bluedeha = 0.f; + imgsrc->preprocess(params.raw, params.lensProf, params.coarse, reddeha, greendeha, bluedeha, params.dirpyrDenoise.enabled); if (pl) { pl->setProgress(0.20); diff --git a/rtgui/bayerrawexposure.cc b/rtgui/bayerrawexposure.cc index 834384a91..7a21d3408 100644 --- a/rtgui/bayerrawexposure.cc +++ b/rtgui/bayerrawexposure.cc @@ -30,6 +30,10 @@ const Glib::ustring BayerRAWExposure::TOOL_NAME = "bayerrawexposure"; BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL"), options.prevdemo != PD_Sidecar) { + auto m = ProcEventMapper::getInstance(); + EvDehablack = m->newEvent(DARKFRAME, "HISTORY_MSG_DEHABLACK"); + EvDehablackVoid = m->newEvent(M_VOID, "HISTORY_MSG_DEHABLACK"); + PexBlack1 = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_1"), -2048, 2048, 1.0, 0)); //black level PexBlack1->setAdjusterListener (this); @@ -58,11 +62,16 @@ BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP PextwoGreen->set_active (true); PextwoGreen->setCheckBoxListener (this); + Dehablack = Gtk::manage(new CheckBox(M("TP_RAWEXPOS_DEHA"), multiImage));// Black dehaze + Dehablack->set_active (false); + Dehablack->setCheckBoxListener (this); + pack_start( *PexBlack1, Gtk::PACK_SHRINK, 0);//black R pack_start( *PexBlack0, Gtk::PACK_SHRINK, 0);//black G1 pack_start( *PexBlack3, Gtk::PACK_SHRINK, 0);//black G2 pack_start( *PexBlack2, Gtk::PACK_SHRINK, 0);//black B pack_start( *PextwoGreen, Gtk::PACK_SHRINK, 0);//black 2 green + pack_start( *Dehablack, Gtk::PACK_SHRINK, 0);//black Dehaze PexBlack0->setLogScale(100, 0); PexBlack1->setLogScale(100, 0); @@ -73,7 +82,6 @@ BayerRAWExposure::BayerRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited) { disableListener (); - if(pedited ) { PexBlack0->setEditedState( pedited->raw.bayersensor.exBlack0 ? Edited : UnEdited ); PexBlack1->setEditedState( pedited->raw.bayersensor.exBlack1 ? Edited : UnEdited ); @@ -82,6 +90,7 @@ void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const Pa } PextwoGreen->setValue (pp->raw.bayersensor.twogreen); + Dehablack->setValue (pp->raw.bayersensor.Dehablack); PexBlack0->setValue (pp->raw.bayersensor.black0);//black PexBlack1->setValue (pp->raw.bayersensor.black1);//black @@ -92,7 +101,7 @@ void BayerRAWExposure::read(const rtengine::procparams::ProcParams* pp, const Pa } else { PexBlack3->setValue (PexBlack0->getValue()); } - + checkBoxToggled (Dehablack, CheckValue::on); enableListener (); } @@ -102,6 +111,7 @@ void BayerRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited pp->raw.bayersensor.black1 = PexBlack1->getValue();// black pp->raw.bayersensor.black2 = PexBlack2->getValue();// black pp->raw.bayersensor.twogreen = PextwoGreen->getLastActive(); + pp->raw.bayersensor.Dehablack = Dehablack->getLastActive(); if(PextwoGreen->getLastActive()) { pp->raw.bayersensor.black3 = pp->raw.bayersensor.black0; // active or desactive 2 green together @@ -115,10 +125,50 @@ void BayerRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdited pedited->raw.bayersensor.exBlack2 = PexBlack2->getEditedState ();//black pedited->raw.bayersensor.exBlack3 = PexBlack3->getEditedState ();//black pedited->raw.bayersensor.exTwoGreen = !PextwoGreen->get_inconsistent(); + pedited->raw.bayersensor.Dehablack = !Dehablack->get_inconsistent(); } } +BayerRAWExposure::~BayerRAWExposure() +{ + idle_register.destroy(); +} + + +void BayerRAWExposure::autoBlackChanged (double reddeha, double greendeha, double bluedeha) +{ + + idle_register.add( + [this, reddeha, greendeha, bluedeha]() -> bool + { + if (reddeha != PexBlack1->getValue()) { + disableListener(); + PexBlack1->setValue(reddeha); + enableListener(); + } + if (greendeha != PexBlack0->getValue()) { + disableListener(); + PexBlack0->setValue(greendeha); + enableListener(); + } + if (greendeha != PexBlack3->getValue()) { + disableListener(); + PexBlack3->setValue(greendeha); + enableListener(); + } + if (bluedeha != PexBlack2->getValue()) { + disableListener(); + PexBlack2->setValue(bluedeha); + enableListener(); + } + + return false; + } + ); +} + + void BayerRAWExposure::adjusterChanged(Adjuster* a, double newval) { if (listener) { @@ -155,9 +205,29 @@ void BayerRAWExposure::checkBoxToggled (CheckBox* c, CheckValue newval) PexBlack3->setValue (PexBlack0->getValue());//two green together } } + } else if(c == Dehablack) { + if(Dehablack->getLastActive()) { + PexBlack1->set_sensitive(false); + PexBlack2->set_sensitive(false); + PexBlack3->set_sensitive(false); + PexBlack0->set_sensitive(false); + } else { + PexBlack1->set_sensitive(true); + PexBlack2->set_sensitive(true); + PexBlack3->set_sensitive(true); + PexBlack0->set_sensitive(true); + } + if (listener) { + if (Dehablack->getLastActive()) { + listener->panelChanged (EvDehablack, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvDehablackVoid, M("GENERAL_DISABLED")); + } + } } } + void BayerRAWExposure::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/bayerrawexposure.h b/rtgui/bayerrawexposure.h index 53c5817f8..7f2713074 100644 --- a/rtgui/bayerrawexposure.h +++ b/rtgui/bayerrawexposure.h @@ -23,17 +23,20 @@ #include "adjuster.h" #include "checkbox.h" #include "toolpanel.h" +#include "eventmapper.h" class BayerRAWExposure final : public ToolParamBlock, public AdjusterListener, public CheckBoxListener, + public rtengine::AutoBlackListener, public FoldableToolPanel { public: static const Glib::ustring TOOL_NAME; BayerRAWExposure (); + ~BayerRAWExposure () override; void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; @@ -43,6 +46,8 @@ public: void checkBoxToggled (CheckBox* c, CheckValue newval) override; void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; + void autoBlackChanged (double reddeha, double greendeha, double bluedeha) override; + protected: Adjuster* PexBlack0; @@ -50,4 +55,8 @@ protected: Adjuster* PexBlack2; Adjuster* PexBlack3; CheckBox* PextwoGreen; + CheckBox* Dehablack; + IdleRegister idle_register; + rtengine::ProcEvent EvDehablack; + rtengine::ProcEvent EvDehablackVoid; }; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index 81b6b34d8..7ca77a794 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -498,6 +498,7 @@ void ParamsEdited::set(bool v) raw.bayersensor.exBlack2 = v; raw.bayersensor.exBlack3 = v; raw.bayersensor.exTwoGreen = v; + raw.bayersensor.Dehablack = v; raw.bayersensor.dcbIterations = v; raw.bayersensor.dcbEnhance = v; //raw.bayersensor.allEnhance = v; @@ -531,6 +532,7 @@ void ParamsEdited::set(bool v) raw.xtranssensor.exBlackRed = v; raw.xtranssensor.exBlackGreen = v; raw.xtranssensor.exBlackBlue = v; + raw.xtranssensor.Dehablackx = v; raw.ca_autocorrect = v; raw.ca_avoidcolourshift = v; raw.caautoiterations = v; @@ -2007,6 +2009,7 @@ void ParamsEdited::initFrom(const std::vector& raw.bayersensor.exBlack2 = raw.bayersensor.exBlack2 && p.raw.bayersensor.black2 == other.raw.bayersensor.black2; raw.bayersensor.exBlack3 = raw.bayersensor.exBlack3 && p.raw.bayersensor.black3 == other.raw.bayersensor.black3; raw.bayersensor.exTwoGreen = raw.bayersensor.exTwoGreen && p.raw.bayersensor.twogreen == other.raw.bayersensor.twogreen; + raw.bayersensor.Dehablack = raw.bayersensor.Dehablack && p.raw.bayersensor.Dehablack == other.raw.bayersensor.Dehablack; raw.bayersensor.dcbIterations = raw.bayersensor.dcbIterations && p.raw.bayersensor.dcb_iterations == other.raw.bayersensor.dcb_iterations; raw.bayersensor.dcbEnhance = raw.bayersensor.dcbEnhance && p.raw.bayersensor.dcb_enhance == other.raw.bayersensor.dcb_enhance; //raw.bayersensor.allEnhance = raw.bayersensor.allEnhance && p.raw.bayersensor.all_enhance == other.raw.bayersensor.all_enhance; @@ -2040,6 +2043,7 @@ void ParamsEdited::initFrom(const std::vector& raw.xtranssensor.exBlackRed = raw.xtranssensor.exBlackRed && p.raw.xtranssensor.blackred == other.raw.xtranssensor.blackred; raw.xtranssensor.exBlackGreen = raw.xtranssensor.exBlackGreen && p.raw.xtranssensor.blackgreen == other.raw.xtranssensor.blackgreen; raw.xtranssensor.exBlackBlue = raw.xtranssensor.exBlackBlue && p.raw.xtranssensor.blackblue == other.raw.xtranssensor.blackblue; + raw.xtranssensor.Dehablackx = raw.xtranssensor.Dehablackx && p.raw.xtranssensor.Dehablackx == other.raw.xtranssensor.Dehablackx; raw.ca_autocorrect = raw.ca_autocorrect && p.raw.ca_autocorrect == other.raw.ca_autocorrect; raw.ca_avoidcolourshift = raw.ca_avoidcolourshift && p.raw.ca_avoidcolourshift == other.raw.ca_avoidcolourshift; raw.caautoiterations = raw.caautoiterations && p.raw.caautoiterations == other.raw.caautoiterations; @@ -6975,6 +6979,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.raw.bayersensor.twogreen = mods.raw.bayersensor.twogreen; } + if (raw.bayersensor.Dehablack) { + toEdit.raw.bayersensor.Dehablack = mods.raw.bayersensor.Dehablack; + } + if (raw.bayersensor.dcbIterations) { toEdit.raw.bayersensor.dcb_iterations = mods.raw.bayersensor.dcb_iterations; } @@ -7103,6 +7111,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.raw.xtranssensor.blackblue = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_BLACKS] ? toEdit.raw.xtranssensor.blackblue + mods.raw.xtranssensor.blackblue : mods.raw.xtranssensor.blackblue; } + if (raw.xtranssensor.Dehablackx) { + toEdit.raw.xtranssensor.Dehablackx = mods.raw.xtranssensor.Dehablackx; + } + if (raw.ca_autocorrect) { toEdit.raw.ca_autocorrect = mods.raw.ca_autocorrect; } @@ -7883,7 +7895,7 @@ bool RAWParamsEdited::BayerSensor::isUnchanged() const return method && border && imageNum && dcbIterations && dcbEnhance && lmmseIterations && dualDemosaicAutoContrast && dualDemosaicContrast /*&& allEnhance*/ && greenEq && pixelShiftMotionCorrectionMethod && pixelShiftEperIso && pixelShiftSigma && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly && pixelShiftHoleFill && pixelShiftMedian && pixelShiftAverage && pixelShiftNonGreenCross && pixelShiftDemosaicMethod && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftEqualBright && pixelShiftEqualBrightChannel - && linenoise && linenoiseDirection && pdafLinesFilter && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; + && linenoise && linenoiseDirection && pdafLinesFilter && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen && Dehablack; } bool RAWParamsEdited::XTransSensor::isUnchanged() const diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index bc617612c..0481009e8 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1531,6 +1531,7 @@ struct RAWParamsEdited { bool exBlack2; bool exBlack3; bool exTwoGreen; + bool Dehablack; bool dcbIterations; bool dcbEnhance; bool lmmseIterations; @@ -1569,6 +1570,7 @@ struct RAWParamsEdited { bool exBlackRed; bool exBlackGreen; bool exBlackBlue; + bool Dehablackx; bool isUnchanged() const; }; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 354d3e47e..9b3bcf6ea 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -1311,6 +1311,8 @@ void ToolPanelCoordinator::initImage(rtengine::StagedImageProcessor* ipc_, bool ipc->setAutoExpListener(toneCurve); ipc->setAutoCamListener(colorappearance); + ipc->setAutoBlackListener(bayerrawexposure); + ipc->setAutoBlackxListener(xtransrawexposure); ipc->setAutoBWListener(blackwhite); ipc->setFrameCountListener(bayerprocess); ipc->setFlatFieldAutoClipListener (flatfield); diff --git a/rtgui/xtransrawexposure.cc b/rtgui/xtransrawexposure.cc index 2e26b8f63..52547d930 100644 --- a/rtgui/xtransrawexposure.cc +++ b/rtgui/xtransrawexposure.cc @@ -31,6 +31,10 @@ const Glib::ustring XTransRAWExposure::TOOL_NAME = "xtransrawexposure"; XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M("TP_EXPOS_BLACKPOINT_LABEL")) { + auto m = ProcEventMapper::getInstance(); + EvDehablackx = m->newEvent(DARKFRAME, "HISTORY_MSG_DEHABLACKX"); + EvDehablackxVoid = m->newEvent(M_VOID, "HISTORY_MSG_DEHABLACKX"); + PexBlackRed = Gtk::manage(new Adjuster (M("TP_RAWEXPOS_BLACK_RED"), -2048, 2048, 1.0, 0)); //black level PexBlackRed->setAdjusterListener (this); @@ -49,10 +53,14 @@ XTransRAWExposure::XTransRAWExposure () : FoldableToolPanel(this, TOOL_NAME, M(" PexBlackBlue->setDelay(std::max(options.adjusterMinDelay, options.adjusterMaxDelay)); PexBlackBlue->show(); + Dehablackx = Gtk::manage(new CheckBox(M("TP_RAWEXPOS_DEHA"), multiImage));// Black dehaze + Dehablackx->set_active (false); + Dehablackx->setCheckBoxListener (this); pack_start( *PexBlackRed, Gtk::PACK_SHRINK, 0);//black pack_start( *PexBlackGreen, Gtk::PACK_SHRINK, 0);//black pack_start( *PexBlackBlue, Gtk::PACK_SHRINK, 0);//black + pack_start( *Dehablackx, Gtk::PACK_SHRINK, 0);//black Dehaze PexBlackRed->setLogScale(100, 0); PexBlackGreen->setLogScale(100, 0); @@ -68,10 +76,12 @@ void XTransRAWExposure::read(const rtengine::procparams::ProcParams* pp, const P PexBlackGreen->setEditedState( pedited->raw.xtranssensor.exBlackGreen ? Edited : UnEdited ); PexBlackBlue->setEditedState( pedited->raw.xtranssensor.exBlackBlue ? Edited : UnEdited ); } + Dehablackx->setValue (pp->raw.xtranssensor.Dehablackx); PexBlackRed->setValue (pp->raw.xtranssensor.blackred);//black PexBlackGreen->setValue (pp->raw.xtranssensor.blackgreen);//black PexBlackBlue->setValue (pp->raw.xtranssensor.blackblue);//black + checkBoxToggled (Dehablackx, CheckValue::on); enableListener (); } @@ -81,15 +91,49 @@ void XTransRAWExposure::write( rtengine::procparams::ProcParams* pp, ParamsEdite pp->raw.xtranssensor.blackred = PexBlackRed->getValue();// black pp->raw.xtranssensor.blackgreen = PexBlackGreen->getValue();// black pp->raw.xtranssensor.blackblue = PexBlackBlue->getValue();// black + pp->raw.xtranssensor.Dehablackx = Dehablackx->getLastActive(); if (pedited) { pedited->raw.xtranssensor.exBlackRed = PexBlackRed->getEditedState ();//black pedited->raw.xtranssensor.exBlackGreen = PexBlackGreen->getEditedState ();//black pedited->raw.xtranssensor.exBlackBlue = PexBlackBlue->getEditedState ();//black + pedited->raw.xtranssensor.Dehablackx = !Dehablackx->get_inconsistent(); } } +XTransRAWExposure::~XTransRAWExposure() +{ + idle_register.destroy(); +} + +void XTransRAWExposure::autoBlackxChanged (double reddeha, double greendeha, double bluedeha) +{ + idle_register.add( + [this, reddeha, greendeha, bluedeha]() -> bool + { + if (reddeha != PexBlackRed->getValue()) { + disableListener(); + PexBlackRed->setValue(reddeha); + enableListener(); + } + if (greendeha != PexBlackGreen->getValue()) { + disableListener(); + PexBlackGreen->setValue(greendeha); + enableListener(); + } + if (bluedeha != PexBlackBlue->getValue()) { + disableListener(); + PexBlackBlue->setValue(bluedeha); + enableListener(); + } + + return false; + } + ); + +} + void XTransRAWExposure::adjusterChanged(Adjuster* a, double newval) { if (listener) { @@ -105,6 +149,29 @@ void XTransRAWExposure::adjusterChanged(Adjuster* a, double newval) } } +void XTransRAWExposure::checkBoxToggled (CheckBox* c, CheckValue newval) +{ + if(c == Dehablackx) { + if(Dehablackx->getLastActive()) { + PexBlackRed->set_sensitive(false); + PexBlackGreen->set_sensitive(false); + PexBlackBlue->set_sensitive(false); + } else { + PexBlackRed->set_sensitive(true); + PexBlackGreen->set_sensitive(true); + PexBlackBlue->set_sensitive(true); + } + if (listener) { + if (Dehablackx->getLastActive()) { + listener->panelChanged (EvDehablackx, M("GENERAL_ENABLED")); + } else { + listener->panelChanged (EvDehablackxVoid, M("GENERAL_DISABLED")); + } + } + } +} + + void XTransRAWExposure::setBatchMode(bool batchMode) { ToolPanel::setBatchMode (batchMode); diff --git a/rtgui/xtransrawexposure.h b/rtgui/xtransrawexposure.h index c332bc510..5e82b3158 100644 --- a/rtgui/xtransrawexposure.h +++ b/rtgui/xtransrawexposure.h @@ -21,11 +21,15 @@ #include #include "adjuster.h" +#include "checkbox.h" #include "toolpanel.h" +#include "eventmapper.h" class XTransRAWExposure final : public ToolParamBlock, public AdjusterListener, + public CheckBoxListener, + public rtengine::AutoBlackxListener, public FoldableToolPanel { @@ -33,6 +37,10 @@ protected: Adjuster* PexBlackRed; Adjuster* PexBlackGreen; Adjuster* PexBlackBlue; + CheckBox* Dehablackx; + IdleRegister idle_register; + rtengine::ProcEvent EvDehablackx; + rtengine::ProcEvent EvDehablackxVoid; private: // Gtk::CheckButton* PextwoGreen; @@ -40,12 +48,15 @@ public: static const Glib::ustring TOOL_NAME; XTransRAWExposure (); + ~XTransRAWExposure () override; void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr) override; void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr) override; void setBatchMode (bool batchMode) override; void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr) override; void adjusterChanged (Adjuster* a, double newval) override; + void checkBoxToggled (CheckBox* c, CheckValue newval) override; void setAdjusterBehavior (bool pexblackadd); void trimValues (rtengine::procparams::ProcParams* pp) override; + void autoBlackxChanged (double reddeha, double greendeha, double bluedeha) override; };