diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 5b0328878..5ddf3aeb1 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -908,6 +908,11 @@ TP_ICM_LABEL;Farbmanagement TP_ICM_NOICM;Kein ICM: sRGB-Ausgabe TP_ICM_OUTPUTDLGLABEL;Wähle Ausgabe-ICC-Profil... TP_ICM_OUTPUTPROFILE;Ausgabeprofil +TP_ICM_PREFERREDPROFILE;Bevorzugtes DCP-Profil +TP_ICM_PREFERREDPROFILE_1;Tageslight +TP_ICM_PREFERREDPROFILE_2;Glühlampe +TP_ICM_PREFERREDPROFILE_3;Neonröhre +TP_ICM_PREFERREDPROFILE_4;Blitz TP_ICM_SAVEREFERENCE;Referenzbild für Profil speichern TP_ICM_WORKINGPROFILE;Arbeitsfarbraum TP_IMPULSEDENOISE_LABEL;Impulsrauschminderung diff --git a/rtdata/languages/default b/rtdata/languages/default index a31b64c02..ca3cb76c6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -478,7 +478,7 @@ MAIN_MSG_EMPTYFILENAME;Filename unspecified! MAIN_MSG_ERRORDURINGIMAGESAVING;Error during image saving MAIN_MSG_EXITJOBSINQUEUEINFO;Unprocessed images in the queue will be lost on exit. MAIN_MSG_EXITJOBSINQUEUEQUEST;Are you sure you want to exit? There are unprocessed images waiting in the queue. -MAIN_MSG_IMAGEUNPROCESSED;This command requires all selected images to be queue process first. +MAIN_MSG_IMAGEUNPROCESSED;This command requires all selected images to be queue processed first. MAIN_MSG_JOBSINQUEUE;job(s) in the queue MAIN_MSG_NAVIGATOR;Navigator MAIN_MSG_PLACES;Places @@ -940,6 +940,11 @@ TP_ICM_LABEL;Color Management TP_ICM_NOICM;No ICM: sRGB output TP_ICM_OUTPUTDLGLABEL;Select Output ICC Profile... TP_ICM_OUTPUTPROFILE;Output Profile +TP_ICM_PREFERREDPROFILE;Preferred DCP profile +TP_ICM_PREFERREDPROFILE_1;Daylight +TP_ICM_PREFERREDPROFILE_2;Tungsten +TP_ICM_PREFERREDPROFILE_3;Fluorescent +TP_ICM_PREFERREDPROFILE_4;Flash TP_ICM_SAVEREFERENCE;Save reference image for profiling TP_ICM_WORKINGPROFILE;Working Profile TP_IMPULSEDENOISE_LABEL;Impulse Noise Reduction diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index e1747a44d..17350126e 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -31,32 +31,32 @@ using namespace rtengine; using namespace rtexif; DCPProfile::DCPProfile(Glib::ustring fname) { + const int TIFFFloatSize=4; const int TagColorMatrix1=50721, TagColorMatrix2=50722, TagProfileHueSatMapDims=50937; const int TagProfileHueSatMapData1=50938, TagProfileHueSatMapData2=50939; const int TagCalibrationIlluminant1=50778, TagCalibrationIlluminant2=50779; const int TagProfileLookTableData=50982, TagProfileLookTableDims=50981; // ProfileLookup is the low quality variant - aDeltas=NULL; iHueDivisions=iSatDivisions=iValDivisions=iArrayCount=0; + aDeltas1=aDeltas2=NULL; iHueDivisions=iSatDivisions=iValDivisions=iArrayCount=0; FILE *pFile = safe_g_fopen(fname, "rb"); TagDirectory *tagDir=ExifManager::parseTIFF(pFile, false); - // If there are two profiles, check what is the best target to take - // We don't mix the profiles as adobe does, since with more and more non-tungsten light - // it makes no sense. Take the daylight reference light - Tag* tag = tagDir->getTag(TagCalibrationIlluminant2); - bool hasSecondHueSat = tagDir->getTag(TagProfileHueSatMapData2)!=NULL; // some profiles have two matrices but just one huesat - bool use2nd = (tag!=NULL && tag->toInt(0,SHORT)>=20 && tag->toInt(0,SHORT)<=23); + Tag* tag = tagDir->getTag(TagCalibrationIlluminant1); iLightSource1 = (tag!=NULL ? tag->toInt(0,SHORT) : -1); + tag = tagDir->getTag(TagCalibrationIlluminant2); iLightSource2 = (tag!=NULL ? tag->toInt(0,SHORT) : -1); - // Color Matrix - tag = tagDir->getTag( use2nd ? TagColorMatrix2 : TagColorMatrix1); + bool hasSecondHueSat = tagDir->getTag(TagProfileHueSatMapData2)!=NULL; // some profiles have two matrices, but just one huesat + + // Color Matrix (1 is always there) + tag = tagDir->getTag(TagColorMatrix1); for (int row=0;row<3;row++) { for (int col=0;col<3;col++) { - mColorMatrix[col][row]=(float)tag->toDouble((col+row*3)*8); + mColorMatrix1[col][row]=(float)tag->toDouble((col+row*3)*8); } } + ConvertDNGMatrix2XYZCAM(mColorMatrix1,mXYZCAM1); // LUT profile? Divisions counts bool useSimpleLookup=false; @@ -70,24 +70,61 @@ DCPProfile::DCPProfile(Glib::ustring fname) { iHueDivisions=tag->toInt(0); iSatDivisions=tag->toInt(4); iValDivisions=tag->toInt(8); // Saturation maps. Need to be unwinded. - tag = tagDir->getTag(useSimpleLookup ? TagProfileLookTableData : ( use2nd && hasSecondHueSat ? TagProfileHueSatMapData2 : TagProfileHueSatMapData1)); + tag = tagDir->getTag(useSimpleLookup ? TagProfileLookTableData : TagProfileHueSatMapData1); iArrayCount = tag->getCount()/3; - aDeltas=new HSBModify[iArrayCount]; + aDeltas1=new HSBModify[iArrayCount]; - const int TIFFFloatSize=4; for (int i=0;itoDouble((i*3)*TIFFFloatSize); - aDeltas[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); - aDeltas[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + aDeltas1[i].fHueShift=tag->toDouble((i*3)*TIFFFloatSize); + aDeltas1[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); + aDeltas1[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + } + } + + // For second profile, copy everything from first profile is no better data is available + if (iLightSource2!=-1) { + // Second matrix + tag = tagDir->getTag(TagColorMatrix2); + + for (int row=0;row<3;row++) { + for (int col=0;col<3;col++) { + mColorMatrix2[col][row]= (tag!=NULL ? (float)tag->toDouble((col+row*3)*8) : mColorMatrix1[col][row]); + } + } + + ConvertDNGMatrix2XYZCAM(mColorMatrix2,mXYZCAM2); + + // Second huesatmap, or copy of first + if (hasSecondHueSat) { + aDeltas2=new HSBModify[iArrayCount]; + + // Saturation maps. Need to be unwinded. + tag = tagDir->getTag(TagProfileHueSatMapData2); + + for (int i=0;itoDouble((i*3)*TIFFFloatSize); + aDeltas2[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize); + aDeltas2[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize); + } + } else { + if (aDeltas1!=NULL) { + aDeltas2=new HSBModify[iArrayCount]; + for (int i=0;i0) { // Convert DNG color matrix to xyz_cam compatible matrix +void DCPProfile::ConvertDNGMatrix2XYZCAM(const double (*mColorMatrix)[3], double (*mXYZCAM)[3]) { int i,j,k; double cam_xyz[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; @@ -114,21 +151,66 @@ DCPProfile::DCPProfile(Glib::ustring fname) { double rgb_cam[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; RawImageSource::inverse33 (cam_rgb, rgb_cam); - memset(mXYZCAM,0,sizeof(mXYZCAM)); + for (i=0; i<3; i++) + for (j=0; j<3; j++) mXYZCAM[i][j]=0; + for (i=0; i<3; i++) for (j=0; j<3; j++) for (k=0; k<3; k++) mXYZCAM[i][j] += xyz_sRGB[i][k] * rgb_cam[k][j]; } + + +const DCPProfile::HSBModify* DCPProfile::GetBestProfile(DCPLightType preferredProfile, double (*mXYZCAM)[3]) const { + bool use2=false; + + if (iLightSource2!=-1) { + DCPLightType t1=GetLightType(iLightSource1); DCPLightType t2=GetLightType(iLightSource2); + + // usually second is the daylight (default if nothing else found) + if (t2==Daylight) use2=true; + + switch (preferredProfile) { + case Tungsten: + if (t1==Tungsten) use2=false; else if (t2==Tungsten) use2=true; + break; + + case Fluorescent: + if (t1==Fluorescent) use2=false; else if (t2==Fluorescent) use2=true; + break; + + case Flash: + if (t1==Flash) use2=false; else if (t2==Flash) use2=true; + break; + + default: break; // e.g. Daylight + } } -DCPProfile::~DCPProfile() { - delete[] aDeltas; + // printf("DCP using LightSource %i: %i for requested %i\n", use2?2:1, use2?iLightSource2:iLightSource1, (int)preferredProfile); + + for (int row=0;row<3;row++) { + for (int col=0;col<3;col++) { + mXYZCAM[col][row]= (use2 ? mXYZCAM2[col][row] : mXYZCAM1[col][row]); + } } -void DCPProfile::Apply(Imagefloat *pImg, Glib::ustring workingSpace) const { + return use2?aDeltas2:aDeltas1; +} + +DCPLightType DCPProfile::GetLightType(short iLightSource) const { + if (iLightSource==3 || iLightSource==17 || iLightSource==24) return Tungsten; + if (iLightSource==2 || (iLightSource>=12 && iLightSource<=15)) return Fluorescent; + if (iLightSource==4) return Flash; + return Daylight; +} + +void DCPProfile::Apply(Imagefloat *pImg, DCPLightType preferredProfile, Glib::ustring workingSpace) const { TMatrix mWork = iccStore->workingSpaceInverseMatrix (workingSpace); + double mXYZCAM[3][3]; + const HSBModify* tableBase=GetBestProfile(preferredProfile,mXYZCAM); + if (iArrayCount==0) { //===== No LUT- Calculate matrix for direct conversion raw>working space double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; @@ -173,8 +255,6 @@ void DCPProfile::Apply(Imagefloat *pImg, Glib::ustring workingSpace) const { int maxSatIndex0 = iSatDivisions - 2; int maxValIndex0 = iValDivisions - 2; - const HSBModify *tableBase = aDeltas; - int hueStep = iSatDivisions; int valStep = iHueDivisions * hueStep; @@ -342,9 +422,12 @@ void DCPProfile::Apply(Imagefloat *pImg, Glib::ustring workingSpace) const { // Integer variant is legacy, only used for thumbs. Simply take the matrix here -void DCPProfile::Apply(Image16 *pImg, Glib::ustring workingSpace) const { +void DCPProfile::Apply(Image16 *pImg, DCPLightType preferredProfile, Glib::ustring workingSpace) const { TMatrix mWork = iccStore->workingSpaceInverseMatrix (workingSpace); + double mXYZCAM[3][3]; + const HSBModify* tableBase=GetBestProfile(preferredProfile,mXYZCAM); + // Calculate matrix for direct conversion raw>working space double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; for (int i=0; i<3; i++) diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 11e5af535..ea90e4344 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -26,6 +26,9 @@ #include namespace rtengine { + enum DCPLightType { + Daylight=1, Tungsten=2, Fluorescent=3, Flash=4 + }; class DCPProfile { struct HSBModify @@ -35,20 +38,27 @@ namespace rtengine { float fValScale; }; - double mColorMatrix[3][3]; - double mXYZCAM[3][3]; // compatible to RTs xyz_cam - HSBModify *aDeltas; + double mColorMatrix1[3][3],mColorMatrix2[3][3]; + double mXYZCAM1[3][3],mXYZCAM2[3][3]; // compatible to RTs xyz_cam + HSBModify *aDeltas1,*aDeltas2; + short iLightSource1,iLightSource2; int iHueDivisions, iSatDivisions, iValDivisions; int iHueStep, iValStep, iArrayCount; + void ConvertDNGMatrix2XYZCAM(const double (*mColorMatrix)[3], double (*mXYZCAM)[3]); + + const HSBModify* GetBestProfile(DCPLightType preferredProfile, double (*mXYZCAM)[3]) const; + + DCPLightType GetLightType(short iLightSource) const; + public: DCPProfile(Glib::ustring fname); ~DCPProfile(); - void Apply(Imagefloat *pImg, Glib::ustring workingSpace) const; - void Apply(Image16 *pImg, Glib::ustring workingSpace) const; + void Apply(Imagefloat *pImg, DCPLightType preferredProfile, Glib::ustring workingSpace) const; + void Apply(Image16 *pImg, DCPLightType preferredProfile, Glib::ustring workingSpace) const; }; class DCPStore { diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 353215f3e..20c4c1539 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -70,7 +70,7 @@ enum ProcEvent { EvCDNEnabled=45, // obsolete EvCDNRadius=46, // obsolete EvCDNEdgeTolerance=47, // obsolete - EvCDNEdgeSensitive=48, // obsolete + EvPrefProfile=48, EvSHEnabled=49, EvSHHighlights=50, EvSHShadows=51, diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 8a4965a5b..bd49c6346 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -33,6 +33,7 @@ #include "rawimage.h" #include "../rtgui/ppversion.h" #include "../rtgui/paramsedited.h" +#include "dcp.h" #define APPVERSION VERSION @@ -295,6 +296,7 @@ void ProcParams::setDefaults () { icm.input = ""; icm.blendCMSMatrix = false; + icm.preferredProfile = (short)rtengine::Daylight; icm.working = "sRGB"; icm.output = "sRGB"; icm.gamma = "default"; @@ -570,6 +572,7 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, ParamsEdited* p // save color management settings if (!pedited || pedited->icm.input) keyFile.set_string ("Color Management", "InputProfile", icm.input); if (!pedited || pedited->icm.blendCMSMatrix) keyFile.set_boolean ("Color Management", "BlendCMSMatrix", icm.blendCMSMatrix); + if (!pedited || pedited->icm.preferredProfile) keyFile.set_boolean ("Color Management", "PreferredProfile", icm.preferredProfile); if (!pedited || pedited->icm.working) keyFile.set_string ("Color Management", "WorkingProfile", icm.working); if (!pedited || pedited->icm.output) keyFile.set_string ("Color Management", "OutputProfile", icm.output); if (!pedited || pedited->icm.gamma) keyFile.set_string ("Color Management", "Gammafree", icm.gamma); @@ -980,6 +983,7 @@ if (keyFile.has_group ("Resize")) { if (keyFile.has_group ("Color Management")) { if (keyFile.has_key ("Color Management", "InputProfile")) { icm.input = keyFile.get_string ("Color Management", "InputProfile"); if (pedited) pedited->icm.input = true; } if (keyFile.has_key ("Color Management", "BlendCMSMatrix")) { icm.blendCMSMatrix = keyFile.get_boolean ("Color Management", "BlendCMSMatrix"); if (pedited) pedited->icm.blendCMSMatrix = true; } + if (keyFile.has_key ("Color Management", "PreferredProfile")) { icm.preferredProfile = keyFile.get_boolean ("Color Management", "PreferredProfile"); if (pedited) pedited->icm.preferredProfile = true; } if (keyFile.has_key ("Color Management", "WorkingProfile")) { icm.working = keyFile.get_string ("Color Management", "WorkingProfile"); if (pedited) pedited->icm.working = true; } if (keyFile.has_key ("Color Management", "OutputProfile")) { icm.output = keyFile.get_string ("Color Management", "OutputProfile"); if (pedited) pedited->icm.output = true; } if (keyFile.has_key ("Color Management", "Gammafree")) { icm.gamma = keyFile.get_string ("Color Management", "Gammafree"); if (pedited) pedited->icm.gamfree = true; } @@ -1271,6 +1275,7 @@ bool ProcParams::operator== (const ProcParams& other) { && raw.linenoise == other.raw.linenoise && icm.input == other.icm.input && icm.blendCMSMatrix == other.icm.blendCMSMatrix + && icm.preferredProfile == other.icm.preferredProfile && icm.working == other.icm.working && icm.output == other.icm.output && icm.gamma == other.icm.gamma diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 147f1b5b2..ec0025d73 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -407,6 +407,7 @@ class ColorManagementParams { public: Glib::ustring input; bool blendCMSMatrix; + short preferredProfile; Glib::ustring working; Glib::ustring output; static const Glib::ustring NoICMString; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 03ee3507d..4c1dc0dba 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1680,7 +1680,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams if (!findInputProfile(cmp.input, embedded, camName, &dcpProf, in)) return; if (dcpProf!=NULL) { - dcpProf->Apply(im, cmp.working); + dcpProf->Apply(im, (DCPLightType)cmp.preferredProfile, cmp.working); } else { // Calculate matrix for direct conversion raw>working space TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); @@ -1903,7 +1903,7 @@ void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams if (!findInputProfile(cmp.input, embedded, camName, &dcpProf, in)) return; if (dcpProf!=NULL) { - dcpProf->Apply(im, cmp.working); + dcpProf->Apply(im, (DCPLightType)cmp.preferredProfile, cmp.working); } else { if (in==NULL) { // Take camprofile from DCRAW diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 00961040e..1a060b977 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -68,7 +68,7 @@ WHITEBALANCE, // EvWBGreen, 0, // EvCDNEnabled:obsolete, 0, // EvCDNRadius: obsolete, 0, // EvCDNEdgeTolerance: obsolete, -0, // EvCDNEdgeSensitive: obsolete, +ALL, // EvPrefProfile, RETINEX, // EvSHEnabled, RGBCURVE, // EvSHHighlights, RGBCURVE, // EvSHShadows, diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index e849643e9..1c3699d4b 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -74,6 +74,20 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), ifromfile->set_group (opts); inone->set_group (opts); + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); + hb->show (); + Gtk::Label* ppl = Gtk::manage (new Gtk::Label (M("TP_ICM_PREFERREDPROFILE")+":")); + ppl->show (); + prefprof = Gtk::manage (new MyComboBoxText ()); + prefprof->append_text (M("TP_ICM_PREFERREDPROFILE_1")); + prefprof->append_text (M("TP_ICM_PREFERREDPROFILE_2")); + prefprof->append_text (M("TP_ICM_PREFERREDPROFILE_3")); + prefprof->append_text (M("TP_ICM_PREFERREDPROFILE_4")); + prefprof->show (); + hb->pack_start(*ppl, Gtk::PACK_SHRINK, 4); + hb->pack_start(*prefprof); + pack_start (*hb, Gtk::PACK_SHRINK, 4); + ckbBlendCMSMatrix = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_BLENDCMSMATRIX"))); ckbBlendCMSMatrix->set_sensitive (false); ckbBlendCMSMatrix->set_tooltip_text (M("TP_ICM_BLENDCMSMATRIX_TOOLTIP")); @@ -181,6 +195,7 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), wnames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::wpChanged) ); onames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::opChanged) ); wgamma->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::gpChanged) ); + prefprof->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::prefProfChanged) ); icamera->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); icameraICC->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); @@ -199,32 +214,33 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { ipc.block (true); if (pp->icm.input == "(none)" && icamera->get_state()!=Gtk::STATE_INSENSITIVE) { - inone->set_active (true); + inone->set_active (true); prefprof->set_sensitive (false); ckbBlendCMSMatrix->set_sensitive (false); } else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()==Gtk::STATE_INSENSITIVE)) { - iembedded->set_active (true); + iembedded->set_active (true); prefprof->set_sensitive (false); ckbBlendCMSMatrix->set_sensitive (false); } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state()!=Gtk::STATE_INSENSITIVE) { - icameraICC->set_active (true); + icameraICC->set_active (true); prefprof->set_sensitive (true); ckbBlendCMSMatrix->set_sensitive (true); } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state()==Gtk::STATE_INSENSITIVE) { // this is the case when (cameraICC) is instructed by packaged profiles, but ICC file is not found // therefore falling back UI to explicitly reflect the (camera) option icamera->set_active (true); + prefprof->set_sensitive (false); // RT's own are always single-illuminant ckbBlendCMSMatrix->set_sensitive (false); } else if ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()!=Gtk::STATE_INSENSITIVE) { icamera->set_active (true); - ckbBlendCMSMatrix->set_sensitive (false); + ckbBlendCMSMatrix->set_sensitive (false); prefprof->set_sensitive (false); } else { ifromfile->set_active (true); oldip = pp->icm.input.substr(5); // cut of "file:" ipDialog->set_filename (pp->icm.input.substr(5)); - ckbBlendCMSMatrix->set_sensitive (true); + ckbBlendCMSMatrix->set_sensitive (true); prefprof->set_sensitive (true); } wnames->set_active_text (pp->icm.working); @@ -238,6 +254,8 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { if (onames->get_active_row_number()==-1) onames->set_active_text (M("TP_ICM_NOICM")); + prefprof->set_active(pp->icm.preferredProfile-1); + ckbBlendCMSMatrix->set_active (pp->icm.blendCMSMatrix); onames->set_sensitive(wgamma->get_active_row_number()==0 || freegamma->get_active()); //"default" wgamma->set_sensitive(!freegamma->get_active()); @@ -249,6 +267,8 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { wnames->set_active_text(M("GENERAL_UNCHANGED")); if (!pedited->icm.output) onames->set_active_text(M("GENERAL_UNCHANGED")); + if (!pedited->icm.preferredProfile) + prefprof->set_active_text(M("GENERAL_UNCHANGED")); if (!pedited->icm.gamma){ wgamma->set_active_text(M("GENERAL_UNCHANGED")); wgamma->set_active_text(M("GENERAL_UNCHANGED")); @@ -296,6 +316,7 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) { pp->icm.working = wnames->get_active_text (); pp->icm.gamma = wgamma->get_active_text (); + pp->icm.preferredProfile = prefprof->get_active_row_number()+1; if (onames->get_active_text()==M("TP_ICM_NOICM")) pp->icm.output = ColorManagementParams::NoICMString; @@ -310,6 +331,7 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) { pedited->icm.input = !iunchanged->get_active (); pedited->icm.working = wnames->get_active_text()!=M("GENERAL_UNCHANGED"); pedited->icm.output = onames->get_active_text()!=M("GENERAL_UNCHANGED"); + pedited->icm.preferredProfile = prefprof->get_active_text()!=M("GENERAL_UNCHANGED"); pedited->icm.blendCMSMatrix = !ckbBlendCMSMatrix->get_inconsistent (); pedited->icm.gamma = wgamma->get_active_text()!=M("GENERAL_UNCHANGED"); pedited->icm.freegamma =!freegamma->get_inconsistent(); @@ -368,28 +390,33 @@ void ICMPanel::gpChanged () { } } +void ICMPanel::prefProfChanged() { + if (listener) + listener->panelChanged (EvPrefProfile, prefprof->get_active_text ()); +} + void ICMPanel::ipChanged () { std::string profname; if (inone->get_active()) { profname = "(none)"; - ckbBlendCMSMatrix->set_sensitive(false); + ckbBlendCMSMatrix->set_sensitive(false); prefprof->set_sensitive (false); } else if (iembedded->get_active ()) { profname = "(embedded)"; - ckbBlendCMSMatrix->set_sensitive(false); + ckbBlendCMSMatrix->set_sensitive(false); prefprof->set_sensitive (false); } else if (icamera->get_active ()) { profname = "(camera)"; - ckbBlendCMSMatrix->set_sensitive(false); + ckbBlendCMSMatrix->set_sensitive(false); prefprof->set_sensitive (false); } else if (icameraICC->get_active ()) { profname = "(cameraICC)"; - ckbBlendCMSMatrix->set_sensitive(true); + ckbBlendCMSMatrix->set_sensitive(true); prefprof->set_sensitive (false); } else { profname = ipDialog->get_filename (); - ckbBlendCMSMatrix->set_sensitive(true); + ckbBlendCMSMatrix->set_sensitive(true); prefprof->set_sensitive (true); } if (listener && profname!=oldip) @@ -488,6 +515,7 @@ void ICMPanel::setBatchMode (bool batchMode) { onames->append_text (M("GENERAL_UNCHANGED")); wnames->append_text (M("GENERAL_UNCHANGED")); wgamma->append_text (M("GENERAL_UNCHANGED")); + prefprof->append_text (M("GENERAL_UNCHANGED")); gampos->showEditedCB (); slpos->showEditedCB (); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 9db6e83b3..0b8c71916 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -48,6 +48,7 @@ class ICMPanel : public Gtk::VBox, public AdjusterListener, public FoldableToolP Gtk::RadioButton* icamera; Gtk::RadioButton* icameraICC; Gtk::RadioButton* ifromfile; + MyComboBoxText* prefprof; Gtk::CheckButton* ckbBlendCMSMatrix; MyComboBoxText* wnames; MyComboBoxText* wgamma; @@ -83,6 +84,7 @@ class ICMPanel : public Gtk::VBox, public AdjusterListener, public FoldableToolP void GamChanged (); void ipSelectionChanged (); void iccTogglesChanged(); + void prefProfChanged(); void setRawMeta (bool raw, const rtengine::ImageData* pMeta); void saveReferencePressed (); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index b411e3557..02be0b244 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -165,6 +165,7 @@ void ParamsEdited::set (bool v) { resize.enabled = v; icm.input = v; icm.blendCMSMatrix = v; + icm.preferredProfile = v; icm.working = v; icm.output = v; icm.gamma = v; @@ -357,6 +358,7 @@ void ParamsEdited::initFrom (const std::vector resize.enabled = resize.enabled && p.resize.enabled == other.resize.enabled; icm.input = icm.input && p.icm.input == other.icm.input; icm.blendCMSMatrix = icm.blendCMSMatrix && p.icm.blendCMSMatrix == other.icm.blendCMSMatrix; + icm.preferredProfile = icm.preferredProfile && p.icm.preferredProfile == other.icm.preferredProfile; icm.working = icm.working && p.icm.working == other.icm.working; icm.output = icm.output && p.icm.output == other.icm.output; icm.gamma = icm.gamma && p.icm.gamma == other.icm.gamma; @@ -544,6 +546,7 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten if (resize.enabled) toEdit.resize.enabled = mods.resize.enabled; if (icm.input) toEdit.icm.input = mods.icm.input; if (icm.blendCMSMatrix) toEdit.icm.blendCMSMatrix = mods.icm.blendCMSMatrix; + if (icm.preferredProfile) toEdit.icm.preferredProfile = mods.icm.preferredProfile; if (icm.working) toEdit.icm.working = mods.icm.working; if (icm.output) toEdit.icm.output = mods.icm.output; //if (icm.gampos) toEdit.icm.gampos = mods.icm.gampos; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 03ae09c2a..38a70b552 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -303,6 +303,7 @@ class ColorManagementParamsEdited { public: bool input; bool blendCMSMatrix; + bool preferredProfile; bool working; bool output; bool gamma;