From 23aa0562aabc2c028202a3291dd03c91dd78ea88 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sun, 25 Nov 2018 00:00:40 +0100 Subject: [PATCH 1/7] crop tool: fix grid spacing for gtkmm < 3.20 --- rtgui/crop.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rtgui/crop.cc b/rtgui/crop.cc index 2484b9060..5bfeca61b 100644 --- a/rtgui/crop.cc +++ b/rtgui/crop.cc @@ -286,6 +286,20 @@ Crop::Crop(): nx = ny = nw = nh = 0; lastRotationDeg = 0; + +//GTK318 +#if GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 20 + methodgrid->set_row_spacing(4); + methodgrid->set_column_spacing(4); + settingsgrid->set_row_spacing(4); + settingsgrid->set_column_spacing(4); + ppigrid->set_row_spacing(4); + ppigrid->set_column_spacing(4); + ppisubgrid->set_row_spacing(4); + ppisubgrid->set_column_spacing(4); +#endif +//GTK318 + show_all (); } From 67aa52b4ff98e4a65963fae203ed21444ea824a1 Mon Sep 17 00:00:00 2001 From: TooWaBoo Date: Sun, 25 Nov 2018 09:50:00 +0100 Subject: [PATCH 2/7] Update TWB-theme (cleaning & minor cosmetic changes (#5027) --- rtdata/themes/TooWaBlue-GTK3-20_.css | 92 +++++++++++++++------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/rtdata/themes/TooWaBlue-GTK3-20_.css b/rtdata/themes/TooWaBlue-GTK3-20_.css index b7b5175a7..d4565829a 100644 --- a/rtdata/themes/TooWaBlue-GTK3-20_.css +++ b/rtdata/themes/TooWaBlue-GTK3-20_.css @@ -2,7 +2,7 @@ This file is part of RawTherapee. Copyright (c) 2016-2018 TooWaBoo - Version 2.96 + Version 2.98 RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -164,7 +164,9 @@ undershoot { } label { - margin: 0 0.19em; + padding: 0.083333333333333333em 0; + margin: 0.19em; + min-height: 1.333333333333333333em; } /*** Frames ************************************************************************************/ @@ -323,11 +325,8 @@ fontchooser scrolledwindow, padding-bottom: 0.25em; background-color: @bg-dark-grey; } -#Navigator box label { - padding: 0.166666666666666666em 0; -} -#Navigator > label:nth-child(2) { - margin-top: 0.5em; +#Navigator label { + padding: 0; } /*** end ***************************************************************************************/ @@ -927,14 +926,18 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border-bottom: 0.083333333333333333em solid @view-grid-border; margin-left: 0.083333333333333333em; margin-right: 0.083333333333333333em; + padding: 0 0.19em; } #ToolPanelNotebook > header tabs { - margin-bottom: 0.333333333333333333em; + margin: 0 0 0.25em; } -#ToolPanelNotebook > header tab > box > image{ +#ToolPanelNotebook > header tab { + padding: 0; +} +#ToolPanelNotebook > header tab image{ min-height: 2em; min-width: 2em; - margin: 0.25em 0 0.333333333333333333em; + margin: 0.19em 0.25em 0.333333333333333333em; padding: 0; } #ToolPanelNotebook > stack { @@ -963,11 +966,6 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { #PrefNotebook > header { margin: -0.666666666666666666em -0.666666666666666666em 0.333333333333333333em; } -#PrefNotebook > header tab label, -#AboutNotebook > header tab label { - padding-top: 0.25em; - padding-bottom: 0.25em; -} #PrefNotebook > stack { margin: 0 -0.666666666666666666em; } @@ -994,9 +992,6 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: @bg-dark-grey; padding-left: 0.333333333333333333em; } -#MetaPanelNotebook > header tab label{ - margin: 0.083333333333333333em 0.083333333333333333em 0.19em; -} #MetaPanelNotebook > stack { background-color: @bg-dark-grey; padding: 0 0 0.5em 0; @@ -1036,8 +1031,10 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { background-color: transparent; } -#MetaPanelNotebook label { - padding: 0.083333333333333333em 0 0; +#MetaPanelNotebook stack label { + margin-top: 0; + margin-bottom: 0; + padding: 0; } /*** end ***************************************************************************************/ @@ -1093,9 +1090,13 @@ window.csd:not(.fullscreen) #MainNotebook > header.top { border-left: 0.083333333333333333em solid @bg-dark-grey; } +/* !!! Must be same height as "Small Lock Button" */ #BeforeAfterContainer label { - min-height: 2.666666666666666666em; padding: 0 0.5em; + min-height: 2em; + min-width: 2em; + margin: 0.25em 0; + border: 0.083333333333333333em solid transparent; } #EditorToolbarTop { @@ -1478,13 +1479,21 @@ scale + image + image + button.flat { margin-bottom: 0.095em; } -/*Color chooser & buttons */ +/* Color chooser & buttons */ button.color { - min-height: 1.166666666666666666em; - min-width: 2.75em; - padding: 0.25em; + min-width: 3.25em; + box-shadow: none; + background-image: none; + background-color: transparent; } -button.color colorswatch, + +button.color colorswatch { + min-height: 0; + min-width: 0; + margin: 1px; + border-radius: 0.2em; +} + colorchooser colorswatch { border: 1px solid @bg-button-border; } @@ -1492,6 +1501,13 @@ colorchooser colorswatch#add-color-button:first-child { border-radius: 5.5px 0 0 5.5px; } +/* Font chooser button */ +button.font label{ + min-height: 0; + min-width: 0; + margin: 0 0.19em; +} + /* Save, Cancel, OK ... buttons */ dialog .dialog-action-area button { min-height: 2.166666666666666666em; @@ -1708,9 +1724,6 @@ window treeview > header image { min-width: 1.333333333333333333em; } -.view button.text-button label { - margin: 0; -} window .view button { border: none; border-bottom: 0.083333333333333333em solid @view-grid-border; @@ -1792,11 +1805,7 @@ popover button.text-button:active { /*** end ***************************************************************************************/ /*** Checkbox & Radio **************************************************************************/ -checkbutton { - padding: 0; - margin: 0.083333333333333333em 0.19em; - min-height: 1.666666666666666666em;/*x*/ -} +checkbutton, radiobutton { padding: 0.083333333333333333em 0; margin: 0.19em; @@ -1839,16 +1848,11 @@ frame > checkbutton check{ } #PartialPaste checkbutton { - min-height: 1.166666666666666666em; - margin-top: calc(0.416666666666666666em - 4px); - margin-bottom: calc(0.416666666666666666em - 4px) + padding: 0; + margin: 0.19em 0 0 0.583333333333333333em; } #PartialPaste checkbutton:not(#PartialPasteHeader) { - margin-left: 1.166666666666666666em; -} -#PartialPasteHeader { - margin-left: 0.5em; - padding-top: calc(0.666666666666666666em - 5px) + margin: 0 0 0 1.166666666666666666em; } /*** end ***************************************************************************************/ @@ -1908,8 +1912,8 @@ spinbutton { margin-bottom: 0.333333333333333333em; } #MyExpander checkbutton + label + spinbutton { - margin-top: 0.333333333333333333em; - margin-bottom: 0.333333333333333333em; + margin-top: 0.416666666666666666em; + margin-bottom: 0.416666666666666666em; } /**/ From 20577ccab67a595a8e98c301a517ba07842b9836 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 25 Nov 2018 13:54:59 +0100 Subject: [PATCH 3/7] custom trc, speedup and reduced memory usage, #5025 --- rtengine/dcrop.cc | 32 +++----------------- rtengine/imagefloat.cc | 21 ++++++++----- rtengine/imagefloat.h | 2 +- rtengine/improccoordinator.cc | 34 ++++------------------ rtengine/improcfun.h | 2 +- rtengine/iplab2rgb.cc | 55 +++++++++++++++-------------------- rtengine/simpleprocess.cc | 34 ++++------------------ 7 files changed, 53 insertions(+), 127 deletions(-) diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 7854dfb81..d9b4f1ca1 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -815,37 +815,13 @@ void Crop::update(int todo) 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") { - int cw = baseCrop->getWidth(); - int ch = baseCrop->getHeight(); + const int cw = baseCrop->getWidth(); + const int ch = baseCrop->getHeight(); workingCrop = new Imagefloat(cw, ch); - baseCrop->copyData(workingCrop); //first put gamma TRC to 1 - Imagefloat* readyImg0 = parent->ipf.workingtrc(workingCrop, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - workingCrop->r(row, col) = (float)readyImg0->r(row, col); - workingCrop->g(row, col) = (float)readyImg0->g(row, col); - workingCrop->b(row, col) = (float)readyImg0->b(row, col); - } - } - - delete readyImg0; - + parent->ipf.workingtrc(baseCrop, workingCrop, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, true, false); //adjust gamma TRC - Imagefloat* readyImg = parent->ipf.workingtrc(workingCrop, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - workingCrop->r(row, col) = (float)readyImg->r(row, col); - workingCrop->g(row, col) = (float)readyImg->g(row, col); - workingCrop->b(row, col) = (float)readyImg->b(row, col); - } - } - - delete readyImg; + parent->ipf.workingtrc(workingCrop, workingCrop, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, false, true); } } double rrm, ggm, bbm; diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 63c521040..2dae72793 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -475,7 +475,7 @@ void Imagefloat::calcCroppedHistogram(const ProcParams ¶ms, float scale, LUT } // Parallelized transformation; create transform with cmsFLAGS_NOCACHE! -void Imagefloat::ExecCMSTransform2(cmsHTRANSFORM hTransform) +void Imagefloat::ExecCMSTransform2(cmsHTRANSFORM hTransform, bool normalizeIn) { // LittleCMS cannot parallelize planar setups -- Hombre: LCMS2.4 can! But it we use this new feature, memory allocation @@ -487,18 +487,25 @@ void Imagefloat::ExecCMSTransform2(cmsHTRANSFORM hTransform) AlignedBuffer pBuf(width * 3); #ifdef _OPENMP - #pragma omp for schedule(static) + #pragma omp for schedule(dynamic, 16) #endif for (int y = 0; y < height; y++) { float *p = pBuf.data, *pR = r(y), *pG = g(y), *pB = b(y); - for (int x = 0; x < width; x++) { - *(p++) = *(pR++)/ 65535.f; - *(p++) = *(pG++)/ 65535.f; - *(p++) = *(pB++)/ 65535.f; - + if (normalizeIn) { + for (int x = 0; x < width; x++) { + *(p++) = *(pR++)/ 65535.f; + *(p++) = *(pG++)/ 65535.f; + *(p++) = *(pB++)/ 65535.f; + } + } else { + for (int x = 0; x < width; x++) { + *(p++) = *(pR++); + *(p++) = *(pG++); + *(p++) = *(pB++); + } } cmsDoTransform (hTransform, pBuf.data, pBuf.data, width); diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h index 9d7c69aef..921f86b59 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -222,7 +222,7 @@ public: void normalizeFloatTo1(); void normalizeFloatTo65535(); void calcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist); - void ExecCMSTransform2(cmsHTRANSFORM hTransform); + void ExecCMSTransform2(cmsHTRANSFORM hTransform, bool normalizeIn = true); void ExecCMSTransform(cmsHTRANSFORM hTransform); void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy); diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index d76ccda27..bbadbf0a7 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -28,7 +28,6 @@ #include #include #include "color.h" - #ifdef _OPENMP #include #endif @@ -511,38 +510,15 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange) orig_prev->copyData(oprevi); } - Glib::ustring profile = params.icm.workingProfile; + 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") { - int cw = oprevi->getWidth(); - int ch = oprevi->getHeight(); + const int cw = oprevi->getWidth(); + const int ch = oprevi->getHeight(); // put gamma TRC to 1 - Imagefloat* readyImg0 = ipf.workingtrc(oprevi, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - oprevi->r(row, col) = (float)readyImg0->r(row, col); - oprevi->g(row, col) = (float)readyImg0->g(row, col); - oprevi->b(row, col) = (float)readyImg0->b(row, col); - } - } - - delete readyImg0; + ipf.workingtrc(oprevi, oprevi, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, true, false); //adjust TRC - Imagefloat* readyImg = ipf.workingtrc(oprevi, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - oprevi->r(row, col) = (float)readyImg->r(row, col); - oprevi->g(row, col) = (float)readyImg->g(row, col); - oprevi->b(row, col) = (float)readyImg->b(row, col); - } - } - - delete readyImg; - + ipf.workingtrc(oprevi, oprevi, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, false, true); } } } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index c3e17a050..470922508 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -350,7 +350,7 @@ public: Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true); Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); // CieImage *ciec; - Imagefloat* workingtrc(Imagefloat* working, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos); + void workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos, bool normalizeIn = true, bool normalizeOut = true); bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index da8e687ed..437144600 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -432,7 +432,7 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i } -Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos) +void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos, bool normalizeIn, bool normalizeOut) { TMatrix wprof; @@ -445,22 +445,20 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int } double toxyz[3][3] = { { - (wprof[0][0] / dx), //I have suppressed / Color::D50x - (wprof[0][1] / dx), - (wprof[0][2] / dx) + (wprof[0][0] / (dx * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x + (wprof[0][1] / (dx * (normalizeIn ? 65535.0 : 1.0))), + (wprof[0][2] / (dx * (normalizeIn ? 65535.0 : 1.0))) }, { - (wprof[1][0]), - (wprof[1][1]), - (wprof[1][2]) + (wprof[1][0] / (normalizeIn ? 65535.0 : 1.0)), + (wprof[1][1] / (normalizeIn ? 65535.0 : 1.0)), + (wprof[1][2] / (normalizeIn ? 65535.0 : 1.0)) }, { - (wprof[2][0] / dz), //I have suppressed / Color::D50z - (wprof[2][1] / dz), - (wprof[2][2] / dz) + (wprof[2][0] / (dz * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50z + (wprof[2][1] / (dz * (normalizeIn ? 65535.0 : 1.0))), + (wprof[2][2] / (dz * (normalizeIn ? 65535.0 : 1.0))) } }; - Imagefloat* image = new Imagefloat(cw, ch); - double pwr; double ts; ts = slpos; @@ -618,27 +616,22 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int #pragma omp parallel for if (multiThread) for (int i = 0; i < ch; i++) { - float* rr = working->r(i); - float* rg = working->g(i); - float* rb = working->b(i); + float* rr = src->r(i); + float* rg = src->g(i); + float* rb = src->b(i); - float* xa = (float*)image->r(i); - float* ya = (float*)image->g(i); - float* za = (float*)image->b(i); + float* xa = (float*)dst->r(i); + float* ya = (float*)dst->g(i); + float* za = (float*)dst->b(i); for (int j = 0; j < cw; j++) { float r1 = rr[j]; float g1 = rg[j]; float b1 = rb[j]; - 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 z_ = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; - - xa[j] = ( x_) ; - ya[j] = ( y_); - za[j] = ( z_); - + xa[j] = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; + ya[j] = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; + za[j] = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; } } @@ -651,16 +644,14 @@ Imagefloat* ImProcFunctions::workingtrc(Imagefloat* working, int cw, int ch, int cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags); lcmsMutex->unlock(); - image->ExecCMSTransform2(hTransform); + dst->ExecCMSTransform2(hTransform, false); cmsDeleteTransform(hTransform); - image->normalizeFloatTo65535(); + if (normalizeOut) { + dst->normalizeFloatTo65535(); + } } - - - return image; - } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index bdb3ced19..e09d2fe3a 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -893,39 +893,15 @@ private: //gamma TRC working if (params.icm.workingTRC == "Custom") { //exec TRC IN free - Glib::ustring profile; - profile = params.icm.workingProfile; + 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") { - int cw = baseImg->getWidth(); - int ch = baseImg->getHeight(); + const int cw = baseImg->getWidth(); + const int ch = baseImg->getHeight(); // put gamma TRC to 1 - Imagefloat* readyImg0 = ipf.workingtrc(baseImg, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - baseImg->r(row, col) = (float)readyImg0->r(row, col); - baseImg->g(row, col) = (float)readyImg0->g(row, col); - baseImg->b(row, col) = (float)readyImg0->b(row, col); - } - } - - delete readyImg0; - + ipf.workingtrc(baseImg, baseImg, cw, ch, -5, params.icm.workingProfile, 2.4, 12.92310, true, false); //adjust TRC - Imagefloat* readyImg = ipf.workingtrc(baseImg, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope); - #pragma omp parallel for - - for (int row = 0; row < ch; row++) { - for (int col = 0; col < cw; col++) { - baseImg->r(row, col) = (float)readyImg->r(row, col); - baseImg->g(row, col) = (float)readyImg->g(row, col); - baseImg->b(row, col) = (float)readyImg->b(row, col); - } - } - - delete readyImg; + ipf.workingtrc(baseImg, baseImg, cw, ch, 5, params.icm.workingProfile, params.icm.workingTRCGamma, params.icm.workingTRCSlope, false, true); } } From cfc947a865cbfe554a28ca9c80f4bf9c1eceda85 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Sun, 25 Nov 2018 14:23:06 +0100 Subject: [PATCH 4/7] Moved the ICC TRC patching code for RTv2 profiles from ImProcFunctions::lab2rgbOut to ICCStore See #5026 --- rtengine/iccstore.cc | 128 ++++++++++++++++++++++++++++++++++++++++-- rtengine/iplab2rgb.cc | 77 +------------------------ 2 files changed, 125 insertions(+), 80 deletions(-) diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index e8463a1d8..33972075c 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -38,6 +38,8 @@ #include "../rtgui/threadutils.h" #include "lcms2_plugin.h" +#include "color.h" + #include "cJSON.h" #define inkc_constant 0x696E6B43 namespace rtengine @@ -208,8 +210,85 @@ const char* wpnames[] = {"sRGB", "Adobe RGB", "ProPhoto", "WideGamut", "BruceRGB // high g=1.3 s=3.35 for high dynamic images //low g=2.6 s=6.9 for low contrast images +//----------------------------------------------------------------------------- +// helper functions to fix V2 profiles TRCs, used in +// rtengine::ProfileContent::toProfile() +// see https://github.com/Beep6581/RawTherapee/issues/5026 +// ----------------------------------------------------------------------------- +bool is_RTv2_profile(cmsHPROFILE profile) +{ + if (int(cmsGetProfileVersion(profile)) != 2) { + return false; + } + const cmsMLU *mlu = static_cast(cmsReadTag(profile, cmsSigDeviceMfgDescTag)); + if (!mlu) { + return false; + } + cmsUInt32Number sz = cmsMLUgetASCII(mlu, "en", "US", nullptr, 0); + if (!sz) { + return false; + } + std::vector buf(sz); + cmsMLUgetASCII(mlu, "en", "US", &buf[0], sz); + buf.back() = 0; // sanity + return strcmp(&buf[0], "RawTherapee") == 0; } + +bool get_RT_gamma_slope(cmsHPROFILE profile, double &gammatag, double &slopetag) +{ + const cmsMLU *modelDescMLU = static_cast(cmsReadTag(profile, cmsSigDeviceModelDescTag)); + if (modelDescMLU) { + cmsUInt32Number count = cmsMLUgetWide(modelDescMLU, "en", "US", nullptr, 0); + if (count) { + std::vector vbuf(count); + wchar_t *buffer = &vbuf[0]; + count = cmsMLUgetWide(modelDescMLU, "en", "US", buffer, count); + Glib::ustring modelDesc; +#if __SIZEOF_WCHAR_T__ == 2 + char *cModelDesc = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, nullptr, nullptr); // convert to utf-8 in a buffer allocated by glib + if (cModelDesc) { + modelDesc.assign(cModelDesc); + g_free(cModelDesc); + } +#else + modelDesc = utf32_to_utf8(buffer, count); +#endif + if (!modelDesc.empty()) { + 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()); + return true; + } + } + } + return false; +} + + +Glib::ustring get_profile_description(cmsHPROFILE profile) +{ + const cmsMLU *mlu = static_cast(cmsReadTag(profile, cmsSigProfileDescriptionTag)); + if (!mlu) { + return ""; + } + cmsUInt32Number sz = cmsMLUgetASCII(mlu, "en", "US", nullptr, 0); + if (!sz) { + return ""; + } + std::vector buf(sz); + cmsMLUgetASCII(mlu, "en", "US", &buf[0], sz); + buf.back() = 0; // sanity + return std::string(&buf[0]); +} + +} // namespace + + rtengine::ProfileContent::ProfileContent() = default; rtengine::ProfileContent::ProfileContent(const Glib::ustring& fileName) @@ -255,11 +334,52 @@ rtengine::ProfileContent::ProfileContent(cmsHPROFILE hProfile) cmsHPROFILE rtengine::ProfileContent::toProfile() const { + cmsHPROFILE profile = nullptr; + if (!data.empty()) { + profile = cmsOpenProfileFromMem(data.c_str(), data.size()); + // if this is a V2 profile generated by RawTherapee, we rebuild the + // TRC. See https://github.com/Beep6581/RawTherapee/issues/5026 and + // the references in there + if (profile && is_RTv2_profile(profile)) { + double gammatag, slopetag; + if (get_RT_gamma_slope(profile, gammatag, slopetag)) { + constexpr double eps = 0.000000001; // not divide by zero + double pwr = 1.0 / gammatag; + double ts = slopetag; + double slope = slopetag == 0 ? eps : slopetag; - return - !data.empty() - ? cmsOpenProfileFromMem(data.c_str(), data.size()) - : nullptr; + GammaValues g_b; //gamma parameters + Color::calcGamma(pwr, ts, 0, g_b); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 + cmsFloat64Number gammaParams[7]; //gamma parameters + gammaParams[4] = g_b[3] * ts; + gammaParams[0] = gammatag; + gammaParams[1] = 1. / (1.0 + g_b[4]); + gammaParams[2] = g_b[4] / (1.0 + g_b[4]); + gammaParams[3] = 1. / slope; + gammaParams[5] = 0.0; + gammaParams[6] = 0.0; + + cmsToneCurve* GammaTRC; + if (slopetag == 0.) { + //printf("gammatag=%f\n", gammatag); + GammaTRC = cmsBuildGamma(NULL, gammatag); + } else { + GammaTRC = cmsBuildParametricToneCurve(nullptr, 5, gammaParams); //5 = smoother than 4 + } + cmsWriteTag(profile, cmsSigRedTRCTag, GammaTRC); + cmsWriteTag(profile, cmsSigGreenTRCTag, GammaTRC); + cmsWriteTag(profile, cmsSigBlueTRCTag, GammaTRC); + cmsFreeToneCurve(GammaTRC); + + if (settings->verbose) { + std::cout << "ICCStore: rebuilt TRC for RTv2 profile " << get_profile_description(profile) << ": gamma=" << gammatag << ", slope=" << slopetag << std::endl; + } + } else if (settings->verbose) { + std::cout << "ICCStore: no gamma/slope info found for RTv2 profile " << get_profile_description(profile) << std::endl; + } + } + } + return profile; } const std::string& rtengine::ProfileContent::getData() const diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index da8e687ed..2cbfc3df3 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -303,82 +303,7 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i } Imagefloat* image = new Imagefloat(cw, ch); - - cmsHPROFILE oprof = nullptr; - - oprof = ICCStore::getInstance()->getProfile(icm.outputProfile); - Glib::ustring outtest = icm.outputProfile; - 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 - const double eps = 0.000000001; // not divide by zero - double gammatag = 2.4; - double slopetag = 12.92310; - cmsMLU *modelDescMLU = (cmsMLU*) (cmsReadTag(oprof, cmsSigDeviceModelDescTag)); - if (modelDescMLU) { - cmsUInt32Number count = cmsMLUgetWide(modelDescMLU, "en", "US", nullptr, 0); // get buffer length first - if (count) { - wchar_t *buffer = new wchar_t[count]; - count = cmsMLUgetWide(modelDescMLU, "en", "US", buffer, count); // now put the string in the buffer - Glib::ustring modelDesc; -#if __SIZEOF_WCHAR_T__ == 2 - char* cModelDesc = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, nullptr, nullptr); // convert to utf-8 in a buffer allocated by glib - if (cModelDesc) { - modelDesc.assign(cModelDesc); - g_free(cModelDesc); - } -#else - modelDesc = utf32_to_utf8(buffer, count); -#endif - delete [] buffer; - if (!modelDesc.empty()) { - 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 - cmsFloat64Number gammaParams[7]; //gamma parameters - gammaParams[4] = g_b[3] * ts; - gammaParams[0] = gammatag; - gammaParams[1] = 1. / (1.0 + g_b[4]); - gammaParams[2] = g_b[4] / (1.0 + g_b[4]); - gammaParams[3] = 1. / slope; - gammaParams[5] = 0.0; - gammaParams[6] = 0.0; - - cmsToneCurve* GammaTRC[3]; - if(slopetag == 0.) { - //printf("gammatag=%f\n", gammatag); - GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildGamma(NULL, gammatag); - } - else { - GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(nullptr, 5, gammaParams); //5 = smoother than 4 - } - cmsWriteTag(oprof, cmsSigRedTRCTag, GammaTRC[0]); - cmsWriteTag(oprof, cmsSigGreenTRCTag, GammaTRC[1]); - cmsWriteTag(oprof, cmsSigBlueTRCTag, GammaTRC[2]); - cmsFreeToneCurve(GammaTRC[0]); - } + cmsHPROFILE oprof = ICCStore::getInstance()->getProfile(icm.outputProfile); if (oprof) { cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; From c9817e369cd0b0d18ee95b2b65897c2fc7ca6d2d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 25 Nov 2018 14:45:28 +0100 Subject: [PATCH 5/7] Remove Imagefloat::ExecCMSTransform2, #5025 --- rtengine/imagefloat.cc | 55 +----------------------------------------- rtengine/imagefloat.h | 2 -- rtengine/iplab2rgb.cc | 2 +- 3 files changed, 2 insertions(+), 57 deletions(-) diff --git a/rtengine/imagefloat.cc b/rtengine/imagefloat.cc index 2dae72793..940806419 100644 --- a/rtengine/imagefloat.cc +++ b/rtengine/imagefloat.cc @@ -474,59 +474,6 @@ void Imagefloat::calcCroppedHistogram(const ProcParams ¶ms, float scale, LUT } -// Parallelized transformation; create transform with cmsFLAGS_NOCACHE! -void Imagefloat::ExecCMSTransform2(cmsHTRANSFORM hTransform, bool normalizeIn) -{ - - // LittleCMS cannot parallelize planar setups -- Hombre: LCMS2.4 can! But it we use this new feature, memory allocation - // have to be modified too to build temporary buffers that allow multi processor execution -#ifdef _OPENMP - #pragma omp parallel -#endif - { - AlignedBuffer pBuf(width * 3); - -#ifdef _OPENMP - #pragma omp for schedule(dynamic, 16) -#endif - - for (int y = 0; y < height; y++) - { - float *p = pBuf.data, *pR = r(y), *pG = g(y), *pB = b(y); - - if (normalizeIn) { - for (int x = 0; x < width; x++) { - *(p++) = *(pR++)/ 65535.f; - *(p++) = *(pG++)/ 65535.f; - *(p++) = *(pB++)/ 65535.f; - } - } else { - for (int x = 0; x < width; x++) { - *(p++) = *(pR++); - *(p++) = *(pG++); - *(p++) = *(pB++); - } - } - - cmsDoTransform (hTransform, pBuf.data, pBuf.data, width); - - p = pBuf.data; - pR = r(y); - pG = g(y); - pB = b(y); - - for (int x = 0; x < width; x++) { - *(pR++) = *(p++); - *(pG++) = *(p++); - *(pB++) = *(p++); - } - } // End of parallelization - } -} - - - - // Parallelized transformation; create transform with cmsFLAGS_NOCACHE! void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) { @@ -540,7 +487,7 @@ void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) AlignedBuffer pBuf(width * 3); #ifdef _OPENMP - #pragma omp for schedule(static) + #pragma omp for schedule(dynamic, 16) #endif for (int y = 0; y < height; y++) diff --git a/rtengine/imagefloat.h b/rtengine/imagefloat.h index 921f86b59..e1e5086b8 100644 --- a/rtengine/imagefloat.h +++ b/rtengine/imagefloat.h @@ -222,8 +222,6 @@ public: void normalizeFloatTo1(); void normalizeFloatTo65535(); void calcCroppedHistogram(const ProcParams ¶ms, float scale, LUTu & hist); - void ExecCMSTransform2(cmsHTRANSFORM hTransform, bool normalizeIn = true); - void ExecCMSTransform(cmsHTRANSFORM hTransform); void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy); }; diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 437144600..3240f06b1 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -644,7 +644,7 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags); lcmsMutex->unlock(); - dst->ExecCMSTransform2(hTransform, false); + dst->ExecCMSTransform(hTransform); cmsDeleteTransform(hTransform); if (normalizeOut) { From a3549a6247926ac05b96d3d66114a97e12ee61fc Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 25 Nov 2018 16:21:47 +0100 Subject: [PATCH 6/7] custom trc: another small speedup, #5025 --- rtengine/iplab2rgb.cc | 339 +++++++++++++++++++++--------------------- 1 file changed, 172 insertions(+), 167 deletions(-) diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 3240f06b1..38cebd17a 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -443,29 +443,26 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c { dx = dz = 1.0; } - double toxyz[3][3] = { + const float toxyz[3][3] = { { - (wprof[0][0] / (dx * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x - (wprof[0][1] / (dx * (normalizeIn ? 65535.0 : 1.0))), - (wprof[0][2] / (dx * (normalizeIn ? 65535.0 : 1.0))) + static_cast(wprof[0][0] / (dx * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50x + static_cast(wprof[0][1] / (dx * (normalizeIn ? 65535.0 : 1.0))), + static_cast(wprof[0][2] / (dx * (normalizeIn ? 65535.0 : 1.0))) }, { - (wprof[1][0] / (normalizeIn ? 65535.0 : 1.0)), - (wprof[1][1] / (normalizeIn ? 65535.0 : 1.0)), - (wprof[1][2] / (normalizeIn ? 65535.0 : 1.0)) + static_cast(wprof[1][0] / (normalizeIn ? 65535.0 : 1.0)), + static_cast(wprof[1][1] / (normalizeIn ? 65535.0 : 1.0)), + static_cast(wprof[1][2] / (normalizeIn ? 65535.0 : 1.0)) }, { - (wprof[2][0] / (dz * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50z - (wprof[2][1] / (dz * (normalizeIn ? 65535.0 : 1.0))), - (wprof[2][2] / (dz * (normalizeIn ? 65535.0 : 1.0))) + static_cast(wprof[2][0] / (dz * (normalizeIn ? 65535.0 : 1.0))), //I have suppressed / Color::D50z + static_cast(wprof[2][1] / (dz * (normalizeIn ? 65535.0 : 1.0))), + static_cast(wprof[2][2] / (dz * (normalizeIn ? 65535.0 : 1.0))) } }; - double pwr; - double ts; - ts = slpos; - + double pwr = 1.0 / gampos; + double ts = slpos; int five = mul; - pwr = 1.0 / gampos; if (gampos < 1.0) { pwr = gampos; @@ -474,7 +471,7 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c } // int select_temp = 1; //5003K - const double eps = 0.000000001; // not divide by zero + constexpr double eps = 0.000000001; // not divide by zero enum class ColorTemp { D50 = 5003, // for Widegamut, ProPhoto Best, Beta -> D50 @@ -484,173 +481,181 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c }; ColorTemp temp = ColorTemp::D50; - cmsHPROFILE oprofdef; float p[6]; //primaries - if (true) { - //primaries for 10 working profiles ==> output profiles - if (profile == "WideGamut") { - p[0] = 0.7350; //Widegamut primaries - p[1] = 0.2650; - p[2] = 0.1150; - p[3] = 0.8260; - p[4] = 0.1570; - p[5] = 0.0180; - } else if (profile == "Adobe RGB") { - p[0] = 0.6400; //Adobe primaries - p[1] = 0.3300; - p[2] = 0.2100; - p[3] = 0.7100; - p[4] = 0.1500; - p[5] = 0.0600; - temp = ColorTemp::D65; - } else if (profile == "sRGB") { - p[0] = 0.6400; // sRGB primaries - p[1] = 0.3300; - p[2] = 0.3000; - p[3] = 0.6000; - p[4] = 0.1500; - p[5] = 0.0600; - temp = ColorTemp::D65; - } else if (profile == "BruceRGB") { - p[0] = 0.6400; // Bruce primaries - p[1] = 0.3300; - p[2] = 0.2800; - p[3] = 0.6500; - p[4] = 0.1500; - p[5] = 0.0600; - temp = ColorTemp::D65; - } else if (profile == "Beta RGB") { - p[0] = 0.6888; // Beta primaries - p[1] = 0.3112; - p[2] = 0.1986; - p[3] = 0.7551; - p[4] = 0.1265; - p[5] = 0.0352; - } else if (profile == "BestRGB") { - p[0] = 0.7347; // Best primaries - p[1] = 0.2653; - p[2] = 0.2150; - p[3] = 0.7750; - p[4] = 0.1300; - p[5] = 0.0350; - } else if (profile == "Rec2020") { - p[0] = 0.7080; // Rec2020 primaries - p[1] = 0.2920; - p[2] = 0.1700; - p[3] = 0.7970; - p[4] = 0.1310; - p[5] = 0.0460; - temp = ColorTemp::D65; - } else if (profile == "ACESp0") { - p[0] = 0.7347; // ACES P0 primaries - p[1] = 0.2653; - p[2] = 0.0000; - p[3] = 1.0; - p[4] = 0.0001; - p[5] = -0.0770; - temp = ColorTemp::D60; - } else if (profile == "ACESp1") { - p[0] = 0.713; // ACES P1 primaries - p[1] = 0.293; - p[2] = 0.165; - p[3] = 0.830; - p[4] = 0.128; - p[5] = 0.044; - temp = ColorTemp::D60; - } else if (profile == "ProPhoto") { - p[0] = 0.7347; //ProPhoto and default primaries - p[1] = 0.2653; - p[2] = 0.1596; - p[3] = 0.8404; - p[4] = 0.0366; - p[5] = 0.0001; - } else { - p[0] = 0.7347; //default primaries always unused - p[1] = 0.2653; - p[2] = 0.1596; - p[3] = 0.8404; - p[4] = 0.0366; - p[5] = 0.0001; - } - - if (slpos == 0) { - slpos = eps; - } - - GammaValues g_a; //gamma parameters - int mode = 0; - Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 - - cmsCIExyY xyD; - - cmsCIExyYTRIPLE Primaries = { - {p[0], p[1], 1.0}, // red - {p[2], p[3], 1.0}, // green - {p[4], p[5], 1.0} // blue - }; - - cmsToneCurve* GammaTRC[3]; - cmsFloat64Number gammaParams[7]; - gammaParams[4] = g_a[3] * ts; - gammaParams[0] = gampos; - gammaParams[1] = 1. / (1.0 + g_a[4]); - gammaParams[2] = g_a[4] / (1.0 + g_a[4]); - gammaParams[3] = 1. / slpos; - gammaParams[5] = 0.0; - gammaParams[6] = 0.0; - // printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4); - - // 7 parameters for smoother curves - cmsWhitePointFromTemp(&xyD, (double)temp); - if (profile == "ACESp0") { - xyD = {0.32168, 0.33767, 1.0};//refine white point to avoid differences - } - - GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, five, gammaParams);//5 = more smoother than 4 - oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); - cmsFreeToneCurve(GammaTRC[0]); + //primaries for 10 working profiles ==> output profiles + if (profile == "WideGamut") { + p[0] = 0.7350; //Widegamut primaries + p[1] = 0.2650; + p[2] = 0.1150; + p[3] = 0.8260; + p[4] = 0.1570; + p[5] = 0.0180; + } else if (profile == "Adobe RGB") { + p[0] = 0.6400; //Adobe primaries + p[1] = 0.3300; + p[2] = 0.2100; + p[3] = 0.7100; + p[4] = 0.1500; + p[5] = 0.0600; + temp = ColorTemp::D65; + } else if (profile == "sRGB") { + p[0] = 0.6400; // sRGB primaries + p[1] = 0.3300; + p[2] = 0.3000; + p[3] = 0.6000; + p[4] = 0.1500; + p[5] = 0.0600; + temp = ColorTemp::D65; + } else if (profile == "BruceRGB") { + p[0] = 0.6400; // Bruce primaries + p[1] = 0.3300; + p[2] = 0.2800; + p[3] = 0.6500; + p[4] = 0.1500; + p[5] = 0.0600; + temp = ColorTemp::D65; + } else if (profile == "Beta RGB") { + p[0] = 0.6888; // Beta primaries + p[1] = 0.3112; + p[2] = 0.1986; + p[3] = 0.7551; + p[4] = 0.1265; + p[5] = 0.0352; + } else if (profile == "BestRGB") { + p[0] = 0.7347; // Best primaries + p[1] = 0.2653; + p[2] = 0.2150; + p[3] = 0.7750; + p[4] = 0.1300; + p[5] = 0.0350; + } else if (profile == "Rec2020") { + p[0] = 0.7080; // Rec2020 primaries + p[1] = 0.2920; + p[2] = 0.1700; + p[3] = 0.7970; + p[4] = 0.1310; + p[5] = 0.0460; + temp = ColorTemp::D65; + } else if (profile == "ACESp0") { + p[0] = 0.7347; // ACES P0 primaries + p[1] = 0.2653; + p[2] = 0.0000; + p[3] = 1.0; + p[4] = 0.0001; + p[5] = -0.0770; + temp = ColorTemp::D60; + } else if (profile == "ACESp1") { + p[0] = 0.713; // ACES P1 primaries + p[1] = 0.293; + p[2] = 0.165; + p[3] = 0.830; + p[4] = 0.128; + p[5] = 0.044; + temp = ColorTemp::D60; + } else if (profile == "ProPhoto") { + p[0] = 0.7347; //ProPhoto and default primaries + p[1] = 0.2653; + p[2] = 0.1596; + p[3] = 0.8404; + p[4] = 0.0366; + p[5] = 0.0001; + } else { + p[0] = 0.7347; //default primaries always unused + p[1] = 0.2653; + p[2] = 0.1596; + p[3] = 0.8404; + p[4] = 0.0366; + p[5] = 0.0001; } + if (slpos == 0) { + slpos = eps; + } + + GammaValues g_a; //gamma parameters + int mode = 0; + Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 + + cmsCIExyY xyD; + + cmsCIExyYTRIPLE Primaries = { + {p[0], p[1], 1.0}, // red + {p[2], p[3], 1.0}, // green + {p[4], p[5], 1.0} // blue + }; + + cmsToneCurve* GammaTRC[3]; + cmsFloat64Number gammaParams[7]; + gammaParams[4] = g_a[3] * ts; + gammaParams[0] = gampos; + gammaParams[1] = 1. / (1.0 + g_a[4]); + gammaParams[2] = g_a[4] / (1.0 + g_a[4]); + gammaParams[3] = 1. / slpos; + gammaParams[5] = 0.0; + gammaParams[6] = 0.0; + // printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4); + + // 7 parameters for smoother curves + cmsWhitePointFromTemp(&xyD, (double)temp); + if (profile == "ACESp0") { + xyD = {0.32168, 0.33767, 1.0};//refine white point to avoid differences + } + + GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, five, gammaParams);//5 = more smoother than 4 + const cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); + cmsFreeToneCurve(GammaTRC[0]); + if (oprofdef) { - #pragma omp parallel for if (multiThread) - - for (int i = 0; i < ch; i++) { - float* rr = src->r(i); - float* rg = src->g(i); - float* rb = src->b(i); - - float* xa = (float*)dst->r(i); - float* ya = (float*)dst->g(i); - float* za = (float*)dst->b(i); - - for (int j = 0; j < cw; j++) { - float r1 = rr[j]; - float g1 = rg[j]; - float b1 = rb[j]; - - xa[j] = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; - ya[j] = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; - za[j] = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; - } - } - cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; - - - lcmsMutex->lock(); cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile(); + lcmsMutex->lock(); // 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); lcmsMutex->unlock(); +#ifdef _OPENMP + #pragma omp parallel if (multiThread) +#endif + { + AlignedBuffer pBuf(cw * 3); - dst->ExecCMSTransform(hTransform); +#ifdef _OPENMP + #pragma omp for schedule(dynamic, 16) +#endif + + for (int i = 0; i < ch; i++) { + float *p = pBuf.data; + float* rr = src->r(i); + float* rg = src->g(i); + float* rb = src->b(i); + + float* xa = (float*)dst->r(i); + float* ya = (float*)dst->g(i); + float* za = (float*)dst->b(i); + + for (int j = 0; j < cw; j++) { + float r1 = rr[j]; + float g1 = rg[j]; + float b1 = rb[j]; + + *(p++) = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; + *(p++) = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; + *(p++) = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; + } + cmsDoTransform (hTransform, pBuf.data, pBuf.data, cw); + p = pBuf.data; + for (int x = 0; x < cw; x++) { + *(xa++) = *(p++); + *(ya++) = *(p++); + *(za++) = *(p++); + } + } + } cmsDeleteTransform(hTransform); if (normalizeOut) { dst->normalizeFloatTo65535(); } - } } From 4f89286b986f5d5b22783eac63f54b114830eb4f Mon Sep 17 00:00:00 2001 From: heckflosse Date: Sun, 25 Nov 2018 17:53:49 +0100 Subject: [PATCH 7/7] ImProcFunctions::workingtrc(): cleanup and another small speedup, #5025 --- rtengine/improcfun.h | 2 +- rtengine/iplab2rgb.cc | 72 ++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 43 deletions(-) diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 470922508..6684c8ee2 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -350,7 +350,7 @@ public: Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true); Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm); // CieImage *ciec; - void workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos, bool normalizeIn = true, bool normalizeOut = true); + void workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, bool normalizeIn = true, bool normalizeOut = true); bool transCoord(int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); bool transCoord(int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr); diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc index 38cebd17a..9e47558ca 100644 --- a/rtengine/iplab2rgb.cc +++ b/rtengine/iplab2rgb.cc @@ -432,11 +432,9 @@ Imagefloat* ImProcFunctions::lab2rgbOut(LabImage* lab, int cx, int cy, int cw, i } -void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, Glib::ustring profile, double gampos, double slpos, bool normalizeIn, bool normalizeOut) +void ImProcFunctions::workingtrc(const Imagefloat* src, Imagefloat* dst, int cw, int ch, int mul, const Glib::ustring &profile, double gampos, double slpos, bool normalizeIn, bool normalizeOut) { - TMatrix wprof; - - wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); + const TMatrix wprof = ICCStore::getInstance()->workingSpaceMatrix(params->icm.workingProfile); double dx = Color::D50x; double dz = Color::D50z; @@ -574,18 +572,10 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c } GammaValues g_a; //gamma parameters - int mode = 0; + constexpr int mode = 0; Color::calcGamma(pwr, ts, mode, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2 - cmsCIExyY xyD; - cmsCIExyYTRIPLE Primaries = { - {p[0], p[1], 1.0}, // red - {p[2], p[3], 1.0}, // green - {p[4], p[5], 1.0} // blue - }; - - cmsToneCurve* GammaTRC[3]; cmsFloat64Number gammaParams[7]; gammaParams[4] = g_a[3] * ts; gammaParams[0] = gampos; @@ -597,65 +587,63 @@ void ImProcFunctions::workingtrc(Imagefloat* src, Imagefloat* dst, int cw, int c // printf("ga0=%f ga1=%f ga2=%f ga3=%f ga4=%f\n", ga0, ga1, ga2, ga3, ga4); // 7 parameters for smoother curves + cmsCIExyY xyD; cmsWhitePointFromTemp(&xyD, (double)temp); if (profile == "ACESp0") { xyD = {0.32168, 0.33767, 1.0};//refine white point to avoid differences } + cmsToneCurve* GammaTRC[3]; GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, five, gammaParams);//5 = more smoother than 4 + + const cmsCIExyYTRIPLE Primaries = { + {p[0], p[1], 1.0}, // red + {p[2], p[3], 1.0}, // green + {p[4], p[5], 1.0} // blue + }; const cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); + cmsFreeToneCurve(GammaTRC[0]); if (oprofdef) { - cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; - cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile(); + constexpr cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE; + const cmsHPROFILE iprof = ICCStore::getInstance()->getXYZProfile(); lcmsMutex->lock(); - // 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); + const cmsHTRANSFORM hTransform = cmsCreateTransform(iprof, TYPE_RGB_FLT, oprofdef, TYPE_RGB_FLT, params->icm.outputIntent, flags); lcmsMutex->unlock(); #ifdef _OPENMP #pragma omp parallel if (multiThread) #endif { AlignedBuffer pBuf(cw * 3); + const float normalize = normalizeOut ? 65535.f : 1.f; #ifdef _OPENMP - #pragma omp for schedule(dynamic, 16) + #pragma omp for schedule(dynamic, 16) nowait #endif - for (int i = 0; i < ch; i++) { + for (int i = 0; i < ch; ++i) { float *p = pBuf.data; - float* rr = src->r(i); - float* rg = src->g(i); - float* rb = src->b(i); + for (int j = 0; j < cw; ++j) { + const float r = src->r(i, j); + const float g = src->g(i, j); + const float b = src->b(i, j); - float* xa = (float*)dst->r(i); - float* ya = (float*)dst->g(i); - float* za = (float*)dst->b(i); - - for (int j = 0; j < cw; j++) { - float r1 = rr[j]; - float g1 = rg[j]; - float b1 = rb[j]; - - *(p++) = toxyz[0][0] * r1 + toxyz[0][1] * g1 + toxyz[0][2] * b1; - *(p++) = toxyz[1][0] * r1 + toxyz[1][1] * g1 + toxyz[1][2] * b1; - *(p++) = toxyz[2][0] * r1 + toxyz[2][1] * g1 + toxyz[2][2] * b1; + *(p++) = toxyz[0][0] * r + toxyz[0][1] * g + toxyz[0][2] * b; + *(p++) = toxyz[1][0] * r + toxyz[1][1] * g + toxyz[1][2] * b; + *(p++) = toxyz[2][0] * r + toxyz[2][1] * g + toxyz[2][2] * b; } - cmsDoTransform (hTransform, pBuf.data, pBuf.data, cw); p = pBuf.data; - for (int x = 0; x < cw; x++) { - *(xa++) = *(p++); - *(ya++) = *(p++); - *(za++) = *(p++); + cmsDoTransform(hTransform, p, p, cw); + for (int j = 0; j < cw; ++j) { + dst->r(i, j) = *(p++) * normalize; + dst->g(i, j) = *(p++) * normalize; + dst->b(i, j) = *(p++) * normalize; } } } cmsDeleteTransform(hTransform); - if (normalizeOut) { - dst->normalizeFloatTo65535(); - } } }