Change ACES matrix with Bradford D50 D60

This commit is contained in:
Desmis
2018-04-10 09:24:25 +02:00
parent 6bc6e7b3a7
commit b5f4cbd728
10 changed files with 2719 additions and 2592 deletions

View File

@@ -156,6 +156,7 @@ bool loadProfile(
if (profileContents) {
profileContents->emplace(name, content);
}
return true;
}
}
@@ -220,7 +221,8 @@ rtengine::ProfileContent::ProfileContent(const Glib::ustring& fileName)
fseek(f, 0, SEEK_END);
long length = ftell(f);
if(length > 0) {
if (length > 0) {
char* d = new char[length + 1];
fseek(f, 0, SEEK_SET);
length = fread(d, 1, length, f);
@@ -230,6 +232,7 @@ rtengine::ProfileContent::ProfileContent(const Glib::ustring& fileName)
} else {
data.clear();
}
fclose(f);
}
@@ -254,8 +257,8 @@ cmsHPROFILE rtengine::ProfileContent::toProfile() const
return
!data.empty()
? cmsOpenProfileFromMem(data.c_str(), data.size())
: nullptr;
? cmsOpenProfileFromMem(data.c_str(), data.size())
: nullptr;
}
const std::string& rtengine::ProfileContent::getData() const
@@ -290,20 +293,23 @@ public:
cmsCloseProfile(p.second);
}
}
// for (auto &p : wProfilesGamma) {
// if (p.second) {
// cmsCloseProfile(p.second);
// }
// }
for (auto &p : fileProfiles) {
if(p.second) {
if (p.second) {
cmsCloseProfile(p.second);
}
}
if(srgb) {
if (srgb) {
cmsCloseProfile(srgb);
}
if(xyz) {
if (xyz) {
cmsCloseProfile(xyz);
}
}
@@ -321,6 +327,7 @@ public:
userICCDir = usrICCDir;
fileProfiles.clear();
fileProfileContents.clear();
if (loadAll) {
loadProfiles(profilesDir, &fileProfiles, &fileProfileContents, nullptr, false);
loadProfiles(userICCDir, &fileProfiles, &fileProfileContents, nullptr, false);
@@ -331,6 +338,7 @@ public:
stdProfilesDir = Glib::build_filename(rtICCDir, "input");
fileStdProfiles.clear();
fileStdProfilesFileNames.clear();
if (loadAll) {
loadProfiles(stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true);
}
@@ -339,7 +347,7 @@ public:
loadWorkingSpaces(rtICCDir);
loadWorkingSpaces(userICCDir);
// initialize the alarm colours for lcms gamut checking -- we use bright green
cmsUInt16Number cms_alarm_codes[cmsMAXCHANNELS] = { 0, 65535, 65535 };
cmsSetAlarmCodes(cms_alarm_codes);
@@ -351,8 +359,8 @@ public:
return
r != wProfiles.end()
? r->second
: wProfiles.find("sRGB")->second;
? r->second
: wProfiles.find("sRGB")->second;
}
// cmsHPROFILE workingSpaceGamma(const Glib::ustring& name) const
@@ -372,8 +380,8 @@ public:
return
r != wMatrices.end()
? r->second
: wMatrices.find("sRGB")->second;
? r->second
: wMatrices.find("sRGB")->second;
}
TMatrix workingSpaceInverseMatrix(const Glib::ustring& name) const
@@ -383,8 +391,8 @@ public:
return
r != iwMatrices.end()
? r->second
: iwMatrices.find("sRGB")->second;
? r->second
: iwMatrices.find("sRGB")->second;
}
bool outputProfileExist(const Glib::ustring& name) const
@@ -418,7 +426,9 @@ public:
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;
}
@@ -443,7 +453,9 @@ public:
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;
}
@@ -478,8 +490,8 @@ public:
return
r != fileProfileContents.end()
? r->second
: ProfileContent();
? r->second
: ProfileContent();
}
cmsHPROFILE getXYZProfile() const
@@ -500,22 +512,22 @@ public:
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
|| cmsGetDeviceClass(profile.second) == cmsSigInputClass
|| cmsGetDeviceClass(profile.second) == cmsSigOutputClass)
&& cmsGetColorSpace(profile.second) == cmsSigRgbData
)
(
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
|| cmsGetDeviceClass(profile.second) == cmsSigInputClass
|| cmsGetDeviceClass(profile.second) == cmsSigOutputClass)
&& cmsGetColorSpace(profile.second) == cmsSigRgbData
)
) {
res.push_back(profile.first);
}
@@ -598,7 +610,7 @@ public:
for (const auto &p : wProfiles) {
res.push_back(p.first);
}
return res;
}
@@ -616,11 +628,13 @@ private:
CMatrix toMatrix() const
{
CMatrix ret;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
ret[i][j] = matrix[i][j];
}
}
return ret;
}
@@ -637,22 +651,28 @@ private:
bool computeWorkingSpaceMatrix(const Glib::ustring &path, const Glib::ustring &filename, PMatrix &out)
{
Glib::ustring fullpath = filename;
if (!Glib::path_is_absolute(fullpath)) {
fullpath = Glib::build_filename(path, filename);
}
ProfileContent content(fullpath);
cmsHPROFILE prof = content.toProfile();
if (!prof) {
return false;
}
if (cmsGetColorSpace(prof) != cmsSigRgbData) {
cmsCloseProfile(prof);
return false;
}
if (!cmsIsMatrixShaper(prof)) {
cmsCloseProfile(prof);
return false;
}
cmsCIEXYZ *white = static_cast<cmsCIEXYZ *>(cmsReadTag(prof, cmsSigMediaWhitePointTag));
cmsCIEXYZ *red = static_cast<cmsCIEXYZ *>(cmsReadTag(prof, cmsSigRedMatrixColumnTag));
cmsCIEXYZ *green = static_cast<cmsCIEXYZ *>(cmsReadTag(prof, cmsSigGreenMatrixColumnTag));
@@ -681,23 +701,29 @@ private:
CVector srcw = dotProduct(bradford_MA, CVector({ white->X, white->Y, white->Z }));
CMatrix m = {
CVector({ bradford_MA_dot_D50[0]/srcw[0], 0.0, 0.0 }),
CVector({ 0.0, bradford_MA_dot_D50[1]/srcw[1], 0.0 }),
CVector({ 0.0, 0.0, bradford_MA_dot_D50[2]/srcw[2] })
CVector({ bradford_MA_dot_D50[0] / srcw[0], 0.0, 0.0 }),
CVector({ 0.0, bradford_MA_dot_D50[1] / srcw[1], 0.0 }),
CVector({ 0.0, 0.0, bradford_MA_dot_D50[2] / srcw[2] })
};
CMatrix adapt = dotProduct(dotProduct(bradford_MA_inv, m), bradford_MA);
m[0][0] = red->X; m[0][1] = green->X; m[0][2] = blue->X;
m[1][0] = red->Y; m[1][1] = green->Y; m[1][2] = blue->Y;
m[2][0] = red->Z; m[2][1] = green->Z; m[2][2] = blue->Z;
m[0][0] = red->X;
m[0][1] = green->X;
m[0][2] = blue->X;
m[1][0] = red->Y;
m[1][1] = green->Y;
m[1][2] = blue->Y;
m[2][0] = red->Z;
m[2][1] = green->Z;
m[2][2] = blue->Z;
m = dotProduct(adapt, m);
out.set(m);
cmsCloseProfile(prof);
return true;
}
bool loadWorkingSpaces(const Glib::ustring &path)
{
Glib::ustring fileName = Glib::build_filename(path, "workingspaces.json");
@@ -706,29 +732,32 @@ private:
if (settings->verbose) {
std::cout << "trying to load extra working spaces from " << fileName << std::flush;
}
if (!f) {
if (settings->verbose) {
std::cout << " FAIL" << std::endl;
}
return false;
}
fseek(f, 0, SEEK_END);
long length = ftell(f);
if (length <= 0) {
if (settings->verbose) {
std::cout << " FAIL" << std::endl;
}
fclose(f);
return false;
}
char *buf = new char[length + 1];
fseek(f, 0, SEEK_SET);
length = fread(buf, 1, length, f);
buf[length] = 0;
fclose(f);
cJSON_Minify(buf);
@@ -738,21 +767,23 @@ private:
if (settings->verbose) {
std::cout << " FAIL" << std::endl;
}
return false;
}
delete[] buf;
cJSON *js = cJSON_GetObjectItem(root, "working_spaces");
if (!js) {
goto parse_error;
}
for (js = js->child; js != nullptr; js = js->next) {
cJSON *ji = cJSON_GetObjectItem(js, "name");
std::unique_ptr<PMatrix> m(new PMatrix);
std::string name;
if (!ji || ji->type != cJSON_String) {
goto parse_error;
}
@@ -764,19 +795,22 @@ private:
}
bool found_matrix = false;
ji = cJSON_GetObjectItem(js, "matrix");
if (ji) {
if (ji->type != cJSON_Array) {
goto parse_error;
}
ji = ji->child;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j, ji = ji->next) {
if (!ji || ji->type != cJSON_Number) {
goto parse_error;
}
m->matrix[i][j] = ji->valuedouble;
}
}
@@ -784,12 +818,15 @@ private:
if (ji) {
goto parse_error;
}
found_matrix = true;
} else {
ji = cJSON_GetObjectItem(js, "file");
if (!ji || ji->type != cJSON_String) {
goto parse_error;
}
found_matrix = computeWorkingSpaceMatrix(path, ji->valuestring, *m);
}
@@ -797,6 +834,7 @@ private:
if (settings->verbose) {
std::cout << "Could not find suitable matrix for working space: " << name << std::endl;
}
continue;
}
@@ -804,10 +842,12 @@ private:
TMatrix w = pMatrices.back()->matrix;
CMatrix b = {};
if (!rtengine::invertMatrix(pMatrices.back()->toMatrix(), b)) {
if (settings->verbose) {
std::cout << "Matrix for working space: " << name << " is not invertible, skipping" << std::endl;
}
pMatrices.pop_back();
} else {
wMatrices[name] = w;
@@ -819,29 +859,36 @@ private:
if (settings->verbose) {
std::cout << "Added working space: " << name << std::endl;
std::cout << " matrix: [";
for (int i = 0; i < 3; ++i) {
std::cout << " [";
for (int j = 0; j < 3; ++j) {
std::cout << " " << w[i][j];
}
std::cout << "]";
}
std::cout << " ]" << std::endl;
}
}
}
cJSON_Delete(root);
if (settings->verbose) {
std::cout << " OK" << std::endl;
}
return true;
parse_error:
parse_error:
if (settings->verbose) {
std::cout << " ERROR in parsing " << fileName << std::endl;
}
cJSON_Delete(root);
return false;
}
@@ -1019,9 +1066,10 @@ std::vector<Glib::ustring> rtengine::ICCStore::getGamma()
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
// gamma : ga[0],ga[1],ga[2],ga[3],ga[4],ga[5] by calcul
if(icm.gamma == "BT709_g2.2_s4.5") {
if (icm.gamma == "BT709_g2.2_s4.5") {
ga[0] = 2.22; //BT709 2.2 4.5 - my preferred as D.Coffin
ga[1] = 0.909995;
ga[2] = 0.090005;
@@ -1057,13 +1105,14 @@ void rtengine::ICCStore::getGammaArray(const procparams::ColorManagementParams &
ga[2] = 0.;
ga[3] = 1. / eps;
ga[4] = 0.;
} else /* if (icm.gamma == "linear_g1.0") */ {
} else { /* if (icm.gamma == "linear_g1.0") */
ga[0] = 1.0; //gamma=1 linear : for high dynamic images(cf : D.Coffin...)
ga[1] = 1.;
ga[2] = 0.;
ga[3] = 1. / eps;
ga[4] = 0.;
}
ga[5] = 0.0;
ga[6] = 0.0;
} else { //free gamma selected
@@ -1077,12 +1126,12 @@ void rtengine::ICCStore::getGammaArray(const procparams::ColorManagementParams &
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;
// printf("ga[0]=%f ga[1]=%f ga[2]=%f ga[3]=%f ga[4]=%f\n", ga[0],ga[1],ga[2],ga[3],ga[4]);
// printf("ga[0]=%f ga[1]=%f ga[2]=%f ga[3]=%f ga[4]=%f\n", ga[0],ga[1],ga[2],ga[3],ga[4]);
}
}
@@ -1117,7 +1166,7 @@ cmsHPROFILE rtengine::ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
const uint32_t gamma = 0x239;
int gamma_size = 14;
int data_size =(gamma_size + 3) & ~3;
int data_size = (gamma_size + 3) & ~3;
for (uint32_t i = 0; i < tag_count; i++) {
memcpy(&tags[i], p, 12);
@@ -1130,7 +1179,7 @@ cmsHPROFILE rtengine::ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
tags[i].sig != 0x67545243 && // gTRC
tags[i].sig != 0x72545243 && // rTRC
tags[i].sig != 0x6B545243) { // kTRC
data_size +=(tags[i].size + 3) & ~3;
data_size += (tags[i].size + 3) & ~3;
}
}
@@ -1161,7 +1210,7 @@ cmsHPROFILE rtengine::ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
memcpy(&nd[offset + 12], &gm, 2);
}
offset +=(gamma_size + 3) & ~3;
offset += (gamma_size + 3) & ~3;
}
tag.offset = htonl(gamma_offset);
@@ -1170,7 +1219,7 @@ cmsHPROFILE rtengine::ICCStore::makeStdGammaProfile(cmsHPROFILE iprof)
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;
offset += (tags[i].size + 3) & ~3;
}
memcpy(&nd[128 + 4 + i * 12], &tag, 12);
@@ -1235,9 +1284,9 @@ cmsHPROFILE rtengine::ICCStore::createFromMatrix(const double matrix[3][3], bool
// 0x74657874 : text
// 0x64657363 : description tag
for (unsigned int i = 0; i < pbody[0]; i++) {
oprof[oprof[0] / 4] = i ?(i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
oprof[oprof[0] / 4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
pbody[i * 3 + 2] = oprof[0];
oprof[0] +=(pbody[i * 3 + 3] + 3) & -4;
oprof[0] += (pbody[i * 3 + 3] + 3) & -4;
}
memcpy(oprof + 32, pbody, sizeof(pbody));
@@ -1285,8 +1334,8 @@ cmsHPROFILE rtengine::ICCStore::createGammaProfile(const procparams::ColorManage
enum class ColorTemp {
D50 = 5003, // for Widegamut, Prophoto Best, Beta -> D50
D65 = 6504, // for sRGB, AdobeRGB, Bruce Rec2020 -> D65
D60 = 6005 //for ACESc
D60 = 6005 //for ACESc
};
ColorTemp temp = ColorTemp::D50;
@@ -1345,7 +1394,7 @@ cmsHPROFILE rtengine::ICCStore::createGammaProfile(const procparams::ColorManage
p[4] = 0.1310;
p[5] = 0.0460;
temp = ColorTemp::D65;
} else if (icm.wprimari == "ACESc") {
} else if (icm.wprimari == "ACESc") {
p[0] = 0.734704; // ACESc primaries
p[1] = 0.265298;
p[2] = -0.000004;
@@ -1361,16 +1410,17 @@ cmsHPROFILE rtengine::ICCStore::createGammaProfile(const procparams::ColorManage
p[4] = 0.0366;
p[5] = 0.0001;
}
//printf("prim p2=%f \n", p[2]);
/*
p[0] = 0.6400; // sRGB primaries
p[1] = 0.3300;
p[2] = 0.3000;
p[3] = 0.6000;
p[4] = 0.1500;
p[5] = 0.0600;
temp = ColorTemp::D65;
*/
/*
p[0] = 0.6400; // sRGB primaries
p[1] = 0.3300;
p[2] = 0.3000;
p[3] = 0.6000;
p[4] = 0.1500;
p[5] = 0.0600;
temp = ColorTemp::D65;
*/
cmsCIExyY xyD;
cmsCIExyYTRIPLE Primaries = {
{p[0], p[1], 1.0}, // red
@@ -1383,15 +1433,15 @@ cmsHPROFILE rtengine::ICCStore::createGammaProfile(const procparams::ColorManage
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);
// cmsCIExyY d60_aces= {0.32168, 0.33767, 1.0};
// xyD = d60_aces;
cmsWhitePointFromTemp(&xyD, (double)temp);
// cmsCIExyY d60_aces= {0.32168, 0.33767, 1.0};
// xyD = d60_aces;
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, Parameters); //5 = smoother than 4
cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); //oprofdef become Outputprofile
//cmsSetProfileVersion(oprofdef, 4.3);
//cmsSetProfileVersion(oprofdef, 4.3);
cmsFreeToneCurve(GammaTRC[0]);
//lcmsMutex->unlock();
@@ -1405,101 +1455,67 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
Glib::ustring outProfile;
cmsHPROFILE outputProfile = nullptr;
Glib::ustring outPr;
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" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto) && !pro) {
outProfile = options.rtSettings.prophoto;
} else if (icm.working == "Adobe RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.adobe) ) {
outProfile = options.rtSettings.adobe;
} else if (icm.working == "WideGamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut) ) {
outProfile = options.rtSettings.widegamut;
} else if (icm.working == "Beta RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta) ) {
outProfile = options.rtSettings.beta;
} else if (icm.working == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best) ) {
outProfile = options.rtSettings.best;
} else if (icm.working == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce) ) {
outProfile = options.rtSettings.bruce;
} else if (icm.working == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb) && !pro) {
outProfile = options.rtSettings.srgb;
} else if (icm.working == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb10) && pro) {
outProfile = options.rtSettings.srgb10;
} else if (icm.working == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto10) && pro) {
outProfile = options.rtSettings.prophoto10;
} else if (icm.working == "Rec2020" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.rec2020) ) {
outProfile = options.rtSettings.rec2020;
} else {
// Should not occurs
if (settings->verbose) {
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", icm.working.c_str() );
}
return nullptr;
}
*/
//outProfile = options.rtSettings.srgb;
//necessary for V2 profile
if (icm.wprimari == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto) && !pro) {
outProfile = options.rtSettings.prophoto;
outPr = "RT_large";
outProfile = options.rtSettings.prophoto;
outPr = "RT_large";
} else if (icm.wprimari == "Adobe RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.adobe) ) {
outProfile = options.rtSettings.adobe;
outPr = "RT_adob";
} else if (icm.wprimari == "WideGamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut) ) {
outProfile = options.rtSettings.widegamut;
outPr = "RT_wide";
} else if (icm.wprimari == "Beta RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta) ) {
} else if (icm.wprimari == "Adobe RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.adobe)) {
outProfile = options.rtSettings.adobe;
outPr = "RT_adob";
} else if (icm.wprimari == "WideGamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut)) {
outProfile = options.rtSettings.widegamut;
outPr = "RT_wide";
} else if (icm.wprimari == "Beta RGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta)) {
outProfile = options.rtSettings.beta;
outPr = "RT_beta";
} else if (icm.wprimari == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best) ) {
outProfile = options.rtSettings.best;
outPr = "RT_best";
} else if (icm.wprimari == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce) ) {
outProfile = options.rtSettings.bruce;
outPr = "RT_bruce";
outPr = "RT_beta";
} else if (icm.wprimari == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best)) {
outProfile = options.rtSettings.best;
outPr = "RT_best";
} else if (icm.wprimari == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce)) {
outProfile = options.rtSettings.bruce;
outPr = "RT_bruce";
} else if (icm.wprimari == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb) && !pro) {
outProfile = options.rtSettings.srgb;
outPr = "RT_srgb";
outProfile = options.rtSettings.srgb;
outPr = "RT_srgb";
} else if (icm.wprimari == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb10) && pro) {
outProfile = options.rtSettings.srgb10;
outPr = "RT_srgb";
outProfile = options.rtSettings.srgb10;
outPr = "RT_srgb";
} else if (icm.wprimari == "ProPhoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto10) && pro) {
outProfile = options.rtSettings.prophoto10;
outPr = "RT_large";
} else if (icm.wprimari == "Rec2020" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.rec2020) ) {
outProfile = options.rtSettings.rec2020;
outPr = "RT_rec2020";
} else if (icm.wprimari == "ACESc" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESc) ) {
outProfile = options.rtSettings.ACESc;
outPr = "RT_acesc";
outProfile = options.rtSettings.prophoto10;
outPr = "RT_large";
} else if (icm.wprimari == "Rec2020" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.rec2020)) {
outProfile = options.rtSettings.rec2020;
outPr = "RT_rec2020";
} else if (icm.wprimari == "ACESc" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESc)) {
outProfile = options.rtSettings.ACESc;
outPr = "RT_acesc";
} else {
// Should not occurs
if (settings->verbose) {
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", icm.working.c_str() );
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", icm.working.c_str());
}
return nullptr;
}
// outProfile = options.rtSettings.prophoto;
//begin adaptation rTRC gTRC bTRC
//"outputProfile" profile has the same characteristics than RGB values, but TRC are adapted... for applying profile
if (settings->verbose) {
printf("Output Gamma - profile Primaries as RT profile: \"%s\"\n", outProfile.c_str() ); //c_str()
printf("Output Gamma - profile Primaries as RT profile: \"%s\"\n", outProfile.c_str()); //c_str()
}
outputProfile = ICCStore::getInstance()->getProfile(outProfile); //get output profile
@@ -1509,6 +1525,7 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
if (settings->verbose) {
printf("\"%s\" ICC output profile not found!\n", outProfile.c_str());
}
return nullptr;
}
@@ -1530,7 +1547,7 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
if (!icm.freegamma) {
std::wstring gammaStr;
if(icm.gamma == "High_g1.3_s3.35") {
if (icm.gamma == "High_g1.3_s3.35") {
gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35");
} else if (icm.gamma == "Low_g2.6_s6.9") {
gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9");
@@ -1548,62 +1565,50 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
cmsMLUsetWide(mlu, "en", "US", gammaStr.c_str());
} else {
/*
// create description with gamma + slope + primaries
std::wostringstream gammaWs;
//std::string gammaWsICC;
std::wstring gammaStrICC;
gammaWs.precision(6);
if(icm.wprofile == "v4") {
outPro = outPr + "_FOIP_V4_"+ std::to_string((float)icm.gampos)+" "+ std::to_string((float)icm.slpos) + ".icc";
} else if(icm.wprofile == "v2") {
outPro = outPr + "_FOIP_V2_"+ std::to_string((float)icm.gampos)+" "+ std::to_string((float)icm.slpos) + ".icc";
}
if(icm.wprofile == "v4") {
outPro = outPr + "_FOIP_V4_"+ std::to_string((float)icm.gampos)+" "+ std::to_string((float)icm.slpos) + ".icc";
} else if(icm.wprofile == "v2") {
outPro = outPr + "_FOIP_V2_"+ std::to_string((float)icm.gampos)+" "+ std::to_string((float)icm.slpos) + ".icc";
}
gammaWs << outPro.c_str() <<(float)icm.gampos << " s=" <<(float)icm.slpos;
cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str());
cmsMLU *copyright = cmsMLUalloc(NULL, 1);
cmsMLU *copyright = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(copyright, "en", "US", "No copyright Rawtherapee");
cmsWriteTag(outputProfile, cmsSigCopyrightTag, copyright);
cmsMLUfree(copyright);
cmsMLU *descrip = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(copyright, "en", "US", "No copyright Rawtherapee");
cmsWriteTag(outputProfile, cmsSigCopyrightTag, copyright);
cmsMLUfree(copyright);
cmsMLU *descrip = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(descrip, "en", "US", "Rawtherapee");
cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, descrip);
cmsMLUfree(descrip);
cmsMLUsetASCII(descrip, "en", "US", "Rawtherapee");
cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, descrip);
cmsMLUfree(descrip);
*/
}
cmsWriteTag(outputProfile, cmsSigProfileDescriptionTag, mlu);//desc changed
cmsMLUfree(mlu);
Glib::ustring manufacturer;
manufacturer="RawTherapee_FOIP";
cmsMLU *MfgDesc;
MfgDesc = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(MfgDesc, "en", "US", manufacturer.c_str());
cmsWriteTag(outputProfile, cmsSigDeviceMfgDescTag, MfgDesc);
cmsMLUfree(MfgDesc);
//cmsMLUsetASCII(mlu, "en", "US", manufacturer.c_str());
//cmsWriteTag(outputProfile, cmsSigDeviceMfgDescTag,mlu);
}
if(icm.wprofile == "v4") {
cmsSetProfileVersion(outputProfile, 4.3);
}
else {
cmsSetProfileVersion(outputProfile, 2.0);
}
//change
if (icm.wprofile == "v4") {
cmsSetProfileVersion(outputProfile, 4.3);
} else {
cmsSetProfileVersion(outputProfile, 2.0);
}
//change
enum class ColorTemp {
D50 = 5003, // for Widegamut, Prophoto Best, Beta -> D50
D65 = 6504, // for sRGB, AdobeRGB, Bruce Rec2020 -> D65
D60 = 6005 //for ACESc->D60
D60 = 6005 //for ACESc->D60
};
ColorTemp temp = ColorTemp::D50;
float p[6]; //primaries
@@ -1661,14 +1666,14 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
p[4] = 0.1310;
p[5] = 0.0460;
temp = ColorTemp::D65;
} else if (icm.wprimari == "ACESc") {
} else if (icm.wprimari == "ACESc") {
p[0] = 0.734704; // ACESc primaries
p[1] = 0.265298;
p[2] = -0.000004;
p[3] = 0.999993;
p[4] = 0.00009989;
p[5] = -0.077007;
temp = ColorTemp::D60;
temp = ColorTemp::D60;
} else {
p[0] = 0.7347; //ProPhoto and default primaries
p[1] = 0.2653;
@@ -1677,40 +1682,75 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
p[4] = 0.0366;
p[5] = 0.0001;
}
cmsCIExyY xyD;
cmsCIExyYTRIPLE Primaries = {
{p[0], p[1], 1.0}, // red
{p[2], p[3], 1.0}, // green
{p[4], p[5], 1.0} // blue
};
cmsWhitePointFromTemp(&xyD,(double)temp);
//cmsCIExyY d60_aces= {0.32168, 0.33767, 1.0};
//xyD = d60_aces;
cmsWhitePointFromTemp(&xyD, (double)temp);
cmsToneCurve* GammaTRC[3];
// Calculate output profile's rTRC gTRC bTRC
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, Parameters);
if(icm.wprofile == "v4") {
outputProfile = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC);
/*
cmsCIEXYZ *red = (cmsCIEXYZ *)cmsReadTag(outputProfile, cmsSigRedColorantTag);
cmsCIEXYZ red_tag = *red;
cmsWriteTag (outputProfile, cmsSigRedColorantTag, &red_tag);
*/
}
cmsWriteTag(outputProfile, cmsSigRedTRCTag,GammaTRC[0] );
cmsWriteTag(outputProfile, cmsSigGreenTRCTag,GammaTRC[1] );
cmsWriteTag(outputProfile, cmsSigBlueTRCTag,GammaTRC[2] );
if(icm.wprofile == "v2" || icm.wprofile == "v4") {
cmsSaveProfileToFile(outputProfile, outPro.c_str());
}
if (icm.wprofile == "v4") {
outputProfile = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC);
}
cmsWriteTag(outputProfile, cmsSigRedTRCTag, GammaTRC[0]);
cmsWriteTag(outputProfile, cmsSigGreenTRCTag, GammaTRC[1]);
cmsWriteTag(outputProfile, cmsSigBlueTRCTag, GammaTRC[2]);
if (icm.freegamma) {
// create description with gamma + slope + primaries
std::wostringstream gammaWs;
//std::string gammaWsICC;
std::wstring gammaStrICC;
gammaWs.precision(6);
if (icm.wprofile == "v4") {
outPro = outPr + "_FOIP_V4_" + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc";
} else if (icm.wprofile == "v2") {
outPro = outPr + "_FOIP_V2_" + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc";
}
gammaWs << outPro.c_str() << (float)icm.gampos << " s=" << (float)icm.slpos;
cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str());
cmsMLU *copyright = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(copyright, "en", "US", "No copyright Rawtherapee");
cmsWriteTag(outputProfile, cmsSigCopyrightTag, copyright);
cmsMLUfree(copyright);
}
cmsMLU *descrip = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(descrip, "en", "US", "Rawtherapee");
cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, descrip);
cmsMLUfree(descrip);
cmsWriteTag(outputProfile, cmsSigProfileDescriptionTag, mlu);//desc changed
cmsMLUfree(mlu);
Glib::ustring manufacturer;
manufacturer = "RawTherapee_FOIP";
cmsMLU *MfgDesc;
MfgDesc = cmsMLUalloc(NULL, 1);
cmsMLUsetASCII(MfgDesc, "en", "US", manufacturer.c_str());
cmsWriteTag(outputProfile, cmsSigDeviceMfgDescTag, MfgDesc);
cmsMLUfree(MfgDesc);
if (icm.wprofile == "v2" || icm.wprofile == "v4") {
cmsSaveProfileToFile(outputProfile, outPro.c_str());
}
if (GammaTRC) {
cmsFreeToneCurve(GammaTRC[0]);
}