diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 6bb0c4c3c..b50320631 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -497,7 +497,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef if (useNoiseLCurve || useNoiseCCurve) { int hei = calclum->height; int wid = calclum->width; - TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); + TMatrix wprofi = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wpi[3][3] = { {static_cast(wprofi[0][0]), static_cast(wprofi[0][1]), static_cast(wprofi[0][2])}, @@ -764,7 +764,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef } } - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); //inverse matrix user select const float wip[3][3] = { {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, @@ -772,7 +772,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef {static_cast(wiprof[2][0]), static_cast(wiprof[2][1]), static_cast(wiprof[2][2])} }; - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wp[3][3] = { {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, @@ -3117,7 +3117,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat float** bcalc; hei = provicalc->height; wid = provicalc->width; - TMatrix wprofi = iccStore->workingSpaceMatrix (params->icm.working); + TMatrix wprofi = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wpi[3][3] = { {static_cast(wprofi[0][0]), static_cast(wprofi[0][1]), static_cast(wprofi[0][2])}, @@ -3192,7 +3192,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); const float wp[3][3] = { {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, diff --git a/rtengine/clutstore.cc b/rtengine/clutstore.cc index 9e9958418..7a5f6fd19 100644 --- a/rtengine/clutstore.cc +++ b/rtengine/clutstore.cc @@ -2,10 +2,12 @@ #include "clutstore.h" +#include "iccstore.h" +#include "imagefloat.h" #include "opthelper.h" #include "rt_math.h" -#include "imagefloat.h" #include "stdimagesource.h" + #include "../rtgui/options.h" namespace @@ -284,7 +286,7 @@ void rtengine::HaldCLUT::splitClutFilename( profile_name = "sRGB"; if (!name.empty()) { - for (const auto& working_profile : rtengine::getWorkingProfiles()) { + for (const auto& working_profile : rtengine::ICCStore::getWorkingProfiles()) { if ( !working_profile.empty() // This isn't strictly needed, but an empty wp name should be skipped anyway && std::search(name.rbegin(), name.rend(), working_profile.rbegin(), working_profile.rend()) == name.rbegin() diff --git a/rtengine/curves.cc b/rtengine/curves.cc index cf2fd0d04..8f2aa03d3 100644 --- a/rtengine/curves.cc +++ b/rtengine/curves.cc @@ -2140,7 +2140,7 @@ void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib: state.isProphoto = true; } else { state.isProphoto = false; - TMatrix Work = iccStore->workingSpaceMatrix(workingSpace); + TMatrix Work = ICCStore::getInstance()->workingSpaceMatrix(workingSpace); memset(state.Working2Prophoto, 0, sizeof(state.Working2Prophoto)); for (int i = 0; i < 3; i++) @@ -2149,7 +2149,7 @@ void PerceptualToneCurve::initApplyState(PerceptualToneCurveState & state, Glib: state.Working2Prophoto[i][j] += prophoto_xyz[i][k] * Work[k][j]; } - Work = iccStore->workingSpaceInverseMatrix (workingSpace); + Work = ICCStore::getInstance()->workingSpaceInverseMatrix (workingSpace); memset(state.Prophoto2Working, 0, sizeof(state.Prophoto2Working)); for (int i = 0; i < 3; i++) diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index b97f913e7..2914fcd74 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -997,7 +997,7 @@ void DCPProfile::apply( ) const { - const TMatrix work_matrix = iccStore->workingSpaceInverseMatrix(working_space); + const TMatrix work_matrix = ICCStore::getInstance()->workingSpaceInverseMatrix(working_space); const Matrix xyz_cam = makeXyzCam(white_balance, pre_mul, cam_wb_matrix, preferred_illuminant); // Camera RGB to XYZ D50 matrix @@ -1119,7 +1119,7 @@ void DCPProfile::setStep2ApplyState(const Glib::ustring& working_space, bool use as_out.data->already_pro_photo = false; TMatrix mWork; - mWork = iccStore->workingSpaceMatrix (working_space); + mWork = ICCStore::getInstance()->workingSpaceMatrix (working_space); memset(as_out.data->pro_photo, 0, sizeof(as_out.data->pro_photo)); for (int i = 0; i < 3; i++) @@ -1128,7 +1128,7 @@ void DCPProfile::setStep2ApplyState(const Glib::ustring& working_space, bool use as_out.data->pro_photo[i][j] += prophoto_xyz[i][k] * mWork[k][j]; } - mWork = iccStore->workingSpaceInverseMatrix (working_space); + mWork = ICCStore::getInstance()->workingSpaceInverseMatrix (working_space); memset(as_out.data->work, 0, sizeof(as_out.data->work)); for (int i = 0; i < 3; i++) diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 7bc21d5d4..bfb08e472 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -1,12 +1,12 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright(c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + *(at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,149 +16,161 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include "iccstore.h" - #include +#include +#include + #ifdef WIN32 #include #else #include #endif -#include +#include "iccstore.h" #include "iccmatrices.h" +#include "procparams.h" #include "../rtgui/options.h" +#include "../rtgui/threadutils.h" namespace rtengine { + extern const Settings* settings; -// not recursive -void loadProfiles (const Glib::ustring& dirName, - std::map* profiles, - std::map* profileContents, - std::map* profileNames, - bool nameUpper) +} + +namespace { - if (dirName.empty ()) { + +// Not recursive +void loadProfiles( + const Glib::ustring& dirName, + std::map* profiles, + std::map* profileContents, + std::map* profileNames, + bool nameUpper +) +{ + if (dirName.empty()) { return; } try { + Glib::Dir dir(dirName); - Glib::Dir dir (dirName); - - for (Glib::DirIterator entry = dir.begin (); entry != dir.end (); ++entry) { - + for (Glib::DirIterator entry = dir.begin(); entry != dir.end(); ++entry) { const Glib::ustring fileName = *entry; - if (fileName.size () < 4) { + if (fileName.size() < 4) { continue; } - const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold (); + const Glib::ustring extension = rtengine::getFileExtension(fileName); - if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0) { + if (extension != ".icc" && extension != ".icm") { continue; } - const Glib::ustring filePath = Glib::build_filename (dirName, fileName); + const Glib::ustring filePath = Glib::build_filename(dirName, fileName); - if (!Glib::file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) { + if (!Glib::file_test(filePath, Glib::FILE_TEST_IS_REGULAR)) { continue; } - Glib::ustring name = fileName.substr (0, fileName.size() - 4); + Glib::ustring name = fileName.substr(0, fileName.size() - 4); if (nameUpper) { - name = name.uppercase (); + name = name.uppercase(); } if (profiles) { - const ProfileContent content (filePath); - const cmsHPROFILE profile = content.toProfile (); + const rtengine::ProfileContent content(filePath); + const cmsHPROFILE profile = content.toProfile(); if (profile) { - profiles->insert (std::make_pair (name, profile)); + profiles->emplace(name, profile); if (profileContents) { - profileContents->insert (std::make_pair (name, content)); + profileContents->emplace(name, content); } } } if (profileNames) { - profileNames->insert (std::make_pair (name, filePath)); + profileNames->emplace(name, filePath); } } - } catch (Glib::Exception&) {} + } catch (Glib::Exception&) { + } } -// version dedicated to single profile load when loadAll==false (cli version "-q" mode) -bool loadProfile (Glib::ustring profile, const Glib::ustring dirName, - std::map* profiles, - std::map* profileContents) +// Version dedicated to single profile load when loadAll==false (cli version "-q" mode) +bool loadProfile( + const Glib::ustring& profile, + const Glib::ustring& dirName, + std::map* profiles, + std::map* profileContents +) { - if (dirName.empty () || profiles == nullptr) { + if (dirName.empty() || profiles == nullptr) { return false; } try { + Glib::Dir dir(dirName); - Glib::Dir dir (dirName); - - for (Glib::DirIterator entry = dir.begin (); entry != dir.end (); ++entry) { - + for (Glib::DirIterator entry = dir.begin(); entry != dir.end(); ++entry) { const Glib::ustring fileName = *entry; - if (fileName.size () < 4) { + if (fileName.size() < 4) { continue; } - const Glib::ustring extension = fileName.substr (fileName.size () - 4).casefold (); + const Glib::ustring extension = rtengine::getFileExtension(fileName); - if (extension.compare (".icc") != 0 && extension.compare (".icm") != 0) { + if (extension != ".icc" && extension != ".icm") { continue; } - const Glib::ustring filePath = Glib::build_filename (dirName, fileName); + const Glib::ustring filePath = Glib::build_filename(dirName, fileName); - if (!Glib::file_test (filePath, Glib::FILE_TEST_IS_REGULAR)) { + if (!Glib::file_test(filePath, Glib::FILE_TEST_IS_REGULAR)) { continue; } - Glib::ustring name = fileName.substr (0, fileName.size() - 4); + const Glib::ustring name = fileName.substr(0, fileName.size() - 4); if (name == profile) { - const ProfileContent content (filePath); - const cmsHPROFILE profile = content.toProfile (); + const rtengine::ProfileContent content(filePath); + const cmsHPROFILE profile = content.toProfile(); if (profile) { - profiles->insert (std::make_pair (name, profile)); + profiles->emplace(name, profile); if (profileContents) { - profileContents->insert (std::make_pair (name, content)); + profileContents->emplace(name, content); } return true; } } } - } catch (Glib::Exception&) {} + } catch (Glib::Exception&) { + } return false; } -inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, uint8_t& result) +void getSupportedIntent(cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, uint8_t& result) { - if (cmsIsIntentSupported (profile, intent, direction)) { + if (cmsIsIntentSupported(profile, intent, direction)) { result |= 1 << intent; } } -inline uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number direction) +uint8_t getSupportedIntents(cmsHPROFILE profile, cmsUInt32Number direction) { if (!profile) { return 0; @@ -166,22 +178,22 @@ inline uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number directi 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); + 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 () +cmsHPROFILE createXYZProfile() { double mat[3][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0} }; - return ICCStore::createFromMatrix (mat, false, "XYZ"); + 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, xyz_rec2020}; -const double (*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz, rec2020_xyz}; +const double(*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best, xyz_rec2020}; +const double(*iwprofiles[])[3] = {sRGB_xyz, adobe_xyz, prophoto_xyz, widegamut_xyz, bruce_xyz, beta_xyz, best_xyz, rec2020_xyz}; const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB", "Beta RGB", "BestRGB", "Rec2020"}; const char* wpgamma[] = {"default", "BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "linear_g1.0", "standard_g2.2", "standard_g1.8", "High_g1.3_s3.35", "Low_g2.6_s6.9"}; //gamma free //default = gamma inside profile @@ -193,238 +205,566 @@ const char* wpgamma[] = {"default", "BT709_g2.2_s4.5", "sRGB_g2.4_s12.92", "line } -namespace rtengine +rtengine::ProfileContent::ProfileContent() = default; + +rtengine::ProfileContent::ProfileContent(const Glib::ustring& fileName) { + FILE* const f = g_fopen(fileName.c_str(), "rb"); -std::vector getGamma () -{ - - std::vector res; - - for (unsigned int i = 0; i < sizeof (wpgamma) / sizeof (wpgamma[0]); i++) { - res.push_back (wpgamma[i]); + if (!f) { + return; } - return res; + fseek(f, 0, SEEK_END); + const long length = ftell(f); + fseek(f, 0, SEEK_SET); + char* d = new char[length + 1]; + fread(d, length, 1, f); + d[length] = 0; + fclose(f); + + data.assign(d, length + 1); + delete[] d; } -std::vector getWorkingProfiles () +rtengine::ProfileContent::ProfileContent(cmsHPROFILE hProfile) { + if (hProfile != nullptr) { + cmsUInt32Number bytesNeeded = 0; + cmsSaveProfileToMem(hProfile, nullptr, &bytesNeeded); - std::vector res; - - for (unsigned int i = 0; i < sizeof (wpnames) / sizeof (wpnames[0]); i++) { - res.push_back (wpnames[i]); + if (bytesNeeded > 0) { + char* d = new char[bytesNeeded + 1]; + cmsSaveProfileToMem(hProfile, d, &bytesNeeded); + data.assign(d, bytesNeeded + 1); + delete[] d; + } } - - return res; } -std::vector ICCStore::getProfiles (const ProfileType type) const +cmsHPROFILE rtengine::ProfileContent::toProfile() const { - MyMutex::MyLock lock (mutex_); + return + !data.empty() + ? cmsOpenProfileFromMem(data.data(), data.size()) + : nullptr; +} - std::vector res; +const std::string& rtengine::ProfileContent::getData() const +{ + return data; +} - for (const auto profile : fileProfiles) { - if ( (type==ICCStore::ProfileType::MONITOR && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass && cmsGetColorSpace (profile.second) == cmsSigRgbData) - || (type==ICCStore::ProfileType::PRINTER && cmsGetDeviceClass(profile.second) == cmsSigOutputClass) - || (type==ICCStore::ProfileType::OUTPUT && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass && cmsGetColorSpace (profile.second) == cmsSigRgbData) ) - { - res.push_back (profile.first); +class rtengine::ICCStore::Implementation +{ +public: + Implementation() : + loadAll(true), + xyz(createXYZProfile()), + srgb(cmsCreate_sRGBProfile()) + { + //cmsErrorAction(LCMS_ERROR_SHOW); + + constexpr int N = sizeof(wpnames) / sizeof(wpnames[0]); + + for (int i = 0; i < N; ++i) { + wProfiles[wpnames[i]] = createFromMatrix(wprofiles[i]); + wProfilesGamma[wpnames[i]] = createFromMatrix(wprofiles[i], true); + wMatrices[wpnames[i]] = wprofiles[i]; + iwMatrices[wpnames[i]] = iwprofiles[i]; } } - return res; -} + void init(const Glib::ustring& usrICCDir, const Glib::ustring& rtICCDir, bool loadAll) + { + // Reads all profiles from the given profiles dir -std::vector ICCStore::getProfilesFromDir (const Glib::ustring& dirName) const -{ + MyMutex::MyLock lock(mutex); - MyMutex::MyLock lock (mutex_); + this->loadAll = loadAll; - std::vector res; + // RawTherapee's profiles take precedence if a user's profile of the same name exists + profilesDir = Glib::build_filename(rtICCDir, "output"); + userICCDir = usrICCDir; + fileProfiles.clear(); + fileProfileContents.clear(); + if (loadAll) { + loadProfiles(profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); + loadProfiles(userICCDir, &fileProfiles, &fileProfileContents, nullptr, false); + } - ProfileMap profiles; - - loadProfiles (profilesDir, &profiles, nullptr, nullptr, false); - loadProfiles (dirName, &profiles, nullptr, nullptr, false); - - 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) { - return nullptr; - } - - cmsUInt32Number bytesNeeded = 0; - cmsSaveProfileToMem (iprof, nullptr, &bytesNeeded); - - if (bytesNeeded == 0) { - return nullptr; - } - - uint8_t *data = new uint8_t[bytesNeeded + 1]; - cmsSaveProfileToMem (iprof, data, &bytesNeeded); - const uint8_t *p = &data[128]; // skip 128 byte header - uint32_t tag_count; - memcpy (&tag_count, p, 4); - p += 4; - tag_count = ntohl (tag_count); - - struct icctag { - uint32_t sig; - uint32_t offset; - uint32_t size; - } tags[tag_count]; - - const uint32_t gamma = 0x239; - int gamma_size = (gamma == 0 || gamma == 256) ? 12 : 14; - int data_size = (gamma_size + 3) & ~3; - - for (uint32_t i = 0; i < tag_count; i++) { - memcpy (&tags[i], p, 12); - tags[i].sig = ntohl (tags[i].sig); - tags[i].offset = ntohl (tags[i].offset); - tags[i].size = ntohl (tags[i].size); - p += 12; - - if (tags[i].sig != 0x62545243 && // bTRC - tags[i].sig != 0x67545243 && // gTRC - tags[i].sig != 0x72545243 && // rTRC - tags[i].sig != 0x6B545243) { // kTRC - data_size += (tags[i].size + 3) & ~3; + // 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(); + if (loadAll) { + loadProfiles(stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true); } } - uint32_t sz = 128 + 4 + tag_count * 12 + data_size; - uint8_t *nd = new uint8_t[sz]; - memset (nd, 0, sz); - memcpy (nd, data, 128 + 4); - sz = htonl (sz); - memcpy (nd, &sz, 4); - uint32_t offset = 128 + 4 + tag_count * 12; - uint32_t gamma_offset = 0; + void findDefaultMonitorProfile() + { + // Determine the first monitor default profile of operating system, if selected - for (uint32_t i = 0; i < tag_count; i++) { - struct icctag tag; - tag.sig = htonl (tags[i].sig); + defaultMonitorProfile.clear(); - if (tags[i].sig == 0x62545243 || // bTRC - tags[i].sig == 0x67545243 || // gTRC - tags[i].sig == 0x72545243 || // rTRC - tags[i].sig == 0x6B545243) { // kTRC - if (gamma_offset == 0) { - gamma_offset = offset; - uint32_t pcurve[] = { htonl(0x63757276), htonl(0), htonl(gamma_size == 12 ? 0U : 1U) }; - memcpy (&nd[offset], pcurve, 12); + #ifdef WIN32 + // Get current main monitor. Could be fine tuned to get the current windows monitor(multi monitor setup), + // but problem is that we live in RTEngine with no GUI window to query around + HDC hDC = GetDC(nullptr); - if (gamma_size == 14) { - uint16_t gm = htons (gamma); - memcpy (&nd[offset + 12], &gm, 2); + if (hDC != nullptr) { + if (SetICMMode(hDC, ICM_ON)) { + char profileName[MAX_PATH + 1]; + DWORD profileLength = MAX_PATH; + + 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); + } } - offset += (gamma_size + 3) & ~3; + // might fail if e.g. the monitor has no profile } - tag.offset = htonl (gamma_offset); - tag.size = htonl (gamma_size); - } else { - tag.offset = htonl (offset); - tag.size = htonl (tags[i].size); - memcpy (&nd[offset], &data[tags[i].offset], tags[i].size); - offset += (tags[i].size + 3) & ~3; + ReleaseDC(NULL, hDC); } - memcpy (&nd[128 + 4 + i * 12], &tag, 12); + #else + // TODO: Add other OS specific code here + #endif + + if (options.rtSettings.verbose) { + printf("Default monitor profile is: %s\n", defaultMonitorProfile.c_str()); + } } - cmsHPROFILE oprof = cmsOpenProfileFromMem (nd, ntohl (sz)); - delete [] nd; - delete [] data; - return oprof; -} - -ICCStore* ICCStore::getInstance () -{ - static ICCStore instance_; - return &instance_; -} - -ICCStore::ICCStore () : - loadAll(true), - xyz (createXYZProfile ()), - srgb (cmsCreate_sRGBProfile ()) -{ - //cmsErrorAction (LCMS_ERROR_SHOW); - - int N = sizeof (wpnames) / sizeof (wpnames[0]); - - for (int i = 0; i < N; i++) { - wProfiles[wpnames[i]] = createFromMatrix (wprofiles[i]); - wProfilesGamma[wpnames[i]] = createFromMatrix (wprofiles[i], true); - wMatrices[wpnames[i]] = wprofiles[i]; - iwMatrices[wpnames[i]] = iwprofiles[i]; + cmsHPROFILE getDefaultMonitorProfile() + { + return getProfile(defaultMonitorProfile); } + + Glib::ustring getDefaultMonitorProfileName() const + { + return defaultMonitorProfile; + } + + cmsHPROFILE workingSpace(const Glib::ustring& name) const + { + const ProfileMap::const_iterator r = wProfiles.find(name); + + return + r != wProfiles.end() + ? r->second + : wProfiles.find("sRGB")->second; + } + + cmsHPROFILE workingSpaceGamma(const Glib::ustring& name) const + { + + const ProfileMap::const_iterator r = wProfilesGamma.find(name); + + return + r != wProfilesGamma.end() + ? r->second + : wProfilesGamma.find("sRGB")->second; + } + + TMatrix workingSpaceMatrix(const Glib::ustring& name) const + { + const MatrixMap::const_iterator r = wMatrices.find(name); + + return + r != wMatrices.end() + ? r->second + : wMatrices.find("sRGB")->second; + } + + TMatrix workingSpaceInverseMatrix(const Glib::ustring& name) const + { + + const MatrixMap::const_iterator r = iwMatrices.find(name); + + return + r != iwMatrices.end() + ? r->second + : iwMatrices.find("sRGB")->second; + } + + bool outputProfileExist(const Glib::ustring& name) const + { + MyMutex::MyLock lock(mutex); + return fileProfiles.find(name) != fileProfiles.end(); + } + + cmsHPROFILE getProfile(const Glib::ustring& name) + { + MyMutex::MyLock lock(mutex); + + const ProfileMap::const_iterator r = fileProfiles.find(name); + + if (r != fileProfiles.end()) { + return r->second; + } + + if (!name.compare(0, 5, "file:")) { + const ProfileContent content(name.substr(5)); + const cmsHPROFILE profile = content.toProfile(); + + if (profile) { + fileProfiles.emplace(name, profile); + fileProfileContents.emplace(name, content); + + return profile; + } + } else if (!loadAll) { + // Look for a standard profile + if (!loadProfile(name, profilesDir, &fileProfiles, &fileProfileContents)) { + loadProfile(name, userICCDir, &fileProfiles, &fileProfileContents); + } + const ProfileMap::const_iterator r = fileProfiles.find(name); + if (r != fileProfiles.end()) { + return r->second; + } + } + + return nullptr; + } + + cmsHPROFILE getStdProfile(const Glib::ustring& name) + { + const Glib::ustring nameUpper = name.uppercase(); + + MyMutex::MyLock lock(mutex); + + const ProfileMap::const_iterator r = fileStdProfiles.find(nameUpper); + + // Return profile from store + if (r != fileStdProfiles.end()) { + return r->second; + } else if (!loadAll) { + // Directory not scanned, so looking and adding now... + if (!loadProfile(name, profilesDir, &fileProfiles, &fileProfileContents)) { + loadProfile(name, userICCDir, &fileProfiles, &fileProfileContents); + } + const ProfileMap::const_iterator r = fileProfiles.find(name); + if (r != fileProfiles.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 nullptr; + } + + // But there exists one --> load it + const ProfileContent content(f->second); + const cmsHPROFILE profile = content.toProfile(); + + if (profile) { + fileStdProfiles.emplace(f->first, profile); + } + + // Profile invalid or stored now --> remove entry from fileStdProfilesFileNames + fileStdProfilesFileNames.erase(f); + return profile; + } + + ProfileContent getContent(const Glib::ustring& name) const + { + MyMutex::MyLock lock(mutex); + + const ContentMap::const_iterator r = fileProfileContents.find(name); + + return + r != fileProfileContents.end() + ? r->second + : ProfileContent(); + } + + cmsHPROFILE getXYZProfile() const + { + return xyz; + } + + cmsHPROFILE getsRGBProfile() const + { + return srgb; + } + + std::vector getProfiles(ProfileType type) const + { + std::vector res; + + MyMutex::MyLock lock(mutex); + + for (const auto profile : fileProfiles) { + if ( +( + type==ICCStore::ProfileType::MONITOR + && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass + && cmsGetColorSpace(profile.second) == cmsSigRgbData + ) + ||( + type==ICCStore::ProfileType::PRINTER + && cmsGetDeviceClass(profile.second) == cmsSigOutputClass + ) + ||( + type==ICCStore::ProfileType::OUTPUT + && cmsGetDeviceClass(profile.second) == cmsSigDisplayClass + && cmsGetColorSpace(profile.second) == cmsSigRgbData + ) + ) { + res.push_back(profile.first); + } + } + + return res; + } + + std::vector getProfilesFromDir(const Glib::ustring& dirName) const + { + std::vector res; + ProfileMap profiles; + + MyMutex::MyLock lock(mutex); + + loadProfiles(profilesDir, &profiles, nullptr, nullptr, false); + loadProfiles(dirName, &profiles, nullptr, nullptr, false); + + for (const auto& profile : profiles) { + res.push_back(profile.first); + } + + return res; + } + + std::uint8_t getInputIntents(cmsHPROFILE profile) + { + MyMutex::MyLock lock(mutex); + + return getSupportedIntents(profile, LCMS_USED_AS_INPUT); + } + + std::uint8_t getOutputIntents(cmsHPROFILE profile) + { + MyMutex::MyLock lock(mutex); + + return getSupportedIntents(profile, LCMS_USED_AS_OUTPUT); + } + + std::uint8_t getProofIntents(cmsHPROFILE profile) + { + MyMutex::MyLock lock(mutex); + + return getSupportedIntents(profile, LCMS_USED_AS_PROOF); + } + + std::uint8_t getInputIntents(const Glib::ustring &name) + { + return getInputIntents(getProfile(name)); + } + + std::uint8_t getOutputIntents(const Glib::ustring &name) + { + return getOutputIntents(getProfile(name)); + } + + std::uint8_t getProofIntents(const Glib::ustring &name) + { + return getProofIntents(getProfile(name)); + } + +private: + using ProfileMap = std::map; + using MatrixMap = std::map; + using ContentMap = std::map; + using NameMap = std::map; + + ProfileMap wProfiles; + ProfileMap wProfilesGamma; + MatrixMap wMatrices; + MatrixMap iwMatrices; + + // These contain profiles from user/system directory(supplied on init) + Glib::ustring profilesDir; + Glib::ustring userICCDir; + ProfileMap fileProfiles; + ContentMap fileProfileContents; + + //These contain standard profiles from RT. Keys are all in uppercase. + Glib::ustring stdProfilesDir; + NameMap fileStdProfilesFileNames; + ProfileMap fileStdProfiles; + + Glib::ustring defaultMonitorProfile; + + bool loadAll; + + const cmsHPROFILE xyz; + const cmsHPROFILE srgb; + + mutable MyMutex mutex; +}; + +rtengine::ICCStore* rtengine::ICCStore::getInstance() +{ + static rtengine::ICCStore instance; + return &instance; } -TMatrix ICCStore::workingSpaceMatrix (const Glib::ustring& name) const +void rtengine::ICCStore::init(const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir, bool loadAll) +{ + implementation->init(usrICCDir, stdICCDir, loadAll); +} + +void rtengine::ICCStore::findDefaultMonitorProfile() +{ + implementation->findDefaultMonitorProfile(); +} + +cmsHPROFILE rtengine::ICCStore::getDefaultMonitorProfile() const +{ + return implementation->getDefaultMonitorProfile(); +} + +Glib::ustring rtengine::ICCStore::getDefaultMonitorProfileName() const +{ + return implementation->getDefaultMonitorProfileName(); +} + +cmsHPROFILE rtengine::ICCStore::workingSpace(const Glib::ustring& name) const +{ + return implementation->workingSpace(name); +} + +cmsHPROFILE rtengine::ICCStore::workingSpaceGamma(const Glib::ustring& name) const +{ + return implementation->workingSpaceGamma(name); +} + +rtengine::TMatrix rtengine::ICCStore::workingSpaceMatrix(const Glib::ustring& name) const +{ + return implementation->workingSpaceMatrix(name); +} + +rtengine::TMatrix rtengine::ICCStore::workingSpaceInverseMatrix(const Glib::ustring& name) const +{ + return implementation->workingSpaceInverseMatrix(name); +} + +bool rtengine::ICCStore::outputProfileExist(const Glib::ustring& name) const +{ + return implementation->outputProfileExist(name); +} + +cmsHPROFILE rtengine::ICCStore::getProfile(const Glib::ustring& name) const +{ + return implementation->getProfile(name); +} + +cmsHPROFILE rtengine::ICCStore::getStdProfile(const Glib::ustring& name) const +{ + return implementation->getStdProfile(name); +} + +rtengine::ProfileContent rtengine::ICCStore::getContent(const Glib::ustring& name) const +{ + return implementation->getContent(name); +} + +cmsHPROFILE rtengine::ICCStore::getXYZProfile() const +{ + return implementation->getXYZProfile(); +} + +cmsHPROFILE rtengine::ICCStore::getsRGBProfile() const +{ + return implementation->getXYZProfile(); +} + +std::vector rtengine::ICCStore::getProfiles(ProfileType type) const +{ + return implementation->getProfiles(type); +} + +std::vector rtengine::ICCStore::getProfilesFromDir(const Glib::ustring& dirName) const +{ + return implementation->getProfilesFromDir(dirName); +} + +std::uint8_t rtengine::ICCStore::getInputIntents(cmsHPROFILE profile) const +{ + return implementation->getInputIntents(profile); +} + +std::uint8_t rtengine::ICCStore::getOutputIntents(cmsHPROFILE profile) const +{ + return implementation->getOutputIntents(profile); +} + +std::uint8_t rtengine::ICCStore::getProofIntents(cmsHPROFILE profile) const +{ + return implementation->getProofIntents(profile); +} + +std::uint8_t rtengine::ICCStore::getInputIntents(const Glib::ustring& name) const +{ + return implementation->getInputIntents(name); +} + +std::uint8_t rtengine::ICCStore::getOutputIntents(const Glib::ustring& name) const +{ + return implementation->getOutputIntents(name); +} + +std::uint8_t rtengine::ICCStore::getProofIntents(const Glib::ustring& name) const +{ + return implementation->getProofIntents(name); +} + +rtengine::ICCStore::ICCStore() : + implementation(new Implementation) +{ +} + +rtengine::ICCStore::~ICCStore() = default; + +std::vector rtengine::ICCStore::getWorkingProfiles() { - const MatrixMap::const_iterator r = wMatrices.find (name); + std::vector res; - if (r != wMatrices.end()) { - return r->second; - } else { - return wMatrices.find ("sRGB")->second; + for (unsigned int i = 0; i < sizeof(wpnames) / sizeof(wpnames[0]); i++) { + res.push_back(wpnames[i]); } + + return res; } -TMatrix ICCStore::workingSpaceInverseMatrix (const Glib::ustring& name) const +std::vector rtengine::ICCStore::getGamma() { - const MatrixMap::const_iterator r = iwMatrices.find (name); + std::vector res; - if (r != iwMatrices.end()) { - return r->second; - } else { - return iwMatrices.find ("sRGB")->second; + for (unsigned int i = 0; i < sizeof(wpgamma) / sizeof(wpgamma[0]); i++) { + res.push_back(wpgamma[i]); } + + return res; } -cmsHPROFILE ICCStore::workingSpace (const Glib::ustring& name) const -{ - - const ProfileMap::const_iterator r = wProfiles.find (name); - - if (r != wProfiles.end()) { - return r->second; - } else { - return wProfiles.find ("sRGB")->second; - } -} - -cmsHPROFILE ICCStore::workingSpaceGamma (const Glib::ustring& name) const -{ - - const ProfileMap::const_iterator r = wProfilesGamma.find (name); - - if (r != wProfilesGamma.end()) { - return r->second; - } else { - return wProfilesGamma.find ("sRGB")->second; - } -} - -void ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga) +void rtengine::ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga) { const double eps = 0.000000001; // not divide by zero if (!icm.freegamma) {//if Free gamma not selected @@ -454,19 +794,19 @@ void ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, Gamma ga[3] = 0.144928; ga[4] = 0.076332; } else if (icm.gamma == "standard_g2.2") { - ga[0] = 2.2; //gamma=2.2 (as gamma of Adobe, Widegamut...) + ga[0] = 2.2; //gamma=2.2(as gamma of Adobe, Widegamut...) ga[1] = 1.; ga[2] = 0.; ga[3] = 1. / eps; ga[4] = 0.; } else if (icm.gamma == "standard_g1.8") { - ga[0] = 1.8; //gamma=1.8 (as gamma of Prophoto) + ga[0] = 1.8; //gamma=1.8(as gamma of Prophoto) ga[1] = 1.; ga[2] = 0.; ga[3] = 1. / eps; ga[4] = 0.; } else /* if (icm.gamma == "linear_g1.0") */ { - ga[0] = 1.0; //gamma=1 linear : for high dynamic images (cf : D.Coffin...) + ga[0] = 1.0; //gamma=1 linear : for high dynamic images(cf : D.Coffin...) ga[1] = 1.; ga[2] = 0.; ga[3] = 1. / eps; @@ -485,8 +825,8 @@ void ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, Gamma ga[4] = g_a[3] * ts; //printf("g_a.gamma0=%f g_a.gamma1=%f g_a.gamma2=%f g_a.gamma3=%f g_a.gamma4=%f\n", g_a.gamma0,g_a.gamma1,g_a.gamma2,g_a.gamma3,g_a.gamma4); ga[0] = icm.gampos; - ga[1] = 1. / (1.0 + g_a[4]); - ga[2] = g_a[4] / (1.0 + g_a[4]); + ga[1] = 1. /(1.0 + g_a[4]); + ga[2] = g_a[4] /(1.0 + g_a[4]); ga[3] = 1. / slope; ga[5] = 0.0; ga[6] = 0.0; @@ -495,7 +835,197 @@ void ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, Gamma } // WARNING: the caller must lock lcmsMutex -cmsHPROFILE ICCStore::createGammaProfile (const procparams::ColorManagementParams &icm, GammaValues &ga) { +cmsHPROFILE rtengine::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) { + return nullptr; + } + + cmsUInt32Number bytesNeeded = 0; + cmsSaveProfileToMem(iprof, nullptr, &bytesNeeded); + + if (bytesNeeded == 0) { + return nullptr; + } + + uint8_t *data = new uint8_t[bytesNeeded + 1]; + cmsSaveProfileToMem(iprof, data, &bytesNeeded); + const uint8_t *p = &data[128]; // skip 128 byte header + uint32_t tag_count; + memcpy(&tag_count, p, 4); + p += 4; + tag_count = ntohl(tag_count); + + struct icctag { + uint32_t sig; + uint32_t offset; + uint32_t size; + } tags[tag_count]; + + const uint32_t gamma = 0x239; + int gamma_size =(gamma == 0 || gamma == 256) ? 12 : 14; + int data_size =(gamma_size + 3) & ~3; + + for (uint32_t i = 0; i < tag_count; i++) { + memcpy(&tags[i], p, 12); + tags[i].sig = ntohl(tags[i].sig); + tags[i].offset = ntohl(tags[i].offset); + tags[i].size = ntohl(tags[i].size); + p += 12; + + if (tags[i].sig != 0x62545243 && // bTRC + tags[i].sig != 0x67545243 && // gTRC + tags[i].sig != 0x72545243 && // rTRC + tags[i].sig != 0x6B545243) { // kTRC + data_size +=(tags[i].size + 3) & ~3; + } + } + + uint32_t sz = 128 + 4 + tag_count * 12 + data_size; + uint8_t *nd = new uint8_t[sz]; + memset(nd, 0, sz); + memcpy(nd, data, 128 + 4); + sz = htonl(sz); + memcpy(nd, &sz, 4); + uint32_t offset = 128 + 4 + tag_count * 12; + uint32_t gamma_offset = 0; + + for (uint32_t i = 0; i < tag_count; i++) { + struct icctag tag; + tag.sig = htonl(tags[i].sig); + + if (tags[i].sig == 0x62545243 || // bTRC + tags[i].sig == 0x67545243 || // gTRC + tags[i].sig == 0x72545243 || // rTRC + tags[i].sig == 0x6B545243) { // kTRC + if (gamma_offset == 0) { + gamma_offset = offset; + uint32_t pcurve[] = { htonl(0x63757276), htonl(0), htonl(gamma_size == 12 ? 0U : 1U) }; + memcpy(&nd[offset], pcurve, 12); + + if (gamma_size == 14) { + uint16_t gm = htons(gamma); + memcpy(&nd[offset + 12], &gm, 2); + } + + offset +=(gamma_size + 3) & ~3; + } + + tag.offset = htonl(gamma_offset); + tag.size = htonl(gamma_size); + } else { + tag.offset = htonl(offset); + tag.size = htonl(tags[i].size); + memcpy(&nd[offset], &data[tags[i].offset], tags[i].size); + offset +=(tags[i].size + 3) & ~3; + } + + memcpy(&nd[128 + 4 + i * 12], &tag, 12); + } + + cmsHPROFILE oprof = cmsOpenProfileFromMem(nd, ntohl(sz)); + delete [] nd; + delete [] data; + return oprof; +} + +cmsHPROFILE rtengine::ICCStore::createFromMatrix(const double matrix[3][3], bool gamma, const Glib::ustring& name) +{ + + static const unsigned phead[] = { + 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, + 0x61637370, 0, 0, 0, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d + }; + unsigned pbody[] = { + 10, 0x63707274, 0, 36, /* cprt */ + 0x64657363, 0, 40, /* desc */ + 0x77747074, 0, 20, /* wtpt */ + 0x626b7074, 0, 20, /* bkpt */ + 0x72545243, 0, 14, /* rTRC */ + 0x67545243, 0, 14, /* gTRC */ + 0x62545243, 0, 14, /* bTRC */ + 0x7258595a, 0, 20, /* rXYZ */ + 0x6758595a, 0, 20, /* gXYZ */ + 0x6258595a, 0, 20 + }; /* bXYZ */ + static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };//D65 + //static const unsigned pwhite[] = { 0xf6d6, 0x10000, 0xd340 };//D50 + + // 0x63757276 : curveType, 0 : reserved, 1 : entries(1=gamma, 0=identity), 0x1000000=1.0 + unsigned pcurve[] = { 0x63757276, 0, 0, 0x1000000 }; +// unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; + + if (gamma) { + pcurve[2] = 1; + // pcurve[3] = 0x1f00000;// pcurve for gamma BT709 : g=2.22 s=4.5 + // normalize gamma in RT, default(Emil's choice = sRGB) + pcurve[3] = 0x2390000;//pcurve for gamma sRGB : g:2.4 s=12.92 + + } else { + // lcms2 up to 2.4 has a bug with linear gamma causing precision loss(banding) + // of floating point data when a normal icc encoding of linear gamma is used + //(i e 0 table entries), but by encoding a gamma curve which is 1.0 the + // floating point path is taken within lcms2 so no precision loss occurs and + // gamma is still 1.0. + pcurve[2] = 1; + pcurve[3] = 0x1000000; //pcurve for gamma 1 + } + + // constructing profile header + unsigned* oprof = new unsigned [phead[0] / sizeof(unsigned)]; + memset(oprof, 0, phead[0]); + memcpy(oprof, phead, sizeof(phead)); + + oprof[0] = 132 + 12 * pbody[0]; + + // constructing tag directory(pointers inside the file), and types + // 0x74657874 : text + // 0x64657363 : description tag + for (unsigned int i = 0; i < pbody[0]; i++) { + oprof[oprof[0] / 4] = i ?(i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; + pbody[i * 3 + 2] = oprof[0]; + oprof[0] +=(pbody[i * 3 + 3] + 3) & -4; + } + + memcpy(oprof + 32, pbody, sizeof(pbody)); + + // wtpt + memcpy((char *)oprof + pbody[8] + 8, pwhite, sizeof(pwhite)); + + // r/g/b TRC + for (int i = 4; i < 7; i++) { + memcpy((char *)oprof + pbody[i * 3 + 2], pcurve, sizeof(pcurve)); + } + + // r/g/b XYZ +// pseudoinverse((double(*)[3]) out_rgb[output_color-1], inverse, 3); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + oprof[pbody[j * 3 + 23] / 4 + i + 2] = matrix[i][j] * 0x10000 + 0.5; +// for (num = k=0; k < 3; k++) +// num += xyzd50_srgb[i][k] * inverse[j][k]; + } + + // convert to network byte order + for (unsigned int i = 0; i < phead[0] / 4; i++) { + oprof[i] = htonl(oprof[i]); + } + + // cprt + strcpy((char *)oprof + pbody[2] + 8, "--rawtherapee profile--"); + + // desc + oprof[pbody[5] / 4 + 2] = name.size() + 1; + strcpy((char *)oprof + pbody[5] + 12, name.c_str()); + + + cmsHPROFILE p = cmsOpenProfileFromMem(oprof, ntohl(oprof[0])); + delete [] oprof; + return p; +} + +cmsHPROFILE rtengine::ICCStore::createGammaProfile(const procparams::ColorManagementParams &icm, GammaValues &ga) { float p[6]; //primaries ga[6] = 0.0; @@ -580,49 +1110,49 @@ cmsHPROFILE ICCStore::createGammaProfile (const procparams::ColorManagementParam // 7 parameters for smoother curves cmsFloat64Number Parameters[7] = { ga[0], ga[1], ga[2], ga[3], ga[4], ga[5], ga[6] } ; - //lcmsMutex->lock (); Mutex acquired by the caller - cmsWhitePointFromTemp(&xyD, (double)temp); + //lcmsMutex->lock(); Mutex acquired by the caller + cmsWhitePointFromTemp(&xyD,(double)temp); GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, Parameters); //5 = smoother than 4 cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); //oprofdef become Outputprofile cmsFreeToneCurve(GammaTRC[0]); - //lcmsMutex->unlock (); + //lcmsMutex->unlock(); return oprofdef; } // WARNING: the caller must lock lcmsMutex -cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorManagementParams &icm, GammaValues &ga) { +cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams::ColorManagementParams &icm, GammaValues &ga) { bool pro = false; Glib::ustring outProfile; cmsHPROFILE outputProfile = nullptr; if (icm.freegamma && icm.gampos < 1.35) { pro = true; //select profil with gammaTRC modified : - } else if (icm.gamma == "linear_g1.0" || (icm.gamma == "High_g1.3_s3.35")) { + } else if (icm.gamma == "linear_g1.0" ||(icm.gamma == "High_g1.3_s3.35")) { pro = true; //pro=0 RT_sRGB || Prophoto } // Check that output profiles exist, otherwise use LCMS2 // Use the icc/icm profiles associated to possible working profiles, set in "options" - if (icm.working == "ProPhoto" && iccStore->outputProfileExist(options.rtSettings.prophoto) && !pro) { + if (icm.working == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto) && !pro) { outProfile = options.rtSettings.prophoto; - } else if (icm.working == "Adobe RGB" && iccStore->outputProfileExist(options.rtSettings.adobe) ) { + } else if (icm.working == "Adobe RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.adobe) ) { outProfile = options.rtSettings.adobe; - } else if (icm.working == "WideGamut" && iccStore->outputProfileExist(options.rtSettings.widegamut) ) { + } else if (icm.working == "WideGamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut) ) { outProfile = options.rtSettings.widegamut; - } else if (icm.working == "Beta RGB" && iccStore->outputProfileExist(options.rtSettings.beta) ) { + } else if (icm.working == "Beta RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta) ) { outProfile = options.rtSettings.beta; - } else if (icm.working == "BestRGB" && iccStore->outputProfileExist(options.rtSettings.best) ) { + } else if (icm.working == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best) ) { outProfile = options.rtSettings.best; - } else if (icm.working == "BruceRGB" && iccStore->outputProfileExist(options.rtSettings.bruce) ) { + } else if (icm.working == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce) ) { outProfile = options.rtSettings.bruce; - } else if (icm.working == "sRGB" && iccStore->outputProfileExist(options.rtSettings.srgb) && !pro) { + } else if (icm.working == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb) && !pro) { outProfile = options.rtSettings.srgb; - } else if (icm.working == "sRGB" && iccStore->outputProfileExist(options.rtSettings.srgb10) && pro) { + } else if (icm.working == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb10) && pro) { outProfile = options.rtSettings.srgb10; - } else if (icm.working == "ProPhoto" && iccStore->outputProfileExist(options.rtSettings.prophoto10) && pro) { + } else if (icm.working == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto10) && pro) { outProfile = options.rtSettings.prophoto10; - } else if (icm.working == "Rec2020" && iccStore->outputProfileExist(options.rtSettings.rec2020) ) { + } else if (icm.working == "Rec2020" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.rec2020) ) { outProfile = options.rtSettings.rec2020; } else { // Should not occurs @@ -639,7 +1169,7 @@ cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorMan printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str() } - outputProfile = iccStore->getProfile(outProfile); //get output profile + outputProfile = ICCStore::getInstance()->getProfile(outProfile); //get output profile if (outputProfile == nullptr) { @@ -687,7 +1217,7 @@ cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorMan // create description with gamma + slope + primaries std::wostringstream gammaWs; gammaWs.precision(2); - gammaWs << "Manual GammaTRC: g=" << (float)icm.gampos << " s=" << (float)icm.slpos; + gammaWs << "Manual GammaTRC: g=" <<(float)icm.gampos << " s=" <<(float)icm.slpos; cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str()); } @@ -706,15 +1236,15 @@ cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorMan */ - cmsMLUfree (mlu); + cmsMLUfree(mlu); } // Calculate output profile's rTRC gTRC bTRC cmsToneCurve* GammaTRC = nullptr; GammaTRC = cmsBuildParametricToneCurve(nullptr, 5, Parameters); - cmsWriteTag(outputProfile, cmsSigRedTRCTag, (void*)GammaTRC ); - cmsWriteTag(outputProfile, cmsSigGreenTRCTag, (void*)GammaTRC ); - cmsWriteTag(outputProfile, cmsSigBlueTRCTag, (void*)GammaTRC ); + cmsWriteTag(outputProfile, cmsSigRedTRCTag,(void*)GammaTRC ); + cmsWriteTag(outputProfile, cmsSigGreenTRCTag,(void*)GammaTRC ); + cmsWriteTag(outputProfile, cmsSigBlueTRCTag,(void*)GammaTRC ); if (GammaTRC) { cmsFreeToneCurve(GammaTRC); @@ -722,359 +1252,3 @@ cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorMan return outputProfile; } - -bool ICCStore::outputProfileExist (const Glib::ustring& name) const -{ - - MyMutex::MyLock lock(mutex_); - return fileProfiles.find(name) != fileProfiles.end(); -} - -cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) -{ - - MyMutex::MyLock lock (mutex_); - - const ProfileMap::const_iterator r = fileProfiles.find (name); - - if (r != fileProfiles.end ()) { - return r->second; - } - - if (name.compare (0, 5, "file:") == 0) { - const ProfileContent content (name.substr (5)); - const cmsHPROFILE profile = content.toProfile (); - - if (profile) { - const_cast (fileProfiles).insert (std::make_pair (name, profile)); - const_cast (fileProfileContents).insert (std::make_pair (name, content)); - - return profile; - } - } else if (!loadAll) { - // look for a standard profile - if (!loadProfile (name, profilesDir, &fileProfiles, &fileProfileContents)) { - loadProfile (name, userICCDir, &fileProfiles, &fileProfileContents); - } - const ProfileMap::const_iterator r = fileProfiles.find (name); - if (r != fileProfiles.end ()) { - return r->second; - } - } - - return nullptr; -} - -cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) -{ - - const Glib::ustring nameUpper = name.uppercase (); - - MyMutex::MyLock lock (mutex_); - - const ProfileMap::const_iterator r = fileStdProfiles.find (nameUpper); - - // return profile from store - if (r != fileStdProfiles.end ()) { - return r->second; - } else if (!loadAll) { - // directory not scanned, so looking and adding now... - if (!loadProfile (name, profilesDir, &fileProfiles, &fileProfileContents)) { - loadProfile (name, userICCDir, &fileProfiles, &fileProfileContents); - } - const ProfileMap::const_iterator r = fileProfiles.find (name); - if (r != fileProfiles.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 nullptr; - } - - // 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 (const Glib::ustring& name) const -{ - - MyMutex::MyLock lock (mutex_); - - const ContentMap::const_iterator r = fileProfileContents.find (name); - - return r != fileProfileContents.end () ? r->second : ProfileContent(); -} - -uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) -{ - MyMutex::MyLock lock (mutex_); - - return getSupportedIntents (profile, LCMS_USED_AS_INPUT); -} - -uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) -{ - MyMutex::MyLock lock (mutex_); - - return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT); -} - -uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) -{ - MyMutex::MyLock lock (mutex_); - - return getSupportedIntents (profile, LCMS_USED_AS_PROOF); -} - -// Reads all profiles from the given profiles dir -void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCDir, bool loadAll) -{ - - MyMutex::MyLock lock (mutex_); - - this->loadAll = loadAll; - - // RawTherapee's profiles take precedence if a user's profile of the same name exists - profilesDir = Glib::build_filename (rtICCDir, "output"); - userICCDir = usrICCDir; - fileProfiles.clear(); - fileProfileContents.clear(); - if (loadAll) { - loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, nullptr, false); - loadProfiles (userICCDir, &fileProfiles, &fileProfileContents, nullptr, false); - } - - // 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(); - if (loadAll) { - loadProfiles (stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true); - } -} - -// Determine the first monitor default profile of operating system, if selected -void ICCStore::findDefaultMonitorProfile () -{ - defaultMonitorProfile.clear (); - -#ifdef WIN32 - // Get current main monitor. Could be fine tuned to get the current windows monitor (multi monitor setup), - // but problem is that we live in RTEngine with no GUI window to query around - HDC hDC = GetDC (NULL); - - if (hDC != NULL) { - if (SetICMMode (hDC, ICM_ON)) { - char profileName[MAX_PATH + 1]; - DWORD profileLength = MAX_PATH; - - 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 - } - - ReleaseDC (NULL, hDC); - } - -#else -// TODO: Add other OS specific code here -#endif - - if (options.rtSettings.verbose) { - printf ("Default monitor profile is: %s\n", defaultMonitorProfile.c_str()); - } -} - -ProfileContent::ProfileContent (const Glib::ustring& fileName) : data(nullptr), length(0) -{ - - FILE* f = g_fopen (fileName.c_str (), "rb"); - - if (!f) { - return; - } - - fseek (f, 0, SEEK_END); - length = ftell (f); - fseek (f, 0, SEEK_SET); - data = new char[length + 1]; - fread (data, length, 1, f); - data[length] = 0; - fclose (f); -} - -ProfileContent::ProfileContent (const ProfileContent& other) -{ - - length = other.length; - - if (other.data) { - data = new char[length + 1]; - memcpy (data, other.data, length + 1); - } else { - data = nullptr; - } -} - -ProfileContent::ProfileContent (cmsHPROFILE hProfile) : data(nullptr), length(0) -{ - - if (hProfile != nullptr) { - cmsUInt32Number bytesNeeded = 0; - cmsSaveProfileToMem (hProfile, nullptr, &bytesNeeded); - - if (bytesNeeded > 0) { - data = new char[bytesNeeded + 1]; - cmsSaveProfileToMem (hProfile, data, &bytesNeeded); - length = (int)bytesNeeded; - } - } -} - - -ProfileContent& ProfileContent::operator= (const ProfileContent& other) -{ - - length = other.length; - - delete [] data; - - if (other.data) { - data = new char[length + 1]; - memcpy (data, other.data, length + 1); - } else { - data = nullptr; - } - - return *this; -} - -cmsHPROFILE ProfileContent::toProfile () const -{ - - if (data) { - return cmsOpenProfileFromMem (data, length); - } else { - return nullptr; - } -} - -cmsHPROFILE ICCStore::createFromMatrix (const double matrix[3][3], bool gamma, const Glib::ustring& name) -{ - - static const unsigned phead[] = { - 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, - 0x61637370, 0, 0, 0, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d - }; - unsigned pbody[] = { - 10, 0x63707274, 0, 36, /* cprt */ - 0x64657363, 0, 40, /* desc */ - 0x77747074, 0, 20, /* wtpt */ - 0x626b7074, 0, 20, /* bkpt */ - 0x72545243, 0, 14, /* rTRC */ - 0x67545243, 0, 14, /* gTRC */ - 0x62545243, 0, 14, /* bTRC */ - 0x7258595a, 0, 20, /* rXYZ */ - 0x6758595a, 0, 20, /* gXYZ */ - 0x6258595a, 0, 20 - }; /* bXYZ */ - static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };//D65 - //static const unsigned pwhite[] = { 0xf6d6, 0x10000, 0xd340 };//D50 - - // 0x63757276 : curveType, 0 : reserved, 1 : entries (1=gamma, 0=identity), 0x1000000=1.0 - unsigned pcurve[] = { 0x63757276, 0, 0, 0x1000000 }; -// unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; - - if (gamma) { - pcurve[2] = 1; - // pcurve[3] = 0x1f00000;// pcurve for gamma BT709 : g=2.22 s=4.5 - // normalize gamma in RT, default (Emil's choice = sRGB) - pcurve[3] = 0x2390000;//pcurve for gamma sRGB : g:2.4 s=12.92 - - } else { - // lcms2 up to 2.4 has a bug with linear gamma causing precision loss (banding) - // of floating point data when a normal icc encoding of linear gamma is used - // (i e 0 table entries), but by encoding a gamma curve which is 1.0 the - // floating point path is taken within lcms2 so no precision loss occurs and - // gamma is still 1.0. - pcurve[2] = 1; - pcurve[3] = 0x1000000; //pcurve for gamma 1 - } - - // constructing profile header - unsigned* oprof = new unsigned [phead[0] / sizeof (unsigned)]; - memset (oprof, 0, phead[0]); - memcpy (oprof, phead, sizeof (phead)); - - oprof[0] = 132 + 12 * pbody[0]; - - // constructing tag directory (pointers inside the file), and types - // 0x74657874 : text - // 0x64657363 : description tag - for (unsigned int i = 0; i < pbody[0]; i++) { - oprof[oprof[0] / 4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; - pbody[i * 3 + 2] = oprof[0]; - oprof[0] += (pbody[i * 3 + 3] + 3) & -4; - } - - memcpy (oprof + 32, pbody, sizeof (pbody)); - - // wtpt - memcpy ((char *)oprof + pbody[8] + 8, pwhite, sizeof (pwhite)); - - // r/g/b TRC - for (int i = 4; i < 7; i++) { - memcpy ((char *)oprof + pbody[i * 3 + 2], pcurve, sizeof (pcurve)); - } - - // r/g/b XYZ -// pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); - for (int i = 0; i < 3; i++) - for (int j = 0; j < 3; j++) { - oprof[pbody[j * 3 + 23] / 4 + i + 2] = matrix[i][j] * 0x10000 + 0.5; -// for (num = k=0; k < 3; k++) -// num += xyzd50_srgb[i][k] * inverse[j][k]; - } - - // convert to network byte order - for (unsigned int i = 0; i < phead[0] / 4; i++) { - oprof[i] = htonl (oprof[i]); - } - - // cprt - strcpy ((char *)oprof + pbody[2] + 8, "--rawtherapee profile--"); - - // desc - oprof[pbody[5] / 4 + 2] = name.size() + 1; - strcpy ((char *)oprof + pbody[5] + 12, name.c_str()); - - - cmsHPROFILE p = cmsOpenProfileFromMem (oprof, ntohl (oprof[0])); - delete [] oprof; - return p; -} - -} diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 5d8ccd5f0..9562f3144 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -1,12 +1,12 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 2004-2010 Gabor Horvath + * Copyright(c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + *(at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,172 +16,103 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef __ICCSTORE__ -#define __ICCSTORE__ +#pragma once + +#include +#include +#include + +#include #include -#include -#include -#include -#include -#include "procparams.h" + #include "color.h" -#include "../rtgui/threadutils.h" namespace rtengine { -typedef const double (*TMatrix)[3]; +namespace procparams +{ + + class ColorManagementParams; + +} + +typedef const double(*TMatrix)[3]; class ProfileContent { - public: - char* data; - int length; + ProfileContent(); - ProfileContent (); - ~ProfileContent (); + explicit ProfileContent(const Glib::ustring& fileName); + explicit ProfileContent(cmsHPROFILE hProfile); + cmsHPROFILE toProfile() const; - ProfileContent (const ProfileContent& other); - ProfileContent& operator= (const rtengine::ProfileContent& other); + const std::string& getData() const; - explicit ProfileContent (const Glib::ustring& fileName); - explicit ProfileContent (cmsHPROFILE hProfile); - cmsHPROFILE toProfile () const; +private: + std::string data; }; class ICCStore { - typedef std::map ProfileMap; - typedef std::map MatrixMap; - typedef std::map ContentMap; - typedef std::map NameMap; - - ProfileMap wProfiles; - ProfileMap wProfilesGamma; - MatrixMap wMatrices; - MatrixMap iwMatrices; - - // these contain profiles from user/system directory (supplied on init) - Glib::ustring profilesDir; - Glib::ustring userICCDir; - ProfileMap fileProfiles; - ContentMap fileProfileContents; - - // these contain standard profiles from RT. keys are all in uppercase - Glib::ustring stdProfilesDir; - NameMap fileStdProfilesFileNames; - ProfileMap fileStdProfiles; - - Glib::ustring defaultMonitorProfile; - - bool loadAll; - - const cmsHPROFILE xyz; - const cmsHPROFILE srgb; - - mutable MyMutex mutex_; - - ICCStore (); - public: - enum class ProfileType { MONITOR, PRINTER, - OUTPUT // (actually correspond to the same profiles than with MONITOR) + OUTPUT //(actually correspond to the same profiles than with MONITOR) }; - static ICCStore* getInstance (); + static ICCStore* getInstance(); - void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir, bool loadAll); - - static void getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga); - static cmsHPROFILE makeStdGammaProfile (cmsHPROFILE iprof); - static cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring()); - static cmsHPROFILE createGammaProfile (const procparams::ColorManagementParams &icm, GammaValues &ga); - static cmsHPROFILE createCustomGammaOutputProfile (const procparams::ColorManagementParams &icm, GammaValues &ga); + void init(const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir, bool loadAll); // Main monitors standard profile name, from OS - void findDefaultMonitorProfile (); - cmsHPROFILE getDefaultMonitorProfile (); - Glib::ustring getDefaultMonitorProfileName (); + void findDefaultMonitorProfile(); + cmsHPROFILE getDefaultMonitorProfile() const; + Glib::ustring getDefaultMonitorProfileName() const; - 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 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; - bool outputProfileExist (const Glib::ustring& name) const; - cmsHPROFILE getProfile (const Glib::ustring& name); - cmsHPROFILE getStdProfile (const Glib::ustring& name); - ProfileContent getContent (const Glib::ustring& name) const; + bool outputProfileExist(const Glib::ustring& name) const; + 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; + cmsHPROFILE getXYZProfile() const; + cmsHPROFILE getsRGBProfile() const; - std::vector getProfiles (const ProfileType type = ProfileType::MONITOR) const; - std::vector getProfilesFromDir (const Glib::ustring& dirName) const; + std::vector getProfiles(ProfileType type = ProfileType::MONITOR) const; + std::vector getProfilesFromDir(const Glib::ustring& dirName) const; - uint8_t getInputIntents (cmsHPROFILE profile); - uint8_t getOutputIntents (cmsHPROFILE profile); - uint8_t getProofIntents (cmsHPROFILE profile); + std::uint8_t getInputIntents(cmsHPROFILE profile) const; + std::uint8_t getOutputIntents(cmsHPROFILE profile) const; + std::uint8_t getProofIntents(cmsHPROFILE profile) const; - uint8_t getInputIntents (const Glib::ustring& name); - uint8_t getOutputIntents (const Glib::ustring& name); - uint8_t getProofIntents (const Glib::ustring& name); + 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; + + static std::vector getWorkingProfiles(); + static std::vector getGamma(); + + static void getGammaArray(const procparams::ColorManagementParams& icm, GammaValues& ga); + static cmsHPROFILE makeStdGammaProfile(cmsHPROFILE iprof); + static cmsHPROFILE createFromMatrix(const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring()); + static cmsHPROFILE createGammaProfile(const procparams::ColorManagementParams& icm, GammaValues& ga); + static cmsHPROFILE createCustomGammaOutputProfile(const procparams::ColorManagementParams& icm, GammaValues& ga); + +private: + class Implementation; + + ICCStore(); + ~ICCStore(); + + const std::unique_ptr implementation; }; -#define iccStore ICCStore::getInstance() - -inline ProfileContent::ProfileContent () : - data(nullptr), - length(0) -{ } - -inline ProfileContent::~ProfileContent () -{ - delete [] data; -} - -inline cmsHPROFILE ICCStore::getDefaultMonitorProfile () -{ - return getProfile (defaultMonitorProfile); -} - -inline Glib::ustring ICCStore::getDefaultMonitorProfileName () -{ - return defaultMonitorProfile; -} - -inline uint8_t ICCStore::getInputIntents (const Glib::ustring &name) -{ - return getInputIntents (getProfile (name)); -} - -inline uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) -{ - return getOutputIntents (getProfile (name)); -} - -inline uint8_t ICCStore::getProofIntents (const Glib::ustring &name) -{ - return getProofIntents (getProfile (name)); -} - -inline cmsHPROFILE ICCStore::getXYZProfile () const -{ - return xyz; -} - -inline cmsHPROFILE ICCStore::getsRGBProfile () const -{ - return srgb; -} - -} - -#endif - diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index f4629682d..665ba3ac6 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -429,7 +429,7 @@ void Imagefloat::calcCroppedHistogram(const ProcParams ¶ms, float scale, LUT hist.clear(); // Set up factors to calc the lightness - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working); float facRed = wprof[1][0]; float facGreen = wprof[1][1]; diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index 05684aaa7..b8f2fb580 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -175,7 +175,7 @@ void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::pr iptc_data_sort (iptc); } -void ImageIO::setOutputProfile (char* pdata, int plen) +void ImageIO::setOutputProfile (const char* pdata, int plen) { delete [] profileData; diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 00bdbece1..1fbeb6e2d 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -176,7 +176,7 @@ public: void setMetadata (const rtexif::TagDirectory* eroot); void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc); - void setOutputProfile (char* pdata, int plen); + void setOutputProfile (const char* pdata, int plen); MyMutex& mutex () { return imutex; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 46cf031bd..e5422f6b3 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -452,13 +452,13 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) opautili = false; if(params.colorToning.enabled) { - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, {wprof[1][0], wprof[1][1], wprof[1][2]}, {wprof[2][0], wprof[2][1], wprof[2][2]} }; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params.icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 1a3a969ae..757b6e0b2 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -80,9 +80,9 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, cmsHPROFILE monitor = nullptr; if (!monitorProfile.empty()) { #if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB - monitor = iccStore->getProfile (monitorProfile); + monitor = ICCStore::getInstance()->getProfile (monitorProfile); #else - monitor = iccStore->getProfile ("RT_sRGB"); + monitor = ICCStore::getInstance()->getProfile ("RT_sRGB"); #endif } @@ -97,7 +97,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, if (softProof) { cmsHPROFILE oprof = nullptr; if (!settings->printerProfile.empty()) { - oprof = iccStore->getProfile(settings->printerProfile); + oprof = ICCStore::getInstance()->getProfile(settings->printerProfile); } if (oprof) { @@ -137,7 +137,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, void ImProcFunctions::firstAnalysis (const Imagefloat* const original, const ProcParams ¶ms, LUTu & histogram) { - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working); lumimul[0] = wprof[1][0]; lumimul[1] = wprof[1][1]; @@ -557,7 +557,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh #endif { //matrix for current working space - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, @@ -1287,7 +1287,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh #pragma omp parallel default(shared) firstprivate(lab,xw2,yw2,zw2,chr,yb,la2,yb2, height,width,begh, endh, nc2,f2,c2, gamu, highlight,pW) #endif { - TMatrix wiprofa = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprofa = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); double wipa[3][3] = { {wiprofa[0][0], wiprofa[0][1], wiprofa[0][2]}, {wiprofa[1][0], wiprofa[1][1], wiprofa[1][2]}, @@ -1891,7 +1891,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int //matrix for current working space - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); const float wip[3][3] = { {(float)wiprof[0][0], (float)wiprof[0][1], (float)wiprof[0][2]}, {(float)wiprof[1][0], (float)wiprof[1][1], (float)wiprof[1][2]}, @@ -2986,8 +2986,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer bool processLCE = params->sh.enabled && shmap && params->sh.localcontrast > 0; double lceamount = params->sh.localcontrast / 200.0; - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); float toxyz[3][3] = { { @@ -3102,8 +3102,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer clutAndWorkingProfilesAreSame = hald_clut->getProfile() == params->icm.working; if ( !clutAndWorkingProfilesAreSame ) { - xyz2clut = iccStore->workingSpaceInverseMatrix( hald_clut->getProfile() ); - clut2xyz = iccStore->workingSpaceMatrix( hald_clut->getProfile() ); + xyz2clut = ICCStore::getInstance()->workingSpaceInverseMatrix( hald_clut->getProfile() ); + clut2xyz = ICCStore::getInstance()->workingSpaceMatrix( hald_clut->getProfile() ); #ifdef __SSE2__ @@ -5642,14 +5642,14 @@ SSEFUNCTION void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBu const bool gamutLch = settings->gamutLch; const float amountchroma = (float) settings->amchroma; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, {wiprof[2][0], wiprof[2][1], wiprof[2][2]} }; - TMatrix wprof = iccStore->workingSpaceMatrix (params->icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params->icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, {wprof[1][0], wprof[1][1], wprof[1][2]}, @@ -6983,7 +6983,7 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace) { - TMatrix wprof = iccStore->workingSpaceMatrix( workingSpace ); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix( workingSpace ); const float wp[3][3] = { {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, @@ -7009,7 +7009,7 @@ void ImProcFunctions::rgb2lab(const Imagefloat &src, LabImage &dst, const Glib:: SSEFUNCTION void ImProcFunctions::lab2rgb(const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace) { - TMatrix wiprof = iccStore->workingSpaceInverseMatrix( workingSpace ); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix( workingSpace ); const float wip[3][3] = { {static_cast(wiprof[0][0]), static_cast(wiprof[0][1]), static_cast(wiprof[0][2])}, {static_cast(wiprof[1][0]), static_cast(wiprof[1][1]), static_cast(wiprof[1][2])}, diff --git a/rtengine/init.cc b/rtengine/init.cc index d6bba9f2b..8b270f1d7 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -40,8 +40,8 @@ MyMutex* lcmsMutex = nullptr; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; - iccStore->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); - iccStore->findDefaultMonitorProfile(); + ICCStore::getInstance()->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); + ICCStore::getInstance()->findDefaultMonitorProfile(); DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll); CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index f970e3a54..dac24411d 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -158,7 +158,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, standard_gamma = false; } - cmsHPROFILE oprof = iccStore->getProfile (profile); + cmsHPROFILE oprof = ICCStore::getInstance()->getProfile (profile); if (oprof) { cmsHPROFILE oprofG = oprof; @@ -216,7 +216,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, } } else { - const auto xyz_rgb = iccStore->workingSpaceInverseMatrix (profile); + const auto xyz_rgb = ICCStore::getInstance()->workingSpaceInverseMatrix (profile); #ifdef _OPENMP #pragma omp parallel for schedule(dynamic,16) if (multiThread) @@ -286,11 +286,11 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int cmsHPROFILE oprof = nullptr; if (ga) { lcmsMutex->lock (); - iccStore->getGammaArray(icm, *ga); - oprof = iccStore->createGammaProfile(icm, *ga); + ICCStore::getInstance()->getGammaArray(icm, *ga); + oprof = ICCStore::getInstance()->createGammaProfile(icm, *ga); lcmsMutex->unlock (); } else { - oprof = iccStore->getProfile (icm.output); + oprof = ICCStore::getInstance()->getProfile (icm.output); } if (oprof) { diff --git a/rtengine/ipvibrance.cc b/rtengine/ipvibrance.cc index 60994175b..8eb565434 100644 --- a/rtengine/ipvibrance.cc +++ b/rtengine/ipvibrance.cc @@ -170,7 +170,7 @@ void ImProcFunctions::vibrance (LabImage* lab) const bool protectskins = params->vibrance.protectskins; const bool avoidcolorshift = params->vibrance.avoidcolorshift; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); //inverse matrix user select const double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index ee8f10ad1..67402cac4 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -148,7 +148,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int // init variables to display Munsell corrections MunsellDebugInfo* MunsDebugInfo = new MunsellDebugInfo(); #endif - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params->icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params->icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6dd71a7e3..80e1f65ba 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1557,7 +1557,7 @@ int RawImageSource::load (const Glib::ustring &fname, bool batch) imatrices.xyz_cam[i][j] += xyz_sRGB[i][k] * imatrices.rgb_cam[k][j]; } - camProfile = iccStore->createFromMatrix (imatrices.xyz_cam, false, "Camera"); + camProfile = ICCStore::getInstance()->createFromMatrix (imatrices.xyz_cam, false, "Camera"); inverse33 (imatrices.xyz_cam, imatrices.cam_xyz); for (int c = 0; c < 4; c++) { @@ -2168,7 +2168,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar } } else { - TMatrix wprof = iccStore->workingSpaceMatrix (cmp.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (cmp.working); float wp[3][3] = { {static_cast(wprof[0][0]), static_cast(wprof[0][1]), static_cast(wprof[0][2])}, {static_cast(wprof[1][0]), static_cast(wprof[1][1]), static_cast(wprof[1][2])}, @@ -2445,7 +2445,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC } } else { - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (cmp.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (cmp.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, @@ -3802,7 +3802,7 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam // in this case we avoid using the slllllooooooowwww lcms // Calculate matrix for direct conversion raw>working space - TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); + TMatrix work = ICCStore::getInstance()->workingSpaceInverseMatrix (cmp.working); double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; for (int i = 0; i < 3; i++) @@ -3894,7 +3894,7 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam // Initialize transform cmsHTRANSFORM hTransform; - cmsHPROFILE prophoto = iccStore->workingSpace("ProPhoto"); // We always use Prophoto to apply the ICC profile to minimize problems with clipping in LUT conversion. + cmsHPROFILE prophoto = ICCStore::getInstance()->workingSpace("ProPhoto"); // We always use Prophoto to apply the ICC profile to minimize problems with clipping in LUT conversion. bool transform_via_pcs_lab = false; bool separate_pcs_lab_highlights = false; lcmsMutex->lock (); @@ -3940,8 +3940,8 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam TMatrix toxyz = {}, torgb = {}; if (!working_space_is_prophoto) { - toxyz = iccStore->workingSpaceMatrix ("ProPhoto"); - torgb = iccStore->workingSpaceInverseMatrix (cmp.working); //sRGB .. Adobe...Wide... + toxyz = ICCStore::getInstance()->workingSpaceMatrix ("ProPhoto"); + torgb = ICCStore::getInstance()->workingSpaceInverseMatrix (cmp.working); //sRGB .. Adobe...Wide... } #ifdef _OPENMP @@ -4154,7 +4154,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed *dcpProf = DCPStore::getInstance()->getStdProfile(camName); if (*dcpProf == nullptr) { - in = iccStore->getStdProfile(camName); + in = ICCStore::getInstance()->getStdProfile(camName); } } else if (inProfile != "(camera)" && inProfile != "") { Glib::ustring normalName = inProfile; @@ -4168,7 +4168,7 @@ bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embed } if (*dcpProf == nullptr) { - in = iccStore->getProfile (inProfile); + in = ICCStore::getInstance()->getProfile (inProfile); } } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 43fcbf06f..f99df3fe3 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -442,13 +442,6 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi /** Cleanup the RT engine (static variables) */ void cleanup (); -/** Returns the available working profile names - * @return a vector of the available working profile names */ -std::vector getWorkingProfiles (); -/** Returns the available output gammas - * @return a vector of the available gamma names */ -std::vector getGamma (); - /** This class holds all the necessary informations to accomplish the full processing of the image */ class ProcessingJob { diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 257a3eeb3..86729fce2 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -768,7 +768,7 @@ void Thumbnail::init () cam2xyz[i][j] += xyz_sRGB[i][k] * colorMatrix[k][j]; } - camProfile = iccStore->createFromMatrix (cam2xyz, false, "Camera"); + camProfile = ICCStore::getInstance()->createFromMatrix (cam2xyz, false, "Camera"); } Thumbnail::Thumbnail () : @@ -1029,13 +1029,13 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei bool opautili = false; if(params.colorToning.enabled) { - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, {wprof[1][0], wprof[1][1], wprof[1][2]}, {wprof[2][0], wprof[2][1], wprof[2][2]} }; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params.icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 4fb193c2b..0f3aea0d0 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -805,13 +805,13 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p bool opautili = false; if(params.colorToning.enabled) { - TMatrix wprof = iccStore->workingSpaceMatrix (params.icm.working); + TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix (params.icm.working); double wp[3][3] = { {wprof[0][0], wprof[0][1], wprof[0][2]}, {wprof[1][0], wprof[1][1], wprof[1][2]}, {wprof[2][0], wprof[2][1], wprof[2][2]} }; - TMatrix wiprof = iccStore->workingSpaceInverseMatrix (params.icm.working); + TMatrix wiprof = ICCStore::getInstance()->workingSpaceInverseMatrix (params.icm.working); double wip[3][3] = { {wiprof[0][0], wiprof[0][1], wiprof[0][2]}, {wiprof[1][0], wiprof[1][1], wiprof[1][2]}, @@ -1165,7 +1165,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p //or selected Free gamma useLCMS = false; - if ((jprof = iccStore->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) { + if ((jprof = ICCStore::getInstance()->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) { useLCMS = true; } @@ -1221,15 +1221,15 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p if (!useLCMS) { // use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16 w/ gamma ProfileContent pc(jprof); - readyImg->setOutputProfile (pc.data, pc.length); + readyImg->setOutputProfile(pc.getData().data(), pc.getData().size()); } } else { // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) { - // if iccStore->getProfile send back an object, then iccStore->getContent will do too - cmsHPROFILE jprof = iccStore->getProfile(params.icm.output); //get outProfile + // if ICCStore::getInstance()->getProfile send back an object, then ICCStore::getInstance()->getContent will do too + cmsHPROFILE jprof = ICCStore::getInstance()->getProfile(params.icm.output); //get outProfile if (jprof == nullptr) { if (settings->verbose) { @@ -1240,8 +1240,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p printf("Using \"%s\" output profile\n", params.icm.output.c_str()); } - ProfileContent pc = iccStore->getContent (params.icm.output); - readyImg->setOutputProfile (pc.data, pc.length); + ProfileContent pc = ICCStore::getInstance()->getContent (params.icm.output); + readyImg->setOutputProfile(pc.getData().data(), pc.getData().size()); } } else { // No ICM diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 95475e6a4..ed960508e 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -218,7 +218,7 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement bool skipTransform = false; cmsHPROFILE in = nullptr; - cmsHPROFILE out = iccStore->workingSpace (cmp.working); + cmsHPROFILE out = ICCStore::getInstance()->workingSpace (cmp.working); if (cmp.input == "(embedded)" || cmp.input == "" || cmp.input == "(camera)" || cmp.input == "(cameraICC)") { if (embedded) { @@ -227,12 +227,12 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) { skipTransform = true; } else { - in = iccStore->getsRGBProfile (); + in = ICCStore::getInstance()->getsRGBProfile (); } } } else { if (cmp.input != "(none)") { - in = iccStore->getProfile (cmp.input); + in = ICCStore::getInstance()->getProfile (cmp.input); if (in == nullptr && embedded) { in = embedded; @@ -240,7 +240,7 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) { skipTransform = true; } else { - in = iccStore->getsRGBProfile (); + in = ICCStore::getInstance()->getsRGBProfile (); } } } @@ -249,7 +249,7 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, const ColorManagement if (!skipTransform && in) { if(in == embedded && cmsGetColorSpace(in) != cmsSigRgbData) { // if embedded profile is not an RGB profile, use sRGB printf("embedded profile is not an RGB profile, using sRGB as input profile\n"); - in = iccStore->getsRGBProfile (); + in = ICCStore::getInstance()->getsRGBProfile (); } lcmsMutex->lock (); diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 8da176fc3..7bc1631d3 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -96,12 +96,12 @@ private: profileBox.append (M ("PREFERENCES_PROFILE_NONE")); #ifdef WIN32 - profileBox.append (M ("MONITOR_PROFILE_SYSTEM") + " (" + rtengine::iccStore->getDefaultMonitorProfileName() + ")"); + profileBox.append (M ("MONITOR_PROFILE_SYSTEM") + " (" + rtengine::ICCStore::getInstance()->getDefaultMonitorProfileName() + ")"); profileBox.set_active (options.rtSettings.autoMonitorProfile ? 1 : 0); #else profileBox.set_active (0); #endif - const std::vector profiles = rtengine::iccStore->getProfiles (rtengine::ICCStore::ProfileType::MONITOR); + const std::vector profiles = rtengine::ICCStore::getInstance()->getProfiles (rtengine::ICCStore::ProfileType::MONITOR); for (const auto profile: profiles) { profileBox.append (profile); } @@ -176,7 +176,7 @@ private: #if !defined(__APPLE__) // monitor profile not supported on apple #ifdef WIN32 if (profileBox.get_active_row_number () == 1) { - profile = rtengine::iccStore->getDefaultMonitorProfileName (); + profile = rtengine::ICCStore::getInstance()->getDefaultMonitorProfileName (); if (profile.empty ()) { profile = options.rtSettings.monitorProfile; } @@ -206,7 +206,7 @@ private: profileBox.set_tooltip_text (""); } else { - const uint8_t supportedIntents = rtengine::iccStore->getProofIntents (profile); + const uint8_t supportedIntents = rtengine::ICCStore::getInstance()->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; diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 5b4883dce..232d626a0 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -166,7 +166,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch wnames = Gtk::manage (new MyComboBoxText ()); wVBox->pack_start (*wnames, Gtk::PACK_SHRINK); - std::vector wpnames = rtengine::getWorkingProfiles (); + std::vector wpnames = rtengine::ICCStore::getWorkingProfiles(); for (size_t i = 0; i < wpnames.size(); i++) { wnames->append (wpnames[i]); @@ -193,7 +193,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch onames->append (M("TP_ICM_NOICM")); onames->set_active (0); - std::vector opnames = iccStore->getProfiles (rtengine::ICCStore::ProfileType::OUTPUT); + std::vector opnames = ICCStore::getInstance()->getProfiles (rtengine::ICCStore::ProfileType::OUTPUT); for (size_t i = 0; i < opnames.size(); i++) { onames->append (opnames[i]); @@ -232,7 +232,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch oVBox->pack_start(*gaHBox, Gtk::PACK_EXPAND_WIDGET); - std::vector wpgamma = rtengine::getGamma (); + std::vector wpgamma = rtengine::ICCStore::getGamma(); for (size_t i = 0; i < wpgamma.size(); i++) { wgamma->append (wpgamma[i]); @@ -332,7 +332,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch } void ICMPanel::updateRenderingIntent (const Glib::ustring &profile) { - const uint8_t supportedIntents = rtengine::iccStore->getOutputIntents (profile); + const uint8_t supportedIntents = rtengine::ICCStore::getInstance()->getOutputIntents (profile); const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL; const bool supportsRelative = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC; const bool supportsSaturation = supportedIntents & 1 << INTENT_SATURATION; @@ -1033,7 +1033,7 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) iembedded->set_active (!raw); icamera->set_sensitive (raw); camName = pMeta->getCamera(); - icameraICC->set_sensitive (raw && (iccStore->getStdProfile(pMeta->getCamera()) != nullptr || DCPStore::getInstance()->getStdProfile(pMeta->getCamera()) != nullptr)); + icameraICC->set_sensitive (raw && (ICCStore::getInstance()->getStdProfile(pMeta->getCamera()) != nullptr || DCPStore::getInstance()->getStdProfile(pMeta->getCamera()) != nullptr)); iembedded->set_sensitive (!raw); enableListener ();