From 83521b0c92cd58e691ee059dd2deb5beccc36b5f Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Thu, 15 Mar 2018 16:17:44 +0100 Subject: [PATCH 1/4] improved out-of-gamut warning, taken from PhotoFlow --- rtengine/improcfun.cc | 92 +++++++++++++++++++++++++++++++++++++------ rtengine/improcfun.h | 7 ++-- rtengine/iplab2rgb.cc | 50 +++++++++++++++++++++++ 3 files changed, 134 insertions(+), 15 deletions(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index d274a056a..605a578ea 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -260,10 +260,18 @@ extern const Settings* settings; ImProcFunctions::~ImProcFunctions () { - if (monitorTransform) { cmsDeleteTransform (monitorTransform); } + if (gw_softproof2refTransform) { + cmsDeleteTransform(gw_softproof2refTransform); + } + if (gw_lab2refTransform) { + cmsDeleteTransform(gw_lab2refTransform); + } + if (gw_lab2softproofTransform) { + cmsDeleteTransform(gw_lab2softproofTransform); + } } void ImProcFunctions::setScale (double iscale) @@ -271,14 +279,34 @@ void ImProcFunctions::setScale (double iscale) scale = iscale; } + +static void cms_log_handler(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) +{ + std::cout << "\n*** LCMS ERROR: " << ErrorCode << ": " << Text << "\n" << std::endl; +} + void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck) { // set up monitor transform if (monitorTransform) { cmsDeleteTransform (monitorTransform); } + if (gw_softproof2refTransform) { + cmsDeleteTransform(gw_softproof2refTransform); + } + if (gw_lab2refTransform) { + cmsDeleteTransform(gw_lab2refTransform); + } + if (gw_lab2softproofTransform) { + cmsDeleteTransform(gw_lab2softproofTransform); + } + + cmsSetLogErrorHandler(&cms_log_handler); monitorTransform = nullptr; + gw_softproof2refTransform = nullptr; + gw_lab2refTransform = nullptr; + gw_lab2softproofTransform = nullptr; cmsHPROFILE monitor = nullptr; @@ -295,6 +323,8 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, cmsUInt32Number flags; cmsHPROFILE iprof = cmsCreateLab4Profile (nullptr); + cmsHPROFILE gamutprof = nullptr; + cmsUInt32Number gamutbpc = 0; bool softProofCreated = false; @@ -321,9 +351,9 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, if (oprof) { // NOCACHE is for thread safety, NOOPTIMIZE for precision - if (gamutCheck) { - flags |= cmsFLAGS_GAMUTCHECK; - } + // if (gamutCheck) { + // flags |= cmsFLAGS_GAMUTCHECK; + // } monitorTransform = cmsCreateProofingTransform ( iprof, TYPE_Lab_FLT, @@ -336,17 +366,28 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, if (monitorTransform) { softProofCreated = true; } + + if (gamutCheck) { + gamutprof = oprof; + if (params->icm.outputBPC) { + gamutbpc = cmsFLAGS_BLACKPOINTCOMPENSATION; + } + } } } else if (gamutCheck) { - flags = cmsFLAGS_GAMUTCHECK | cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; + // flags = cmsFLAGS_GAMUTCHECK | cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; + // if (settings->monitorBPC) { + // flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; + // } + + // monitorTransform = cmsCreateProofingTransform(iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitor, monitorIntent, monitorIntent, flags); + + // if (monitorTransform) { + // softProofCreated = true; + // } + gamutprof = monitor; if (settings->monitorBPC) { - flags |= cmsFLAGS_BLACKPOINTCOMPENSATION; - } - - monitorTransform = cmsCreateProofingTransform(iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitor, monitorIntent, monitorIntent, flags); - - if (monitorTransform) { - softProofCreated = true; + gamutbpc = cmsFLAGS_BLACKPOINTCOMPENSATION; } } @@ -360,6 +401,33 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent, flags); } + if (gamutCheck) { + if (cmsIsMatrixShaper(gamutprof)) { + cmsHPROFILE aces = ICCStore::getInstance()->getProfile("ACES"); + if (aces) { + gw_lab2refTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + gw_lab2softproofTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + gw_softproof2refTransform = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); + } + } else { + gw_lab2refTransform = nullptr; + gw_lab2softproofTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + gw_softproof2refTransform = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, iprof, TYPE_Lab_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); + } + + if (!gw_softproof2refTransform) { + if (gw_lab2softproofTransform) { + cmsDeleteTransform(gw_lab2softproofTransform); + gw_lab2softproofTransform = nullptr; + } + } else if (!gw_lab2softproofTransform) { + if (gw_softproof2refTransform) { + cmsDeleteTransform(gw_softproof2refTransform); + gw_softproof2refTransform = nullptr; + } + } + } + cmsCloseProfile (iprof); } } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 8204516fd..2af71e005 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -45,8 +45,9 @@ class ImProcFunctions cmsHTRANSFORM monitorTransform; - cmsHTRANSFORM lab2outputTransform; - cmsHTRANSFORM output2monitorTransform; + cmsHTRANSFORM gw_lab2refTransform; + cmsHTRANSFORM gw_lab2softproofTransform; + cmsHTRANSFORM gw_softproof2refTransform; const ProcParams* params; double scale; @@ -197,7 +198,7 @@ public: double lumimul[3]; ImProcFunctions (const ProcParams* iparams, bool imultiThread = true) - : monitorTransform (nullptr), lab2outputTransform (nullptr), output2monitorTransform (nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {} + : monitorTransform (nullptr), gw_lab2refTransform(nullptr), gw_lab2softproofTransform(nullptr), gw_softproof2refTransform(nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {} ~ImProcFunctions (); bool needsLuminanceOnly() { return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient());} void setScale (double iscale); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 16eb4f50e..0555053f7 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -46,12 +46,28 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) int H = lab->H; unsigned char * data = image->data; + const auto set_gamut_warning = + [](Image8 *image, int y, int x) -> void + { + image->r(y, x) = 0; + image->g(y, x) = 255; + image->b(y, x) = 255; + }; + // cmsDoTransform is relatively expensive #ifdef _OPENMP #pragma omp parallel firstprivate(lab, data, W, H) #endif { AlignedBuffer pBuf(3 * lab->W); + + AlignedBuffer gwBuf1; + AlignedBuffer gwBuf2; + if (gw_softproof2refTransform) { + gwBuf1.resize(3 * lab->W); + gwBuf2.resize(3 * lab->W); + } + float *buffer = pBuf.data; #ifdef _OPENMP @@ -74,6 +90,40 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) } cmsDoTransform (monitorTransform, buffer, data + ix, W); + + if (gw_softproof2refTransform) { + float delta_max = gw_lab2refTransform ? 0.0001f : 4.9999f; + cmsDoTransform(gw_lab2softproofTransform, buffer, gwBuf2.data, W); + + cmsDoTransform(gw_softproof2refTransform, gwBuf2.data, gwBuf1.data, W); + float *proofdata = gwBuf1.data; + float *refdata = buffer; + if (gw_lab2refTransform) { + cmsDoTransform(gw_lab2refTransform, buffer, gwBuf2.data, W); + refdata = gwBuf2.data; + + int iy = 0; + for (int j = 0; j < W; ++j) { + float delta = max(std::abs(proofdata[iy] - refdata[iy]), std::abs(proofdata[iy+1] - refdata[iy+1]), std::abs(proofdata[iy+2] - refdata[iy+2])); + iy += 3; + + if (delta > delta_max) { + set_gamut_warning(image, i, j); + } + } + } else { + int iy = 0; + for (int j = 0; j < W; ++j) { + cmsCIELab lab1 = { proofdata[iy], proofdata[iy+1], proofdata[iy+2] }; + cmsCIELab lab2 = { refdata[iy], refdata[iy+1], refdata[iy+2] }; + iy += 3; + float delta = cmsDeltaE(&lab1, &lab2); + if (delta > delta_max) { + set_gamut_warning(image, i, j); + } + } + } + } } } // End of parallelization } else { From 956c44905ea4b73f8a22619935fb70916f045b61 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 16 Mar 2018 17:57:03 +0100 Subject: [PATCH 2/4] cleaned up gamut warning code --- rtengine/CMakeLists.txt | 1 + rtengine/gamutwarning.cc | 125 +++++++++++++++++++++++++++++++++++++++ rtengine/gamutwarning.h | 48 +++++++++++++++ rtengine/iccstore.h | 2 +- rtengine/improcfun.cc | 54 +---------------- rtengine/improcfun.h | 7 +-- rtengine/iplab2rgb.cc | 44 +------------- 7 files changed, 183 insertions(+), 98 deletions(-) create mode 100644 rtengine/gamutwarning.cc create mode 100644 rtengine/gamutwarning.h diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 080a76410..d6fa934e3 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -117,6 +117,7 @@ set(RTENGINESOURCEFILES tmo_fattal02.cc iplocalcontrast.cc histmatching.cc + gamutwarning.cc ) if(LENSFUN_HAS_LOAD_DIRECTORY) diff --git a/rtengine/gamutwarning.cc b/rtengine/gamutwarning.cc new file mode 100644 index 000000000..a52f08429 --- /dev/null +++ b/rtengine/gamutwarning.cc @@ -0,0 +1,125 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +/** + * Adapted from PhotoFlow, Copyright (C) 2014 Ferrero Andrea + * also distributed under the GPL V3+ + */ + +#include "gamutwarning.h" + +namespace rtengine { + +GamutWarning::GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, bool gamutbpc): + lab2ref(nullptr), + lab2softproof(nullptr), + softproof2ref(nullptr) +{ + if (cmsIsMatrixShaper(gamutprof)) { + cmsHPROFILE aces = ICCStore::getInstance()->getProfile("ACES"); + if (aces) { + lab2ref = cmsCreateTransform(iprof, TYPE_Lab_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + lab2softproof = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + softproof2ref = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); + } + } else { + lab2ref = nullptr; + lab2softproof = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); + softproof2ref = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, iprof, TYPE_Lab_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); + } + + if (!softproof2ref) { + if (lab2softproof) { + cmsDeleteTransform(lab2softproof); + lab2softproof = nullptr; + } + } else if (!lab2softproof) { + if (softproof2ref) { + cmsDeleteTransform(softproof2ref); + softproof2ref = nullptr; + } + } +} + + +GamutWarning::~GamutWarning() +{ + if (softproof2ref) { + cmsDeleteTransform(softproof2ref); + } + if (lab2ref) { + cmsDeleteTransform(lab2ref); + } + if (lab2softproof) { + cmsDeleteTransform(lab2softproof); + } +} + + +void GamutWarning::markLine(Image8 *image, int y, float *srcbuf, float *buf1, float *buf2) +{ + if (softproof2ref) { + const int width = image->getWidth(); + + float delta_max = lab2ref ? 0.0001f : 4.9999f; + cmsDoTransform(lab2softproof, srcbuf, buf2, width); + cmsDoTransform(softproof2ref, buf2, buf1, width); + + float *proofdata = buf1; + float *refdata = srcbuf; + + if (lab2ref) { + cmsDoTransform(lab2ref, srcbuf, buf2, width); + refdata = buf2; + + int iy = 0; + for (int j = 0; j < width; ++j) { + float delta = max(std::abs(proofdata[iy] - refdata[iy]), std::abs(proofdata[iy+1] - refdata[iy+1]), std::abs(proofdata[iy+2] - refdata[iy+2])); + iy += 3; + + if (delta > delta_max) { + mark(image, y, j); + } + } + } else { + int iy = 0; + for (int j = 0; j < width; ++j) { + cmsCIELab lab1 = { proofdata[iy], proofdata[iy+1], proofdata[iy+2] }; + cmsCIELab lab2 = { refdata[iy], refdata[iy+1], refdata[iy+2] }; + iy += 3; + float delta = cmsDeltaE(&lab1, &lab2); + if (delta > delta_max) { + mark(image, y, j); + } + } + } + } +} + + +inline void GamutWarning::mark(Image8 *image, int y, int x) +{ + image->r(y, x) = 0; + image->g(y, x) = 255; + image->b(y, x) = 255; +} + + +} // namespace rtengine diff --git a/rtengine/gamutwarning.h b/rtengine/gamutwarning.h new file mode 100644 index 000000000..2e21883d4 --- /dev/null +++ b/rtengine/gamutwarning.h @@ -0,0 +1,48 @@ +/* -*- C++ -*- + * + * This file is part of RawTherapee. + * + * Copyright (c) 2018 Alberto Griggio + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +/** + * Adapted from PhotoFlow, Copyright (C) 2014 Ferrero Andrea + * also distributed under the GPL V3+ + */ + +#pragma once + +#include "iccstore.h" +#include "noncopyable.h" +#include "image8.h" + +namespace rtengine { + +class GamutWarning: public NonCopyable { +public: + GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, bool bpc); + ~GamutWarning(); + void markLine(Image8 *image, int y, float *srcbuf, float *buf1, float *buf2); + +private: + void mark(Image8 *image, int i, int j); + + cmsHTRANSFORM lab2ref; + cmsHTRANSFORM lab2softproof; + cmsHTRANSFORM softproof2ref; +}; + +} // namespace rtengine diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index bdb15d2c0..4604404fb 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 605a578ea..c50c4f6f5 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -263,15 +263,6 @@ ImProcFunctions::~ImProcFunctions () if (monitorTransform) { cmsDeleteTransform (monitorTransform); } - if (gw_softproof2refTransform) { - cmsDeleteTransform(gw_softproof2refTransform); - } - if (gw_lab2refTransform) { - cmsDeleteTransform(gw_lab2refTransform); - } - if (gw_lab2softproofTransform) { - cmsDeleteTransform(gw_lab2softproofTransform); - } } void ImProcFunctions::setScale (double iscale) @@ -280,33 +271,15 @@ void ImProcFunctions::setScale (double iscale) } -static void cms_log_handler(cmsContext ContextID, cmsUInt32Number ErrorCode, const char *Text) -{ - std::cout << "\n*** LCMS ERROR: " << ErrorCode << ": " << Text << "\n" << std::endl; -} - void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck) { // set up monitor transform if (monitorTransform) { cmsDeleteTransform (monitorTransform); } - if (gw_softproof2refTransform) { - cmsDeleteTransform(gw_softproof2refTransform); - } - if (gw_lab2refTransform) { - cmsDeleteTransform(gw_lab2refTransform); - } - if (gw_lab2softproofTransform) { - cmsDeleteTransform(gw_lab2softproofTransform); - } - - cmsSetLogErrorHandler(&cms_log_handler); + gamutWarning.reset(nullptr); monitorTransform = nullptr; - gw_softproof2refTransform = nullptr; - gw_lab2refTransform = nullptr; - gw_lab2softproofTransform = nullptr; cmsHPROFILE monitor = nullptr; @@ -402,30 +375,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, } if (gamutCheck) { - if (cmsIsMatrixShaper(gamutprof)) { - cmsHPROFILE aces = ICCStore::getInstance()->getProfile("ACES"); - if (aces) { - gw_lab2refTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); - gw_lab2softproofTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); - gw_softproof2refTransform = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); - } - } else { - gw_lab2refTransform = nullptr; - gw_lab2softproofTransform = cmsCreateTransform(iprof, TYPE_Lab_FLT, gamutprof, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); - gw_softproof2refTransform = cmsCreateTransform(gamutprof, TYPE_RGB_FLT, iprof, TYPE_Lab_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE | gamutbpc); - } - - if (!gw_softproof2refTransform) { - if (gw_lab2softproofTransform) { - cmsDeleteTransform(gw_lab2softproofTransform); - gw_lab2softproofTransform = nullptr; - } - } else if (!gw_lab2softproofTransform) { - if (gw_softproof2refTransform) { - cmsDeleteTransform(gw_softproof2refTransform); - gw_softproof2refTransform = nullptr; - } - } + gamutWarning.reset(new GamutWarning(iprof, gamutprof, gamutbpc)); } cmsCloseProfile (iprof); diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 2af71e005..0627b19f5 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -34,6 +34,7 @@ #include "curves.h" #include "cplx_wavelet_dec.h" #include "pipettebuffer.h" +#include "gamutwarning.h" namespace rtengine { @@ -45,9 +46,7 @@ class ImProcFunctions cmsHTRANSFORM monitorTransform; - cmsHTRANSFORM gw_lab2refTransform; - cmsHTRANSFORM gw_lab2softproofTransform; - cmsHTRANSFORM gw_softproof2refTransform; + std::unique_ptr gamutWarning; const ProcParams* params; double scale; @@ -198,7 +197,7 @@ public: double lumimul[3]; ImProcFunctions (const ProcParams* iparams, bool imultiThread = true) - : monitorTransform (nullptr), gw_lab2refTransform(nullptr), gw_lab2softproofTransform(nullptr), gw_softproof2refTransform(nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {} + : monitorTransform (nullptr), params (iparams), scale (1), multiThread (imultiThread), lumimul{} {} ~ImProcFunctions (); bool needsLuminanceOnly() { return !(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient());} void setScale (double iscale); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 0555053f7..a8e35bd18 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -46,14 +46,6 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) int H = lab->H; unsigned char * data = image->data; - const auto set_gamut_warning = - [](Image8 *image, int y, int x) -> void - { - image->r(y, x) = 0; - image->g(y, x) = 255; - image->b(y, x) = 255; - }; - // cmsDoTransform is relatively expensive #ifdef _OPENMP #pragma omp parallel firstprivate(lab, data, W, H) @@ -63,7 +55,7 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) AlignedBuffer gwBuf1; AlignedBuffer gwBuf2; - if (gw_softproof2refTransform) { + if (gamutWarning) { gwBuf1.resize(3 * lab->W); gwBuf2.resize(3 * lab->W); } @@ -91,38 +83,8 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) cmsDoTransform (monitorTransform, buffer, data + ix, W); - if (gw_softproof2refTransform) { - float delta_max = gw_lab2refTransform ? 0.0001f : 4.9999f; - cmsDoTransform(gw_lab2softproofTransform, buffer, gwBuf2.data, W); - - cmsDoTransform(gw_softproof2refTransform, gwBuf2.data, gwBuf1.data, W); - float *proofdata = gwBuf1.data; - float *refdata = buffer; - if (gw_lab2refTransform) { - cmsDoTransform(gw_lab2refTransform, buffer, gwBuf2.data, W); - refdata = gwBuf2.data; - - int iy = 0; - for (int j = 0; j < W; ++j) { - float delta = max(std::abs(proofdata[iy] - refdata[iy]), std::abs(proofdata[iy+1] - refdata[iy+1]), std::abs(proofdata[iy+2] - refdata[iy+2])); - iy += 3; - - if (delta > delta_max) { - set_gamut_warning(image, i, j); - } - } - } else { - int iy = 0; - for (int j = 0; j < W; ++j) { - cmsCIELab lab1 = { proofdata[iy], proofdata[iy+1], proofdata[iy+2] }; - cmsCIELab lab2 = { refdata[iy], refdata[iy+1], refdata[iy+2] }; - iy += 3; - float delta = cmsDeltaE(&lab1, &lab2); - if (delta > delta_max) { - set_gamut_warning(image, i, j); - } - } - } + if (gamutWarning) { + gamutWarning->markLine(image, i, buffer, gwBuf1.data, gwBuf2.data); } } } // End of parallelization From 17dc4af424f5d9543e8260a70515f2e720ddcf79 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sat, 17 Mar 2018 22:54:48 +0100 Subject: [PATCH 3/4] fixed bug in discriminating between matrix and lut profiles for the OOG check --- rtengine/gamutwarning.cc | 5 +++-- rtengine/gamutwarning.h | 2 +- rtengine/improcfun.cc | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/rtengine/gamutwarning.cc b/rtengine/gamutwarning.cc index a52f08429..dde784db5 100644 --- a/rtengine/gamutwarning.cc +++ b/rtengine/gamutwarning.cc @@ -24,15 +24,16 @@ */ #include "gamutwarning.h" +#include namespace rtengine { -GamutWarning::GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, bool gamutbpc): +GamutWarning::GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, RenderingIntent intent, bool gamutbpc): lab2ref(nullptr), lab2softproof(nullptr), softproof2ref(nullptr) { - if (cmsIsMatrixShaper(gamutprof)) { + if (cmsIsMatrixShaper(gamutprof) && !cmsIsCLUT(gamutprof, intent, LCMS_USED_AS_OUTPUT)) { cmsHPROFILE aces = ICCStore::getInstance()->getProfile("ACES"); if (aces) { lab2ref = cmsCreateTransform(iprof, TYPE_Lab_FLT, aces, TYPE_RGB_FLT, INTENT_ABSOLUTE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); diff --git a/rtengine/gamutwarning.h b/rtengine/gamutwarning.h index 2e21883d4..be6d7b61b 100644 --- a/rtengine/gamutwarning.h +++ b/rtengine/gamutwarning.h @@ -33,7 +33,7 @@ namespace rtengine { class GamutWarning: public NonCopyable { public: - GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, bool bpc); + GamutWarning(cmsHPROFILE iprof, cmsHPROFILE gamutprof, RenderingIntent intent, bool bpc); ~GamutWarning(); void markLine(Image8 *image, int y, float *srcbuf, float *buf1, float *buf2); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index c50c4f6f5..44edd8b17 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -298,6 +298,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, cmsHPROFILE iprof = cmsCreateLab4Profile (nullptr); cmsHPROFILE gamutprof = nullptr; cmsUInt32Number gamutbpc = 0; + RenderingIntent gamutintent = RI_RELATIVE; bool softProofCreated = false; @@ -345,6 +346,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, if (params->icm.outputBPC) { gamutbpc = cmsFLAGS_BLACKPOINTCOMPENSATION; } + gamutintent = outIntent; } } } else if (gamutCheck) { @@ -362,6 +364,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, if (settings->monitorBPC) { gamutbpc = cmsFLAGS_BLACKPOINTCOMPENSATION; } + gamutintent = monitorIntent; } if (!softProofCreated) { @@ -375,7 +378,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, } if (gamutCheck) { - gamutWarning.reset(new GamutWarning(iprof, gamutprof, gamutbpc)); + gamutWarning.reset(new GamutWarning(iprof, gamutprof, gamutintent, gamutbpc)); } cmsCloseProfile (iprof); From c7c8f68e3287a7c87a3cdf1140248b3d7aa3f06a Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Tue, 20 Mar 2018 15:50:55 +0100 Subject: [PATCH 4/4] fixed segfault in the oog check when the gamut profile is null --- rtengine/improcfun.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 44edd8b17..19d6cb6c1 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -377,7 +377,7 @@ void ImProcFunctions::updateColorProfiles (const Glib::ustring& monitorProfile, monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent, flags); } - if (gamutCheck) { + if (gamutCheck && gamutprof) { gamutWarning.reset(new GamutWarning(iprof, gamutprof, gamutintent, gamutbpc)); }