* Restore settings and options * Clean code and windows.yml * Gui improvment * Fixed wrong value maxicam * Change GUI TRC and Log encoding and sigmoid * Clean code locallabtools2 * Fomat locallabtools2 * New calcualtion gray when using Q * Improve sigmoid Q with meanQ * Change labels and tooltip * Change DR with log * Change location GUI TRC * Change GUI sigmoid hide - show * Fixed bug with trc * Added whites to TRC & whites * Small modification whites - comment code * Change GUI and selection for sigmoid and log encoding Q * Change yml worksflow * Added cat to workingtrc rtthumbnail * Delete entries in defualt languages * Blacks and whites distribution * Change tooltips * Fixed some issues * Change GUI hide to set_sensitive * first step white and black log encoding * GUI Labels - tooltips * Compress brightness log encoding * Change compression threshold * Clean procparams * Improve GUI and threshold compression * Improvment GUI and tooltips * First step primaries cam16 * Primaries loc step 2 * Primaries loc step 3 * jdcmax primaries - format iplab2rgb * Improve GUI * Beta RGB primaries and message * Change tooltips * Change order prim * CIExy diagram step 1 * CIExy step 2 * CIExy step 2 * CIExy diagram step 4 * CIExy diagram step 5 * Change improccordinator and locallabtool2s listener * Forgoten delete in improccordinator * Disable setListener * Improve GUI and behavior TRC and Primaries * TRC primaries - illuminant step 1 * TRC primaries - illuminant step 2 * TRC primaries - illuminant step 3 * TRC primaries - illuminant step 4 * Gamut control - remove old listener and added listener locallabcieLC * publish pre dev labels windows appimage * publish pre dev labels windows appimage [] * Move log encoding cie - step 1 * Step 2 * Move Log encoding CIE and improve GUI step 3 * Pre Ciecam midtones step 1 * Mid tones step 2 and tooltips * Forgoten label and tooltips * Improve tooltips - and change yml files * Include repository in appimage and windows.yml - change labels * Forgotten surroundcie in procparams.cc * Improve GUI with expander - clean code * Change tooltip * Clean locallabtools2 - improve Jpro * Bypass Ciecam step 1 * step 2 * Step 3 * Change settings - improve GUI * Clean code * Improve sigmoid cam16 * Improve sigmoid cam16 * Added illuminant E to illmethod * Change iccmatrices * Working profile JDCmax stdA and Abstract Profile * Pre-ciecam JDCmax stdA * Abstract profile - cat method step 1 * Step 3 * Step 4 and various changes * Enable default gamutcontrol - improve GUI * Refine color pre-ciecam * Step 2 * step 3 * Step - 4 * Refine colors Abstract profiles * Expander true Abstract Profile * Clean and comment code * Tooltip pre-ciecam * Change tooltips * Improve GUI free primaries * Labgrid dominant color * Shift dominant color step 1 * Shift xy dominant color * History msg shift * Fixed various bad behavior - change scalrefi * Improve behavior DR vs deltaE - log encoding and pre-ciecam * Limited reduce deltaE to 1 - comment code * Improve behavior TIF/JPG * Forgotten code * Various small changes to refinement color pre-ciecam * Foramt iplab2rgb and simpleprocees - small change meanx meany * Bad behavior with simpleprocess abstract profile and pre-ciecam * Re-enable code for simpleprocess * Iprove iplab2rgb * Improve GUI if selection Jz * provis with precision * Chnage GUI log encoding basic - improve shiftxl shiftyl pre-ciecam * Improve GUI with expanders * Change location pre-ciecam expander * Change label tooltip pre-ciecam * Improve white distribution and equalizer * Bad behavior Source data adjustments * Comment code * Improve Dynamic Range Compression - for some images with very high DR * Clean code * Improve TM fattal with saturation control in LA * saturation control fattal LA * RE-order paramsedit * Change local contrast in LA - log encoding and Cam16 * LA settings avoidcolorshift XYZabsolute * Change GUI precision blackEv WhiteEv BlackEvjz WhiteEvjz * Check button smoothcie - smooth highlights * Change order midtones - log encoding - other method smooth * Change maximum gamma in TRC cam16 * Change maximum slope in TRC cam16 * refine smooth highlights * Small improvment - comment code * Bad behavior - black screen - in Cam16 * setLogscale for slopjcie * Change source data GUI - PQ and other DR functions * PQ mode advanced - adjustments and tooltip * Comment and clean code * Simplified GUI in Basic mode - Source Data Adjustments * Added primaries to source date adjustements - fix basic problem * GUI graduaded filter cie cam16 * Graduated filter - LA Color appearance * More illuminant cam16 - D120 - Tungsten 2000K - Tungsten 1500K * Abstract profile ICM - shift x - shift y * Frame color dominant Abstract profile * Frame color dominant Abstract profile * Illuminant E - abstract profile * Abstact profile - midtones * Abstrcat profile - smooth highlights checkbutton * Abstract Profile - Smooth highligts rtengine * Bad behavior LA gamut - re-enabled Munsell in settings * adapts Abstract profile and auto-match tone curve * Change chromaticity curve c(h) - ppversion 351 and procparams * icmpanel fixed bad wmidtcie * Change in procparams assignfromkeyfile color Management * Remove message in console * Missing code procparams.cc wcat * Clean message in console * Disable ppversion 351 - surround extremely dark * Choice surround scene Disable ciecam * Improve GUI for surround Disable Ciecam * Small change gamutcontrol - message g0..g5 verbose * Remove gautcontrol on limits * Strength log encoding - Source data adjustments * Fixed genral bug in lacam16n - bad behavior color * Checkbutton saturation control - Cam16 log encoding * Change default saturation controle log encoding - false * GUI LA Log encoding - Strength - saturation control - part 1 * Checkbox saturation control LA Log encoding * Change repartition GUI brightnees - hue - chroma * Hide primaries and illuminant in standard mode * Merge with dev 2 * reduces sigmoid Q contrast * Provisory disable Sigmoid Q * Re-enable sigmoid function complexity mode * Re-enable log encoding Q - with Ciecam * GUI improvments - small code improvments * Change tooltip * Simplify GUI mode Basic - Standard - added tooltip * Change tooltip - LA settings - Avoid color shift * hope to fix the bug between Jz and Cam16 * Another change for Jz - format astyle locallabtool2.cc * Clean code GUI - remove Zcam * Change label in Recovery based on luminance mask * Reduces minimum spot size from 2 to 1.5 * Improve behavior GUI with Jzczhz * Clean code iplocallab.cc * Small improvement ciecam02.cc * Fixed bad behvior GUI and code between Cam16 and Jzczhz * Improve Jz and surround effects * Improve Jz and Local contrast Cam16 & Jz taking account surround * Disable local contrast if cam16 and not ciecam surround * Restore epsil 0.001 loccont * Improve local contrast when surround low and Jz * Clean code locallabtool2 - weakened a little Local Contrast in connection with surround * Remove Laplacian threshold in Cam16 and JzCzHz mask * Simplify Mask for JzCzHz * Enable choice complexity mask in mode advanced * Solved bad behavior GUI masks * Optimize GUI mask Jz and cam16 * Change 3 icon .png without png * Remove wrong message in console without problem * Remove warning with & in some tooltips and TP_WBALANCE_AUTO_HEADER * Smoothcie Method GUI * Replace checkbutton smooth highlight bya combobox * Improve behavior GUI - CIECAM - advanced - tempout and greenout * Fixed - I hope - crash when delete spot and cam16 * Clean code with maxcam and dependencies * Added Smooth highlight rolloff or not * Improve smooth lights - gamma mode only - standard and advanced - gray balance * Improve Smoothing lights - take into account the 2 Yb * Change tooltip * Chnage wrong lable scope => slope * Clean and comment code * Reduces the effect of - Smoothing light -Ev mode - Small change range Slope * Scale Yb scene white whiteEv * Hide Scale in some GUI cases * Clean comment code Smotth and TM function * Change GUI - Smooth highlights and tone mapping - allows also Basic * Change labels * Change tooltip * Remove arrow.cur in windows.yml as suggested by Lawrence37 * Reverse last changes * Change limits slope based in SDA * Clean locallabtools2.cc * Set minimum slope based to 0.6 * Change label highlight * Change listener scene parameters to GUI * Clean code sine changes listener * Limits Blackev Whiteev values in slope base to avoid crash * Change a little limits BlackEv WhiteEv * Small changes in console - remove warnings * Change XYZ relative - avoid color shift * Improve gamutmap * re build gamutmap
383 lines
11 KiB
C++
383 lines
11 KiB
C++
#include "color.h"
|
|
#include "guidedfilter.h"
|
|
#include "iccstore.h"
|
|
#include "imagefloat.h"
|
|
#include "improcfun.h"
|
|
#include "sleef.h"
|
|
#include "StopWatch.h"
|
|
|
|
|
|
namespace
|
|
{
|
|
|
|
const std::vector<std::array<float, 3>> colormap = {
|
|
{0.5f, 0.f, 0.5f},
|
|
{0.5f, 0.f, 0.5f},
|
|
{0.5f, 0.f, 0.5f},
|
|
{0.5f, 0.f, 0.5f},
|
|
{0.5f, 0.f, 0.5f}, // blacks
|
|
{0.f, 0.f, 1.f}, // shadows
|
|
{0.5f, 0.5f, 0.5f}, // midtones
|
|
{1.f, 1.f, 0.f}, // highlights
|
|
{1.f, 0.f, 0.f}, // whites
|
|
{1.f, 0.f, 0.f},
|
|
{1.f, 0.f, 0.f},
|
|
{1.f, 0.f, 0.f},
|
|
{1.f, 0.f, 0.f},
|
|
{1.f, 0.f, 0.f},
|
|
{1.f, 0.f, 0.f}
|
|
|
|
};
|
|
|
|
|
|
void toneEqualizer(
|
|
array2D<float> &R, array2D<float> &G, array2D<float> &B,
|
|
const rtengine::ToneEqualizerParams ¶ms,
|
|
const Glib::ustring &workingProfile,
|
|
double scale,
|
|
bool multithread)
|
|
// adapted from the tone equalizer of darktable
|
|
/*
|
|
Copyright 2019 Alberto Griggio <alberto.griggio@gmail.com>
|
|
Small adaptation to Local Adjustment 10 2019 Jacques Desmis <jdesmis@gmail.com>
|
|
This file is part of darktable,
|
|
copyright (c) 2018 Aurelien Pierre.
|
|
|
|
darktable 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.
|
|
|
|
darktable 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 darktable. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
{
|
|
// BENCHFUN
|
|
|
|
const int W = R.getWidth();
|
|
const int H = R.getHeight();
|
|
array2D<float> Y(W, H);
|
|
|
|
const auto log2 =
|
|
[](float x) -> float {
|
|
static const float l2 = xlogf(2);
|
|
return xlogf(x) / l2;
|
|
};
|
|
|
|
const auto exp2 =
|
|
[](float x) -> float {
|
|
return pow_F(2.f, x);
|
|
};
|
|
// Build the luma channels: band-pass filters with gaussian windows of
|
|
// std 2 EV, spaced by 2 EV
|
|
const float centers[15] = {
|
|
-16.0f, -14.0f, -12.0f, -10.0f, -8.0f, -6.0f,
|
|
-4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f
|
|
};
|
|
|
|
const auto conv = [&](int v, float lo, float hi) -> float {
|
|
const float f = v < 0 ? lo : hi;
|
|
return exp2(float(v) / 100.f * f);
|
|
};
|
|
const float factors[15] = {
|
|
conv(params.bands[0], 2.f, 3.f), // -16 EV
|
|
conv(params.bands[0], 2.f, 3.f), // -14 EV
|
|
conv(params.bands[0], 2.f, 3.f), // -12 EV
|
|
conv(params.bands[0], 2.f, 3.f), // -10 EV
|
|
conv(params.bands[0], 2.f, 3.f), // -8 EV
|
|
conv(params.bands[1], 2.f, 3.f), // -6 EV
|
|
conv(params.bands[2], 2.5f, 2.5f), // -4 EV
|
|
conv(params.bands[3], 3.f, 2.f), // -2 EV
|
|
conv(params.bands[4], 3.f, 2.f), // 0 EV
|
|
conv(params.bands[4], 3.f, 2.f), // 2 EV
|
|
conv(params.bands[4], 3.f, 2.f), // 4 EV
|
|
conv(params.bands[4], 3.f, 2.f), // 6 EV
|
|
// this settings under are very rarely used...images with very high DR - I add a slider, but it's not the goal: the goal is white distribution (in very rare case)
|
|
// I have not change "main" Tone Equalizer.
|
|
conv(params.bands[5], 3.f, 2.f), // 8 EV Added for white distribution (Cam16 and Log encode) and images with very high DR
|
|
conv(params.bands[5], 3.f, 2.f), // 10 EV Added for white distribution(Cam16 and Log encode) and images with very high DR
|
|
conv(params.bands[5], 3.f, 2.f) // 12 EV Added for white distribution(Cam16 and Log encode) and images with very high DR
|
|
};
|
|
|
|
rtengine::TMatrix ws = rtengine::ICCStore::getInstance()->workingSpaceMatrix(workingProfile);
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp parallel for if (multithread)
|
|
#endif
|
|
for (int y = 0; y < H; ++y) {
|
|
for (int x = 0; x < W; ++x) {
|
|
Y[y][x] = rtengine::Color::rgbLuminance(R[y][x], G[y][x], B[y][x], ws);
|
|
}
|
|
}
|
|
|
|
int detail = rtengine::LIM(params.regularization + 5, 0, 5);
|
|
int radius = detail / scale + 0.5;
|
|
float epsilon2 = 0.01f + 0.002f * rtengine::max(detail - 3, 0);
|
|
|
|
if (radius > 0) {
|
|
rtengine::guidedFilterLog(10.f, Y, radius, epsilon2, multithread);
|
|
}
|
|
|
|
if (params.regularization > 0) {
|
|
array2D<float> Y2(W, H);
|
|
constexpr float base_epsilon = 0.02f;
|
|
constexpr float base_posterization = 5.f;
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp parallel for if (multithread)
|
|
#endif
|
|
for (int y = 0; y < H; ++y) {
|
|
for (int x = 0; x < W; ++x) {
|
|
float l = rtengine::LIM(log2(rtengine::max(Y[y][x], 1e-9f)), centers[0], centers[13]);
|
|
float ll = round(l * base_posterization) / base_posterization;
|
|
Y2[y][x] = Y[y][x];
|
|
Y[y][x] = exp2(ll);
|
|
}
|
|
}
|
|
|
|
radius = 350.0 / scale;
|
|
epsilon2 = base_epsilon / float(6 - rtengine::min(params.regularization, 5));
|
|
rtengine::guidedFilter(Y2, Y, Y, radius, epsilon2, multithread);
|
|
}
|
|
|
|
const auto gauss =
|
|
[](float b, float x) -> float {
|
|
return xexpf((-rtengine::SQR(x - b) / 4.0f));
|
|
};
|
|
|
|
// For every pixel luminance, the sum of the gaussian masks
|
|
float w_sum = 0.f;
|
|
|
|
for (int i = 0; i < 15; ++i) {
|
|
w_sum += gauss(centers[i], 0.f);
|
|
}
|
|
|
|
constexpr float luma_lo = -14.f;
|
|
constexpr float luma_hi = 6.f;
|
|
|
|
const auto process_pixel =
|
|
[&](float y) -> float {
|
|
// convert to log space
|
|
const float luma = rtengine::LIM(log2(rtengine::max(y, 0.f)), luma_lo, luma_hi);
|
|
|
|
// build the correction as the sum of the contribution of each
|
|
// luminance channel to current pixel
|
|
float correction = 0.0f;
|
|
|
|
for (int c = 0; c < 15; ++c)
|
|
{
|
|
correction += gauss(centers[c], luma) * factors[c];
|
|
}
|
|
|
|
correction /= w_sum;
|
|
|
|
return correction;
|
|
};
|
|
|
|
std::vector<std::array<float, 3>> cur_colormap;
|
|
if (params.show_colormap) {
|
|
rtengine::lcmsMutex->lock();
|
|
cmsHPROFILE in = rtengine::ICCStore::getInstance()->getsRGBProfile();
|
|
cmsHPROFILE out = rtengine::ICCStore::getInstance()->workingSpace(workingProfile);
|
|
cmsHTRANSFORM xform = cmsCreateTransform(in, TYPE_RGB_FLT, out, TYPE_RGB_FLT, INTENT_RELATIVE_COLORIMETRIC, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
|
|
rtengine::lcmsMutex->unlock();
|
|
|
|
for (auto &c : colormap) {
|
|
cur_colormap.push_back(c);
|
|
auto &cc = cur_colormap.back();
|
|
cmsDoTransform(xform, &cc[0], &cc[0], 1);
|
|
}
|
|
|
|
cmsDeleteTransform(xform);
|
|
}
|
|
|
|
const auto process_colormap =
|
|
[&](float y) -> std::array<float, 3>
|
|
{
|
|
std::array<float, 3> ret = { 0.f, 0.f, 0.f };
|
|
|
|
// convert to log space
|
|
const float luma = rtengine::LIM(log2(rtengine::max(y, 0.f)), luma_lo, luma_hi);
|
|
|
|
// build the correction as the sum of the contribution of each
|
|
// luminance channel to current pixel
|
|
for (int c = 0; c < 15; ++c) {
|
|
float w = gauss(centers[c], luma);
|
|
for (int i = 0; i < 3; ++i) {
|
|
ret[i] += w * cur_colormap[c][i];
|
|
}
|
|
}
|
|
for (int i = 0; i < 3; ++i) {
|
|
ret[i] = rtengine::LIM01(ret[i] / w_sum);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
|
|
#ifdef __SSE2__
|
|
vfloat vfactors[15];
|
|
vfloat vcenters[15];
|
|
|
|
for (int i = 0; i < 15; ++i) {
|
|
vfactors[i] = F2V(factors[i]);
|
|
vcenters[i] = F2V(centers[i]);
|
|
}
|
|
|
|
const auto vgauss =
|
|
[](vfloat b, vfloat x) -> vfloat {
|
|
static const vfloat fourv = F2V(4.f);
|
|
return xexpf((-rtengine::SQR(x - b) / fourv));
|
|
};
|
|
|
|
vfloat zerov = F2V(0.f);
|
|
vfloat vw_sum = F2V(w_sum);
|
|
|
|
const vfloat vluma_lo = F2V(luma_lo);
|
|
const vfloat vluma_hi = F2V(luma_hi);
|
|
const vfloat xlog2v = F2V(xlogf(2.f));
|
|
|
|
const auto vprocess_pixel =
|
|
[&](vfloat y) -> vfloat {
|
|
const vfloat luma = vminf(vmaxf(xlogf(vmaxf(y, zerov)) / xlog2v, vluma_lo), vluma_hi);
|
|
|
|
vfloat correction = zerov;
|
|
|
|
for (int c = 0; c < 15; ++c)
|
|
{
|
|
correction += vgauss(vcenters[c], luma) * vfactors[c];
|
|
}
|
|
|
|
correction /= vw_sum;
|
|
|
|
return correction;
|
|
};
|
|
|
|
|
|
vfloat v1 = F2V(1.f);
|
|
vfloat v65535 = F2V(65535.f);
|
|
#endif // __SSE2__
|
|
|
|
|
|
if (params.show_colormap) {
|
|
LUTf lut_r(65537), lut_g(65537), lut_b(65537);
|
|
for (int i = 0; i < 65536; ++i) {
|
|
float y = float(i)/65535.f;
|
|
auto rgb = process_colormap(y);
|
|
lut_r[i] = rgb[0];
|
|
lut_g[i] = rgb[1];
|
|
lut_b[i] = rgb[2];
|
|
}
|
|
lut_r[65536] = cur_colormap.back()[0];
|
|
lut_g[65536] = cur_colormap.back()[1];
|
|
lut_b[65536] = cur_colormap.back()[2];
|
|
|
|
#ifdef _OPENMP
|
|
# pragma omp parallel for if (multithread)
|
|
#endif
|
|
for (int y = 0; y < H; ++y) {
|
|
for (int x = 0; x < W; ++x) {
|
|
float cY = Y[y][x] * 65535.f;
|
|
R[y][x] = lut_r[cY];
|
|
G[y][x] = lut_g[cY];
|
|
B[y][x] = lut_b[cY];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
LUTf lut(65536);
|
|
|
|
for (int i = 0; i < 65536; ++i) {
|
|
float y = float(i) / 65535.f;
|
|
float c = process_pixel(y);
|
|
lut[i] = c;
|
|
}
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp parallel for if (multithread)
|
|
#endif
|
|
for (int y = 0; y < H; ++y) {
|
|
int x = 0;
|
|
|
|
|
|
#ifdef __SSE2__
|
|
|
|
for (; x < W - 3; x += 4) {
|
|
vfloat cY = LVFU(Y[y][x]);
|
|
vmask m = vmaskf_gt(cY, v1);
|
|
vfloat corr;
|
|
|
|
if (_mm_movemask_ps((vfloat)m)) {
|
|
corr = vprocess_pixel(cY);
|
|
} else {
|
|
corr = lut[cY * v65535];
|
|
}
|
|
|
|
STVF(R[y][x], LVF(R[y][x]) * corr);
|
|
STVF(G[y][x], LVF(G[y][x]) * corr);
|
|
STVF(B[y][x], LVF(B[y][x]) * corr);
|
|
}
|
|
|
|
#endif // __SSE2__
|
|
|
|
for (; x < W; ++x) {
|
|
float cY = Y[y][x];
|
|
float corr = cY > 1.f ? process_pixel(cY) : lut[cY * 65535.f];
|
|
R[y][x] *= corr;
|
|
G[y][x] *= corr;
|
|
B[y][x] *= corr;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
namespace rtengine
|
|
{
|
|
|
|
void ImProcFunctions::toneEqualizer(
|
|
Imagefloat *rgb,
|
|
const ToneEqualizerParams ¶ms,
|
|
const Glib::ustring &workingProfile,
|
|
double scale,
|
|
bool multiThread)
|
|
{
|
|
if (!params.enabled) {
|
|
return;
|
|
}
|
|
|
|
BENCHFUN
|
|
|
|
const float gain = 1.f / 65535.f * std::pow(2.f, -params.pivot);
|
|
|
|
rgb->multiply(gain, multiThread);
|
|
|
|
const int W = rgb->getWidth();
|
|
const int H = rgb->getHeight();
|
|
|
|
array2D<float> R(W, H, rgb->r.ptrs, ARRAY2D_BYREFERENCE);
|
|
array2D<float> G(W, H, rgb->g.ptrs, ARRAY2D_BYREFERENCE);
|
|
array2D<float> B(W, H, rgb->b.ptrs, ARRAY2D_BYREFERENCE);
|
|
|
|
::toneEqualizer(R, G, B, params, workingProfile, scale, multiThread);
|
|
|
|
rgb->multiply(params.show_colormap ? 65535.f : 1.f/gain, multiThread);
|
|
}
|
|
|
|
void ImProcFunctions::toneEqualizer(Imagefloat *rgb)
|
|
{
|
|
toneEqualizer(rgb, params->toneEqualizer, params->icm.workingProfile, scale, multiThread);
|
|
}
|
|
|
|
}
|