From 3e269764031e09db701456c8645f3da85c632ed7 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Mon, 26 Feb 2024 11:32:01 +0100 Subject: [PATCH] Read embedded dcp profile from raw files raw files, usually dng files, can provide a dcp profile by providing the related tags. This patch will make the "Use embedded" options in the color management panel selectable if the source raw file embeds a dcp profile. In this case the DCP panel will be enabled like when reading an external dcp profile. Additional changes: * Rename "Use embedded, if possible" to just "Use embedded" since the option is already disabled when no embedded profile is found. * Update the "Use embedded" options tooltip as it's now not related to only non raw images. --- rtdata/languages/default | 4 ++-- rtengine/rawimagesource.cc | 39 +++++++++++++++++++++++++------------- rtengine/rawimagesource.h | 9 +++------ rtengine/rtthumbnail.cc | 4 ++-- rtgui/icmpanel.cc | 11 +++++++---- rtgui/icmpanel.h | 1 + 6 files changed, 41 insertions(+), 27 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 07b5f18c9..4e76b7b00 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2634,8 +2634,8 @@ TP_ICM_INPUTCAMERA_TOOLTIP;Use a simple color matrix from dcraw, an enhanced Raw TP_ICM_INPUTCUSTOM;Custom TP_ICM_INPUTCUSTOM_TOOLTIP;Select your own DCP/ICC color profile file for the camera. TP_ICM_INPUTDLGLABEL;Select Input DCP/ICC Profile... -TP_ICM_INPUTEMBEDDED;Use embedded, if possible -TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files. +TP_ICM_INPUTEMBEDDED;Use embedded +TP_ICM_INPUTEMBEDDED_TOOLTIP;Use the color profile embedded in the file.\nIf unavailable, fall back to Camera standard TP_ICM_INPUTNONE;No profile TP_ICM_INPUTNONE_TOOLTIP;Use no input color profile at all.\nUse only in special cases. TP_ICM_INPUTPROFILE;Input Profile diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 8149c0464..c027cd7d4 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1078,7 +1078,7 @@ DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, DCPProfileA DCPProfile *dcpProf = nullptr; cmsHPROFILE dummy; - findInputProfile(cmp.inputProfile, nullptr, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); + findInputProfile(cmp.inputProfile, nullptr, (static_cast(getMetaData()))->getCamera(), fileName, &dcpProf, dummy); if (dcpProf == nullptr) { if (settings->verbose) { @@ -1094,8 +1094,24 @@ DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, DCPProfileA void RawImageSource::convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb) { + cmsHPROFILE in; + DCPProfile *dcpProf; + + if (!findInputProfile(cmp.inputProfile, embProfile, (static_cast(getMetaData()))->getCamera(), fileName, &dcpProf, in)) { + return; + } + double pre_mul[3] = { ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2) }; - colorSpaceConversion(image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); + colorSpaceConversion_(image, cmp, wb, pre_mul, camProfile, imatrices.xyz_cam, in, dcpProf); +} + +void RawImageSource::colorSpaceConversion(Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName, const Glib::ustring &fileName) +{ + cmsHPROFILE in; + DCPProfile *dcpProf; + if (findInputProfile(cmp.inputProfile, embedded, camName, fileName, &dcpProf, in)) { + colorSpaceConversion_(im, cmp, wb, pre_mul, camprofile, cam, in, dcpProf); + } } void RawImageSource::getFullSize(int& w, int& h, int tr) @@ -3156,18 +3172,11 @@ lab2ProphotoRgbD50(float L, float A, float B, float& r, float& g, float& b) } // Converts raw image including ICC input profile to working space - floating point version -void RawImageSource::colorSpaceConversion_(Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], const std::string &camName) +void RawImageSource::colorSpaceConversion_(Imagefloat* im, const ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE camprofile, double camMatrix[3][3], cmsHPROFILE in, DCPProfile *dcpProf) { // MyTime t1, t2, t3; // t1.set (); - cmsHPROFILE in; - DCPProfile *dcpProf; - - if (!findInputProfile(cmp.inputProfile, embedded, camName, &dcpProf, in)) { - return; - } - if (dcpProf != nullptr) { // DCP processing const DCPProfile::Triple pre_mul_row = { @@ -3557,7 +3566,7 @@ void RawImageSource::colorSpaceConversion_(Imagefloat* im, const ColorManagement // Determine RAW input and output profiles. Returns TRUE on success -bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in) +bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, const Glib::ustring &fileName, DCPProfile **dcpProf, cmsHPROFILE& in) { in = nullptr; // cam will be taken on NULL *dcpProf = nullptr; @@ -3566,8 +3575,12 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed return false; } - if (embedded && inProfile == "(embedded)") { - in = embedded; + if (inProfile == "(embedded)") { + if (embedded) { + in = embedded; + } else { + *dcpProf = DCPStore::getInstance()->getProfile(fileName); + } } else if (inProfile == "(cameraICC)") { // DCPs have higher quality, so use them first *dcpProf = DCPStore::getInstance()->getStdProfile(camName); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index e65cadaa3..739a6371f 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -46,7 +46,7 @@ private: static DiagonalCurve *phaseOneIccCurveInv; static LUTf invGrad; // for fast_demosaic static LUTf initInvGrad (); - static void colorSpaceConversion_ (Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName); + static void colorSpaceConversion_ (Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE camprofile, double cam[3][3], cmsHPROFILE in, DCPProfile *dcpProf); static int defTransform (const RawImage *ri, int tran); protected: @@ -190,11 +190,8 @@ public: DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) override; void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override; - static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion(Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) - { - colorSpaceConversion_(im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); - } + static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, const Glib::ustring &filename, DCPProfile **dcpProf, cmsHPROFILE& in); + static void colorSpaceConversion(Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName, const Glib::ustring &fileName); static void inverse33(const double (*coeff)[3], double (*icoeff)[3]); void MSR(float** luminance, float **originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const procparams::RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 65c03ac96..1ae5d30a7 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1328,7 +1328,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT if (isRaw) { double pre_mul[3] = { redMultiplier, greenMultiplier, blueMultiplier }; - RawImageSource::colorSpaceConversion (baseImg, params.icm, currWB, pre_mul, embProfile, camProfile, cam2xyz, camName ); + RawImageSource::colorSpaceConversion (baseImg, params.icm, currWB, pre_mul, embProfile, camProfile, cam2xyz, camName, metadata->getFileName()); } else { StdImageSource::colorSpaceConversion (baseImg, params.icm, embProfile, thumbImg->getSampleFormat()); } @@ -1467,7 +1467,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT if (isRaw) { cmsHPROFILE dummy; - RawImageSource::findInputProfile (params.icm.inputProfile, nullptr, camName, &dcpProf, dummy); + RawImageSource::findInputProfile (params.icm.inputProfile, nullptr, camName, metadata->getFileName(), &dcpProf, dummy); if (dcpProf) { dcpProf->setStep2ApplyState (params.icm.workingProfile, params.icm.toneCurve, params.icm.applyLookTable, params.icm.applyBaselineExposureOffset, as); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index b18afe5aa..772f8e38e 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -705,6 +705,8 @@ void ICMPanel::updateDCP(int dcpIlluminant, Glib::ustring dcp_name) if (dcp_name == "(cameraICC)") { dcp = DCPStore::getInstance()->getStdProfile(camName); + } else if (dcp_name == "(embedded)") { + dcp = DCPStore::getInstance()->getProfile(filename); } else if (ifromfile->get_active() && DCPStore::getInstance()->isValidDCPFileName(dcp_name)) { dcp = DCPStore::getInstance()->getProfile(dcp_name); } @@ -806,8 +808,8 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) ConnectionBlocker wprimconn_(wprimconn); trcExp->set_expanded(false); - if (pp->icm.inputProfile.substr(0, 5) != "file:") { - ipDialog->set_filename(" "); + if (pp->icm.inputProfile.substr(0, 5) != "file:" && !ipDialog->get_filename().empty()) { + ipDialog->set_filename(pp->icm.inputProfile); } if (pp->icm.inputProfile == "(none)") { @@ -815,7 +817,7 @@ void ICMPanel::read(const ProcParams* pp, const ParamsEdited* pedited) updateDCP(pp->icm.dcpIlluminant, ""); } else if (pp->icm.inputProfile == "(embedded)" || ((pp->icm.inputProfile == "(camera)" || pp->icm.inputProfile.empty()) && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { iembedded->set_active(true); - updateDCP(pp->icm.dcpIlluminant, ""); + updateDCP(pp->icm.dcpIlluminant, "(embedded)"); } else if ((pp->icm.inputProfile == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { icameraICC->set_active(true); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); @@ -2126,8 +2128,9 @@ void ICMPanel::setRawMeta(bool raw, const rtengine::FramesData* pMeta) iembedded->set_active(!raw); icamera->set_sensitive(raw); camName = pMeta->getCamera(); + filename = pMeta->getFileName(); icameraICC->set_sensitive(raw && (ICCStore::getInstance()->getStdProfile(pMeta->getCamera()) != nullptr || DCPStore::getInstance()->getStdProfile(pMeta->getCamera()) != nullptr)); - iembedded->set_sensitive(!raw); + iembedded->set_sensitive(!raw || DCPStore::getInstance()->getProfile(filename)); enableListener(); } diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index f41e17b7b..b11b9478c 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -167,6 +167,7 @@ private: double dcpTemperatures[2]; Glib::ustring lastRefFilename; Glib::ustring camName; + Glib::ustring filename; void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); void updateRenderingIntent(const Glib::ustring &profile); void foldAllButMe (GdkEventButton* event, MyExpander *expander);