diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 25172add8..bb08c9404 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -36,8 +36,10 @@ #include "../rtgui/options.h" #include "../rtgui/threadutils.h" +#include "lcms2_plugin.h" #include "cJSON.h" +#define inkc_constant 0x696E6B43 namespace rtengine { @@ -1499,45 +1501,45 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams: //necessary for V2 profile if (icm.wprimaries == "Prophoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto) && !pro) { outProfile = options.rtSettings.prophoto; - outPr = "RT_Large"; + outPr = "Large_"; } else if (icm.wprimaries == "Adobe" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.adobe)) { outProfile = options.rtSettings.adobe; - outPr = "RT_Adob"; + outPr = "Medium_"; } else if (icm.wprimaries == "Widegamut" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.widegamut)) { outProfile = options.rtSettings.widegamut; - outPr = "RT_Wide"; + outPr = "Wide_"; } else if (icm.wprimaries == "BetaRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.beta)) { outProfile = options.rtSettings.beta; - outPr = "RT_Beta"; + outPr = "Beta_"; } else if (icm.wprimaries == "BestRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.best)) { outProfile = options.rtSettings.best; - outPr = "RT_Best"; + outPr = "Best_"; } else if (icm.wprimaries == "BruceRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.bruce)) { outProfile = options.rtSettings.bruce; - outPr = "RT_Bruce"; + outPr = "Bruce_"; } else if (icm.wprimaries == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb) && !pro) { outProfile = options.rtSettings.srgb; - outPr = "RT_sRGB"; + outPr = "sRGB_"; } else if (icm.wprimaries == "sRGB" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.srgb10) && pro) { outProfile = options.rtSettings.srgb10; - outPr = "RT_sRGB"; + outPr = "sRGB_"; } else if (icm.wprimaries == "Prophoto" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.prophoto10) && pro) { outProfile = options.rtSettings.prophoto10; - outPr = "RT_Large"; + outPr = "Large_"; } else if (icm.wprimaries == "Rec2020" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.rec2020)) { outProfile = options.rtSettings.rec2020; - outPr = "RT_Rec2020"; + outPr = "Rec2020_"; } else if (icm.wprimaries == "Acesp0" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESp0)) { outProfile = options.rtSettings.ACESp0; - outPr = "RT_Acesp0"; + outPr = "Acesp0_"; } else if (icm.wprimaries == "Acesp1" && rtengine::ICCStore::getInstance()->outputProfileExist(options.rtSettings.ACESp1)) { outProfile = options.rtSettings.ACESp1; - outPr = "RT_Acesp1"; + outPr = "Acesp1_"; } else if (icm.wprimaries == "pfree") { outProfile = options.rtSettings.srgb; printf("PFRRE\n"); - outPr = "RT_pfree"; + outPr = "pfree_"; } else { // Should not occurs @@ -1575,23 +1577,40 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams: mlu = cmsMLUalloc(ContextID, 1); Glib::ustring outPro; Glib::ustring outTemp; - + double gammsave = 2.4; + double slopesave = 12.92; if (icm.gamma == "High_g1.3_s3.35") { gammaStr = "_High_g=1.3_s=3.35"; + gammsave = 1.3; + slopesave = 3.35; } else if (icm.gamma == "Low_g2.6_s6.9") { gammaStr = "_Low_g=2.6_s=6.9"; + gammsave = 2.6; + slopesave = 6.9; } else if (icm.gamma == "sRGB_g2.4_s12.92") { gammaStr = "_sRGB_g=2.4_s=12.92"; + gammsave = 2.4; + slopesave = 12.92; } else if (icm.gamma == "BT709_g2.2_s4.5") { gammaStr = "_BT709_g=2.2_s=4.5"; + gammsave = 2.22; + slopesave = 4.5; } else if (icm.gamma == "linear_g1.0") { gammaStr = "_Linear_g=1.0"; + gammsave = 1.; + slopesave = 0.; } else if (icm.gamma == "standard_g2.2") { gammaStr = "_g=2.2"; + gammsave = 2.2; + slopesave = 0.; } else if (icm.gamma == "standard_g1.8") { gammaStr = "_g=1.8"; + gammsave = 1.8; + slopesave = 0.; } else if (icm.gamma == "Lab_g3.0s9.03296") { gammaStr = "_LAB_g3.0_s9.03296"; + gammsave = 3.0; + slopesave = 9.03296; } outTemp = outPr; @@ -1618,42 +1637,56 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams: } // create description with gamma + slope + primaries - std::wostringstream gammaWs; + std::wostringstream gammaWs; std::wstring gammaStrICC; gammaWs.precision(3); + + Glib::ustring gammaGS;//to save gamma and slope in a tag if (icm.gamma == "Custom") { if (icm.wprofile == "v4") { - outPro = outPr + "_v4_" + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc"; + outPro = "RTv4_" + outPr + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc"; } else if (icm.wprofile == "v2" || icm.wprofile == "none") { - outPro = outPr + "_v2_" + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc"; + outPro = "RTv2_" + outPr + std::to_string((float)icm.gampos) + " " + std::to_string((float)icm.slpos) + ".icc"; } gammaWs.precision(2); gammaWs << outTemp << " g=" << (float)icm.gampos << " s=" << (float)icm.slpos; + gammaGS ="g" +std::to_string((double)icm.gampos) + "s" + std::to_string((double)icm.slpos) + "!"; - // cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str()); - } else { if (icm.wprofile == "v4") { - outPro = outPr + "_v4_" + gammaStr + ".icc"; + outPro = "RTv4_" + outPr + gammaStr + ".icc"; } else if (icm.wprofile == "v2" || icm.wprofile == "none") { - outPro = outPr + "_v2_" + gammaStr + ".icc"; + outPro = "RTv2_" + outPr + gammaStr + ".icc"; } gammaWs << outTemp << gammaStr; + gammaGS = "g" + std::to_string(gammsave) + "s" + std::to_string(slopesave) + "!"; - // gammaWs << outPro.c_str() ; - // cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str()); } + + //write in tag 'dmdd' values of current gamma and slope to retrive after in Output profile + wchar_t *wGammaGS = (wchar_t*)g_utf8_to_utf16 (gammaGS.c_str(), -1, NULL, NULL, NULL); + if (!wGammaGS) { + printf("Error: lab2rgbOut / g_utf8_to_utf16 failed!\n"); + } + cmsMLU *description = cmsMLUalloc(NULL, 1); + // Language code (3 letters code) : https://www.iso.org/obp/ui/ + // Country code (3 letters code) : http://www.loc.gov/standards/iso639-2/php/code_list.php + if (cmsMLUsetWide(description, "eng", "USA", wGammaGS)) { + cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, description); //save 'dmdd' in description + } else { + printf("Error: lab2rgbOut / cmsMLUsetWide failed for \"%s\" !\n", gammaGS.c_str()); + } - + cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str()); cmsMLU *copyright = cmsMLUalloc(NULL, 1); @@ -1662,14 +1695,8 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams: cmsMLUfree(copyright); cmsWriteTag(outputProfile, cmsSigProfileDescriptionTag, mlu);//desc changed - - cmsMLU *descrip = cmsMLUalloc(NULL, 1); - - cmsMLUsetASCII(descrip, "en", "US", "Rawtherapee"); - cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, descrip); - cmsMLUfree(descrip); - - + + cmsMLUfree(description); // instruction with //ICC are used to generate ICC profile if (mlu == nullptr) { diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 86af5e4ab..1a76b4e90 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -26,7 +26,6 @@ #include "curves.h" #include "alignedbuffer.h" #include "color.h" - namespace rtengine { @@ -314,6 +313,71 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i lcmsMutex->unlock(); } else { oprof = ICCStore::getInstance()->getProfile(icm.output); + Glib::ustring outtest = icm.output; + std::string fileis_RTv2 = outtest.substr(0, 4); + //printf("IsRTv2=%s\n", fileis_RTv2.c_str()); + if(fileis_RTv2 == "RTv2") {//Only fot ICC v2 : read tag from desc to retrieve gamma and slope save before in generate ICC v2 + //due to bug in LCMS in CmsToneCurve + //printf("icmout=%s \n",icm.output.c_str()); + GammaValues g_b; //gamma parameters + GammaValues gb; //gamma parameters + const double eps = 0.000000001; // not divide by zero + double gammatag = 2.4; + double slopetag = 12.92; + cmsMLU *modelDescMLU = (cmsMLU*) (cmsReadTag(oprof, cmsSigDeviceModelDescTag)); + if (modelDescMLU) { + cmsUInt32Number count = cmsMLUgetWide(modelDescMLU, "eng", "USA", nullptr, 0); // get buffer length first + if (count) { + wchar_t *buffer = new wchar_t[count]; + count = cmsMLUgetWide(modelDescMLU, "eng", "USA", buffer, count); // now put the string in the buffer + char* cModelDesc = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, nullptr, nullptr); // convert to utf-8 in a buffer allocated by glib + delete [] buffer; + if (cModelDesc) { + Glib::ustring modelDesc(cModelDesc); + g_free(cModelDesc); + // printf("dmdd=%s\n", modelDesc.c_str()); + + std::size_t pos = modelDesc.find("g"); + std::size_t posmid = modelDesc.find("s"); + std::size_t posend = modelDesc.find("!"); + std::string strgamma = modelDesc.substr(pos + 1, (posmid - pos)); + gammatag = std::stod(strgamma.c_str()); + std::string strslope = modelDesc.substr(posmid + 1, (posend - posmid)); + slopetag = std::stod(strslope.c_str()); + // printf("gam=%f slo=%f\n", gammatag, slopetag); + } + } else { + printf("Error: lab2rgbOut / String length is null!\n"); + } + } else { + printf("Error: lab2rgbOut / cmsReadTag/cmsSigDeviceModelDescTag failed!\n"); + } + + double pwr = 1.0 / gammatag; + double ts = slopetag; + double slope = slopetag == 0 ? eps : slopetag; + + int mode = 0; + Color::calcGamma(pwr, ts, mode, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 + gb[4] = g_b[3] * ts; + gb[0] = gammatag; + gb[1] = 1. / (1.0 + g_b[4]); + gb[2] = g_b[4] / (1.0 + g_b[4]); + gb[3] = 1. / slope; + gb[5] = 0.0; + gb[6] = 0.0; + + cmsToneCurve* GammaTRC[3]; + cmsFloat64Number Parameters[7] = { gb[0], gb[1], gb[2], gb[3], gb[4], gb[5], gb[6] } ; + + GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, Parameters); //5 = smoother than 4 + cmsWriteTag(oprof, cmsSigRedTRCTag, GammaTRC[0]); + cmsWriteTag(oprof, cmsSigGreenTRCTag, GammaTRC[1]); + cmsWriteTag(oprof, cmsSigBlueTRCTag, GammaTRC[2]); + cmsFreeToneCurve(GammaTRC[0]); + } + + } if (oprof) { diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 800bfeef5..85ac8e728 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1293,7 +1293,8 @@ private: useLCMS = false; if ((jprof = ICCStore::getInstance()->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) { - useLCMS = true; + + useLCMS = true; } } else { diff --git a/rtgui/options.cc b/rtgui/options.cc index 661b3d6c5..928d3cf47 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -530,18 +530,18 @@ void Options::setDefaults() rtSettings.monitorIntent = rtengine::RI_RELATIVE; rtSettings.monitorBPC = true; rtSettings.autoMonitorProfile = false; - rtSettings.adobe = "RT_ClayRGB-V2-srgbtrc"; // put the name of yours profiles (here windows) - rtSettings.prophoto = "RT_LargeRGB-V2-rgbtrc"; // these names appear in the menu "output profile" - rtSettings.prophoto10 = "RT_Large-V4-g10"; // these names appear in the menu "output profile" - rtSettings.srgb10 = "RT_sRGB_g10"; - rtSettings.widegamut = "WideGamutRGB"; - rtSettings.srgb = "RT_sRGB-V2-srgbtrc"; - rtSettings.bruce = "RT_bruce_V4"; - rtSettings.beta = "RT_beta_V4"; - rtSettings.best = "RT_best_V4"; - rtSettings.rec2020 = "RT_Rec2020-V2-srgbtrc"; - rtSettings.ACESp0 = "RT_ACEScg-V2-srgbtrc"; - rtSettings.ACESp1 = "RT_acesp1_V4"; + rtSettings.adobe = "RTv2_Medium"; // put the name of yours profiles (here windows) + rtSettings.prophoto = "RTv2_Large"; // these names appear in the menu "output profile" + rtSettings.prophoto10 = "RTv2_Large"; // these names appear in the menu "output profile" + rtSettings.srgb10 = "RTv2_sRGB"; + rtSettings.widegamut = "RTv2_Wide"; + rtSettings.srgb = "RTv2_sRGB"; + rtSettings.bruce = "RTv2_Bruce"; + rtSettings.beta = "RTv2_Beta"; + rtSettings.best = "RTv2_Best"; + rtSettings.rec2020 = "RTv2_Rec2020"; + rtSettings.ACESp0 = "RTv2_Acesp0"; + rtSettings.ACESp1 = "RTv2_Acesp1"; rtSettings.verbose = false; rtSettings.gamutICC = true; rtSettings.gamutLch = true;