Fix #4565 : Segfault saving image using RTv2_sRGB.icc

Also, replace identing tabs by spaces in some files
This commit is contained in:
Hombre 2018-05-19 00:19:06 +02:00
parent aca72b5641
commit b06e07034e
5 changed files with 100 additions and 76 deletions

View File

@ -1683,7 +1683,6 @@ cmsHPROFILE rtengine::ICCStore::createCustomGammaOutputProfile(const procparams:
printf("Error: lab2rgbOut / cmsMLUsetWide failed for \"%s\" !\n", gammaGS.c_str()); printf("Error: lab2rgbOut / cmsMLUsetWide failed for \"%s\" !\n", gammaGS.c_str());
} }
cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str()); cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str());
cmsMLUfree(description); cmsMLUfree(description);

View File

@ -313,71 +313,78 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i
lcmsMutex->unlock(); lcmsMutex->unlock();
} else { } else {
oprof = ICCStore::getInstance()->getProfile(icm.outputProfile); oprof = ICCStore::getInstance()->getProfile(icm.outputProfile);
Glib::ustring outtest = icm.outputProfile; Glib::ustring outtest = icm.outputProfile;
std::string fileis_RTv2 = outtest.substr(0, 4); std::string fileis_RTv2 = outtest.substr(0, 4);
//printf("IsRTv2=%s\n", fileis_RTv2.c_str()); //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 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 //due to bug in LCMS in CmsToneCurve
//printf("icmout=%s \n",icm.output.c_str()); //printf("icmout=%s \n",icm.output.c_str());
GammaValues g_b; //gamma parameters GammaValues g_b; //gamma parameters
GammaValues gb; //gamma parameters GammaValues gb; //gamma parameters
const double eps = 0.000000001; // not divide by zero const double eps = 0.000000001; // not divide by zero
double gammatag = 2.4; double gammatag = 2.4;
double slopetag = 12.92; double slopetag = 12.92;
cmsMLU *modelDescMLU = (cmsMLU*) (cmsReadTag(oprof, cmsSigDeviceModelDescTag)); cmsMLU *modelDescMLU = (cmsMLU*) (cmsReadTag(oprof, cmsSigDeviceModelDescTag));
if (modelDescMLU) { if (modelDescMLU) {
cmsUInt32Number count = cmsMLUgetWide(modelDescMLU, "eng", "USA", nullptr, 0); // get buffer length first cmsUInt32Number count = cmsMLUgetWide(modelDescMLU, "eng", "USA", nullptr, 0); // get buffer length first
if (count) { if (count) {
wchar_t *buffer = new wchar_t[count]; wchar_t *buffer = new wchar_t[count];
count = cmsMLUgetWide(modelDescMLU, "eng", "USA", buffer, count); // now put the string in the buffer 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 Glib::ustring modelDesc;
delete [] buffer; #if __SIZEOF_WCHAR_T__ == 2
if (cModelDesc) { char* cModelDesc = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, nullptr, nullptr); // convert to utf-8 in a buffer allocated by glib
Glib::ustring modelDesc(cModelDesc); if (cModelDesc) {
g_free(cModelDesc); modelDesc.assign(cModelDesc);
// printf("dmdd=%s\n", modelDesc.c_str()); g_free(cModelDesc);
}
std::size_t pos = modelDesc.find("g"); #else
std::size_t posmid = modelDesc.find("s"); modelDesc = utf32_to_utf8(buffer, count);
std::size_t posend = modelDesc.find("!"); #endif
std::string strgamma = modelDesc.substr(pos + 1, (posmid - pos)); delete [] buffer;
gammatag = std::stod(strgamma.c_str()); if (!modelDesc.empty()) {
std::string strslope = modelDesc.substr(posmid + 1, (posend - posmid)); printf("dmdd=%s\n", modelDesc.c_str());
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; std::size_t pos = modelDesc.find("g");
double ts = slopetag; std::size_t posmid = modelDesc.find("s");
double slope = slopetag == 0 ? eps : slopetag; 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");
}
int mode = 0; double pwr = 1.0 / gammatag;
Color::calcGamma(pwr, ts, mode, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 double ts = slopetag;
gb[4] = g_b[3] * ts; double slope = slopetag == 0 ? eps : slopetag;
gb[0] = gammatag;
gb[1] = 1. / (1.0 + g_b[4]); int mode = 0;
gb[2] = g_b[4] / (1.0 + g_b[4]); Color::calcGamma(pwr, ts, mode, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
gb[3] = 1. / slope; gb[4] = g_b[3] * ts;
gb[5] = 0.0; gb[0] = gammatag;
gb[6] = 0.0; 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]; cmsToneCurve* GammaTRC[3];
cmsFloat64Number Parameters[7] = { gb[0], gb[1], gb[2], gb[3], gb[4], gb[5], gb[6] } ; 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 GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, Parameters); //5 = smoother than 4
cmsWriteTag(oprof, cmsSigRedTRCTag, GammaTRC[0]); cmsWriteTag(oprof, cmsSigRedTRCTag, GammaTRC[0]);
cmsWriteTag(oprof, cmsSigGreenTRCTag, GammaTRC[1]); cmsWriteTag(oprof, cmsSigGreenTRCTag, GammaTRC[1]);
cmsWriteTag(oprof, cmsSigBlueTRCTag, GammaTRC[2]); cmsWriteTag(oprof, cmsSigBlueTRCTag, GammaTRC[2]);
cmsFreeToneCurve(GammaTRC[0]); cmsFreeToneCurve(GammaTRC[0]);
} }
} }
if (oprof) { if (oprof) {
@ -569,14 +576,12 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int
p[4] = 0.0366; p[4] = 0.0366;
p[5] = 0.0001; p[5] = 0.0001;
} else { } else {
p[0] = 0.7347; //default primaries always unused p[0] = 0.7347; //default primaries always unused
p[1] = 0.2653; p[1] = 0.2653;
p[2] = 0.1596; p[2] = 0.1596;
p[3] = 0.8404; p[3] = 0.8404;
p[4] = 0.0366; p[4] = 0.0366;
p[5] = 0.0001; p[5] = 0.0001;
} }
if (slpos == 0) { if (slpos == 0) {
@ -593,7 +598,7 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int
ga2 = g_a[4] / (1.0 + g_a[4]); ga2 = g_a[4] / (1.0 + g_a[4]);
ga3 = 1. / slpos; ga3 = 1. / slpos;
ga5 = 0.0; ga5 = 0.0;
ga6 = 0.0; ga6 = 0.0;
// printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4); // printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4);
cmsCIExyY xyD; cmsCIExyY xyD;
@ -627,23 +632,20 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int
float* rr = working->r(i); float* rr = working->r(i);
float* rg = working->g(i); float* rg = working->g(i);
float* rb = working->b(i); float* rb = working->b(i);
float* xa = (float*)image->r(i); float* xa = (float*)image->r(i);
float* ya = (float*)image->g(i); float* ya = (float*)image->g(i);
float* za = (float*)image->b(i); float* za = (float*)image->b(i);
for (int j = 0; j < cw; j++) { for (int j = 0; j < cw; j++) {
float r1 = rr[j]; float r1 = rr[j];
float g1 = rg[j]; float g1 = rg[j];
float b1 = rb[j]; float b1 = rb[j];
float x_ = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; float x_ = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1;
float y_ = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; float y_ = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1;
float z_ = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; float z_ = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1;
xa[j] = ( x_) ; xa[j] = ( x_) ;
ya[j] = ( y_); ya[j] = ( y_);
za[j] = ( z_); za[j] = ( z_);
@ -656,12 +658,12 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int
lcmsMutex->lock(); lcmsMutex->lock();
cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile(); cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile();
// cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, params->icm.outputIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); // cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, params->icm.outputIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags); cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags);
lcmsMutex->unlock(); lcmsMutex->unlock();
image->ExecCMSTransform2(hTransform); image->ExecCMSTransform2(hTransform);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
image->normalizeFloatTo65535(); image->normalizeFloatTo65535();

View File

@ -3152,7 +3152,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile( saveToKeyfile(
!pedited || pedited->icm.outputIntent, !pedited || pedited->icm.outputIntent,
"Color Management", "Color Management",
"OutputProfileIntent", { "OutputProfileIntent", {
{RI_PERCEPTUAL, "Perceptual"}, {RI_PERCEPTUAL, "Perceptual"},
{RI_RELATIVE, "Relative"}, {RI_RELATIVE, "Relative"},
{RI_SATURATION, "Saturation"}, {RI_SATURATION, "Saturation"},

View File

@ -265,3 +265,21 @@ void swab(const void* from, void* to, ssize_t n)
} }
} }
#if __SIZEOF_WCHAR_T__ == 4
Glib::ustring utf32_to_utf8(wchar_t* UTF32Buffer, size_t sizeOfUTF32Buffer)
{
char *buffer2 = new char[sizeOfUTF32Buffer];
char *pBuffer2 = buffer2;
gchar a[6];
for (size_t i=0; i < sizeOfUTF32Buffer/4; ++i) {
gint bytesWritten = g_unichar_to_utf8((gunichar)UTF32Buffer[i], a);
for (gint j=0; j < bytesWritten; ++j) {
*(pBuffer2++) = a[j];
}
}
Glib::ustring modelDesc(buffer2);
delete [] buffer2;
return buffer2;
}
#endif

View File

@ -55,3 +55,8 @@ bool hasPngExtension(const Glib::ustring& filename);
void swab(const void* from, void* to, ssize_t n); void swab(const void* from, void* to, ssize_t n);
} }
#if __SIZEOF_WCHAR_T__ == 4
Glib::ustring utf32_to_utf8(wchar_t* UTF32Buffer, size_t sizeOfUTF32Buffer);
#endif