Introducting soft-proofing and Black Point Compensation, simplify the
CMM at the end of the pipeline + sparse code refactoring A new BPC checkbutton has been created in 'Preferences/Color Management' and in the ICM tool. Better hanbling of widget sensitivity of the output profile / gamma part of the ICM tool.
This commit is contained in:
@@ -1158,211 +1158,27 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
|
||||
cmsHPROFILE jprof = NULL;
|
||||
bool customGamma = false;
|
||||
bool useLCMS = false;
|
||||
bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled && !autili && !butili ;
|
||||
|
||||
if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
|
||||
cmsMLU *DescriptionMLU, *CopyrightMLU, *DmndMLU, *DmddMLU;// for modification TAG
|
||||
|
||||
cmsToneCurve* GammaTRC[3] = { NULL, NULL, NULL };
|
||||
cmsFloat64Number Parameters[7];
|
||||
double ga0, ga1, ga2, ga3, ga4, ga5, ga6;
|
||||
double ga[7];
|
||||
// if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
|
||||
readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos, ga0, ga1, ga2, ga3, ga4, ga5, ga6, params.blackwhite.enabled );
|
||||
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly, ga);
|
||||
customGamma = true;
|
||||
|
||||
//or selected Free gamma
|
||||
useLCMS = false;
|
||||
bool pro = false;
|
||||
Glib::ustring chpro, outProfile;
|
||||
bool present_space[10] = {false, false, false, false, false, false, false, false, false, false};
|
||||
std::vector<Glib::ustring> opnames = iccStore->getProfiles ();
|
||||
|
||||
//test if files are in system
|
||||
for (int j = 0; j < 10; j++) {
|
||||
// one can modify "option" [Color Management] to adapt the profile's name if they are different for windows, MacOS, Linux ??
|
||||
// some of them are actually provided by RT, thanks to Jacques Desmis
|
||||
if (j == 0) {
|
||||
chpro = options.rtSettings.prophoto;
|
||||
} else if(j == 1) {
|
||||
chpro = options.rtSettings.adobe;
|
||||
} else if(j == 2) {
|
||||
chpro = options.rtSettings.widegamut;
|
||||
} else if(j == 3) {
|
||||
chpro = options.rtSettings.beta;
|
||||
} else if(j == 4) {
|
||||
chpro = options.rtSettings.best;
|
||||
} else if(j == 5) {
|
||||
chpro = options.rtSettings.bruce;
|
||||
} else if(j == 6) {
|
||||
chpro = options.rtSettings.srgb;
|
||||
} else if(j == 7) {
|
||||
chpro = options.rtSettings.srgb10; //gamma 1.0
|
||||
} else if(j == 8) {
|
||||
chpro = options.rtSettings.prophoto10; //gamma 1.0
|
||||
} else if(j == 9) {
|
||||
chpro = options.rtSettings.rec2020;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < opnames.size(); i++) {
|
||||
if(chpro.compare(opnames[i]) == 0) {
|
||||
present_space[j] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!present_space[j] && settings->verbose) {
|
||||
printf("Missing file: %s\n", chpro.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (params.icm.freegamma && params.icm.gampos < 1.35) {
|
||||
pro = true; //select profil with gammaTRC modified :
|
||||
} else if (params.icm.gamma == "linear_g1.0" || (params.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 (params.icm.working == "ProPhoto" && present_space[0] && !pro) {
|
||||
outProfile = options.rtSettings.prophoto;
|
||||
} else if (params.icm.working == "Adobe RGB" && present_space[1] ) {
|
||||
outProfile = options.rtSettings.adobe;
|
||||
} else if (params.icm.working == "WideGamut" && present_space[2] ) {
|
||||
outProfile = options.rtSettings.widegamut;
|
||||
} else if (params.icm.working == "Beta RGB" && present_space[3] ) {
|
||||
outProfile = options.rtSettings.beta;
|
||||
} else if (params.icm.working == "BestRGB" && present_space[4] ) {
|
||||
outProfile = options.rtSettings.best;
|
||||
} else if (params.icm.working == "BruceRGB" && present_space[5] ) {
|
||||
outProfile = options.rtSettings.bruce;
|
||||
} else if (params.icm.working == "sRGB" && present_space[6] && !pro) {
|
||||
outProfile = options.rtSettings.srgb;
|
||||
} else if (params.icm.working == "sRGB" && present_space[7] && pro) {
|
||||
outProfile = options.rtSettings.srgb10;
|
||||
} else if (params.icm.working == "ProPhoto" && present_space[8] && pro) {
|
||||
outProfile = options.rtSettings.prophoto10;
|
||||
} else if (params.icm.working == "Rec2020" && present_space[9]) {
|
||||
outProfile = options.rtSettings.rec2020;
|
||||
} else {
|
||||
// Should not occurs
|
||||
if (settings->verbose) {
|
||||
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", params.icm.working.c_str() );
|
||||
}
|
||||
|
||||
if ((jprof = iccStore->createCustomGammaOutputProfile (params.icm, ga)) == NULL) {
|
||||
useLCMS = true;
|
||||
}
|
||||
|
||||
//begin adaptation rTRC gTRC bTRC
|
||||
//"jprof" profile has the same characteristics than RGB values, but TRC are adapted... for applying profile
|
||||
if (!useLCMS) {
|
||||
if (settings->verbose) {
|
||||
printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str()
|
||||
}
|
||||
|
||||
jprof = iccStore->getProfile(outProfile); //get output profile
|
||||
|
||||
if (jprof == NULL) {
|
||||
useLCMS = true;
|
||||
|
||||
if (settings->verbose) {
|
||||
printf("\"%s\" ICC output profile not found!\n", outProfile.c_str());
|
||||
}
|
||||
} else {
|
||||
Parameters[0] = ga0;
|
||||
Parameters[1] = ga1;
|
||||
Parameters[2] = ga2;
|
||||
Parameters[3] = ga3;
|
||||
Parameters[4] = ga4;
|
||||
Parameters[5] = ga5;
|
||||
Parameters[6] = ga6;
|
||||
// 7 parameters for smoother curves
|
||||
//change desc Tag , to "free gamma", or "BT709", etc.
|
||||
cmsContext ContextID = cmsGetProfileContextID(jprof);//modification TAG
|
||||
DescriptionMLU = cmsMLUalloc(ContextID, 1);
|
||||
CopyrightMLU = cmsMLUalloc(ContextID, 1);//for ICC
|
||||
DmndMLU = cmsMLUalloc(ContextID, 1); //for ICC
|
||||
DmddMLU = cmsMLUalloc(ContextID, 1); // for ICC
|
||||
|
||||
|
||||
// instruction with //ICC are used for generate icc profile
|
||||
if (DescriptionMLU == NULL) {
|
||||
printf("Description error\n");
|
||||
}
|
||||
|
||||
cmsMLUsetWide(CopyrightMLU, "en", "US", L"General Public License - AdobeRGB compatible") ;//adapt to profil
|
||||
cmsMLUsetWide(DmndMLU, "en", "US", L"RawTherapee") ;
|
||||
cmsMLUsetWide(DmddMLU, "en", "US", L"RTMedium") ; //adapt to profil
|
||||
|
||||
//display Tag desc with : selection of gamma and Primaries
|
||||
if (!params.icm.freegamma) {
|
||||
std::wstring gammaStr;
|
||||
|
||||
if(params.icm.gamma == "High_g1.3_s3.35") {
|
||||
gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35");
|
||||
} else if (params.icm.gamma == "Low_g2.6_s6.9") {
|
||||
gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9");
|
||||
} else if (params.icm.gamma == "sRGB_g2.4_s12.92") {
|
||||
gammaStr = std::wstring(L"GammaTRC: sRGB g=2.4 s=12.92");
|
||||
} else if (params.icm.gamma == "BT709_g2.2_s4.5") {
|
||||
gammaStr = std::wstring(L"GammaTRC: BT709 g=2.2 s=4.5");
|
||||
} else if (params.icm.gamma == "linear_g1.0") {
|
||||
gammaStr = std::wstring(L"GammaTRC: Linear g=1.0");
|
||||
} else if (params.icm.gamma == "standard_g2.2") {
|
||||
gammaStr = std::wstring(L"GammaTRC: g=2.2");
|
||||
} else if (params.icm.gamma == "standard_g1.8") {
|
||||
gammaStr = std::wstring(L"GammaTRC: g=1.8");
|
||||
}
|
||||
|
||||
cmsMLUsetWide(DescriptionMLU, "en", "US", gammaStr.c_str());
|
||||
|
||||
//for elaboration ICC profiles
|
||||
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Medium gamma sRGB(AdobeRGB compatible)");
|
||||
// else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma BT709(IEC61966 equivalent)");
|
||||
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma sRGB(IEC61966 equivalent)");
|
||||
// else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma Linear1.0(IEC61966 equivalent)");
|
||||
//else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma BT709(Prophoto compatible)");
|
||||
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma sRGB(Prophoto compatible)");
|
||||
// else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma Linear1.0(Prophoto compatible)");
|
||||
} else {
|
||||
// create description with gamma + slope + primaries
|
||||
std::wostringstream gammaWs;
|
||||
gammaWs.precision(2);
|
||||
gammaWs << "Manual GammaTRC: g=" << (float)params.icm.gampos << " s=" << (float)params.icm.slpos;
|
||||
cmsMLUsetWide(DescriptionMLU, "en", "US", gammaWs.str().c_str());
|
||||
}
|
||||
|
||||
cmsWriteTag(jprof, cmsSigProfileDescriptionTag, DescriptionMLU);//desc changed
|
||||
// cmsWriteTag(jprof, cmsSigCopyrightTag, CopyrightMLU);
|
||||
// cmsWriteTag(jprof, cmsSigDeviceMfgDescTag, DmndMLU);
|
||||
// cmsWriteTag(jprof, cmsSigDeviceModelDescTag, DmddMLU);
|
||||
|
||||
// Calculate output profile's rTRC bTRC gTRC
|
||||
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters);
|
||||
cmsWriteTag(jprof, cmsSigGreenTRCTag, (void*)GammaTRC[1] );
|
||||
cmsWriteTag(jprof, cmsSigRedTRCTag, (void*)GammaTRC[0] );
|
||||
cmsWriteTag(jprof, cmsSigBlueTRCTag, (void*)GammaTRC[2] );
|
||||
//for generation ICC profiles : here Prophoto ==> Large
|
||||
// if(params.icm.gamma== "BT709_g2.2_s4.5") cmsSaveProfileToFile(jprof, "RT_sRGB_gBT709.icm");
|
||||
// else if (params.icm.gamma== "sRGB_g2.4_s12.92") cmsSaveProfileToFile(jprof, "RT_Medium_gsRGB.icc");
|
||||
// else if (params.icm.gamma== "linear_g1.0") cmsSaveProfileToFile(jprof, "RT_Large_g10.icc");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (GammaTRC[0]) {
|
||||
cmsFreeToneCurve(GammaTRC[0]);
|
||||
}
|
||||
} else {
|
||||
// if Default gamma mode: we use the profile selected in the "Output profile" combobox;
|
||||
// gamma come from the selected profile, otherwise it comes from "Free gamma" tool
|
||||
|
||||
// readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.blackwhite.enabled);
|
||||
bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled ;
|
||||
|
||||
if(autili || butili ) {
|
||||
bwonly = false;
|
||||
}
|
||||
|
||||
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, bwonly);
|
||||
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly);
|
||||
|
||||
if (settings->verbose) {
|
||||
printf("Output profile_: \"%s\"\n", params.icm.output.c_str());
|
||||
@@ -1374,17 +1190,15 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
|
||||
|
||||
|
||||
|
||||
if(!autili && !butili ) {
|
||||
if(params.blackwhite.enabled && !params.colorToning.enabled ) {//force BW r=g=b
|
||||
if (settings->verbose) {
|
||||
printf("Force BW\n");
|
||||
}
|
||||
if(bwonly) { //force BW r=g=b
|
||||
if (settings->verbose) {
|
||||
printf("Force BW\n");
|
||||
}
|
||||
|
||||
for (int ccw = 0; ccw < cw; ccw++) {
|
||||
for (int cch = 0; cch < ch; cch++) {
|
||||
readyImg->r(cch, ccw) = readyImg->g(cch, ccw);
|
||||
readyImg->b(cch, ccw) = readyImg->g(cch, ccw);
|
||||
}
|
||||
for (int ccw = 0; ccw < cw; ccw++) {
|
||||
for (int cch = 0; cch < ch; cch++) {
|
||||
readyImg->r(cch, ccw) = readyImg->g(cch, ccw);
|
||||
readyImg->b(cch, ccw) = readyImg->g(cch, ccw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1410,37 +1224,28 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
|
||||
// Setting the output curve to readyImg
|
||||
if (customGamma) {
|
||||
if (!useLCMS) {
|
||||
// use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16b
|
||||
// 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);
|
||||
}
|
||||
} else {
|
||||
// use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b
|
||||
Glib::ustring outputProfile;
|
||||
// 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) {
|
||||
outputProfile = params.icm.output;
|
||||
|
||||
/* if we'd wanted the RT_sRGB profile we would have selected it
|
||||
else {
|
||||
// use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b
|
||||
if (settings->verbose) printf("No output profiles set ; looking for the default sRGB profile (\"%s\")...\n", options.rtSettings.srgb.c_str());
|
||||
outputProfile = options.rtSettings.srgb;
|
||||
}*/
|
||||
|
||||
// if iccStore->getProfile send back an object, then iccStore->getContent will do too
|
||||
cmsHPROFILE jprof = iccStore->getProfile(outputProfile); //get outProfile
|
||||
cmsHPROFILE jprof = iccStore->getProfile(params.icm.output); //get outProfile
|
||||
|
||||
if (jprof == NULL) {
|
||||
if (settings->verbose) {
|
||||
printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", outputProfile.c_str());
|
||||
printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", params.icm.output.c_str());
|
||||
}
|
||||
} else {
|
||||
if (settings->verbose) {
|
||||
printf("Using \"%s\" output profile\n", outputProfile.c_str());
|
||||
printf("Using \"%s\" output profile\n", params.icm.output.c_str());
|
||||
}
|
||||
|
||||
ProfileContent pc = iccStore->getContent (outputProfile);
|
||||
ProfileContent pc = iccStore->getContent (params.icm.output);
|
||||
readyImg->setOutputProfile (pc.data, pc.length);
|
||||
}
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user