diff --git a/rtdata/images/Dark/actions/intent-absolute.png b/rtdata/images/Dark/actions/intent-absolute.png
new file mode 100644
index 000000000..6d274a2c0
Binary files /dev/null and b/rtdata/images/Dark/actions/intent-absolute.png differ
diff --git a/rtdata/images/Dark/actions/intent-perceptual.png b/rtdata/images/Dark/actions/intent-perceptual.png
new file mode 100644
index 000000000..821a714ae
Binary files /dev/null and b/rtdata/images/Dark/actions/intent-perceptual.png differ
diff --git a/rtdata/images/Dark/actions/intent-relative.png b/rtdata/images/Dark/actions/intent-relative.png
new file mode 100644
index 000000000..d586b47b2
Binary files /dev/null and b/rtdata/images/Dark/actions/intent-relative.png differ
diff --git a/rtdata/images/Dark/actions/intent-saturation.png b/rtdata/images/Dark/actions/intent-saturation.png
new file mode 100644
index 000000000..0654f78b6
Binary files /dev/null and b/rtdata/images/Dark/actions/intent-saturation.png differ
diff --git a/rtdata/images/Dark/actions/softProof.png b/rtdata/images/Dark/actions/softProof.png
new file mode 100644
index 000000000..5f17df3ea
Binary files /dev/null and b/rtdata/images/Dark/actions/softProof.png differ
diff --git a/rtdata/images/Light/actions/intent-absolute.png b/rtdata/images/Light/actions/intent-absolute.png
new file mode 100644
index 000000000..fb5919181
Binary files /dev/null and b/rtdata/images/Light/actions/intent-absolute.png differ
diff --git a/rtdata/images/Light/actions/intent-perceptual.png b/rtdata/images/Light/actions/intent-perceptual.png
new file mode 100644
index 000000000..88de7b5e9
Binary files /dev/null and b/rtdata/images/Light/actions/intent-perceptual.png differ
diff --git a/rtdata/images/Light/actions/intent-relative.png b/rtdata/images/Light/actions/intent-relative.png
new file mode 100644
index 000000000..f952f4ab7
Binary files /dev/null and b/rtdata/images/Light/actions/intent-relative.png differ
diff --git a/rtdata/images/Light/actions/intent-saturation.png b/rtdata/images/Light/actions/intent-saturation.png
new file mode 100644
index 000000000..92908b030
Binary files /dev/null and b/rtdata/images/Light/actions/intent-saturation.png differ
diff --git a/rtdata/images/Light/actions/softProof.png b/rtdata/images/Light/actions/softProof.png
new file mode 100644
index 000000000..3e5eb2f18
Binary files /dev/null and b/rtdata/images/Light/actions/softProof.png differ
diff --git a/rtdata/languages/default b/rtdata/languages/default
index 2df0b7fb9..9762a38a6 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -657,6 +657,7 @@ HISTORY_MSG_423;Retinex - Gamma slope
HISTORY_MSG_424;Retinex - HL threshold
HISTORY_MSG_425;Retinex - Log base
HISTORY_MSG_426;Retinex - Hue equalizer
+HISTORY_MSG_427;Output rendering intent
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: Alt-s
HISTORY_SNAPSHOT;Snapshot
@@ -774,6 +775,8 @@ MAIN_TOOLTIP_SHOWHIDERP1;Show/Hide the right panel.\nShortcut: Alt-l
MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l
MAIN_TOOLTIP_THRESHOLD;Threshold
MAIN_TOOLTIP_TOGGLE;Toggle the Before/After view.\nShortcut: Shift-b
+MONITOR_SOFTPROOF;Soft-proof
+MONITOR_PROFILE_SYSTEM;System default
NAVIGATOR_B;B:
NAVIGATOR_G;G:
NAVIGATOR_H;H:
@@ -887,7 +890,7 @@ PREFERENCES_CLIPPINGIND;Clipping Indication
PREFERENCES_CLUTSCACHE;HaldCLUT Cache
PREFERENCES_CLUTSCACHE_LABEL;Maximum number of cached CLUTs
PREFERENCES_CLUTSDIR;HaldCLUT directory
-PREFERENCES_CMETRICINTENT;Colorimetric intent
+PREFERENCES_MONINTENT;Default monitor intent
PREFERENCES_CURVEBBOXPOS;Position of curve copypasta buttons
PREFERENCES_CURVEBBOXPOS_ABOVE;Above
PREFERENCES_CURVEBBOXPOS_BELOW;Below
@@ -982,7 +985,7 @@ PREFERENCES_MENUGROUPRANK;Group "Rank"
PREFERENCES_MENUOPTIONS;Context Menu Options
PREFERENCES_METADATA;Metadata
PREFERENCES_MIN;Mini (100x115)
-PREFERENCES_MONITORICC;Monitor color profile
+PREFERENCES_MONPROFILE;Default monitor profile
PREFERENCES_MULTITAB;Multiple Editor Tabs Mode
PREFERENCES_MULTITABDUALMON;Multiple Editor Tabs In Own Window Mode
PREFERENCES_NAVGUIDEBRUSH;Navigator guide color
@@ -1013,6 +1016,7 @@ PREFERENCES_PROFILEPRCACHE;Profile in cache
PREFERENCES_PROFILEPRFILE;Profile next to the input file
PREFERENCES_PROFILESAVECACHE;Save processing profile to the cache
PREFERENCES_PROFILESAVEINPUT;Save processing profile next to the input file
+PREFERENCES_PROFILE_NONE;None
PREFERENCES_PROPERTY;Property
PREFERENCES_PSPATH;Adobe Photoshop installation directory
PREFERENCES_REMEMBERZOOMPAN;Remember zoom % and pan offset
@@ -1514,6 +1518,7 @@ TP_ICM_INPUTPROFILE;Input Profile
TP_ICM_LABEL;Color Management
TP_ICM_NOICM;No ICM: sRGB Output
TP_ICM_OUTPUTPROFILE;Output Profile
+TP_ICM_PROFILEINTENT;Rendering Intent
TP_ICM_SAVEREFERENCE;Save Reference Image for Profiling
TP_ICM_SAVEREFERENCE_APPLYWB;Apply white balance
TP_ICM_SAVEREFERENCE_APPLYWB_TOOLTIP;Generally, apply the white balance when saving images to create ICC profiles, and do not apply the white balance to create DCP profiles.
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index a97ae7f39..2220f68c5 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -989,40 +989,6 @@ void Crop::update (int todo)
// switch back to rgb
parent->ipf.lab2monitorRgb (labnCrop, cropImg);
- //parent->ipf.lab2monitorRgb (laboCrop, cropImg);
-
- //cropImg = baseCrop->to8();
- /*
- // int xref,yref;
- xref=000;yref=000;
- if (colortest && cropw>115 && croph>115)
- for(int j=1;j<5;j++){
- xref+=j*30;yref+=j*30;
- int rlin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))]/255.0) * 255.0);
- int glin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1]/255.0) * 255.0);
- int blin = (CurveFactory::igamma2((float)cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2]/255.0) * 255.0);
-
- printf("after lab2rgb RGB lab2 Xr%i Yr%i Skip=%d R=%d G=%d B=%d \n",xref,yref,skip,
- rlin,glin,blin);
- //cropImg->data[3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))],
- //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+1)],
- //cropImg->data[(3*((int)(xref/skip)*cropImg->width+(int)(yref/skip))+2)]);
- //printf("after lab2rgb Lab lab2 Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip, labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327,labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327);
- printf("after lab2rgb Lab Xr%i Yr%i Skip=%d l=%f a=%f b=%f \n",xref,yref,skip,
- labnCrop->L[(int)(xref/skip)][(int)(yref/skip)]/327,
- labnCrop->a[(int)(xref/skip)][(int)(yref/skip)]/327,
- labnCrop->b[(int)(xref/skip)][(int)(yref/skip)]/327)q;
- }
- */
- /*
- if (colortest && cropImg->height>115 && cropImg->width>115) {//for testing
- xref=000;yref=000;
- printf("dcrop final R= %d G= %d B= %d \n",
- cropImg->data[3*xref/(skip)*(cropImg->width+1)],
- cropImg->data[3*xref/(skip)*(cropImg->width+1)+1],
- cropImg->data[3*xref/(skip)*(cropImg->width+1)+2]);
- }
- */
if (cropImageListener) {
// this in output space held in parallel to allow analysis like shadow/highlight
Glib::ustring outProfile = params.icm.output;
@@ -1030,13 +996,13 @@ void Crop::update (int todo)
Image8 *cropImgtrue;
if(settings->HistogramWorking) {
- cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, workProfile, false);
+ cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, workProfile, RI_RELATIVE, false); // HOMBRE: was RELATIVE by default in lab2rgb, is it safe to assume we have to use it again ?
} else {
if (params.icm.output == "" || params.icm.output == ColorManagementParams::NoICMString) {
outProfile = "sRGB";
}
- cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, outProfile, false);
+ cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, outProfile, params.icm.outputIntent, false);
}
int finalW = rqcropw;
diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc
index bad4e8dfa..b77da03dd 100644
--- a/rtengine/iccstore.cc
+++ b/rtengine/iccstore.cc
@@ -29,9 +29,90 @@
#include
-namespace rtengine
+namespace
{
+void loadProfiles (const Glib::ustring& dirName,
+ std::map* profiles,
+ std::map* profileContents,
+ std::map* profileNames,
+ bool nameUpper, bool onlyRgb)
+{
+ if (dirName.empty ())
+ return;
+
+ try {
+
+ Glib::Dir dir (dirName);
+
+ for (Glib::DirIterator entry = dir.begin (); entry != dir.end (); ++entry) {
+
+ const Glib::ustring fileName = *entry;
+
+ if (fileName.size () < 4)
+ continue;
+
+ const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold ();
+
+ if (extension.compare(".icc") == 0 && extension.compare(".icm") == 0)
+ continue;
+
+ const Glib::ustring filePath = Glib::build_filename (dirName, fileName);
+
+ if (!safe_file_test (filePath, Glib::FILE_TEST_IS_REGULAR))
+ continue;
+
+ Glib::ustring name = fileName.substr (0, fileName.size() - 4);
+
+ if (nameUpper)
+ name = name.uppercase ();
+
+ if (profiles) {
+ const rtengine::ProfileContent content (filePath);
+ const cmsHPROFILE profile = content.toProfile ();
+
+ if (profile && (!onlyRgb || cmsGetColorSpace (profile) == cmsSigRgbData)) {
+ profiles->insert (std::make_pair (name, profile));
+
+ if (profileContents)
+ profileContents->insert (std::make_pair (name, content));
+ }
+ }
+
+ if (profileNames)
+ profileNames->insert (std::make_pair (name, filePath));
+ }
+ }
+ catch (Glib::Exception&) {}
+}
+
+inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, std::uint8_t& result)
+{
+ if (cmsIsIntentSupported (profile, intent, direction))
+ result |= 1 << intent;
+}
+
+inline std::uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number direction)
+{
+ if (!profile)
+ return 0;
+
+ std::uint8_t result = 0;
+
+ getSupportedIntent (profile, INTENT_PERCEPTUAL, direction, result);
+ getSupportedIntent (profile, INTENT_RELATIVE_COLORIMETRIC, direction, result);
+ getSupportedIntent (profile, INTENT_SATURATION, direction, result);
+ getSupportedIntent (profile, INTENT_ABSOLUTE_COLORIMETRIC, direction, result);
+
+ return result;
+}
+
+inline cmsHPROFILE createXYZProfile ()
+{
+ double mat[3][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0} };
+ return rtengine::ICCStore::createFromMatrix (mat, false, "XYZ");
+}
+
const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best};
const double (*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz};
const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB"};
@@ -43,8 +124,12 @@ const char* wpgamma[] = {"default", "BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "line
// high g=1.3 s=3.35 for high dynamic images
//low g=2.6 s=6.9 for low contrast images
+}
-std::vector getGamma () //return gamma
+namespace rtengine
+{
+
+std::vector getGamma ()
{
std::vector res;
@@ -56,7 +141,6 @@ std::vector getGamma () //return gamma
return res;
}
-
std::vector getWorkingProfiles ()
{
@@ -69,32 +153,38 @@ std::vector getWorkingProfiles ()
return res;
}
-std::vector ICCStore::getOutputProfiles ()
+std::vector ICCStore::getProfiles () const
{
MyMutex::MyLock lock(mutex_);
std::vector res;
- for (std::map::iterator i = fileProfiles.begin(); i != fileProfiles.end(); i++) {
- Glib::ustring name(i->first);
- std::string::size_type i2 = name.find_last_of('/');
-
- if( i2 == std::string::npos ) {
- i2 = name.find_last_of('\\');
- }
-
- if( i2 == std::string::npos ) {
- res.push_back ( name ); // list only profiles inside selected profiles directory
- }
- }
+ for (ProfileMap::const_iterator profile = fileProfiles.begin (); profile != fileProfiles.end (); ++profile)
+ res.push_back (profile->first);
return res;
}
+std::vector ICCStore::getProfilesFromDir (const Glib::ustring& dirName) const
+{
-cmsHPROFILE
-ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
+ MyMutex::MyLock lock(mutex_);
+
+ std::vector res;
+
+ ProfileMap profiles;
+
+ loadProfiles (profilesDir, &profiles, NULL, NULL, false, true);
+ loadProfiles (dirName, &profiles, NULL, NULL, false, true);
+
+ for (ProfileMap::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile)
+ res.push_back (profile->first);
+
+ return res;
+}
+
+cmsHPROFILE ICCStore::makeStdGammaProfile (cmsHPROFILE iprof)
{
// forgive me for the messy code, quick hack to change gamma of an ICC profile to the RT standard gamma
if (!iprof) {
@@ -189,14 +279,15 @@ ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
return oprof;
}
-ICCStore*
-ICCStore::getInstance(void)
+ICCStore* ICCStore::getInstance ()
{
static ICCStore instance_;
return &instance_;
}
-ICCStore::ICCStore ()
+ICCStore::ICCStore () :
+ xyz (createXYZProfile ()),
+ srgb (cmsCreate_sRGBProfile ())
{
//cmsErrorAction (LCMS_ERROR_SHOW);
@@ -208,234 +299,172 @@ ICCStore::ICCStore ()
wMatrices[wpnames[i]] = wprofiles[i];
iwMatrices[wpnames[i]] = iwprofiles[i];
}
-
- double mat[3][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0}};
- xyz = createFromMatrix (mat, false, "XYZ");
- srgb = cmsCreate_sRGBProfile ();
}
-int ICCStore::numOfWProfiles ()
+TMatrix ICCStore::workingSpaceMatrix (const Glib::ustring& name) const
{
- return sizeof(wpnames) / sizeof(wpnames[0]);
-}
-
-TMatrix ICCStore::workingSpaceMatrix (Glib::ustring name)
-{
-
- std::map::iterator r = wMatrices.find (name);
+ const MatrixMap::const_iterator r = wMatrices.find (name);
if (r != wMatrices.end()) {
return r->second;
} else {
- return wMatrices["sRGB"];
+ return wMatrices.find ("sRGB")->second;
}
}
-TMatrix ICCStore::workingSpaceInverseMatrix (Glib::ustring name)
+TMatrix ICCStore::workingSpaceInverseMatrix (const Glib::ustring& name) const
{
- std::map::iterator r = iwMatrices.find (name);
+ const MatrixMap::const_iterator r = iwMatrices.find (name);
if (r != iwMatrices.end()) {
return r->second;
} else {
- return iwMatrices["sRGB"];
+ return iwMatrices.find ("sRGB")->second;
}
}
-cmsHPROFILE ICCStore::workingSpace (Glib::ustring name)
+cmsHPROFILE ICCStore::workingSpace (const Glib::ustring& name) const
{
- std::map::iterator r = wProfiles.find (name);
+ const ProfileMap::const_iterator r = wProfiles.find (name);
if (r != wProfiles.end()) {
return r->second;
} else {
- return wProfiles["sRGB"];
+ return wProfiles.find ("sRGB")->second;
}
}
-cmsHPROFILE ICCStore::workingSpaceGamma (Glib::ustring name)
+cmsHPROFILE ICCStore::workingSpaceGamma (const Glib::ustring& name) const
{
- std::map::iterator r = wProfilesGamma.find (name);
+ const ProfileMap::const_iterator r = wProfilesGamma.find (name);
if (r != wProfilesGamma.end()) {
return r->second;
} else {
- return wProfilesGamma["sRGB"];
+ return wProfilesGamma.find ("sRGB")->second;
}
}
-cmsHPROFILE ICCStore::getProfile (Glib::ustring name)
+cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const
{
MyMutex::MyLock lock(mutex_);
- std::map::iterator r = fileProfiles.find (name);
+ const ProfileMap::const_iterator r = fileProfiles.find (name);
- if (r != fileProfiles.end()) {
+ if (r != fileProfiles.end ())
return r->second;
- } else {
- if (!name.compare (0, 5, "file:") && safe_file_test (name.substr(5), Glib::FILE_TEST_EXISTS) && !safe_file_test (name.substr(5), Glib::FILE_TEST_IS_DIR)) {
- ProfileContent pc (name.substr(5));
- if (pc.data) {
- cmsHPROFILE profile = pc.toProfile ();
+ if (name.compare (0, 5, "file:") == 0) {
+ const ProfileContent content (name.substr (5));
+ const cmsHPROFILE profile = content.toProfile ();
- if (profile) {
- fileProfiles[name] = profile;
- fileProfileContents[name] = pc;
- return profile;
- }
- }
+ if (profile) {
+ const_cast(fileProfiles).insert(std::make_pair(name, profile));
+ const_cast(fileProfileContents).insert(std::make_pair(name, content));
+
+ return profile;
}
}
return NULL;
}
-cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name)
+cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const
{
+ const Glib::ustring nameUpper = name.uppercase ();
+
MyMutex::MyLock lock(mutex_);
- std::map::iterator r = fileStdProfiles.find (name.uppercase());
+ const ProfileMap::const_iterator r = fileStdProfiles.find (nameUpper);
- if (r == fileStdProfiles.end()) {
- // profile is not yet in store
- std::map::iterator f = fileStdProfilesFileNames.find (name.uppercase());
-
- if(f != fileStdProfilesFileNames.end()) {
- // but there exists one => load it
- ProfileContent pc (f->second);
-
- if (pc.data) {
- cmsHPROFILE profile = pc.toProfile ();
-
- if (profile) {
- fileStdProfiles[name.uppercase()] = profile;
- }
-
- // profile is not valid or it is now stored => remove entry from fileStdProfilesFileNames
- fileStdProfilesFileNames.erase(f);
- return profile;
- } else {
- // profile not valid => remove entry from fileStdProfilesFileNames
- fileStdProfilesFileNames.erase(f);
- return NULL;
- }
- } else {
- // profile does not exist
- return NULL;
- }
- } else {
- // return profile from store
+ // return profile from store
+ if (r != fileStdProfiles.end ())
return r->second;
- }
+
+ // profile is not yet in store
+ const NameMap::const_iterator f = fileStdProfilesFileNames.find (nameUpper);
+
+ // profile does not exist
+ if (f == fileStdProfilesFileNames.end ())
+ return NULL;
+
+ // but there exists one => load it
+ const ProfileContent content (f->second);
+ const cmsHPROFILE profile = content.toProfile ();
+
+ if (profile)
+ const_cast(fileStdProfiles).insert (std::make_pair (f->first, profile));
+
+ // profile is not valid or it is now stored => remove entry from fileStdProfilesFileNames
+ const_cast(fileStdProfilesFileNames).erase (f);
+ return profile;
}
-ProfileContent ICCStore::getContent (Glib::ustring name)
+ProfileContent ICCStore::getContent (const Glib::ustring& name) const
{
MyMutex::MyLock lock(mutex_);
- return fileProfileContents[name];
+ const ContentMap::const_iterator r = fileProfileContents.find (name);
+
+ return r != fileProfileContents.end () ? r->second : ProfileContent();
+}
+
+std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const
+{
+
+ MyMutex::MyLock lock (mutex_);
+
+ return getSupportedIntents (profile, LCMS_USED_AS_INPUT);
+}
+
+std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const
+{
+
+ MyMutex::MyLock lock (mutex_);
+
+ return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT);
+}
+
+std::uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const
+{
+
+ MyMutex::MyLock lock (mutex_);
+
+ return getSupportedIntents (profile, LCMS_USED_AS_PROOF);
}
// Reads all profiles from the given profiles dir
-void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring rtICCDir)
+void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCDir)
{
MyMutex::MyLock lock(mutex_);
- //
+ // RawTherapee's profiles take precedence if a user's profile of the same name exists
+ profilesDir = Glib::build_filename (rtICCDir, "output");
fileProfiles.clear();
fileProfileContents.clear();
- // RawTherapee's profiles take precedence if a user's profile of the same name exists
- loadICCs(Glib::build_filename(rtICCDir, "output"), false, fileProfiles, &fileProfileContents, true, true);
- loadICCs(usrICCDir, false, fileProfiles, &fileProfileContents, true, true);
+ loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, NULL, false, true);
+ loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, NULL, false, true);
// Input profiles
// Load these to different areas, since the short name (e.g. "NIKON D700" may overlap between system/user and RT dir)
+ stdProfilesDir = Glib::build_filename (rtICCDir, "input");
fileStdProfiles.clear();
fileStdProfilesFileNames.clear();
- loadICCs(Glib::build_filename(rtICCDir, "input"), true, fileStdProfiles, NULL);
-}
-
-void ICCStore::loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch, bool onlyRgb)
-{
- if (rootDirName != "") {
- std::deque qDirs;
-
- qDirs.push_front(rootDirName);
-
- while (!qDirs.empty()) {
- // process directory
- Glib::ustring dirname = qDirs.back();
- qDirs.pop_back();
-
- Glib::Dir* dir = NULL;
-
- try {
- if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) {
- return;
- }
-
- dir = new Glib::Dir (dirname);
- } catch (Glib::Exception& fe) {
- return;
- }
-
- dirname = dirname + "/";
-
- for (Glib::DirIterator i = dir->begin(); i != dir->end(); ++i) {
- Glib::ustring fname = dirname + *i;
- Glib::ustring sname = *i;
-
- // ignore directories
- if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) {
- size_t lastdot = sname.find_last_of ('.');
-
- if (lastdot != Glib::ustring::npos && lastdot <= sname.size() - 4 && (!sname.casefold().compare (lastdot, 4, ".icm") || !sname.casefold().compare (lastdot, 4, ".icc"))) {
- Glib::ustring name = nameUpper ? sname.substr(0, lastdot).uppercase() : sname.substr(0, lastdot);
-
- if(!prefetch) {
- fileStdProfilesFileNames[name] = fname;
- } else {
- ProfileContent pc (fname);
-
- if (pc.data) {
- cmsHPROFILE profile = pc.toProfile ();
-
- if (profile && (!onlyRgb || cmsGetColorSpace(profile) == cmsSigRgbData)) {
- resultProfiles[name] = profile;
-
- if(resultProfileContents) {
- (*resultProfileContents)[name] = pc;
- }
- }
- }
- }
- }
- }
-
- // Removed recursive scanning, see issue #1730.
- // To revert to the recursive method, just uncomment the next line.
-
- //else qDirs.push_front(fname); // for later scanning
- }
-
- delete dir;
- }
- }
+ loadProfiles (stdProfilesDir, NULL, NULL, &fileStdProfilesFileNames, true, false);
}
// Determine the first monitor default profile of operating system, if selected
-void ICCStore::findDefaultMonitorProfile()
+void ICCStore::findDefaultMonitorProfile ()
{
- defaultMonitorProfile = "";
+ defaultMonitorProfile.clear ();
#ifdef WIN32
// Get current main monitor. Could be fine tuned to get the current windows monitor (multi monitor setup),
@@ -449,6 +478,11 @@ void ICCStore::findDefaultMonitorProfile()
if (GetICMProfileA(hDC, &profileLength, profileName)) {
defaultMonitorProfile = Glib::ustring(profileName);
+ defaultMonitorProfile = Glib::path_get_basename(defaultMonitorProfile);
+ size_t pos = defaultMonitorProfile.rfind(".");
+ if (pos != Glib::ustring::npos) {
+ defaultMonitorProfile = defaultMonitorProfile.substr(0, pos);
+ }
}
// might fail if e.g. the monitor has no profile
@@ -466,7 +500,7 @@ void ICCStore::findDefaultMonitorProfile()
}
}
-ProfileContent::ProfileContent (Glib::ustring fileName) : data(NULL), length(0)
+ProfileContent::ProfileContent (const Glib::ustring& fileName) : data(NULL), length(0)
{
FILE* f = safe_g_fopen (fileName, "rb");
@@ -518,9 +552,7 @@ ProfileContent& ProfileContent::operator= (const ProfileContent& other)
length = other.length;
- if (data) {
- delete [] data;
- }
+ delete [] data;
if (other.data) {
data = new char[length + 1];
@@ -532,15 +564,7 @@ ProfileContent& ProfileContent::operator= (const ProfileContent& other)
return *this;
}
-ProfileContent::~ProfileContent ()
-{
-
- if (data) {
- delete [] data;
- }
-}
-
-cmsHPROFILE ProfileContent::toProfile ()
+cmsHPROFILE ProfileContent::toProfile () const
{
if (data) {
@@ -550,7 +574,7 @@ cmsHPROFILE ProfileContent::toProfile ()
}
}
-cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, Glib::ustring name)
+cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, const Glib::ustring& name)
{
static const unsigned phead[] = {
@@ -644,4 +668,5 @@ cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, G
delete [] oprof;
return p;
}
+
}
diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h
index acb31e4cf..8b6e6465c 100644
--- a/rtengine/iccstore.h
+++ b/rtengine/iccstore.h
@@ -37,74 +37,135 @@ public:
char* data;
int length;
- ProfileContent (): data(NULL), length(0) {}
- ProfileContent (Glib::ustring fileName);
- ProfileContent (const ProfileContent& other);
- ProfileContent (cmsHPROFILE hProfile);
+ ProfileContent ();
~ProfileContent ();
+
+ ProfileContent (const ProfileContent& other);
ProfileContent& operator= (const rtengine::ProfileContent& other);
- cmsHPROFILE toProfile ();
+
+ ProfileContent (const Glib::ustring& fileName);
+ ProfileContent (cmsHPROFILE hProfile);
+ cmsHPROFILE toProfile () const;
};
class ICCStore
{
+ typedef std::map ProfileMap;
+ typedef std::map MatrixMap;
+ typedef std::map ContentMap;
+ typedef std::map NameMap;
- std::map wProfiles;
- std::map wProfilesGamma;
- std::map wMatrices;
- std::map iwMatrices;
+ ProfileMap wProfiles;
+ ProfileMap wProfilesGamma;
+ MatrixMap wMatrices;
+ MatrixMap iwMatrices;
// these contain profiles from user/system directory (supplied on init)
- std::map fileProfiles;
- std::map fileProfileContents;
+ Glib::ustring profilesDir;
+ ProfileMap fileProfiles;
+ ContentMap fileProfileContents;
// these contain standard profiles from RT. keys are all in uppercase
- std::map fileStdProfilesFileNames;
- std::map fileStdProfiles;
+ Glib::ustring stdProfilesDir;
+ NameMap fileStdProfilesFileNames;
+ ProfileMap fileStdProfiles;
- cmsHPROFILE xyz;
- cmsHPROFILE srgb;
+ Glib::ustring defaultMonitorProfile;
- MyMutex mutex_;
+ const cmsHPROFILE xyz;
+ const cmsHPROFILE srgb;
+
+ mutable MyMutex mutex_;
ICCStore ();
- void loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map *resultProfileContents, bool prefetch = false, bool onlyRgb = false);
public:
- static ICCStore* getInstance(void);
- static cmsHPROFILE makeStdGammaProfile(cmsHPROFILE iprof);
+ static ICCStore* getInstance ();
- Glib::ustring defaultMonitorProfile; // Main monitors standard profile name, from OS
- void findDefaultMonitorProfile();
+ void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir);
- int numOfWProfiles ();
- cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, Glib::ustring name = "");
- cmsHPROFILE workingSpace (Glib::ustring name);
- cmsHPROFILE workingSpaceGamma (Glib::ustring name);
- TMatrix workingSpaceMatrix (Glib::ustring name);
- TMatrix workingSpaceInverseMatrix (Glib::ustring name);
+ static cmsHPROFILE makeStdGammaProfile (cmsHPROFILE iprof);
+ static cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring());
- cmsHPROFILE getProfile (Glib::ustring name);
- cmsHPROFILE getStdProfile(Glib::ustring name);
+ // Main monitors standard profile name, from OS
+ void findDefaultMonitorProfile ();
+ cmsHPROFILE getDefaultMonitorProfile () const;
+ Glib::ustring getDefaultMonitorProfileName () const;
- void init (Glib::ustring usrICCDir, Glib::ustring stdICCDir);
- ProfileContent getContent (Glib::ustring name);
+ cmsHPROFILE workingSpace (const Glib::ustring& name) const;
+ cmsHPROFILE workingSpaceGamma (const Glib::ustring& name) const;
+ TMatrix workingSpaceMatrix (const Glib::ustring& name) const;
+ TMatrix workingSpaceInverseMatrix (const Glib::ustring& name) const;
- cmsHPROFILE getXYZProfile ()
- {
- return xyz;
- }
- cmsHPROFILE getsRGBProfile ()
- {
- return srgb;
- }
- std::vector getOutputProfiles ();
+ cmsHPROFILE getProfile (const Glib::ustring& name) const;
+ cmsHPROFILE getStdProfile (const Glib::ustring& name) const;
+ ProfileContent getContent (const Glib::ustring& name) const;
+
+ cmsHPROFILE getXYZProfile () const;
+ cmsHPROFILE getsRGBProfile () const;
+
+ std::vector getProfiles () const;
+ std::vector getProfilesFromDir (const Glib::ustring& dirName) const;
+
+ std::uint8_t getInputIntents (cmsHPROFILE profile) const;
+ std::uint8_t getOutputIntents (cmsHPROFILE profile) const;
+ std::uint8_t getProofIntents (cmsHPROFILE profile) const;
+
+ std::uint8_t getInputIntents (const Glib::ustring& name) const;
+ std::uint8_t getOutputIntents (const Glib::ustring& name) const;
+ std::uint8_t getProofIntents (const Glib::ustring& name) const;
};
#define iccStore ICCStore::getInstance()
-//extern const char* wpnames[];
+inline ProfileContent::ProfileContent () :
+ data(NULL),
+ length(0)
+{
}
+
+inline ProfileContent::~ProfileContent ()
+{
+ delete [] data;
+}
+
+inline cmsHPROFILE ICCStore::getDefaultMonitorProfile () const
+{
+ return getProfile (defaultMonitorProfile);
+}
+
+inline Glib::ustring ICCStore::getDefaultMonitorProfileName () const
+{
+ return defaultMonitorProfile;
+}
+
+inline std::uint8_t ICCStore::getInputIntents (const Glib::ustring &name) const
+{
+ return getInputIntents (getProfile (name));
+}
+
+inline std::uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) const
+{
+ return getOutputIntents (getProfile (name));
+}
+
+inline std::uint8_t ICCStore::getProofIntents (const Glib::ustring &name) const
+{
+ return getProofIntents (getProfile (name));
+}
+
+inline cmsHPROFILE ICCStore::getXYZProfile () const
+{
+ return xyz;
+}
+
+inline cmsHPROFILE ICCStore::getsRGBProfile () const
+{
+ return srgb;
+}
+
+}
+
#endif
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index 8389ec34e..96a55989e 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -31,7 +31,7 @@ extern const Settings* settings;
ImProcCoordinator::ImProcCoordinator ()
: orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL),
- ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(¶ms, true), scale(10),
+ ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(¶ms, true), monitorIntent(RI_RELATIVE), scale(10),
highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false),
bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(0.),
@@ -781,6 +781,11 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
}
+ // Update the monitor color transform if necessary
+ if (todo & M_MONITOR) {
+ ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent);
+ }
+
// process crop, if needed
for (size_t i = 0; i < crops.size(); i++)
if (crops[i]->hasListener () && cropCall != crops[i] ) {
@@ -794,7 +799,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
progress ("Conversion to RGB...", 100 * readyphase / numofphases);
- if (todo != CROP && todo != MINUPDATE) {
+ if ((todo != CROP && todo != MINUPDATE) || (todo & M_MONITOR)) {
MyMutex::MyLock prevImgLock(previmg->getMutex());
try {
@@ -804,13 +809,13 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
if(settings->HistogramWorking) {
Glib::ustring workProfile = params.icm.working;
- workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, workProfile, true);
+ workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, workProfile, RI_RELATIVE, true); // HOMBRE: was RELATIVE by default in lab2rgb, is it safe to assume we have to use it again ?
} else {
- if (params.icm.output == "" || params.icm.output == ColorManagementParams::NoICMString) {
+ if (params.icm.output.empty() || params.icm.output == ColorManagementParams::NoICMString) {
outProfile = "sRGB";
}
- workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, outProfile, false);
+ workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, outProfile, params.icm.outputIntent, false);
}
} catch(char * str) {
progress ("Error converting file...", 0);
@@ -1126,6 +1131,17 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &
y = (fullh - h) / 2;
}
+void ImProcCoordinator::setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent)
+{
+ monitorProfile = profile;
+ monitorIntent = intent;
+}
+
+void ImProcCoordinator::getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const
+{
+ profile = monitorProfile;
+ intent = monitorIntent;
+}
void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb)
{
diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h
index ef981fe6a..4d442482e 100644
--- a/rtengine/improccoordinator.h
+++ b/rtengine/improccoordinator.h
@@ -72,6 +72,10 @@ protected:
ImProcFunctions ipf;
+ Glib::ustring monitorProfile;
+
+ RenderingIntent monitorIntent;
+
int scale;
bool highDetailPreprocessComputed;
bool highDetailRawComputed;
@@ -249,6 +253,9 @@ public:
void getSpotWB (int x, int y, int rectSize, double& temp, double& green);
void getAutoCrop (double ratio, int &x, int &y, int &w, int &h);
+ void setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent);
+ void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const;
+
bool updateTryLock ()
{
return updaterThreadStart.trylock();
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index f21748a3b..b1f47c3a9 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -140,58 +140,10 @@ void ImProcFunctions::firstAnalysisThread (Imagefloat* original, Glib::ustring w
}
}
}
-/*
-void ImProcFunctions::CAT02 (Imagefloat* baseImg, const ProcParams* params)
+
+void ImProcFunctions::updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent)
{
- const double toxyz[3][3] = {{0.7976749, 0.1351917, 0.0313534},
- {0.2880402, 0.7118741, 0.0000857},
- {0.0000000, 0.0000000, 0.8252100}};
-
- const double xyzto[3][3] = {{1.3459433, -0.2556075, -0.0511118},
- {-0.5445989, 1.5081673, 0.0205351},
- {0.0000000, 0.0000000, 1.2118128}};
- int fw = baseImg->width;
- int fh = baseImg->height;
-
- double CAM02BB00,CAM02BB01,CAM02BB02,CAM02BB10,CAM02BB11,CAM02BB12,CAM02BB20,CAM02BB21,CAM02BB22;
- double Xxx,Yyy,Zzz;
- // Xxx=1.09844;
- // Yyy=1.0;
- // Zzz=0.355961;
- //params.wb.temperature, params.wb.green, params.wb.method
- double Xxyz, Zxyz;
-// ColorTemp::temp2mulxyz (params->wb.temperature, params->wb.green, params->wb.method, Xxyz, Zxyz);
- ColorTemp::temp2mulxyz (5000.0, 1.0, "Camera", Xxyz, Zxyz);
-
- ColorTemp::cieCAT02(Xxx, Yyy, Zzz, CAM02BB00,CAM02BB01,CAM02BB02,CAM02BB10,CAM02BB11,CAM02BB12,CAM02BB20,CAM02BB21,CAM02BB22);
- printf("00=%f 01=%f 11=%f 20=%f 22=%f\n", CAM02BB00,CAM02BB01,CAM02BB11,CAM02BB20,CAM02BB22);
-
-
- for (int i=0; ir(i,j);
- float g = baseImg->g(i,j);
- float b = baseImg->b(i,j);
-
- float x = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b;
- float y = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b;
- float z = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b;
- float Xcam=CAM02BB00* x +CAM02BB01* y + CAM02BB02* z ;
- float Ycam=CAM02BB10* x +CAM02BB11* y + CAM02BB12* z ;
- float Zcam=CAM02BB20* x +CAM02BB21* y + CAM02BB22* z ;
- baseImg->r(i,j) = xyzto[0][0] * Xcam + xyzto[0][1] * Ycam + xyzto[0][2] * Zcam;
- baseImg->g(i,j) = xyzto[1][0] * Xcam + xyzto[1][1] * Ycam + xyzto[1][2] * Zcam;
- baseImg->b(i,j) = xyzto[2][0] * Xcam + xyzto[2][1] * Ycam + xyzto[2][2] * Zcam;
- }
- }
-}
-*/
-void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram)
-{
-
// set up monitor transform
- Glib::ustring wprofile = params->icm.working;
-
if (monitorTransform != NULL) {
cmsDeleteTransform (monitorTransform);
}
@@ -209,43 +161,38 @@ void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* par
lab2outputTransform = NULL;
#if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB
- Glib::ustring monitorProfile = settings->monitorProfile;
-#if defined(WIN32)
- if (settings->autoMonitorProfile) {
- monitorProfile = iccStore->defaultMonitorProfile;
- }
-
-#endif
-
- cmsHPROFILE monitor = iccStore->getProfile ("file:" + monitorProfile);
+ cmsHPROFILE monitor = iccStore->getProfile (monitorProfile);
if (monitor) {
- lcmsMutex->lock ();
+ MyMutex::MyLock lcmsLock (*lcmsMutex);
cmsHPROFILE iprof = cmsCreateLab4Profile(NULL);
- monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC,
+ monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is for thread safety, NOOPTIMIZE for precision
Glib::ustring outputProfile;
- if (params->icm.output != "" && params->icm.output != ColorManagementParams::NoICMString) {
- outputProfile = params->icm.output;
+ if (!icm.output.empty() && icm.output != ColorManagementParams::NoICMString) {
+ outputProfile = icm.output;
cmsHPROFILE jprof = iccStore->getProfile(outputProfile);
if (jprof) {
- lab2outputTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, jprof, TYPE_RGB_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE );
-
- if (monitor) {
- output2monitorTransform = cmsCreateTransform (jprof, TYPE_RGB_FLT, monitor, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE );
- }
+ lab2outputTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, jprof, TYPE_RGB_FLT, icm.outputIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE );
+ output2monitorTransform = cmsCreateTransform (jprof, TYPE_RGB_FLT, monitor, TYPE_RGB_8, monitorIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE );
}
}
cmsCloseProfile(iprof);
- lcmsMutex->unlock ();
}
#endif
+}
+
+void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* params, LUTu & histogram)
+{
+
+ Glib::ustring wprofile = params->icm.working;
+
// calculate histogram of the y channel needed for contrast curve calculation in exposure adjustments
int T = 1;
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index cfabbba64..ec81f26eb 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -233,6 +233,7 @@ public:
bool needsPCVignetting ();
void firstAnalysis (Imagefloat* working, const ProcParams* params, LUTu & vhist16);
+ void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent);
void rgbProc (Imagefloat* working, LabImage* lab, EditBuffer *editBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2,
const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf);
@@ -379,9 +380,9 @@ public:
void Badpixelscam(CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad);
void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom);
- Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool standard_gamma);
- Image16* lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw);// for gamma output
- Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool bw);//without gamma ==>default
+ Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool standard_gamma);
+ Image16* lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw);// for gamma output
+ Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool bw);//without gamma ==>default
// CieImage *ciec;
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = NULL);
diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc
index cc01b783f..c36e185d0 100644
--- a/rtengine/iplab2rgb.cc
+++ b/rtengine/iplab2rgb.cc
@@ -134,7 +134,7 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
}
}
-Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool standard_gamma)
+Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool standard_gamma)
{
//gamutmap(lab);
@@ -167,7 +167,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
lcmsMutex->lock ();
cmsHPROFILE hLab = cmsCreateLab4Profile(NULL);
- cmsHTRANSFORM hTransform = cmsCreateTransform (hLab, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, INTENT_RELATIVE_COLORIMETRIC,
+ cmsHTRANSFORM hTransform = cmsCreateTransform (hLab, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, intent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety
cmsCloseProfile(hLab);
lcmsMutex->unlock ();
@@ -259,7 +259,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
return image;
}
// for default (not gamma)
-Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, bool bw)
+Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool bw)
{
//gamutmap(lab);
@@ -322,7 +322,7 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock ();
- cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_16, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
+ cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_16, intent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
lcmsMutex->unlock ();
image->ExecCMSTransform(hTransform);
@@ -363,7 +363,7 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
// for gamma options (BT709...sRGB linear...)
-Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw)
+Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw)
{
//gamutmap(lab);
@@ -593,7 +593,7 @@ Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int
cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock ();
- cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
+ cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, intent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
lcmsMutex->unlock ();
image->ExecCMSTransform(hTransform);
diff --git a/rtengine/procevents.h b/rtengine/procevents.h
index 4dbbad07c..21ecf5a83 100644
--- a/rtengine/procevents.h
+++ b/rtengine/procevents.h
@@ -454,6 +454,8 @@ enum ProcEvent {
EvLbaselog = 424,
// EvLgrbl = 425,
EvRetinexlhcurve = 425,
+ EvOIntent = 426,
+ EvMonitorTransform = 427,
NUMOFEVENTS
};
}
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index becd8932e..613334469 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -894,6 +894,7 @@ void ColorManagementParams::setDefaults()
dcpIlluminant = 0;
working = "ProPhoto";
output = "RT_sRGB";
+ outputIntent = RI_RELATIVE;
gamma = "default";
gampos = 2.22;
slpos = 4.5;
@@ -2548,6 +2549,27 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
keyFile.set_string ("Color Management", "OutputProfile", icm.output);
}
+ if (!pedited || pedited->icm.outputIntent) {
+ Glib::ustring intent;
+ switch (icm.outputIntent) {
+ default:
+ case RI_PERCEPTUAL:
+ intent = "Perceptual";
+ break;
+ case RI_RELATIVE:
+ intent = "Relative";
+ break;
+ case RI_SATURATION:
+ intent = "Saturation";
+ break;
+ case RI_ABSOLUTE:
+ intent = "Absolute";
+ break;
+ }
+
+ keyFile.set_string ("Color Management", "OutputProfileIntent", intent);
+ }
+
if (!pedited || pedited->icm.gamma) {
keyFile.set_string ("Color Management", "Gammafree", icm.gamma);
}
@@ -5672,6 +5694,23 @@ int ProcParams::load (Glib::ustring fname, ParamsEdited* pedited)
}
}
+ if (keyFile.has_key ("Color Management", "OutputProfileIntent")) {
+ Glib::ustring intent = keyFile.get_string ("Color Management", "OutputProfileIntent");
+ if (intent == "Perceptual") {
+ icm.outputIntent = RI_PERCEPTUAL;
+ } else if (intent == "Relative") {
+ icm.outputIntent = RI_RELATIVE;
+ } else if (intent == "Saturation") {
+ icm.outputIntent = RI_SATURATION;
+ } else if (intent == "Absolute") {
+ icm.outputIntent = RI_ABSOLUTE;
+ }
+
+ if (pedited) {
+ pedited->icm.outputIntent = true;
+ }
+ }
+
if (keyFile.has_key ("Color Management", "Gammafree")) {
icm.gamma = keyFile.get_string ("Color Management", "Gammafree");
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index d46fd4181..1103d274d 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "LUT.h"
#include "coord.h"
@@ -41,6 +42,14 @@ class WavOpacityCurveW;
class WavOpacityCurveWL;
class RetinextransmissionCurve;
+enum RenderingIntent {
+ RI_PERCEPTUAL = INTENT_PERCEPTUAL,
+ RI_RELATIVE = INTENT_RELATIVE_COLORIMETRIC,
+ RI_SATURATION = INTENT_SATURATION,
+ RI_ABSOLUTE = INTENT_ABSOLUTE_COLORIMETRIC,
+ RI__COUNT
+};
+
namespace procparams
{
@@ -941,6 +950,7 @@ public:
int dcpIlluminant;
Glib::ustring working;
Glib::ustring output;
+ RenderingIntent outputIntent;
static const Glib::ustring NoICMString;
Glib::ustring gamma;
diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc
index 3505da24f..f31300a64 100644
--- a/rtengine/refreshmap.cc
+++ b/rtengine/refreshmap.cc
@@ -64,9 +64,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
DARKFRAME, // EvLCPUseVign,
TRANSFORM, // EvLCPUseCA,
M_VOID, // EvFixedExp
- WHITEBALANCE, // EvWBMethod,
- WHITEBALANCE, // EvWBTemp,
- WHITEBALANCE, // EvWBGreen,
+ ALLNORAW, // EvWBMethod,
+ ALLNORAW, // EvWBTemp,
+ ALLNORAW, // EvWBGreen,
RGBCURVE, // EvToneCurveMode1,
RGBCURVE, // EvToneCurve2,
RGBCURVE, // EvToneCurveMode2,
@@ -75,7 +75,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
0, // EvCDNEnabled:obsolete,
ALL, // EvBlendCMSMatrix,
RGBCURVE, // EvDCPToneCurve,
- INPUTPROFILE, // EvDCPIlluminant,
+ ALLNORAW, // EvDCPIlluminant,
RETINEX, // EvSHEnabled,
RGBCURVE, // EvSHHighlights,
RGBCURVE, // EvSHShadows,
@@ -97,7 +97,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
ALLNORAW, // EvHRMethod,
ALLNORAW, // EvWProfile,
OUTPUTPROFILE, // EvOProfile,
- INPUTPROFILE, // EvIProfile,
+ ALLNORAW, // EvIProfile,
TRANSFORM, // EvVignettingAmount,
RGBCURVE, // EvChMixer,
RESIZE, // EvResizeScale,
@@ -234,8 +234,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvCATbadpix
LUMINANCECURVE, // EvCATAutoadap
DEFRINGE, // EvPFCurve
- WHITEBALANCE, // EvWBequal
- WHITEBALANCE, // EvWBequalbo
+ ALLNORAW, // EvWBequal
+ ALLNORAW, // EvWBequalbo
TRANSFORM, // EvGradientDegree
TRANSFORM, // EvGradientEnabled
TRANSFORM, // EvPCVignetteStrength
@@ -421,7 +421,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
DIRPYREQUALIZER, // EvWavNeutral
RGBCURVE, // EvDCPApplyLookTable,
RGBCURVE, // EvDCPApplyBaselineExposureOffset,
- INPUTPROFILE, // EvDCPApplyHueSatMap
+ ALLNORAW, // EvDCPApplyHueSatMap
DIRPYREQUALIZER, // EvWavenacont
DIRPYREQUALIZER, // EvWavenachrom
DIRPYREQUALIZER, // EvWavenaedge
@@ -452,7 +452,10 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
DEMOSAIC, // EvLslope
RETINEX, // EvLhighl
DEMOSAIC, // EvLbaselog
-// DEMOSAIC, // EvLgrbl
- DEMOSAIC // EvRetinexlhcurve
+// DEMOSAIC, // EvLgrbl
+ DEMOSAIC, // EvRetinexlhcurve
+ ALLNORAW, // EvOIntent
+ MONITORTRANSFORM // EvMonitorTransform
+
};
diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h
index e24d0c422..23e179f9f 100644
--- a/rtengine/refreshmap.h
+++ b/rtengine/refreshmap.h
@@ -20,15 +20,16 @@
#define __REFRESHMAP__
// Use M_VOID if you wish to update the proc params without updating the preview at all !
-#define M_VOID (1<<15)
+#define M_VOID (1<<16)
// Use M_MINUPDATE if you wish to update the preview without modifying the image (think about it like a "refreshPreview")
// Must NOT be used with other event (i.e. will be used for MINUPDATE only)
-#define M_MINUPDATE (1<<14)
+#define M_MINUPDATE (1<<15)
// Force high quality
-#define M_HIGHQUAL (1<<13)
+#define M_HIGHQUAL (1<<14)
// Elementary functions that can be done to
// the preview image when an event occurs
+#define M_MONITOR (1<<13)
#define M_RETINEX (1<<12)
#define M_CROP (1<<11)
#define M_PREPROC (1<<10)
@@ -45,31 +46,30 @@
// Bitfield of functions to do to the preview image when an event occurs
// Use those or create new ones for your new events
-#define FIRST (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
-#define ALL (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
-#define TRANSFORM (M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define AUTOEXP (M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define RGBCURVE (M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define LUMINANCECURVE (M_LUMACURVE|M_LUMINANCE)
-#define SHARPENING M_LUMINANCE
-#define IMPULSEDENOISE M_LUMINANCE
-#define DEFRINGE M_LUMINANCE
-#define WHITEBALANCE (M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define DEMOSAIC (M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define DIRPYRDENOISE (M_COLOR|M_LUMINANCE)
-#define CROP M_CROP
-#define RESIZE M_VOID
-#define EXIF M_VOID
-#define IPTC M_VOID
-#define DIRPYREQUALIZER (M_COLOR|M_LUMINANCE)
-#define OUTPUTPROFILE (M_INIT|M_COLOR|M_LUMINANCE)
-#define INPUTPROFILE WHITEBALANCE
-#define GAMMA (M_COLOR|M_LUMINANCE)
-#define MINUPDATE M_MINUPDATE
-#define ALLNORAW (M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
-#define RETINEX (M_RETINEX|ALLNORAW)
+#define FIRST (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
+#define ALL (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
+#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define DEMOSAIC (M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define ALLNORAW (M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define TRANSFORM (M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define AUTOEXP (M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define RGBCURVE (M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define LUMINANCECURVE (M_LUMACURVE|M_LUMINANCE|M_COLOR)
+#define SHARPENING (M_LUMINANCE|M_COLOR)
+#define IMPULSEDENOISE (M_LUMINANCE|M_COLOR)
+#define DEFRINGE (M_LUMINANCE|M_COLOR)
+#define DIRPYRDENOISE (M_LUMINANCE|M_COLOR)
+#define DIRPYREQUALIZER (M_LUMINANCE|M_COLOR)
+#define GAMMA (M_LUMINANCE|M_COLOR)
+#define CROP M_CROP
+#define RESIZE M_VOID
+#define EXIF M_VOID
+#define IPTC M_VOID
+#define MINUPDATE M_MINUPDATE
+#define RETINEX (M_RETINEX|ALLNORAW)
+#define MONITORTRANSFORM M_MONITOR
+#define OUTPUTPROFILE (ALLNORAW|MONITORTRANSFORM)
extern int refreshmap[];
#endif
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index 195911a3a..42e06406e 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -35,7 +35,7 @@
#include "LUT.h"
/**
* @file
- * This file contains the main functionality of the raw therapee engine.
+ * This file contains the main functionality of the RawTherapee engine.
*
*/
@@ -413,9 +413,12 @@ public:
virtual void setAutoBWListener (AutoBWListener* l) = 0;
virtual void setAutoColorTonListener (AutoColorTonListener* l) = 0;
virtual void setAutoChromaListener (AutoChromaListener* l) = 0;
- virtual void setRetinexListener (RetinexListener* l) = 0;
+ virtual void setRetinexListener (RetinexListener* l) = 0;
virtual void setWaveletListener (WaveletListener* l) = 0;
+ virtual void setMonitorProfile (const Glib::ustring& monitorProfile, RenderingIntent intent) = 0;
+ virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0;
+
virtual ~StagedImageProcessor () {}
/** Returns a staged, cached image processing manager supporting partial updates
diff --git a/rtengine/settings.h b/rtengine/settings.h
index 373103d07..3e9c9d38a 100644
--- a/rtengine/settings.h
+++ b/rtengine/settings.h
@@ -19,6 +19,8 @@
#ifndef _RTSETTINGS_
#define _RTSETTINGS_
+#include "procparams.h"
+
namespace rtengine
{
@@ -27,7 +29,6 @@ class Settings
{
public:
Glib::ustring iccDirectory; ///< The directory containing the possible output icc profiles
- int colorimetricIntent; ///< Colorimetric intent used at color space conversions
int viewingdevice; // white of output device (D50...D65..)
int viewingdevicegrey; // level of grey output device
int viewinggreySc; // level of grey Scene
@@ -37,7 +38,8 @@ public:
int leveldnliss; // level of auto multi zone
int leveldnautsimpl; // STD or EXPERT
- Glib::ustring monitorProfile; ///< ICC profile of the monitor (full path recommended)
+ Glib::ustring monitorProfile; ///< ICC profile name used for the monitor
+ RenderingIntent monitorIntent; ///< Colorimetric intent used with the above profile
bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile
bool autocielab;
bool rgbcurveslumamode_gamut;// controls gamut enforcement for RGB curves in lumamode
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index da44b25e3..6e1c876cf 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -1155,7 +1155,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
cmsFloat64Number Parameters[7];
double ga0, ga1, ga2, ga3, ga4, ga5, ga6;
// if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
- readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos, ga0, ga1, ga2, ga3, ga4, ga5, ga6, params.blackwhite.enabled );
+ readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos, ga0, ga1, ga2, ga3, ga4, ga5, ga6, params.blackwhite.enabled );
customGamma = true;
//or selected Free gamma
@@ -1163,7 +1163,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
bool pro = false;
Glib::ustring chpro, outProfile;
bool present_space[9] = {false, false, false, false, false, false, false, false, false};
- std::vector opnames = iccStore->getOutputProfiles ();
+ std::vector opnames = iccStore->getProfiles ();
//test if files are in system
for (int j = 0; j < 9; j++) {
@@ -1347,7 +1347,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
bwonly = false;
}
- readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, bwonly);
+ readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, bwonly);
if (settings->verbose) {
printf("Output profile_: \"%s\"\n", params.icm.output.c_str());
diff --git a/rtgui/colortoning.cc b/rtgui/colortoning.cc
index 38cf88230..99ad03e9f 100644
--- a/rtgui/colortoning.cc
+++ b/rtgui/colortoning.cc
@@ -3,6 +3,7 @@
*/
#include "colortoning.h"
#include "mycurve.h"
+#include "rtimage.h"
using namespace rtengine;
using namespace rtengine::procparams;
diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc
index ad896789f..4ca2bb159 100644
--- a/rtgui/diagonalcurveeditorsubgroup.cc
+++ b/rtgui/diagonalcurveeditorsubgroup.cc
@@ -30,6 +30,7 @@
#include "mydiagonalcurve.h"
#include "curveeditor.h"
#include "diagonalcurveeditorsubgroup.h"
+#include "rtimage.h"
DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir)
{
diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc
index 82e8d9fcf..b9f123ac5 100644
--- a/rtgui/editorpanel.cc
+++ b/rtgui/editorpanel.cc
@@ -25,12 +25,188 @@
#include "procparamchangers.h"
#include "../rtengine/safegtk.h"
#include "../rtengine/imagesource.h"
+#include "../rtengine/iccstore.h"
#include "soundman.h"
#include "rtimage.h"
#include
+#include "popupbutton.h"
using namespace rtengine::procparams;
+class EditorPanel::MonitorProfileSelector
+{
+private:
+ MyComboBoxText profileBox;
+ PopUpButton intentBox;
+ sigc::connection profileConn, intentConn;
+
+ rtengine::StagedImageProcessor* const& processor;
+
+private:
+ void prepareProfileBox ()
+ {
+ profileBox.set_size_request (100, -1);
+
+ profileBox.append_text (M("PREFERENCES_PROFILE_NONE"));
+#ifdef WIN32
+ profileBox.append_text (M("MONITOR_PROFILE_SYSTEM") + " (" + rtengine::iccStore->getDefaultMonitorProfileName() + ")");
+ profileBox.set_active (options.rtSettings.autoMonitorProfile ? 1 : 0);
+#else
+ profileBox.set_active (0);
+#endif
+
+ const std::vector profiles = rtengine::iccStore->getProfiles ();
+ for (std::vector::const_iterator iterator = profiles.begin (); iterator != profiles.end (); ++iterator) {
+ profileBox.append_text (*iterator);
+ }
+ }
+
+ void prepareIntentBox ()
+ {
+ intentBox.addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE"));
+ intentBox.addEntry("intent-perceptual.png", M("PREFERENCES_INTENT_PERCEPTUAL"));
+ intentBox.addEntry("intent-absolute.png", M("PREFERENCES_INTENT_ABSOLUTE"));
+
+ intentBox.setSelected(0);
+ intentBox.show ();
+ }
+
+ void profileBoxChanged ()
+ {
+ updateParameters ();
+
+ profileBox.set_tooltip_text (profileBox.get_active_text ());
+ }
+
+ void intentBoxChanged (int)
+ {
+ updateParameters ();
+ }
+
+ void updateParameters ()
+ {
+ ConnectionBlocker profileBlocker (profileConn);
+ ConnectionBlocker intentBlocker (intentConn);
+
+ Glib::ustring profile;
+
+#ifdef WIN32
+ if (profileBox.get_active_row_number () == 1) {
+ profile = rtengine::iccStore->getDefaultMonitorProfileName ();
+ if (profile.empty ()) {
+ profile = options.rtSettings.monitorProfile;
+ }
+ if (profile.empty ()) {
+ profile = "sRGB IEC61966-2.1";
+ }
+ } else if (profileBox.get_active_row_number () > 1) {
+ profile = profileBox.get_active_text ();
+ }
+#else
+ profile = profileBox.get_active_row_number () > 0 ? profileBox.get_active_text () : Glib::ustring ();
+#endif
+
+ if (profileBox.get_active_row_number () == 0) {
+
+ profile.clear();
+
+ intentBox.set_sensitive (false);
+ intentBox.setSelected (0);
+
+ } else {
+ const std::uint8_t supportedIntents = rtengine::iccStore->getProofIntents (profile);
+ const bool supportsRelativeColorimetric = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC;
+ const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL;
+ const bool supportsAbsoluteColorimetric = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC;
+
+ if (supportsPerceptual || supportsRelativeColorimetric || supportsAbsoluteColorimetric) {
+ intentBox.set_sensitive (true);
+ intentBox.setItemSensitivity(0, supportsRelativeColorimetric);
+ intentBox.setItemSensitivity(1, supportsPerceptual);
+ intentBox.setItemSensitivity(2, supportsAbsoluteColorimetric);
+ } else {
+ intentBox.set_sensitive (false);
+ intentBox.setSelected (0);
+ }
+ }
+
+ rtengine::RenderingIntent intent;
+ switch (intentBox.getSelected ()) {
+ default:
+ case 0:
+ intent = rtengine::RI_RELATIVE;
+ break;
+ case 1:
+ intent = rtengine::RI_PERCEPTUAL;
+ break;
+ case 2:
+ intent = rtengine::RI_ABSOLUTE;
+ break;
+ }
+
+ if (!processor) {
+ return;
+ }
+
+ processor->beginUpdateParams ();
+ processor->setMonitorProfile (profile, intent);
+ processor->endUpdateParams (rtengine::EvMonitorTransform);
+ }
+
+public:
+ MonitorProfileSelector (rtengine::StagedImageProcessor* const& ipc) :
+ intentBox (Glib::ustring (), true),
+ processor (ipc)
+ {
+ prepareProfileBox ();
+ prepareIntentBox ();
+
+ reset ();
+
+ profileConn = profileBox.signal_changed ().connect (sigc::mem_fun (this, &MonitorProfileSelector::profileBoxChanged));
+ intentConn = intentBox.signal_changed ().connect (sigc::mem_fun (this, &MonitorProfileSelector::intentBoxChanged));
+ }
+
+ void pack_end_in (Gtk::Box* box)
+ {
+ box->pack_end (*intentBox.buttonGroup, Gtk::PACK_SHRINK, 0);
+ box->pack_end (profileBox, Gtk::PACK_SHRINK, 0);
+ }
+
+ void reset ()
+ {
+ ConnectionBlocker profileBlocker (profileConn);
+ ConnectionBlocker intentBlocker (intentConn);
+
+#ifdef WIN32
+ if (options.rtSettings.autoMonitorProfile) {
+ setActiveTextOrIndex (profileBox, options.rtSettings.monitorProfile, 1);
+ } else {
+ setActiveTextOrIndex (profileBox, options.rtSettings.monitorProfile, 0);
+ }
+#else
+ setActiveTextOrIndex (profileBox, options.rtSettings.monitorProfile, 0);
+#endif
+
+ switch (options.rtSettings.monitorIntent)
+ {
+ default:
+ case rtengine::RI_RELATIVE:
+ intentBox.setSelected (0);
+ break;
+ case rtengine::RI_PERCEPTUAL:
+ intentBox.setSelected (1);
+ break;
+ case rtengine::RI_ABSOLUTE:
+ intentBox.setSelected (2);
+ break;
+ }
+
+ updateParameters ();
+ }
+
+};
+
EditorPanel::EditorPanel (FilePanel* filePanel)
: realized(false), iHistoryShow(NULL), iHistoryHide(NULL), iTopPanel_1_Show(NULL), iTopPanel_1_Hide(NULL), iRightPanel_1_Show(NULL), iRightPanel_1_Hide(NULL), iBeforeLockON(NULL), iBeforeLockOFF(NULL), beforePreviewHandler(NULL), beforeIarea(NULL), beforeBox(NULL), afterBox(NULL), afterHeaderBox(NULL), parent(NULL), openThm(NULL), ipc(NULL), beforeIpc(NULL), isProcessing(false), catalogPane(NULL)
{
@@ -179,6 +355,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
// Save buttons
Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ());
+ iops->set_spacing(2);
//Gtk::Image *saveButtonImage = Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON));
Gtk::Image *saveButtonImage = Gtk::manage (new RTImage ("gtk-save-large.png"));
@@ -262,6 +439,12 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
iops->pack_end (*navPrev, Gtk::PACK_SHRINK, 0);
}
+ iops->pack_end (*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_SHRINK, 0);
+
+ // Monitor profile buttons
+ monitorProfile.reset (new MonitorProfileSelector (ipc));
+ monitorProfile->pack_end_in (iops);
+
editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0);
editbox->pack_start (*iops, Gtk::PACK_SHRINK, 0);
editbox->show_all ();
@@ -568,6 +751,8 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc)
}
history->resetSnapShotNumber();
+
+ monitorProfile->reset ();
}
void EditorPanel::close ()
diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h
index cf446da97..6de9928bd 100644
--- a/rtgui/editorpanel.h
+++ b/rtgui/editorpanel.h
@@ -84,6 +84,9 @@ protected:
Gtk::Button* navNext;
Gtk::Button* navPrev;
+ class MonitorProfileSelector;
+ std::auto_ptr monitorProfile;
+
ImageAreaPanel* iareapanel;
PreviewHandler* previewHandler;
PreviewHandler* beforePreviewHandler; // for the before-after view
diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc
index e464b050e..915f0d84e 100644
--- a/rtgui/filecatalog.cc
+++ b/rtgui/filecatalog.cc
@@ -1152,6 +1152,7 @@ void FileCatalog::developRequested (std::vector tbe, bool fas
params.icm.input = options.fastexport_icm_input ;
params.icm.working = options.fastexport_icm_working ;
params.icm.output = options.fastexport_icm_output ;
+ params.icm.outputIntent = options.fastexport_icm_outputIntent ;
params.icm.gamma = options.fastexport_icm_gamma ;
params.resize.enabled = options.fastexport_resize_enabled ;
params.resize.scale = options.fastexport_resize_scale ;
diff --git a/rtgui/flatcurveeditorsubgroup.cc b/rtgui/flatcurveeditorsubgroup.cc
index 516bed44a..691fbe3dd 100644
--- a/rtgui/flatcurveeditorsubgroup.cc
+++ b/rtgui/flatcurveeditorsubgroup.cc
@@ -31,6 +31,7 @@
#include "myflatcurve.h"
#include "curveeditor.h"
#include "flatcurveeditorsubgroup.h"
+#include "rtimage.h"
FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir)
{
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index 1e65f2753..79f050c2f 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -76,6 +76,22 @@ public:
}
};
+class ConnectionBlocker
+{
+public:
+ ConnectionBlocker (sigc::connection& connection) : connection (connection)
+ {
+ wasBlocked = connection.block();
+ }
+ ~ConnectionBlocker ()
+ {
+ connection.block(wasBlocked);
+ }
+private:
+ sigc::connection& connection;
+ bool wasBlocked;
+};
+
/**
* @brief Glue box to control visibility of the MyExpender's content ; also handle the frame around it
*/
@@ -496,5 +512,12 @@ public:
}
};
+inline void setActiveTextOrIndex (Gtk::ComboBoxText& comboBox, const Glib::ustring& text, int index)
+{
+ comboBox.set_active_text (text);
+
+ if (comboBox.get_active_row_number () < 0)
+ comboBox.set_active (index);
+}
#endif
diff --git a/rtgui/history.cc b/rtgui/history.cc
index 57f7549db..689ea6394 100644
--- a/rtgui/history.cc
+++ b/rtgui/history.cc
@@ -24,7 +24,6 @@ using namespace rtengine;
using namespace rtengine::procparams;
Glib::ustring eventDescrArray[NUMOFEVENTS];
-extern Glib::ustring argv0;
History::History (bool bookmarkSupport) : blistener(NULL), tpc (NULL), bmnum (1)
{
@@ -204,8 +203,8 @@ void History::bookmarkSelectionChanged ()
void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited)
{
- // to prevent recursion, we filter out the events triggered by the history
- if (ev == EvHistoryBrowsed) {
+ // to prevent recursion, we filter out the events triggered by the history and events that should not be registered
+ if (ev == EvHistoryBrowsed || ev == EvMonitorTransform) {
return;
}
diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc
index e9e4e05ff..8b8057d45 100644
--- a/rtgui/icmpanel.cc
+++ b/rtgui/icmpanel.cc
@@ -83,7 +83,8 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
dcpFrame = Gtk::manage (new Gtk::Frame ("DCP"));
Gtk::VBox* dcpFrameVBox = Gtk::manage (new Gtk::VBox ());
- dcpFrameVBox->set_border_width(4);
+ dcpFrameVBox->set_border_width(0);
+ dcpFrameVBox->set_spacing(2);
Gtk::HBox* dcpIllHBox = Gtk::manage (new Gtk::HBox ());
dcpIllLabel = Gtk::manage (new Gtk::Label (M("TP_ICM_DCPILLUMINANT") + ":"));
@@ -101,29 +102,25 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
dcpIllHBox->pack_start(*dcpIllLabel, Gtk::PACK_SHRINK, 4);
dcpIllHBox->pack_start(*dcpIll);
- Gtk::HBox* c1HBox = Gtk::manage ( new Gtk::HBox(true, 4));
ckbToneCurve = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_TONECURVE")));
ckbToneCurve->set_sensitive (false);
ckbToneCurve->set_tooltip_text (M("TP_ICM_TONECURVE_TOOLTIP"));
ckbApplyHueSatMap = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_APPLYHUESATMAP")));
ckbApplyHueSatMap->set_sensitive (false);
ckbApplyHueSatMap->set_tooltip_text (M("TP_ICM_APPLYHUESATMAP_TOOLTIP"));
- c1HBox->pack_start (*ckbToneCurve);
- c1HBox->pack_start (*ckbApplyHueSatMap);
- Gtk::HBox* c2HBox = Gtk::manage ( new Gtk::HBox(true, 4));
ckbApplyLookTable = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_APPLYLOOKTABLE")));
ckbApplyLookTable->set_sensitive (false);
ckbApplyLookTable->set_tooltip_text (M("TP_ICM_APPLYLOOKTABLE_TOOLTIP"));
ckbApplyBaselineExposureOffset = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_APPLYBASELINEEXPOSUREOFFSET")));
ckbApplyBaselineExposureOffset->set_sensitive (false);
ckbApplyBaselineExposureOffset->set_tooltip_text (M("TP_ICM_APPLYBASELINEEXPOSUREOFFSET_TOOLTIP"));
- c2HBox->pack_start (*ckbApplyLookTable);
- c2HBox->pack_start (*ckbApplyBaselineExposureOffset);
- dcpFrameVBox->pack_start(*dcpIllHBox);
- dcpFrameVBox->pack_start(*c1HBox);
- dcpFrameVBox->pack_start(*c2HBox);
+ dcpFrameVBox->pack_start(*dcpIllHBox, Gtk::PACK_SHRINK, 0);
+ dcpFrameVBox->pack_start(*ckbToneCurve, Gtk::PACK_SHRINK,0);
+ dcpFrameVBox->pack_start(*ckbApplyHueSatMap, Gtk::PACK_SHRINK,0);
+ dcpFrameVBox->pack_start(*ckbApplyLookTable, Gtk::PACK_SHRINK,0);
+ dcpFrameVBox->pack_start(*ckbApplyBaselineExposureOffset, Gtk::PACK_SHRINK,0);
dcpFrame->add(*dcpFrameVBox);
dcpFrame->set_sensitive(false);
iVBox->pack_start (*dcpFrame);
@@ -185,7 +182,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
onames->append_text (M("TP_ICM_NOICM"));
onames->set_active (0);
- std::vector opnames = iccStore->getOutputProfiles ();
+ std::vector opnames = iccStore->getProfiles ();
for (size_t i = 0; i < opnames.size(); i++) {
onames->append_text (opnames[i]);
@@ -193,6 +190,19 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
onames->set_active (0);
+ // Rendering intent
+ Gtk::HBox *riHBox = Gtk::manage ( new Gtk::HBox());
+ Gtk::Label* outputIntentLbl = Gtk::manage (new Gtk::Label(M("TP_ICM_PROFILEINTENT")+":"));
+ riHBox->pack_start (*outputIntentLbl, Gtk::PACK_SHRINK);
+ ointent = Gtk::manage (new MyComboBoxText ());
+ riHBox->pack_start (*ointent, Gtk::PACK_EXPAND_WIDGET);
+ ointent->append_text (M("PREFERENCES_INTENT_PERCEPTUAL"));
+ ointent->append_text (M("PREFERENCES_INTENT_RELATIVE"));
+ ointent->append_text (M("PREFERENCES_INTENT_SATURATION"));
+ ointent->append_text (M("PREFERENCES_INTENT_ABSOLUTE"));
+ ointent->set_active (1);
+ oVBox->pack_start(*riHBox, Gtk::PACK_SHRINK);
+
// Output gamma
Gtk::HBox* gaHBox = Gtk::manage (new Gtk::HBox ());
@@ -282,6 +292,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
wnames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::wpChanged) );
onames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::opChanged) );
+ ointent->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::oiChanged) );
wgamma->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::gpChanged) );
dcpIll->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::dcpIlluminantChanged) );
@@ -507,6 +518,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
if (onames->get_active_row_number() == -1) {
onames->set_active_text (M("TP_ICM_NOICM"));
}
+ ointent->set_active(pp->icm.outputIntent);
ckbToneCurve->set_active (pp->icm.toneCurve);
lastToneCurve = pp->icm.toneCurve;
@@ -545,6 +557,10 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
onames->set_active_text(M("GENERAL_UNCHANGED"));
}
+ if (!pedited->icm.outputIntent) {
+ ointent->set_active_text(M("GENERAL_UNCHANGED"));
+ }
+
if (!pedited->icm.dcpIlluminant) {
dcpIll->set_active_text(M("GENERAL_UNCHANGED"));
}
@@ -605,6 +621,13 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited)
pp->icm.output = onames->get_active_text();
}
+ int ointentVal = ointent->get_active_row_number();
+ if (ointentVal >= 0 && ointentVal < RI__COUNT) {
+ pp->icm.outputIntent = static_cast(ointentVal);
+ } else {
+ pp->icm.outputIntent = rtengine::RI_RELATIVE;
+ }
+
pp->icm.freegamma = freegamma->get_active();
DCPProfile* dcp = NULL;
@@ -641,6 +664,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.outputIntent = ointent->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent ();
pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent ();
@@ -880,6 +904,14 @@ void ICMPanel::opChanged ()
}
}
+void ICMPanel::oiChanged ()
+{
+
+ if (listener) {
+ listener->panelChanged (EvOIntent, ointent->get_active_text());
+ }
+}
+
void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta)
{
@@ -979,6 +1011,7 @@ void ICMPanel::setBatchMode (bool batchMode)
iVBox->reorder_child (*iunchanged, 5);
removeIfThere (this, saveRef);
onames->append_text (M("GENERAL_UNCHANGED"));
+ ointent->append_text (M("GENERAL_UNCHANGED"));
wnames->append_text (M("GENERAL_UNCHANGED"));
wgamma->append_text (M("GENERAL_UNCHANGED"));
dcpIll->append_text (M("GENERAL_UNCHANGED"));
diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h
index 93828f5fd..863e88a46 100644
--- a/rtgui/icmpanel.h
+++ b/rtgui/icmpanel.h
@@ -78,6 +78,7 @@ private:
MyComboBoxText* wgamma;
MyComboBoxText* onames;
+ MyComboBoxText* ointent;
Gtk::RadioButton* ofromdir;
Gtk::RadioButton* ofromfile;
Gtk::RadioButton* iunchanged;
@@ -107,6 +108,7 @@ public:
void wpChanged ();
void opChanged ();
+ void oiChanged ();
void ipChanged ();
void gpChanged ();
void GamChanged ();
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 6d0b6a0d0..e97a27ecb 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -470,6 +470,7 @@ void Options::setDefaults ()
fastexport_icm_input = "(camera)";
fastexport_icm_working = "ProPhoto";
fastexport_icm_output = "RT_sRGB";
+ fastexport_icm_outputIntent = rtengine::RI_RELATIVE;
fastexport_icm_gamma = "default";
fastexport_resize_enabled = true;
fastexport_resize_scale = 1;
@@ -626,7 +627,6 @@ void Options::setDefaults ()
#else
rtSettings.iccDirectory = "/usr/share/color/icc";
#endif
- rtSettings.colorimetricIntent = 1;
rtSettings.viewingdevice = 0;
rtSettings.viewingdevicegrey = 3;
rtSettings.viewinggreySc = 1;
@@ -636,7 +636,8 @@ void Options::setDefaults ()
rtSettings.leveldnliss = 0;
rtSettings.leveldnautsimpl = 0;
- rtSettings.monitorProfile = "";
+ rtSettings.monitorProfile = Glib::ustring();
+ rtSettings.monitorIntent = rtengine::RI_RELATIVE;
rtSettings.autoMonitorProfile = false;
rtSettings.adobe = "RT_Medium_gsRGB"; // put the name of yours profiles (here windows)
rtSettings.prophoto = "RT_Large_gBT709"; // these names appear in the menu "output profile"
@@ -1461,7 +1462,7 @@ int Options::readFromFile (Glib::ustring fname)
}
if (keyFile.has_key ("Color Management", "Intent")) {
- rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent");
+ rtSettings.monitorIntent = static_cast(keyFile.get_integer("Color Management", "Intent"));
}
if (keyFile.has_key ("Color Management", "CRI")) {
@@ -1712,6 +1713,10 @@ int Options::readFromFile (Glib::ustring fname)
fastexport_icm_output = keyFile.get_string ("Fast Export", "fastexport_icm_output" );
}
+ if (keyFile.has_key ("Fast Export", "fastexport_icm_output_intent" )) {
+ fastexport_icm_outputIntent = static_cast(keyFile.get_integer ("Fast Export", "fastexport_icm_output_intent" ));
+ }
+
if (keyFile.has_key ("Fast Export", "fastexport_icm_gamma" )) {
fastexport_icm_gamma = keyFile.get_string ("Fast Export", "fastexport_icm_gamma" );
}
@@ -2008,7 +2013,7 @@ int Options::saveToFile (Glib::ustring fname)
keyFile.set_boolean ("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile);
keyFile.set_boolean ("Color Management", "Autocielab", rtSettings.autocielab);
keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut);
- keyFile.set_integer ("Color Management", "Intent", rtSettings.colorimetricIntent);
+ keyFile.set_integer ("Color Management", "Intent", rtSettings.monitorIntent);
keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice);
keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
@@ -2075,6 +2080,7 @@ int Options::saveToFile (Glib::ustring fname)
keyFile.set_string ("Fast Export", "fastexport_icm_input" , fastexport_icm_input );
keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working );
keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output );
+ keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent );
keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma );
keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled );
keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale );
diff --git a/rtgui/options.h b/rtgui/options.h
index 614042fa2..b896f4129 100644
--- a/rtgui/options.h
+++ b/rtgui/options.h
@@ -264,6 +264,7 @@ public:
Glib::ustring fastexport_icm_input;
Glib::ustring fastexport_icm_working;
Glib::ustring fastexport_icm_output;
+ rtengine::RenderingIntent fastexport_icm_outputIntent;
Glib::ustring fastexport_icm_gamma;
bool fastexport_resize_enabled;
double fastexport_resize_scale;
diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc
index ac2fe6523..866142a10 100644
--- a/rtgui/paramsedited.cc
+++ b/rtgui/paramsedited.cc
@@ -339,6 +339,7 @@ void ParamsEdited::set (bool v)
icm.dcpIlluminant = v;
icm.working = v;
icm.output = v;
+ icm.outputIntent = v;
icm.gamma = v;
icm.freegamma = v;
icm.gampos = v;
@@ -816,6 +817,7 @@ void ParamsEdited::initFrom (const std::vector
icm.dcpIlluminant = icm.dcpIlluminant && p.icm.dcpIlluminant == other.icm.dcpIlluminant;
icm.working = icm.working && p.icm.working == other.icm.working;
icm.output = icm.output && p.icm.output == other.icm.output;
+ icm.outputIntent = icm.outputIntent && p.icm.outputIntent == other.icm.outputIntent;
icm.gamma = icm.gamma && p.icm.gamma == other.icm.gamma;
icm.freegamma = icm.freegamma && p.icm.freegamma == other.icm.freegamma;
icm.gampos = icm.gampos && p.icm.gampos == other.icm.gampos;
@@ -2119,6 +2121,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.icm.output = mods.icm.output;
}
+ if (icm.outputIntent) {
+ toEdit.icm.outputIntent = mods.icm.outputIntent;
+ }
+
//if (icm.gampos) toEdit.icm.gampos = mods.icm.gampos;
//if (icm.slpos) toEdit.icm.slpos = mods.icm.slpos;
if (icm.gampos) {
diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h
index 3fa753013..1993c7aaa 100644
--- a/rtgui/paramsedited.h
+++ b/rtgui/paramsedited.h
@@ -530,6 +530,7 @@ public:
bool dcpIlluminant;
bool working;
bool output;
+ bool outputIntent;
bool gamma;
bool gampos;
bool slpos;
diff --git a/rtgui/popupbutton.cc b/rtgui/popupbutton.cc
index 440d7b420..554f41cc6 100644
--- a/rtgui/popupbutton.cc
+++ b/rtgui/popupbutton.cc
@@ -21,6 +21,8 @@
#include "popupbutton.h"
+#include
+
/*
* PopUpButton::PopUpButton (const Glib::ustring& label, bool imgRight)
*
@@ -28,8 +30,14 @@
*
* Parameters:
* label = label displayed in the button
+ * nextOnClicked = selects the next entry if the button is clicked
*/
-PopUpButton::PopUpButton (const Glib::ustring& label) : Gtk::Button(), PopUpCommon(this, label) { }
+PopUpButton::PopUpButton (const Glib::ustring& label, bool nextOnClicked)
+ : Gtk::Button ()
+ , PopUpCommon (this, label)
+ , nextOnClicked(nextOnClicked)
+{
+}
void PopUpButton::show()
{
@@ -39,3 +47,27 @@ void PopUpButton::set_tooltip_text (const Glib::ustring &text)
{
PopUpCommon::set_tooltip_text (text);
}
+
+void PopUpButton::set_sensitive (bool isSensitive)
+{
+ buttonGroup->set_sensitive(isSensitive);
+}
+
+bool PopUpButton::on_button_release_event (GdkEventButton* event)
+{
+ if (nextOnClicked && getEntryCount () > 1)
+ {
+ const int last = getEntryCount () - 1;
+ int next = getSelected ();
+
+ if (event->state & GDK_SHIFT_MASK) {
+ next = next > 0 ? next - 1 : last;
+ } else {
+ next = next < last ? next + 1 : 0;
+ }
+
+ entrySelected (next);
+ }
+
+ return Gtk::Button::on_button_release_event(event);
+}
diff --git a/rtgui/popupbutton.h b/rtgui/popupbutton.h
index 23a9211a8..245d29aee 100644
--- a/rtgui/popupbutton.h
+++ b/rtgui/popupbutton.h
@@ -21,16 +21,24 @@
#ifndef _POPUPBUTTON_
#define _POPUPBUTTON_
-#include
+#include
#include "popupcommon.h"
class PopUpButton : public Gtk::Button, public PopUpCommon
{
public:
- PopUpButton (const Glib::ustring& label = "");
+ PopUpButton (const Glib::ustring& label = Glib::ustring (), bool nextOnClicked = false);
void show ();
void set_tooltip_text (const Glib::ustring &text);
+ void set_sensitive (bool isSensitive=true);
+
+protected:
+ bool on_button_release_event (GdkEventButton* event);
+
+private:
+ bool nextOnClicked;
+
};
#endif
diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc
index 881994589..f7e667219 100644
--- a/rtgui/popupcommon.cc
+++ b/rtgui/popupcommon.cc
@@ -19,12 +19,16 @@
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
+#include
#include "multilangmgr.h"
#include "popupcommon.h"
#include "../rtengine/safegtk.h"
#include "rtimage.h"
PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label)
+ : selected (-1) // -1 means that the button is invalid
+ , menu (0)
+ , buttonImage (0)
{
button = thisButton;
hasMenu = false;
@@ -41,15 +45,6 @@ PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label)
// Create the global container and put the button in it
buttonGroup = Gtk::manage( new Gtk::HBox(false, 0));
buttonGroup->pack_start(*button, Gtk::PACK_EXPAND_WIDGET, 0);
- // Create the list entry
- imageFilenames.clear();
- images.clear();
- sItems.clear();
- items.clear();
- selected = -1; // -1 : means that the button is invalid
- menu = 0;
- buttonImage = 0;
- buttonHint = "";
}
PopUpCommon::~PopUpCommon ()
@@ -58,83 +53,68 @@ PopUpCommon::~PopUpCommon ()
delete *i;
}
- for (std::vector::iterator i = items.begin(); i != items.end(); ++i) {
- delete *i;
- }
-
- if (menu) {
- delete menu;
- }
-
- if (buttonImage) {
- delete buttonImage;
- }
-
- delete buttonGroup;
+ delete menu;
+ delete buttonImage;
}
-PopUpCommon::type_signal_changed PopUpCommon::signal_changed()
+bool PopUpCommon::addEntry (const Glib::ustring& fileName, const Glib::ustring& label)
{
- return message;
-}
+ if (label.empty ())
+ return false;
-bool PopUpCommon::addEntry (Glib::ustring fileName, Glib::ustring label)
-{
- bool added = false;
+ // Create the image
+ RTImage* newImage = new RTImage(fileName);
+ images.push_back(newImage);
+ imageFilenames.push_back(fileName);
+ int currPos = (int)images.size();
+ // Create the menu item
+ Gtk::ImageMenuItem* newItem = Gtk::manage(new Gtk::ImageMenuItem (*newImage, label));
- if ( label.size() ) {
- imageFilenames.push_back(fileName);
- sItems.push_back(label);
- // Create the image
- RTImage* newImage = new RTImage(fileName);
- images.push_back(newImage);
- int currPos = (int)images.size();
- // Create the menu item
- Gtk::ImageMenuItem* newItem = new Gtk::ImageMenuItem (*newImage, label);
- items.push_back(newItem);
-
- if (selected == -1) {
- // Create the menu on the first item
- menu = new Gtk::Menu ();
- // Create the image for the button
- buttonImage = new RTImage(fileName);
- // Use the first image by default
- imageContainer->pack_start(*buttonImage, Gtk::PACK_EXPAND_WIDGET);
- selected = 0;
- }
-
- // When there is at least 1 choice, we add the arrow button
- if (images.size() == 1) {
- Gtk::Button* arrowButton = Gtk::manage( new Gtk::Button() );
- RTImage* arrowImage = Gtk::manage( new RTImage("popuparrow.png") );
- arrowButton->add(*arrowImage); //menuSymbol);
- arrowButton->set_relief (Gtk::RELIEF_NONE);
- arrowButton->set_border_width (0);
- buttonGroup->pack_start(*arrowButton, Gtk::PACK_SHRINK, 0);
- arrowButton->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &PopUpCommon::showMenu) );
- hasMenu = true;
- }
-
- newItem->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &PopUpCommon::entrySelected), currPos - 1));
- menu->attach (*newItem, 0, 1, currPos - 1, currPos);
- // The item has been created
- added = true;
+ if (selected == -1) {
+ // Create the menu on the first item
+ menu = new Gtk::Menu ();
+ // Create the image for the button
+ buttonImage = new RTImage(fileName);
+ // Use the first image by default
+ imageContainer->pack_start(*buttonImage, Gtk::PACK_EXPAND_WIDGET);
+ selected = 0;
}
- return added;
+ // When there is at least 1 choice, we add the arrow button
+ if (images.size() == 1) {
+ Gtk::Button* arrowButton = Gtk::manage( new Gtk::Button() );
+ RTImage* arrowImage = Gtk::manage( new RTImage("popuparrow.png") );
+ arrowButton->add(*arrowImage); //menuSymbol);
+ arrowButton->set_relief (Gtk::RELIEF_NONE);
+ arrowButton->set_border_width (0);
+ buttonGroup->pack_start(*arrowButton, Gtk::PACK_SHRINK, 0);
+ arrowButton->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &PopUpCommon::showMenu) );
+ hasMenu = true;
+ }
+
+ newItem->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &PopUpCommon::entrySelected), currPos - 1));
+ menu->attach (*newItem, 0, 1, currPos - 1, currPos);
+
+ return true;
}
// TODO: 'PopUpCommon::removeEntry' method to be created...
void PopUpCommon::entrySelected (int i)
{
- if (setSelected((unsigned int)i))
- // Emit a a signal if the selected item has changed
- {
- message.emit(selected);
+ // Emit a a signal if the selected item has changed
+ if (setSelected (i))
+ message (selected);
+}
+
+void PopUpCommon::setItemSensitivity (int i, bool isSensitive) {
+ Gtk::Menu_Helpers::MenuList items = menu->items();
+ if (i < items.size()) {
+ items[i].set_sensitive(isSensitive);
}
}
+
/*
* Set the button image with the selected item
*/
@@ -172,7 +152,12 @@ void PopUpCommon::setButtonHint()
}
if (selected > -1) {
- hint += sItems.at(selected);
+ // HACK: Gtk::MenuItem::get_label does not seem to work reliably.
+ Gtk::MenuItem& item = menu->items ()[selected];
+ Gtk::Label* label = dynamic_cast(item.get_child ());
+
+ if (label)
+ hint += label->get_text ();
}
button->set_tooltip_markup(hint);
diff --git a/rtgui/popupcommon.h b/rtgui/popupcommon.h
index 872beb434..b5cb757f4 100644
--- a/rtgui/popupcommon.h
+++ b/rtgui/popupcommon.h
@@ -21,11 +21,21 @@
#ifndef _POPUPCOMMON_
#define _POPUPCOMMON_
+#include
+#include
+#include
-#include
-#include
-#include "rtimage.h"
+namespace Gtk
+{
+class HBox;
+class Menu;
+class Button;
+class ImageMenuItem;
+}
+typedef struct _GdkEventButton GdkEventButton;
+
+class RTImage;
class PopUpCommon
{
@@ -37,27 +47,20 @@ public:
PopUpCommon (Gtk::Button* button, const Glib::ustring& label = "");
virtual ~PopUpCommon ();
- bool addEntry (Glib::ustring fileName, Glib::ustring label);
+ bool addEntry (const Glib::ustring& fileName, const Glib::ustring& label);
+ int getEntryCount () const;
bool setSelected (int entryNum);
- int getSelected ()
- {
- return selected;
- }
+ int getSelected () const;
void setButtonHint();
void show ();
void set_tooltip_text (const Glib::ustring &text);
+ void setItemSensitivity (int i, bool isSensitive);
private:
type_signal_changed message;
- /*
- TODO: MenuItem::get_label() doesn't return any string, or an empty string !?
- That's why we store entries strings in sItems, but it would be nice to get ride of it...
- */
- std::vector sItems;
std::vector imageFilenames;
std::vector images;
- std::vector items;
Glib::ustring buttonHint;
RTImage* buttonImage;
Gtk::HBox* imageContainer;
@@ -67,8 +70,25 @@ private:
bool hasMenu;
void showMenu(GdkEventButton* event);
+
+protected:
void entrySelected (int i);
};
+inline PopUpCommon::type_signal_changed PopUpCommon::signal_changed ()
+{
+ return message;
+}
+
+inline int PopUpCommon::getEntryCount () const
+{
+ return images.size();
+}
+
+inline int PopUpCommon::getSelected () const
+{
+ return selected;
+}
+
#endif
diff --git a/rtgui/popuptogglebutton.h b/rtgui/popuptogglebutton.h
index 58342e66c..930fae4f2 100644
--- a/rtgui/popuptogglebutton.h
+++ b/rtgui/popuptogglebutton.h
@@ -21,7 +21,7 @@
#ifndef _POPUPTOGGLEBUTTON_
#define _POPUPTOGGLEBUTTON_
-#include "popupbutton.h"
+#include
#include "popupcommon.h"
class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon
diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc
index dca0eff17..0033978c3 100644
--- a/rtgui/preferences.cc
+++ b/rtgui/preferences.cc
@@ -687,32 +687,28 @@ Gtk::Widget* Preferences::getColorManagementPanel ()
Gtk::VBox* mvbcm = Gtk::manage (new Gtk::VBox ());
mvbcm->set_border_width (4);
- /*
- Gtk::Label* intlab = Gtk::manage (new Gtk::Label (M("PREFERENCES_CMETRICINTENT")+":", Gtk::ALIGN_LEFT));
- intent = Gtk::manage (new Gtk::ComboBoxText ());
- intent->append_text (M("PREFERENCES_INTENT_PERCEPTUAL"));
- intent->append_text (M("PREFERENCES_INTENT_RELATIVE"));
- intent->append_text (M("PREFERENCES_INTENT_SATURATION"));
- intent->append_text (M("PREFERENCES_INTENT_ABSOLUTE"));
- */
-
iccDir = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_ICCDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
Gtk::Label* pdlabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_ICCDIR") + ":", Gtk::ALIGN_LEFT));
- Gtk::FileFilter monProfileFilter_colprof;
- monProfileFilter_colprof.set_name(M("FILECHOOSER_FILTER_COLPROF"));
- monProfileFilter_colprof.add_pattern("*.icc");
- monProfileFilter_colprof.add_pattern("*.ICC");
- monProfileFilter_colprof.add_pattern("*.icm");
- monProfileFilter_colprof.add_pattern("*.ICM");
- Gtk::FileFilter monProfileFilter_any;
- monProfileFilter_any.set_name(M("FILECHOOSER_FILTER_ANY"));
- monProfileFilter_any.add_pattern("*");
+ monProfile = Gtk::manage (new Gtk::ComboBoxText ());
+ Gtk::Label* mplabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_MONPROFILE") + ":", Gtk::ALIGN_LEFT));
- monProfile = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_MONITORICC"), Gtk::FILE_CHOOSER_ACTION_OPEN));
- monProfile->add_filter (monProfileFilter_colprof);
- monProfile->add_filter (monProfileFilter_any);
- Gtk::Label* mplabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_MONITORICC") + ":", Gtk::ALIGN_LEFT));
+ monIntent = Gtk::manage (new Gtk::ComboBoxText ());
+ Gtk::Label* milabel = Gtk::manage (new Gtk::Label (M("PREFERENCES_MONINTENT")+":", Gtk::ALIGN_LEFT));
+
+ monProfile->append_text (M("PREFERENCES_PROFILE_NONE"));
+ monProfile->set_active (0);
+
+ const std::vector profiles = rtengine::ICCStore::getInstance ()->getProfiles ();
+ for (std::vector::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile)
+ monProfile->append_text (*profile);
+
+ monIntent->append_text (M("PREFERENCES_INTENT_RELATIVE"));
+ monIntent->append_text (M("PREFERENCES_INTENT_PERCEPTUAL"));
+ monIntent->append_text (M("PREFERENCES_INTENT_ABSOLUTE"));
+ monIntent->set_active (1);
+
+ iccDir->signal_selection_changed ().connect (sigc::mem_fun (this, &Preferences::iccDirChanged));
#if defined(WIN32) // Auto-detection not implemented for Linux, see issue 851
cbAutoMonProfile = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_AUTOMONPROFILE")));
@@ -720,17 +716,21 @@ Gtk::Widget* Preferences::getColorManagementPanel ()
#endif
Gtk::Table* colt = Gtk::manage (new Gtk::Table (3, 2));
- //colt->attach (*intlab, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
- //colt->attach (*intent, 1, 2, 0, 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
- colt->attach (*pdlabel, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
- colt->attach (*iccDir, 1, 2, 1, 2, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
+ int row = 0;
+ colt->attach (*pdlabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
+ colt->attach (*iccDir, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
#if !defined(__APPLE__) // monitor profile not supported on apple
- colt->attach (*mplabel, 0, 1, 2, 3, Gtk::FILL, Gtk::SHRINK, 2, 2);
- colt->attach (*monProfile, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
+ ++row;
+ colt->attach (*mplabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
+ colt->attach (*monProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
#if defined(WIN32)
- colt->attach (*cbAutoMonProfile, 1, 2, 3, 4, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
+ ++row;
+ colt->attach (*cbAutoMonProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
#endif
#endif
+ ++row;
+ colt->attach (*milabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
+ colt->attach (*monIntent, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2);
mvbcm->pack_start (*colt, Gtk::PACK_SHRINK, 4);
#if defined(WIN32)
@@ -1445,12 +1445,26 @@ void Preferences::storePreferences ()
moptions.CPBPath = txtCustProfBuilderPath->get_text();
moptions.CPBKeys = CPBKeyType(custProfBuilderLabelType->get_active_row_number());
- moptions.rtSettings.monitorProfile = monProfile->get_filename ();
+#if !defined(__APPLE__) // monitor profile not supported on apple
+ moptions.rtSettings.monitorProfile = monProfile->get_active_text ();
+ switch (monIntent->get_active_row_number ()) {
+ default:
+ case 0:
+ moptions.rtSettings.monitorIntent = rtengine::RI_RELATIVE;
+ break;
+ case 1:
+ moptions.rtSettings.monitorIntent = rtengine::RI_PERCEPTUAL;
+ break;
+ case 2:
+ moptions.rtSettings.monitorIntent = rtengine::RI_ABSOLUTE;
+ break;
+ }
#if defined(WIN32)
moptions.rtSettings.autoMonitorProfile = cbAutoMonProfile->get_active ();
#endif
+#endif
+
moptions.rtSettings.iccDirectory = iccDir->get_filename ();
- //moptions.rtSettings.colorimetricIntent = intent->get_active_row_number ();
moptions.rtSettings.viewingdevice = view->get_active_row_number ();
moptions.rtSettings.viewingdevicegrey = grey->get_active_row_number ();
moptions.rtSettings.viewinggreySc = greySc->get_active_row_number ();
@@ -1560,16 +1574,21 @@ void Preferences::fillPreferences ()
panFactor->set_value (moptions.panAccelFactor);
rememberZoomPanCheckbutton->set_active (moptions.rememberZoomAndPan);
ctiffserialize->set_active(moptions.serializeTiffRead);
+
#if !defined(__APPLE__) // monitor profile not supported on apple
-
- if (safe_file_test (moptions.rtSettings.monitorProfile, Glib::FILE_TEST_EXISTS)) {
- monProfile->set_filename (moptions.rtSettings.monitorProfile);
+ setActiveTextOrIndex (*monProfile, moptions.rtSettings.monitorProfile, 0);
+ switch (moptions.rtSettings.monitorIntent) {
+ default:
+ case rtengine::RI_RELATIVE:
+ monIntent->set_active (0);
+ break;
+ case rtengine::RI_PERCEPTUAL:
+ monIntent->set_active (1);
+ break;
+ case rtengine::RI_ABSOLUTE:
+ monIntent->set_active (2);
+ break;
}
-
- if (moptions.rtSettings.monitorProfile.empty()) {
- monProfile->set_current_folder (moptions.rtSettings.iccDirectory);
- }
-
#if defined(WIN32)
cbAutoMonProfile->set_active(moptions.rtSettings.autoMonitorProfile);
#endif
@@ -1579,7 +1598,6 @@ void Preferences::fillPreferences ()
iccDir->set_current_folder (moptions.rtSettings.iccDirectory);
}
- //intent->set_active (moptions.rtSettings.colorimetricIntent);
view->set_active (moptions.rtSettings.viewingdevice);
grey->set_active (moptions.rtSettings.viewingdevicegrey);
greySc->set_active (moptions.rtSettings.viewinggreySc);
@@ -1931,6 +1949,22 @@ void Preferences::bundledProfilesChanged ()
rpconn.block (false);
}
+void Preferences::iccDirChanged ()
+{
+ const Glib::ustring currentSelection = monProfile->get_active_text ();
+
+ monProfile->clear();
+
+ monProfile->append_text (M("PREFERENCES_PROFILE_NONE"));
+ monProfile->set_active (0);
+
+ const std::vector profiles = rtengine::ICCStore::getInstance ()->getProfilesFromDir (iccDir->get_filename ());
+ for (std::vector::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile)
+ monProfile->append_text (*profile);
+
+ monProfile->set_active_text (currentSelection);
+}
+
void Preferences::storeCurrentValue()
{
// TODO: Find a way to get and restore the current selection; the following line can't work anymore
diff --git a/rtgui/preferences.h b/rtgui/preferences.h
index ee885c568..1cfb435cf 100644
--- a/rtgui/preferences.h
+++ b/rtgui/preferences.h
@@ -95,7 +95,8 @@ protected:
Gtk::CheckButton* showExpComp;
Gtk::FileChooserButton* iccDir;
- Gtk::FileChooserButton* monProfile;
+ Gtk::ComboBoxText* monProfile;
+ Gtk::ComboBoxText* monIntent;
Gtk::CheckButton* cbAutoMonProfile;
//Gtk::CheckButton* cbAutocielab;
Gtk::CheckButton* cbciecamfloat;
@@ -106,7 +107,6 @@ protected:
Gtk::SpinButton* panFactor;
Gtk::CheckButton* rememberZoomPanCheckbutton;
- Gtk::ComboBoxText* intent;
Gtk::ComboBoxText* view;
Gtk::ComboBoxText* grey;
Gtk::ComboBoxText* greySc;
@@ -212,7 +212,8 @@ protected:
void forRAWComboChanged ();
void forImageComboChanged ();
void layoutComboChanged ();
- void bundledProfilesChanged();
+ void bundledProfilesChanged ();
+ void iccDirChanged ();
void switchThemeTo (Glib::ustring newTheme, bool slimInterface);
void switchFontTo (Glib::ustring newFont);
bool splashClosed(GdkEventAny* event);
diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc
index b964ecbb5..43cbe4f28 100644
--- a/rtgui/retinex.cc
+++ b/rtgui/retinex.cc
@@ -3,6 +3,7 @@
*/
#include "retinex.h"
#include "mycurve.h"
+#include "rtimage.h"
using namespace rtengine;
using namespace rtengine::procparams;
diff --git a/rtgui/wavelet.cc b/rtgui/wavelet.cc
index 4bebb10ad..abab1d2d1 100644
--- a/rtgui/wavelet.cc
+++ b/rtgui/wavelet.cc
@@ -21,6 +21,7 @@
#include
#include "edit.h"
#include "guiutils.h"
+#include "rtimage.h"
using namespace rtengine;
using namespace rtengine::procparams;
diff --git a/tools/source_icons/scalable/intent-absolute.file b/tools/source_icons/scalable/intent-absolute.file
new file mode 100644
index 000000000..57278bff2
--- /dev/null
+++ b/tools/source_icons/scalable/intent-absolute.file
@@ -0,0 +1 @@
+intent-absolute.png,w25,actions
diff --git a/tools/source_icons/scalable/intent-absolute.svg b/tools/source_icons/scalable/intent-absolute.svg
new file mode 100644
index 000000000..b5092b0c5
--- /dev/null
+++ b/tools/source_icons/scalable/intent-absolute.svg
@@ -0,0 +1,1376 @@
+
+
+
+
diff --git a/tools/source_icons/scalable/intent-perceptual.file b/tools/source_icons/scalable/intent-perceptual.file
new file mode 100644
index 000000000..3e7520042
--- /dev/null
+++ b/tools/source_icons/scalable/intent-perceptual.file
@@ -0,0 +1 @@
+intent-perceptual.png,w25,actions
diff --git a/tools/source_icons/scalable/intent-perceptual.svg b/tools/source_icons/scalable/intent-perceptual.svg
new file mode 100644
index 000000000..3c949c91e
--- /dev/null
+++ b/tools/source_icons/scalable/intent-perceptual.svg
@@ -0,0 +1,1362 @@
+
+
+
+
diff --git a/tools/source_icons/scalable/intent-relative.file b/tools/source_icons/scalable/intent-relative.file
new file mode 100644
index 000000000..5191a25c3
--- /dev/null
+++ b/tools/source_icons/scalable/intent-relative.file
@@ -0,0 +1 @@
+intent-relative.png,w25,actions
diff --git a/tools/source_icons/scalable/intent-relative.svg b/tools/source_icons/scalable/intent-relative.svg
new file mode 100644
index 000000000..706de23d1
--- /dev/null
+++ b/tools/source_icons/scalable/intent-relative.svg
@@ -0,0 +1,1361 @@
+
+
+
+
diff --git a/tools/source_icons/scalable/intent-saturation.file b/tools/source_icons/scalable/intent-saturation.file
new file mode 100644
index 000000000..9f33b978e
--- /dev/null
+++ b/tools/source_icons/scalable/intent-saturation.file
@@ -0,0 +1 @@
+intent-saturation.png,w25,actions
diff --git a/tools/source_icons/scalable/intent-saturation.svg b/tools/source_icons/scalable/intent-saturation.svg
new file mode 100644
index 000000000..1af08f4f2
--- /dev/null
+++ b/tools/source_icons/scalable/intent-saturation.svg
@@ -0,0 +1,1362 @@
+
+
+
+
diff --git a/tools/source_icons/scalable/softProof.file b/tools/source_icons/scalable/softProof.file
new file mode 100644
index 000000000..e275113ec
--- /dev/null
+++ b/tools/source_icons/scalable/softProof.file
@@ -0,0 +1 @@
+softProof.png,w22,actions
diff --git a/tools/source_icons/scalable/softProof.svg b/tools/source_icons/scalable/softProof.svg
new file mode 100644
index 000000000..d09f316a2
--- /dev/null
+++ b/tools/source_icons/scalable/softProof.svg
@@ -0,0 +1,1389 @@
+
+
+
+