Custom TRC Tone response curve and Illuminant - change Histogram - RGB and Lab values - for output (screen, TIF, JPG..) (#5949)

* Change TRC in the process

* Improve GUI slope

* Add tooltip output profile

* Various change to enable and tooltip

* Chnage rtthumbnail

* Small change tooltip trc

* Another small change tooltip

* Improve GUI - change default TRC BT709 - change tooltip

* Other GUI improvment

* Small changes to BT709 values

* Various change to TRC - add illuminant working profile

* Change labels tooltip TRC illuminant

* Display wp in console if wp provided

* Change tooltip

* Change max wlope

* Init trc + illum + primaries

* Add black point compensation

* Change location abstract

* Fixed bug with rtthumbnail...

* Added tooltip

* Logscale for wslope

* Change tooltip abstract

* Change labels tooltips abstract profile

* Added 6 sliders custom primaries X and Y

* Change GUI custom primaries

* Use custom primaries abstract profiles

* Tooltip with primaries red green blue

* Fixed warning gtk

* Change one tooltip

* Change range custom primaries

* Change GUI default Primaries

* Change one tooltip

* Speedup for trc

* Rendering intent for abstract profile

* Hide intent abstract

* Preserve neutral tones

* Chnage settings preserves neutral tones

* Improve GUI

* Improvment to preserv

* Clean code - speedup TRC when illuminant and primaries default

* Change label

* Change bad default value Blux

* Add forgoten illuminant when selecting primaries

* clean code

* Change labels

* improve workingtrc for LA

* Change default primaries when select default

* Added others working profile to primaries

* Change labels and GUI

* Change tooltip

* CIExy diagram displaying the primaries (interactive) and the white point (#6207)

* Ciexy diagram

* Change to Ciexy graph

* Change graph and defaut coordonates

* Various changes to graph - params

* Disable setListener(ToolPanelListener)

* Add some graduation to graph

* Clean comment code graph

* Change radius 0

* Enable sensitive graph Ciexy

* update Ciexy graph with primaries

* Remove reset button graph

* Change labels and behavior

* First step third spot green

* Second step 3rd spot green

* First try 3 primaries graph Ciexy

* Fixed bad behavior in lab grid

* Fixed another bad behavior graph

* Clean and comment code

* Change default gamma

* More accurate graph Cie xy

* Added white point to Ciexy graph

* Added tooltip Cie xy diagram

* Improvment when illuminant change

* Refine diagram CIE xy - added WP 2000K

* White point D120 + tooltip

* Change label

* Change labels

* Change tooltips

* Improve diagram CIE xy with parabolic

* Other parabolic to improve Cie xy diagram

* Small change GUI

* Added Label CIE xy - change labels

* Change behavior when none - change labels

* Improve gUI and trys to fix LGTM alerts

* CIE xy change set sensitive

* Improve tooltip primaries sliders

* Adapt tooltip to new labels

* Fixed crash and some bad behavior

* First fix bad behavior with some primaries

* Second fixed bad behavior primaries

* Third fixed bad behavior primaries

* Change white point BestRGB

* Change order rgb in history msg Ciexy

* Change tooltip

* Change tooltip

* Improve GUI primaries

* Illuminant 1500K - display in console matrix XYZ-RGB

* Improve GUI illuminant

* Change a tooltip

* Somme changes to GUI and verbose

* Test code for wprim in read

* clean code for wprims

* further cleanups, not tested

* Some cleanups and bugfixes, #5949

* Simplify `std::unique_ptr<>` dereferencing

Also some minor cleanups.

* Some changes suggested by Floessie

* Others change suggested

* Others changes suggested by Floessie

* Forgotten change in procparams.cc

* Added black and white for use with the primaries channel mixer

* Small change behavior GUI - illuminant

* Change pragma omp in iplab2rgb

* Add enums and clean up

* Remove unused code icmpanel.cc

* Fix LGTM alert, #5949

Co-authored-by: Ingo Weyrich <heckflosse67@gmx.de>
Co-authored-by: Flössie <floessie.mail@gmail.com>
This commit is contained in:
Desmis
2021-05-16 06:18:25 +02:00
committed by GitHub
parent 7040aed540
commit 35abd92209
27 changed files with 2751 additions and 309 deletions

View File

@@ -17,6 +17,7 @@
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fstream>
#include <glibmm/thread.h>
#include "improccoordinator.h"
@@ -27,6 +28,7 @@
#include "colortemp.h"
#include "curves.h"
#include "dcp.h"
#include "guidedfilter.h"
#include "iccstore.h"
#include "image8.h"
#include "imagefloat.h"
@@ -35,7 +37,7 @@
#include "lcp.h"
#include "procparams.h"
#include "refreshmap.h"
#include "guidedfilter.h"
#include "utils.h"
#include "../rtgui/options.h"
@@ -600,16 +602,16 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float max_r[nbw*nbh];
float max_b[nbw*nbh];
if(denoiseParams.Lmethod == "CUR") {
if(noiseLCurve)
if (denoiseParams.Lmethod == "CUR") {
if (noiseLCurve)
denoiseParams.luma = 0.5f;
else
denoiseParams.luma = 0.0f;
} else if(denoiseParams.Lmethod == "SLI")
} else if (denoiseParams.Lmethod == "SLI")
noiseLCurve.Reset();
if(noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1
if (noiseLCurve || noiseCCurve){//only allocate memory if enabled and scale=1
// we only need image reduced to 1/4 here
calclum = new Imagefloat ((pW+1)/2, (pH+1)/2);//for luminance denoise curve
for(int ii=0;ii<pH;ii+=2){
@@ -829,42 +831,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
if (todo & (M_AUTOEXP | M_RGBCURVE)) {
/* if (params->icm.workingTRC == "Custom") { //exec TRC IN free
if (oprevi == orig_prev) {
oprevi = new Imagefloat(pW, pH);
orig_prev->copyData(oprevi);
}
const Glib::ustring profile = params->icm.workingProfile;
if (profile == "sRGB" || profile == "Adobe RGB" || profile == "ProPhoto" || profile == "WideGamut" || profile == "BruceRGB" || profile == "Beta RGB" || profile == "BestRGB" || profile == "Rec2020" || profile == "ACESp0" || profile == "ACESp1") {
const int cw = oprevi->getWidth();
const int ch = oprevi->getHeight();
// put gamma TRC to 1
if (customTransformIn) {
cmsDeleteTransform(customTransformIn);
customTransformIn = nullptr;
}
ipf.workingtrc(oprevi, oprevi, cw, ch, -5, params->icm.workingProfile, 2.4, 12.92310, customTransformIn, true, false, true);
//adjust TRC
if (customTransformOut) {
cmsDeleteTransform(customTransformOut);
customTransformOut = nullptr;
}
ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params->icm.workingProfile, params->icm.workingTRCGamma, params->icm.workingTRCSlope, customTransformOut, false, true, true);
}
}
*/
}
// if ((todo & (M_LUMINANCE + M_COLOR)) || (todo & M_AUTOEXP)) {
// if (todo & M_RGBCURVE) {
if (((todo & (M_AUTOEXP | M_RGBCURVE)) || (todo & M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) {
if ((todo & (M_AUTOEXP | M_RGBCURVE | M_CROP)) && params->locallab.enabled && !params->locallab.spots.empty()) {
ipf.rgb2lab(*oprevi, *oprevl, params->icm.workingProfile);
@@ -920,11 +888,11 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
for (int sp = 0; sp < (int)params->locallab.spots.size(); sp++) {
if(params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
if (params->locallab.spots.at(sp).equiltm && params->locallab.spots.at(sp).exptonemap) {
savenormtm.reset(new LabImage(*oprevl, true));
}
if(params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
if (params->locallab.spots.at(sp).equilret && params->locallab.spots.at(sp).expreti) {
savenormreti.reset(new LabImage(*oprevl, true));
}
// Set local curves of current spot to LUT
@@ -1034,7 +1002,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
float yend = 1.f;
float xsta = 0.f;
float xend = 1.f;
if(istm || isreti) {
if (istm || isreti) {
locx = params->locallab.spots.at(sp).loc.at(0) / 2000.0;
locy = params->locallab.spots.at(sp).loc.at(2) / 2000.0;
locxl= params->locallab.spots.at(sp).loc.at(1) / 2000.0;
@@ -1054,10 +1022,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
int yys = ysta * hh;
int yye = yend * hh;
if(istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
if (istm) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
ipf.mean_sig (nprevl->L, meantme, stdtme, xxs, xxe, yys, yye);
}
if(isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
if (isreti) { //calculate mean and sigma on full image for RT-spot use by normalize_mean_dt
ipf.mean_sig (nprevl->L, meanretie, stdretie,xxs, xxe, yys, yye) ;
}
@@ -1146,20 +1114,20 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if(istm) { //calculate mean and sigma on full image for use by normalize_mean_dt
if (istm) { //calculate mean and sigma on full image for use by normalize_mean_dt
float meanf = 0.f;
float stdf = 0.f;
ipf.mean_sig (savenormtm.get()->L, meanf, stdf, xxs, xxe, yys, yye);
ipf.mean_sig (savenormtm->L, meanf, stdf, xxs, xxe, yys, yye);
//using 2 unused variables noiselumc and softradiustm
params->locallab.spots.at(sp).noiselumc = (int) meanf;
params->locallab.spots.at(sp).softradiustm = stdf ;
}
if(isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt
if (isreti) { //calculate mean and sigma on full image for use by normalize_mean_dt
float meanf = 0.f;
float stdf = 0.f;
ipf.mean_sig (savenormreti.get()->L, meanf, stdf,xxs, xxe, yys, yye );
ipf.mean_sig (savenormreti->L, meanf, stdf,xxs, xxe, yys, yye );
//using 2 unused variables sensihs and sensiv
params->locallab.spots.at(sp).sensihs = (int) meanf;
params->locallab.spots.at(sp).sensiv = (int) stdf;
@@ -1334,7 +1302,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
lhist16.clear();
#ifdef _OPENMP
const int numThreads = min(max(pW * pH / (int)lhist16.getSize(), 1), omp_get_max_threads());
#pragma omp parallel num_threads(numThreads) if(numThreads>1)
#pragma omp parallel num_threads(numThreads) if (numThreads>1)
#endif
{
LUTu lhist16thr(lhist16.getSize());
@@ -1414,7 +1382,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
bool proton = WaveParams.exptoning;
bool pronois = WaveParams.expnoise;
if(WaveParams.showmask) {
if (WaveParams.showmask) {
// WaveParams.showmask = false;
// WaveParams.expclari = true;
}
@@ -1540,7 +1508,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
float indic = 1.f;
if(WaveParams.showmask){
if (WaveParams.showmask){
mL0 = mC0 = -1.f;
indic = -1.f;
mL = fabs(mL);
@@ -1611,6 +1579,134 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
ipf.softLight(nprevl, params->softlight);
if (params->icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
const int GW = nprevl->W;
const int GH = nprevl->H;
std::unique_ptr<LabImage> provis;
const float pres = 0.01f * params->icm.preser;
if (pres > 0.f && params->icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
provis.reset(new LabImage(GW, GH));
provis->CopyFrom(nprevl);
}
std::unique_ptr<Imagefloat> tmpImage1(new Imagefloat(GW, GH));
ipf.lab2rgb(*nprevl, *tmpImage1, params->icm.workingProfile);
const float gamtone = params->icm.workingTRCGamma;
const float slotone = params->icm.workingTRCSlope;
int illum = toUnderlying(params->icm.will);
const int prim = toUnderlying(params->icm.wprim);
Glib::ustring prof = params->icm.workingProfile;
cmsHTRANSFORM dummy = nullptr;
int ill = 0;
ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true);
ipf.rgb2lab(*tmpImage1, *nprevl, params->icm.workingProfile);
//nprevl and provis
if (provis) {
ipf.preserv(nprevl, provis.get(), GW, GH);
}
if (params->icm.fbw) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int x = 0; x < GH; x++)
for (int y = 0; y < GW; y++) {
nprevl->a[x][y] = 0.f;
nprevl->b[x][y] = 0.f;
}
}
tmpImage1.reset();
if (prim == 12) {//pass red gre blue xy in function of area dats Ciexy
float redgraphx = params->icm.labgridcieALow;
float redgraphy = params->icm.labgridcieBLow;
float blugraphx = params->icm.labgridcieAHigh;
float blugraphy = params->icm.labgridcieBHigh;
float gregraphx = params->icm.labgridcieGx;
float gregraphy = params->icm.labgridcieGy;
float redxx = 0.55f * (redgraphx + 1.f) - 0.1f;
redxx = rtengine::LIM(redxx, 0.41f, 1.f);
float redyy = 0.55f * (redgraphy + 1.f) - 0.1f;
redyy = rtengine::LIM(redyy, 0.f, 0.7f);
float bluxx = 0.55f * (blugraphx + 1.f) - 0.1f;
bluxx = rtengine::LIM(bluxx, -0.1f, 0.5f);
float bluyy = 0.55f * (blugraphy + 1.f) - 0.1f;
bluyy = rtengine::LIM(bluyy, -0.1f, 0.5f);
float grexx = 0.55f * (gregraphx + 1.f) - 0.1f;
grexx = rtengine::LIM(grexx, -0.1f, 0.4f);
float greyy = 0.55f * (gregraphy + 1.f) - 0.1f;
greyy = rtengine::LIM(greyy, 0.5f, 1.f);
if (primListener) {
primListener->primChanged (redxx, redyy, bluxx, bluyy, grexx, greyy);
}
} else {//all other cases - pass Cie xy to update graph Ciexy
float r_x = params->icm.redx;
float r_y = params->icm.redy;
float b_x = params->icm.blux;
float b_y = params->icm.bluy;
float g_x = params->icm.grex;
float g_y = params->icm.grey;
//printf("rx=%f ry=%f \n", (double) r_x, (double) r_y);
float wx = 0.33f;
float wy = 0.33f;
switch (illum) {
case 1://D41
wx = 0.37798f;
wy = 0.38123f;
break;
case 2://D50
wx = 0.3457f;
wy = 0.3585f;
break;
case 3://D55
wx = 0.3324f;
wy = 0.3474f;
break;
case 4://D60
wx = 0.3217f;
wy = 0.3377f;
break;
case 5://D65
wx = 0.3127f;
wy = 0.3290f;
break;
case 6://D80
wx = 0.2937f;
wy = 0.3092f;
break;
case 7://D120
wx = 0.2697f;
wy = 0.2808f;
break;
case 8://stdA
wx = 0.4476f;
wy = 0.4074f;
break;
case 9://2000K
wx = 0.5266f;
wy = 0.4133f;
break;
case 10://1500K
wx = 0.5857f;
wy = 0.3932f;
break;
}
if (primListener) {
primListener->iprimChanged (r_x, r_y, b_x, b_y, g_x, g_y, wx, wy);
}
}
}
if (params->colorappearance.enabled) {
// L histo and Chroma histo for ciecam
// histogram well be for Lab (Lch) values, because very difficult to do with J,Q, M, s, C
@@ -1718,6 +1814,8 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
}
}
// if (todo & (M_AUTOEXP | M_RGBCURVE)) {
// Update the monitor color transform if necessary
if ((todo & M_MONITOR) || (lastOutputProfile != params->icm.outputProfile) || lastOutputIntent != params->icm.outputIntent || lastOutputBPC != params->icm.outputBPC) {
lastOutputProfile = params->icm.outputProfile;