Fixed bad quality ICCv2 for RT output profile

This commit is contained in:
Desmis
2018-05-12 18:10:18 +02:00
parent 0268b9428b
commit 3806eb1408
4 changed files with 138 additions and 46 deletions

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -1293,7 +1293,8 @@ private:
useLCMS = false;
if ((jprof = ICCStore::getInstance()->createCustomGammaOutputProfile (params.icm, ga)) == nullptr) {
useLCMS = true;
useLCMS = true;
}
} else {