merged 'colortoning-labregions' into 'dev'

This commit is contained in:
Alberto Griggio 2018-11-01 15:18:11 +01:00
commit 5e30b5ac58
18 changed files with 953 additions and 90 deletions

View File

@ -402,7 +402,7 @@ HISTORY_MSG_145;Microcontrast - Uniformity
HISTORY_MSG_146;Edge sharpening HISTORY_MSG_146;Edge sharpening
HISTORY_MSG_147;ES - Luminance only HISTORY_MSG_147;ES - Luminance only
HISTORY_MSG_148;Microcontrast HISTORY_MSG_148;Microcontrast
HISTORY_MSG_149;Microcontrast - 3×3 matrix HISTORY_MSG_149;Microcontrast - 33 matrix
HISTORY_MSG_150;Post-demosaic artifact/noise red. HISTORY_MSG_150;Post-demosaic artifact/noise red.
HISTORY_MSG_151;Vibrance HISTORY_MSG_151;Vibrance
HISTORY_MSG_152;Vib - Pastel tones HISTORY_MSG_152;Vib - Pastel tones
@ -732,6 +732,14 @@ HISTORY_MSG_492;RGB Curves
HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_493;L*a*b* Adjustments
HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors
HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction
HISTORY_MSG_COLORTONING_LABREGION_LIST;CT - List
HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction
HISTORY_MSG_COLORTONING_LABREGION_SATURATION;CT - Saturation
HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESS;CT - Lightness
HISTORY_MSG_COLORTONING_LABREGION_HUEMASK;CT - H mask
HISTORY_MSG_COLORTONING_LABREGION_CHROMATICITYMASK;CT - C mask
HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESSMASK;CT - L mask
HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;CT - Show mask
HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth HISTORY_MSG_DEHAZE_DEPTH;Dehaze - Depth
HISTORY_MSG_DEHAZE_ENABLED;Haze Removal HISTORY_MSG_DEHAZE_ENABLED;Haze Removal
HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;Dehaze - Show depth map
@ -816,7 +824,7 @@ IPTCPANEL_CITY;City
IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image. IPTCPANEL_CITYHINT;Enter the name of the city pictured in this image.
IPTCPANEL_COPYHINT;Copy IPTC settings to clipboard. IPTCPANEL_COPYHINT;Copy IPTC settings to clipboard.
IPTCPANEL_COPYRIGHT;Copyright notice IPTCPANEL_COPYRIGHT;Copyright notice
IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as ©2008 Jane Doe. IPTCPANEL_COPYRIGHTHINT;Enter a Notice on the current owner of the Copyright for this image, such as 2008 Jane Doe.
IPTCPANEL_COUNTRY;Country IPTCPANEL_COUNTRY;Country
IPTCPANEL_COUNTRYHINT;Enter the name of the country pictured in this image. IPTCPANEL_COUNTRYHINT;Enter the name of the country pictured in this image.
IPTCPANEL_CREATOR;Creator IPTCPANEL_CREATOR;Creator
@ -1376,9 +1384,9 @@ TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\n\nShortcuts:\n<b>[</b> - Multiple Ed
TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\n\nShortcuts:\n<b>]</b> - Multiple Editor Tabs Mode,\n<b>Alt-]</b> - Single Editor Tab Mode. TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\n\nShortcuts:\n<b>]</b> - Multiple Editor Tabs Mode,\n<b>Alt-]</b> - Single Editor Tab Mode.
TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically. TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically.
TP_COLORAPP_ADAPTSCENE;Scene absolute luminance TP_COLORAPP_ADAPTSCENE;Scene absolute luminance
TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m²).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider. TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environment (cd/m).\n1) Calculated from the Exif data:\nShutter speed - ISO speed - F number - camera exposure correction.\n2) Calculated from the raw white point and RT's Exposure Compensation slider.
TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m²) TP_COLORAPP_ADAPTVIEWING;Viewing absolute luminance (cd/m)
TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m²). TP_COLORAPP_ADAPTVIEWING_TOOLTIP;Absolute luminance of the viewing environment\n(usually 16cd/m).
TP_COLORAPP_ADAP_AUTO_TOOLTIP;If the checkbox is checked (recommended) RawTherapee calculates an optimum value from the Exif data.\nTo set the value manually, uncheck the checkbox first. TP_COLORAPP_ADAP_AUTO_TOOLTIP;If the checkbox is checked (recommended) RawTherapee calculates an optimum value from the Exif data.\nTo set the value manually, uncheck the checkbox first.
TP_COLORAPP_ALGO;Algorithm TP_COLORAPP_ALGO;Algorithm
TP_COLORAPP_ALGO_ALL;All TP_COLORAPP_ALGO_ALL;All
@ -1415,7 +1423,7 @@ TP_COLORAPP_FREE;Free temp+green + CAT02 + [output]
TP_COLORAPP_GAMUT;Gamut control (L*a*b*) TP_COLORAPP_GAMUT;Gamut control (L*a*b*)
TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode. TP_COLORAPP_GAMUT_TOOLTIP;Allow gamut control in L*a*b* mode.
TP_COLORAPP_HUE;Hue (h) TP_COLORAPP_HUE;Hue (h)
TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0° and 360°. TP_COLORAPP_HUE_TOOLTIP;Hue (h) - angle between 0 and 360.
TP_COLORAPP_LABEL;CIE Color Appearance Model 2002 TP_COLORAPP_LABEL;CIE Color Appearance Model 2002
TP_COLORAPP_LABEL_CAM02;Image Adjustments TP_COLORAPP_LABEL_CAM02;Image Adjustments
TP_COLORAPP_LABEL_SCENE;Scene Conditions TP_COLORAPP_LABEL_SCENE;Scene Conditions
@ -1467,6 +1475,16 @@ TP_COLORTONING_LAB;L*a*b* blending
TP_COLORTONING_LABEL;Color Toning TP_COLORTONING_LABEL;Color Toning
TP_COLORTONING_LABGRID;L*a*b* color correction grid TP_COLORTONING_LABGRID;L*a*b* color correction grid
TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nS: a=%3 b=%4 TP_COLORTONING_LABGRID_VALUES;HL: a=%1 b=%2\nS: a=%3 b=%4
TP_COLORTONING_LABREGION_LIST_TITLE;Correction
TP_COLORTONING_LABREGION_SATURATION;Saturation
TP_COLORTONING_LABREGION_LIGHTNESS;Lightness
TP_COLORTONING_LABREGION_MASK;Mask
TP_COLORTONING_LABREGION_HUEMASK;H
TP_COLORTONING_LABREGION_CHROMATICITYMASK;C
TP_COLORTONING_LABREGION_LIGHTNESSMASK;L
TP_COLORTONING_LABREGION_ABVALUES;a=%1 b=%2
TP_COLORTONING_LABREGION_SHOWMASK;Show mask
TP_COLORTONING_LABREGIONS;L*a*b* correction regions
TP_COLORTONING_LUMA;Luminance TP_COLORTONING_LUMA;Luminance
TP_COLORTONING_LUMAMODE;Preserve luminance TP_COLORTONING_LUMAMODE;Preserve luminance
TP_COLORTONING_LUMAMODE_TOOLTIP;If enabled, when you change color (red, green, cyan, blue, etc.) the luminance of each pixel is preserved. TP_COLORTONING_LUMAMODE_TOOLTIP;If enabled, when you change color (red, green, cyan, blue, etc.) the luminance of each pixel is preserved.
@ -1566,16 +1584,16 @@ TP_DIRPYRDENOISE_MEDIAN_METHOD_RGB;RGB
TP_DIRPYRDENOISE_MEDIAN_METHOD_TOOLTIP;When using the "Luminance only" and "L*a*b*" methods, median filtering will be performed just after the wavelet step in the noise reduction pipeline.\nWhen using the "RGB" mode, it will be performed at the very end of the noise reduction pipeline. TP_DIRPYRDENOISE_MEDIAN_METHOD_TOOLTIP;When using the "Luminance only" and "L*a*b*" methods, median filtering will be performed just after the wavelet step in the noise reduction pipeline.\nWhen using the "RGB" mode, it will be performed at the very end of the noise reduction pipeline.
TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (little) + a*b* (normal) TP_DIRPYRDENOISE_MEDIAN_METHOD_WEIGHTED;Weighted L* (little) + a*b* (normal)
TP_DIRPYRDENOISE_MEDIAN_PASSES;Median iterations TP_DIRPYRDENOISE_MEDIAN_PASSES;Median iterations
TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 3×3 window size often leads to better results than using one median filter iteration with a 7×7 window size. TP_DIRPYRDENOISE_MEDIAN_PASSES_TOOLTIP;Applying three median filter iterations with a 33 window size often leads to better results than using one median filter iteration with a 77 window size.
TP_DIRPYRDENOISE_MEDIAN_TYPE;Median type TP_DIRPYRDENOISE_MEDIAN_TYPE;Median type
TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n3×3 soft: treats 5 pixels in a 3×3 pixel window.\n3×3: treats 9 pixels in a 3×3 pixel window.\n5×5 soft: treats 13 pixels in a 5×5 pixel window.\n5×5: treats 25 pixels in a 5×5 pixel window.\n7×7: treats 49 pixels in a 7×7 pixel window.\n9×9: treats 81 pixels in a 9×9 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one. TP_DIRPYRDENOISE_MEDIAN_TYPE_TOOLTIP;Apply a median filter of the desired window size. The larger the window's size, the longer it takes.\n\n33 soft: treats 5 pixels in a 33 pixel window.\n33: treats 9 pixels in a 33 pixel window.\n55 soft: treats 13 pixels in a 55 pixel window.\n55: treats 25 pixels in a 55 pixel window.\n77: treats 49 pixels in a 77 pixel window.\n99: treats 81 pixels in a 99 pixel window.\n\nSometimes it is possible to achieve higher quality running several iterations with a smaller window size than one iteration with a larger one.
TP_DIRPYRDENOISE_SLI;Slider TP_DIRPYRDENOISE_SLI;Slider
TP_DIRPYRDENOISE_TYPE_3X3;3×3 TP_DIRPYRDENOISE_TYPE_3X3;33
TP_DIRPYRDENOISE_TYPE_3X3SOFT;3×3 soft TP_DIRPYRDENOISE_TYPE_3X3SOFT;33 soft
TP_DIRPYRDENOISE_TYPE_5X5;5×5 TP_DIRPYRDENOISE_TYPE_5X5;55
TP_DIRPYRDENOISE_TYPE_5X5SOFT;5×5 soft TP_DIRPYRDENOISE_TYPE_5X5SOFT;55 soft
TP_DIRPYRDENOISE_TYPE_7X7;7×7 TP_DIRPYRDENOISE_TYPE_7X7;77
TP_DIRPYRDENOISE_TYPE_9X9;9×9 TP_DIRPYRDENOISE_TYPE_9X9;99
TP_DIRPYREQUALIZER_ALGO;Skin Color Range TP_DIRPYREQUALIZER_ALGO;Skin Color Range
TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fine: closer to the colors of the skin, minimizing the action on other colors\nLarge: avoid more artifacts. TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fine: closer to the colors of the skin, minimizing the action on other colors\nLarge: avoid more artifacts.
TP_DIRPYREQUALIZER_ARTIF;Reduce artifacts TP_DIRPYREQUALIZER_ARTIF;Reduce artifacts
@ -2021,7 +2039,7 @@ TP_SHARPENING_USM;Unsharp Mask
TP_SHARPENMICRO_AMOUNT;Quantity TP_SHARPENMICRO_AMOUNT;Quantity
TP_SHARPENMICRO_CONTRAST;Contrast threshold TP_SHARPENMICRO_CONTRAST;Contrast threshold
TP_SHARPENMICRO_LABEL;Microcontrast TP_SHARPENMICRO_LABEL;Microcontrast
TP_SHARPENMICRO_MATRIX;3×3 matrix instead of 5×5 TP_SHARPENMICRO_MATRIX;33 matrix instead of 55
TP_SHARPENMICRO_UNIFORMITY;Uniformity TP_SHARPENMICRO_UNIFORMITY;Uniformity
TP_SOFTLIGHT_LABEL;Soft Light TP_SOFTLIGHT_LABEL;Soft Light
TP_SOFTLIGHT_STRENGTH;Strength TP_SOFTLIGHT_STRENGTH;Strength

View File

@ -129,6 +129,7 @@ set(RTENGINESOURCEFILES
ipsoftlight.cc ipsoftlight.cc
guidedfilter.cc guidedfilter.cc
ipdehaze.cc ipdehaze.cc
iplabregions.cc
) )
if(LENSFUN_HAS_LOAD_DIRECTORY) if(LENSFUN_HAS_LOAD_DIRECTORY)

View File

@ -897,6 +897,7 @@ void Crop::update(int todo)
// parent->ipf.MSR(labnCrop, labnCrop->W, labnCrop->H, 1); // parent->ipf.MSR(labnCrop, labnCrop->W, labnCrop->H, 1);
parent->ipf.chromiLuminanceCurve(this, 1, labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy); parent->ipf.chromiLuminanceCurve(this, 1, labnCrop, labnCrop, parent->chroma_acurve, parent->chroma_bcurve, parent->satcurve, parent->lhskcurve, parent->clcurve, parent->lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
parent->ipf.vibrance(labnCrop); parent->ipf.vibrance(labnCrop);
parent->ipf.labColorCorrectionRegions(labnCrop);
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
parent->ipf.EPDToneMap(labnCrop, 5, skip); parent->ipf.EPDToneMap(labnCrop, 5, skip);

View File

@ -718,6 +718,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
histLCurve.clear(); histLCurve.clear();
ipf.chromiLuminanceCurve(nullptr, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histLCurve); ipf.chromiLuminanceCurve(nullptr, pW, nprevl, nprevl, chroma_acurve, chroma_bcurve, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, histCCurve, histLCurve);
ipf.vibrance(nprevl); ipf.vibrance(nprevl);
ipf.labColorCorrectionRegions(nprevl);
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) { if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || (!params.colorappearance.enabled)) {
ipf.EPDToneMap(nprevl, 5, scale); ipf.EPDToneMap(nprevl, 5, scale);

View File

@ -4151,6 +4151,42 @@ void ImProcFunctions::chromiLuminanceCurve (PipetteBuffer *pipetteBuffer, int pW
} }
} }
//-------------------------------------------------------------------------
// support for pipettes for the new LabRegions color toning mode this is a
// hack to fill the pipette buffers also when
// !params->labCurve.enabled. It is ugly, but it's the smallest code
// change that I could find
//-------------------------------------------------------------------------
class TempParams {
const ProcParams **p_;
const ProcParams *old_;
ProcParams tmp_;
public:
explicit TempParams(const ProcParams **p): p_(p)
{
old_ = *p;
tmp_.labCurve.enabled = true;
*p_ = &tmp_;
}
~TempParams()
{
*p_ = old_;
}
};
std::unique_ptr<TempParams> tempparams;
bool pipette_for_colortoning_labregions =
editPipette &&
params->colorToning.enabled && params->colorToning.method == "LabRegions";
if (!params->labCurve.enabled && pipette_for_colortoning_labregions) {
utili = autili = butili = ccutili = cclutili = clcutili = false;
tempparams.reset(new TempParams(&params));
curve.makeIdentity();
}
//-------------------------------------------------------------------------
if (!params->labCurve.enabled) { if (!params->labCurve.enabled) {
if (editPipette && (editID == EUID_Lab_LCurve || editID == EUID_Lab_aCurve || editID == EUID_Lab_bCurve || editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve || editID == EUID_Lab_CLCurve || editID == EUID_Lab_CCurve || editID == EUID_Lab_LCCurve)) { if (editPipette && (editID == EUID_Lab_LCurve || editID == EUID_Lab_aCurve || editID == EUID_Lab_bCurve || editID == EUID_Lab_LHCurve || editID == EUID_Lab_CHCurve || editID == EUID_Lab_HHCurve || editID == EUID_Lab_CLCurve || editID == EUID_Lab_CCurve || editID == EUID_Lab_LCCurve)) {
// fill pipette buffer with zeros to avoid crashes // fill pipette buffer with zeros to avoid crashes
@ -5746,8 +5782,8 @@ void ImProcFunctions::lab2rgb (const LabImage &src, Imagefloat &dst, const Glib:
*/ */
void ImProcFunctions::colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread) void ImProcFunctions::colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread)
{ {
const float factor = ColorToningParams::LABGRID_CORR_MAX * 3.f; const float factor = 3.f;
const float scaling = ColorToningParams::LABGRID_CORR_SCALE; const float scaling = 3.f;
float a_scale = (params->colorToning.labgridAHigh - params->colorToning.labgridALow) / factor / scaling; float a_scale = (params->colorToning.labgridAHigh - params->colorToning.labgridALow) / factor / scaling;
float a_base = params->colorToning.labgridALow / scaling; float a_base = params->colorToning.labgridALow / scaling;
float b_scale = (params->colorToning.labgridBHigh - params->colorToning.labgridBLow) / factor / scaling; float b_scale = (params->colorToning.labgridBHigh - params->colorToning.labgridBLow) / factor / scaling;

View File

@ -345,6 +345,7 @@ public:
void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread); void colorToningLabGrid(LabImage *lab, int xstart, int xend, int ystart, int yend, bool MultiThread);
void shadowsHighlights(LabImage *lab); void shadowsHighlights(LabImage *lab);
void softLight(LabImage *lab); void softLight(LabImage *lab);
void labColorCorrectionRegions(LabImage *lab);
Image8* lab2rgb(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool consider_histogram_settings = true); 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); Imagefloat* lab2rgbOut(LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);

165
rtengine/iplabregions.cc Normal file
View File

@ -0,0 +1,165 @@
/* -*- C++ -*-
*
* This file is part of RawTherapee.
*
* Copyright 2018 Alberto Griggio <alberto.griggio@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifdef _OPENMP
#include <omp.h>
#endif
#include "improcfun.h"
#include "guidedfilter.h"
namespace rtengine {
void ImProcFunctions::labColorCorrectionRegions(LabImage *lab)
{
if (!params->colorToning.enabled || params->colorToning.method != "LabRegions") {
return;
}
int n = params->colorToning.labregions.size();
int show_mask_idx = params->colorToning.labregionsShowMask;
if (show_mask_idx >= n) {
show_mask_idx = -1;
}
std::vector<std::unique_ptr<FlatCurve>> hmask(n);
std::vector<std::unique_ptr<FlatCurve>> cmask(n);
std::vector<std::unique_ptr<FlatCurve>> lmask(n);
const int begin_idx = max(show_mask_idx, 0);
const int end_idx = (show_mask_idx < 0 ? n : show_mask_idx+1);
for (int i = begin_idx; i < end_idx; ++i) {
auto &r = params->colorToning.labregions[i];
if (!r.hueMask.empty() && r.hueMask[0] != FCT_Linear) {
hmask[i].reset(new FlatCurve(r.hueMask, true));
}
if (!r.chromaticityMask.empty() && r.chromaticityMask[0] != FCT_Linear) {
cmask[i].reset(new FlatCurve(r.chromaticityMask, false));
}
if (!r.lightnessMask.empty() && r.lightnessMask[0] != FCT_Linear) {
lmask[i].reset(new FlatCurve(r.lightnessMask, false));
}
}
std::vector<array2D<float>> abmask(n);
std::vector<array2D<float>> Lmask(n);
for (int i = begin_idx; i < end_idx; ++i) {
abmask[i](lab->W, lab->H);
Lmask[i](lab->W, lab->H);
}
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < lab->H; ++y) {
for (int x = 0; x < lab->W; ++x) {
float l = lab->L[y][x];
float a = lab->a[y][x];
float b = lab->b[y][x];
float c, h;
Color::Lab2Lch(a, b, c, h);
// magic constant c_factor: normally chromaticity is in [0; 42000] (see color.h), but here we use the constant to match how the chromaticity pipette works (see improcfun.cc lines 4705-4706 and color.cc line 1930
constexpr float c_factor = 327.68f / 48000.f;
float c1 = lin2log(c * c_factor, 10.f);
float h1 = Color::huelab_to_huehsv2(h);
h1 = h1 + 1.f/6.f; // offset the hue because we start from purple instead of red
if (h1 > 1.f) {
h1 -= 1.f;
}
h1 = lin2log(h1, 3.f);
float l1 = l / 32768.f;
for (int i = begin_idx; i < end_idx; ++i) {
auto &hm = hmask[i];
auto &cm = cmask[i];
auto &lm = lmask[i];
float blend = LIM01((hm ? hm->getVal(h1) : 1.f) * (cm ? cm->getVal(c1) : 1.f) * (lm ? lm->getVal(l1) : 1.f));
Lmask[i][y][x] = abmask[i][y][x] = blend;
}
}
}
{
array2D<float> guide(lab->W, lab->H, lab->L);
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < lab->H; ++y) {
for (int x = 0; x < lab->W; ++x) {
guide[y][x] = LIM01(lab->L[y][x] / 32768.f);
}
}
for (int i = begin_idx; i < end_idx; ++i) {
rtengine::guidedFilter(guide, abmask[i], abmask[i], max(int(4 / scale + 0.5), 1), 0.001, multiThread);
rtengine::guidedFilter(guide, Lmask[i], Lmask[i], max(int(25 / scale + 0.5), 1), 0.0001, multiThread);
}
}
if (show_mask_idx >= 0) {
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < lab->H; ++y) {
for (int x = 0; x < lab->W; ++x) {
auto blend = abmask[show_mask_idx][y][x];
lab->a[y][x] = 0.f;
lab->b[y][x] = blend * 42000.f;
lab->L[y][x] = LIM(lab->L[y][x] + 32768.f * blend, 0.f, 32768.f);
}
}
return;
}
const auto abcoord =
[](float x) -> float
{
return 12000.f * SGN(x) * log2lin(std::abs(x), 4.f);
};
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int y = 0; y < lab->H; ++y) {
for (int x = 0; x < lab->W; ++x) {
float l = lab->L[y][x];
float a = lab->a[y][x];
float b = lab->b[y][x];
for (int i = 0; i < n; ++i) {
auto &r = params->colorToning.labregions[i];
float blend = abmask[i][y][x];
float s = 1.f + r.saturation / 100.f;
float a_new = LIM(s * (a + abcoord(r.a)), -42000.f, 42000.f);
float b_new = LIM(s * (b + abcoord(r.b)), -42000.f, 42000.f);
float l_new = LIM(l * (1.f + float(r.lightness) / 500.f), 0.f, 32768.f);
l = intp(Lmask[i][y][x], l_new, l);
a = intp(blend, a_new, a);
b = intp(blend, b_new, b);
}
lab->L[y][x] = l;
lab->a[y][x] = a;
lab->b[y][x] = b;
}
}
}
} // namespace rtengine

View File

@ -607,6 +607,66 @@ bool LocalContrastParams::operator!=(const LocalContrastParams &other) const
const double ColorToningParams::LABGRID_CORR_MAX = 12000.f; const double ColorToningParams::LABGRID_CORR_MAX = 12000.f;
const double ColorToningParams::LABGRID_CORR_SCALE = 3.f; const double ColorToningParams::LABGRID_CORR_SCALE = 3.f;
ColorToningParams::LabCorrectionRegion::LabCorrectionRegion():
a(0),
b(0),
saturation(0),
lightness(0),
hueMask{
FCT_MinMaxCPoints,
0.166666667,
1.,
0.35,
0.35,
0.8287775246,
1.,
0.35,
0.35
},
chromaticityMask{
FCT_MinMaxCPoints,
0.,
1.,
0.35,
0.35,
1.,
1.,
0.35,
0.35
},
lightnessMask{
FCT_MinMaxCPoints,
0.,
1.,
0.35,
0.35,
1.,
1.,
0.35,
0.35
}
{
}
bool ColorToningParams::LabCorrectionRegion::operator==(const LabCorrectionRegion &other) const
{
return a == other.a
&& b == other.b
&& saturation == other.saturation
&& lightness == other.lightness
&& hueMask == other.hueMask
&& chromaticityMask == other.chromaticityMask
&& lightnessMask == other.lightnessMask;
}
bool ColorToningParams::LabCorrectionRegion::operator!=(const LabCorrectionRegion &other) const
{
return !(*this == other);
}
ColorToningParams::ColorToningParams() : ColorToningParams::ColorToningParams() :
enabled(false), enabled(false),
autosat(true), autosat(true),
@ -664,7 +724,7 @@ ColorToningParams::ColorToningParams() :
1.00, 1.00,
1.00 1.00
}, },
method("Lab"), method("LabRegions"),
twocolor("Std"), twocolor("Std"),
redlow(0.0), redlow(0.0),
greenlow(0.0), greenlow(0.0),
@ -681,7 +741,9 @@ ColorToningParams::ColorToningParams() :
labgridALow(0.0), labgridALow(0.0),
labgridBLow(0.0), labgridBLow(0.0),
labgridAHigh(0.0), labgridAHigh(0.0),
labgridBHigh(0.0) labgridBHigh(0.0),
labregions{LabCorrectionRegion()},
labregionsShowMask(-1)
{ {
} }
@ -717,7 +779,9 @@ bool ColorToningParams::operator ==(const ColorToningParams& other) const
&& labgridALow == other.labgridALow && labgridALow == other.labgridALow
&& labgridBLow == other.labgridBLow && labgridBLow == other.labgridBLow
&& labgridAHigh == other.labgridAHigh && labgridAHigh == other.labgridAHigh
&& labgridBHigh == other.labgridBHigh; && labgridBHigh == other.labgridBHigh
&& labregions == other.labregions
&& labregionsShowMask == other.labregionsShowMask;
} }
bool ColorToningParams::operator !=(const ColorToningParams& other) const bool ColorToningParams::operator !=(const ColorToningParams& other) const
@ -3408,6 +3472,20 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
saveToKeyfile(!pedited || pedited->colorToning.labgridBLow, "ColorToning", "LabGridBLow", colorToning.labgridBLow, keyFile); saveToKeyfile(!pedited || pedited->colorToning.labgridBLow, "ColorToning", "LabGridBLow", colorToning.labgridBLow, keyFile);
saveToKeyfile(!pedited || pedited->colorToning.labgridAHigh, "ColorToning", "LabGridAHigh", colorToning.labgridAHigh, keyFile); saveToKeyfile(!pedited || pedited->colorToning.labgridAHigh, "ColorToning", "LabGridAHigh", colorToning.labgridAHigh, keyFile);
saveToKeyfile(!pedited || pedited->colorToning.labgridBHigh, "ColorToning", "LabGridBHigh", colorToning.labgridBHigh, keyFile); saveToKeyfile(!pedited || pedited->colorToning.labgridBHigh, "ColorToning", "LabGridBHigh", colorToning.labgridBHigh, keyFile);
if (!pedited || pedited->colorToning.labregions) {
for (size_t j = 0; j < colorToning.labregions.size(); ++j) {
std::string n = std::to_string(j+1);
auto &l = colorToning.labregions[j];
putToKeyfile("ColorToning", Glib::ustring("LabRegionA_") + n, l.a, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionB_") + n, l.b, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionSaturation_") + n, l.saturation, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionLightness_") + n, l.lightness, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionHueMask_") + n, l.hueMask, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionChromaticityMask_") + n, l.chromaticityMask, keyFile);
putToKeyfile("ColorToning", Glib::ustring("LabRegionLightnessMask_") + n, l.lightnessMask, keyFile);
}
}
saveToKeyfile(!pedited || pedited->colorToning.labregionsShowMask, "ColorToning", "LabRegionsShowMask", colorToning.labregionsShowMask, keyFile);
// Raw // Raw
saveToKeyfile(!pedited || pedited->raw.darkFrame, "RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame), keyFile); saveToKeyfile(!pedited || pedited->raw.darkFrame, "RAW", "DarkFrame", relativePathIfInside(fname, fnameAbsolute, raw.dark_frame), keyFile);
@ -4772,6 +4850,49 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
colorToning.labgridBLow *= scale; colorToning.labgridBLow *= scale;
colorToning.labgridBHigh *= scale; colorToning.labgridBHigh *= scale;
} }
std::vector<ColorToningParams::LabCorrectionRegion> lg;
bool found = false;
bool done = false;
for (int i = 1; !done; ++i) {
ColorToningParams::LabCorrectionRegion cur;
done = true;
std::string n = std::to_string(i);
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionA_") + n, pedited, cur.a, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionB_") + n, pedited, cur.b, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionSaturation_") + n, pedited, cur.saturation, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionLightness_") + n, pedited, cur.lightness, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionHueMask_") + n, pedited, cur.hueMask, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionChromaticityMask_") + n, pedited, cur.chromaticityMask, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (assignFromKeyfile(keyFile, "ColorToning", Glib::ustring("LabRegionLightnessMask_") + n, pedited, cur.lightnessMask, pedited->colorToning.labregions)) {
found = true;
done = false;
}
if (!done) {
lg.emplace_back(cur);
}
}
if (found) {
colorToning.labregions = std::move(lg);
}
assignFromKeyfile(keyFile, "ColorToning", "LabRegionsShowMask", pedited, colorToning.labregionsShowMask, pedited->colorToning.labregionsShowMask);
} }
if (keyFile.has_group("RAW")) { if (keyFile.has_group("RAW")) {

View File

@ -455,6 +455,22 @@ struct ColorToningParams {
static const double LABGRID_CORR_MAX; static const double LABGRID_CORR_MAX;
static const double LABGRID_CORR_SCALE; static const double LABGRID_CORR_SCALE;
struct LabCorrectionRegion {
double a;
double b;
double saturation;
double lightness;
std::vector<double> hueMask;
std::vector<double> chromaticityMask;
std::vector<double> lightnessMask;
LabCorrectionRegion();
bool operator==(const LabCorrectionRegion &other) const;
bool operator!=(const LabCorrectionRegion &other) const;
};
std::vector<LabCorrectionRegion> labregions;
int labregionsShowMask;
ColorToningParams(); ColorToningParams();
bool operator ==(const ColorToningParams& other) const; bool operator ==(const ColorToningParams& other) const;

View File

@ -220,5 +220,21 @@ std::array<T, 3> dotProduct(const std::array<std::array<T, 3>, 3> &a, const std:
return res; return res;
} }
template <typename T>
T lin2log(T x, T base)
{
constexpr T one(1);
return std::log(x * (base - one) + one) / std::log(base);
}
template <typename T>
T log2lin(T x, T base)
{
constexpr T one(1);
return (std::pow(base, x) - one) / (base - one);
}
} }

View File

@ -1388,6 +1388,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
ipf.chromiLuminanceCurve (nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy); ipf.chromiLuminanceCurve (nullptr, 1, labView, labView, curve1, curve2, satcurve, lhskcurve, clcurve, lumacurve, utili, autili, butili, ccutili, cclutili, clcutili, dummy, dummy);
ipf.vibrance (labView); ipf.vibrance (labView);
ipf.labColorCorrectionRegions(labView);
if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) { if ((params.colorappearance.enabled && !params.colorappearance.tonecie) || !params.colorappearance.enabled) {
ipf.EPDToneMap (labView, 5, 6); ipf.EPDToneMap (labView, 5, 6);

View File

@ -1081,6 +1081,7 @@ private:
ipf.vibrance (labView); ipf.vibrance (labView);
ipf.labColorCorrectionRegions(labView);
if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) { if ((params.colorappearance.enabled && !settings->autocielab) || (!params.colorappearance.enabled)) {
ipf.impulsedenoise (labView); ipf.impulsedenoise (labView);

View File

@ -11,6 +11,24 @@ using namespace rtengine;
using namespace rtengine::procparams; using namespace rtengine::procparams;
namespace {
constexpr int ID_LABREGION_HUE = 5;
inline bool hasMask(const std::vector<double> &dflt, const std::vector<double> &mask)
{
return !(mask.empty() || mask[0] == FCT_Linear || mask == dflt);
}
inline float round_ab(float v)
{
return int(v * 1000) / 1000.f;
}
} // namespace
ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true) ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLORTONING_LABEL"), false, true)
{ {
nextbw = 0; nextbw = 0;
@ -25,6 +43,7 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR
method->append (M("TP_COLORTONING_SPLITCOCO")); method->append (M("TP_COLORTONING_SPLITCOCO"));
method->append (M("TP_COLORTONING_SPLITLR")); method->append (M("TP_COLORTONING_SPLITLR"));
method->append(M("TP_COLORTONING_LABGRID")); method->append(M("TP_COLORTONING_LABGRID"));
method->append(M("TP_COLORTONING_LABREGIONS"));
method->set_active (0); method->set_active (0);
method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP")); method->set_tooltip_text (M("TP_COLORTONING_METHOD_TOOLTIP"));
@ -320,22 +339,114 @@ ColorToning::ColorToning () : FoldableToolPanel(this, "colortoning", M("TP_COLOR
// LAB grid // LAB grid
auto m = ProcEventMapper::getInstance(); auto m = ProcEventMapper::getInstance();
EvColorToningLabGridValue = m->newEvent(RGBCURVE, "HISTORY_MSG_COLORTONING_LABGRID_VALUE"); EvColorToningLabGridValue = m->newEvent(RGBCURVE, "HISTORY_MSG_COLORTONING_LABGRID_VALUE");
labgridBox = Gtk::manage(new Gtk::HBox()); labgrid = Gtk::manage(new LabGrid(EvColorToningLabGridValue, M("TP_COLORTONING_LABGRID_VALUES")));
labgrid = Gtk::manage(new LabGrid(EvColorToningLabGridValue)); pack_start(*labgrid, Gtk::PACK_EXPAND_WIDGET, 4);
labgridBox->pack_start(*labgrid, true, true);
labgridReset = Gtk::manage(new Gtk::Button ());
labgridReset->add (*Gtk::manage(new RTImage ("undo-small.png", "redo-small.png")));
setExpandAlignProperties(labgridReset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START);
labgridReset->set_relief(Gtk::RELIEF_NONE);
labgridReset->set_tooltip_markup(M("ADJUSTER_RESET_TO_DEFAULT"));
labgridReset->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT);
labgridReset->set_can_focus(false);
labgridReset->set_size_request(-1, 20);
labgridReset->signal_button_release_event().connect(sigc::mem_fun(*this, &ColorToning::resetPressed));
labgridBox->pack_start(*labgridReset, false, false);
pack_start(*labgridBox, Gtk::PACK_EXPAND_WIDGET, 4);
//------------------------------------------------------------------------ //------------------------------------------------------------------------
//------------------------------------------------------------------------
// LAB regions
const auto add_button =
[&](Gtk::Button *btn, Gtk::Box *box) -> void
{
setExpandAlignProperties(btn, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START);
btn->set_relief(Gtk::RELIEF_NONE);
btn->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT);
btn->set_can_focus(false);
btn->set_size_request(-1, 20);
box->pack_start(*btn, false, false);
};
EvLabRegionList = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_LIST");
EvLabRegionAB = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_AB");
EvLabRegionSaturation = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_SATURATION");
EvLabRegionLightness = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESS");
EvLabRegionHueMask = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_HUEMASK");
EvLabRegionChromaticityMask = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_CHROMATICITYMASK");
EvLabRegionLightnessMask = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_LIGHTNESSMASK");
EvLabRegionShowMask = m->newEvent(LUMINANCECURVE, "HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK");
labRegionBox = Gtk::manage(new Gtk::VBox());
labRegionList = Gtk::manage(new Gtk::ListViewText(3));
labRegionList->set_size_request(-1, 100);
labRegionList->set_can_focus(false);
labRegionList->set_column_title(0, "#");
labRegionList->set_column_title(1, M("TP_COLORTONING_LABREGION_LIST_TITLE"));
labRegionList->set_column_title(2, M("TP_COLORTONING_LABREGION_MASK"));
labRegionList->set_activate_on_single_click(true);
labRegionSelectionConn = labRegionList->get_selection()->signal_changed().connect(sigc::mem_fun(this, &ColorToning::onLabRegionSelectionChanged));
Gtk::HBox *hb = Gtk::manage(new Gtk::HBox());
hb->pack_start(*labRegionList, Gtk::PACK_EXPAND_WIDGET);
Gtk::VBox *vb = Gtk::manage(new Gtk::VBox());
labRegionAdd = Gtk::manage(new Gtk::Button());
labRegionAdd->add(*Gtk::manage(new RTImage("add-small.png")));
labRegionAdd->signal_clicked().connect(sigc::mem_fun(*this, &ColorToning::labRegionAddPressed));
add_button(labRegionAdd, vb);
labRegionRemove = Gtk::manage(new Gtk::Button());
labRegionRemove->add(*Gtk::manage(new RTImage("remove-small.png")));
labRegionRemove->signal_clicked().connect(sigc::mem_fun(*this, &ColorToning::labRegionRemovePressed));
add_button(labRegionRemove, vb);
labRegionUp = Gtk::manage(new Gtk::Button());
labRegionUp->add(*Gtk::manage(new RTImage("arrow-up-small.png")));
labRegionUp->signal_clicked().connect(sigc::mem_fun(*this, &ColorToning::labRegionUpPressed));
add_button(labRegionUp, vb);
labRegionDown = Gtk::manage(new Gtk::Button());
labRegionDown->add(*Gtk::manage(new RTImage("arrow-down-small.png")));
labRegionDown->signal_clicked().connect(sigc::mem_fun(*this, &ColorToning::labRegionDownPressed));
add_button(labRegionDown, vb);
hb->pack_start(*vb, Gtk::PACK_SHRINK);
labRegionBox->pack_start(*hb, true, true);
labRegionAB = Gtk::manage(new LabGrid(EvLabRegionAB, M("TP_COLORTONING_LABREGION_ABVALUES"), false));
labRegionBox->pack_start(*labRegionAB);
labRegionSaturation = Gtk::manage(new Adjuster(M("TP_COLORTONING_LABREGION_SATURATION"), -100, 100, 1, 0));
labRegionSaturation->setAdjusterListener(this);
labRegionBox->pack_start(*labRegionSaturation);
labRegionLightness = Gtk::manage(new Adjuster(M("TP_COLORTONING_LABREGION_LIGHTNESS"), -100, 100, 1, 0));
labRegionLightness->setAdjusterListener(this);
labRegionBox->pack_start(*labRegionLightness);
CurveEditorGroup *labRegionEditorG = Gtk::manage(new CurveEditorGroup(options.lastColorToningCurvesDir, M("TP_COLORTONING_LABREGION_MASK")));
labRegionEditorG->setCurveListener(this);
labRegionHueMask = static_cast<FlatCurveEditor *>(labRegionEditorG->addCurve(CT_Flat, M("TP_COLORTONING_LABREGION_HUEMASK"), nullptr, false, true));
labRegionHueMask->setIdentityValue(0.);
labRegionHueMask->setResetCurve(FlatCurveType(default_params.labregions[0].hueMask[0]), default_params.labregions[0].hueMask);
labRegionHueMask->setCurveColorProvider(this, ID_LABREGION_HUE);
labRegionHueMask->setBottomBarColorProvider(this, ID_LABREGION_HUE);
labRegionHueMask->setEditID(EUID_Lab_HHCurve, BT_SINGLEPLANE_FLOAT);
labRegionChromaticityMask = static_cast<FlatCurveEditor *>(labRegionEditorG->addCurve(CT_Flat, M("TP_COLORTONING_LABREGION_CHROMATICITYMASK"), nullptr, false, false));
labRegionChromaticityMask->setIdentityValue(0.);
labRegionChromaticityMask->setResetCurve(FlatCurveType(default_params.labregions[0].chromaticityMask[0]), default_params.labregions[0].chromaticityMask);
labRegionChromaticityMask->setBottomBarColorProvider(this, ID_LABREGION_HUE+1);
labRegionChromaticityMask->setEditID(EUID_Lab_CCurve, BT_SINGLEPLANE_FLOAT);
labRegionLightnessMask = static_cast<FlatCurveEditor *>(labRegionEditorG->addCurve(CT_Flat, M("TP_COLORTONING_LABREGION_LIGHTNESSMASK"), nullptr, false, false));
labRegionLightnessMask->setIdentityValue(0.);
labRegionLightnessMask->setResetCurve(FlatCurveType(default_params.labregions[0].lightnessMask[0]), default_params.labregions[0].lightnessMask);
labRegionLightnessMask->setBottomBarBgGradient(milestones);
labRegionLightnessMask->setEditID(EUID_Lab_LCurve, BT_SINGLEPLANE_FLOAT);
labRegionData = default_params.labregions;
labRegionSelected = 0;
{
auto n = labRegionList->append("1");
labRegionList->set_text(n, 1, "a=0 b=0 s=0 l=0");
}
labRegionEditorG->curveListComplete();
labRegionEditorG->show();
labRegionBox->pack_start(*labRegionEditorG, Gtk::PACK_SHRINK, 2);
labRegionShowMask = Gtk::manage(new Gtk::CheckButton(M("TP_COLORTONING_LABREGION_SHOWMASK")));
labRegionShowMask->signal_toggled().connect(sigc::mem_fun(*this, &ColorToning::labRegionShowMaskChanged));
labRegionBox->pack_start(*labRegionShowMask, Gtk::PACK_SHRINK, 4);
pack_start(*labRegionBox, Gtk::PACK_EXPAND_WIDGET, 4);
//------------------------------------------------------------------------
show_all(); show_all();
disableListener(); disableListener();
@ -358,6 +469,7 @@ void ColorToning::setListener(ToolPanelListener *tpl)
{ {
ToolPanel::setListener(tpl); ToolPanel::setListener(tpl);
labgrid->setListener(tpl); labgrid->setListener(tpl);
labRegionAB->setListener(tpl);
} }
/* /*
@ -409,6 +521,20 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited)
clshape->setCurve (pp->colorToning.clcurve); clshape->setCurve (pp->colorToning.clcurve);
cl2shape->setCurve (pp->colorToning.cl2curve); cl2shape->setCurve (pp->colorToning.cl2curve);
labRegionData = pp->colorToning.labregions;
if (labRegionData.empty()) {
labRegionData.emplace_back(rtengine::ColorToningParams::LabCorrectionRegion());
}
if (pp->colorToning.labregionsShowMask >= 0) {
labRegionSelected = pp->colorToning.labregionsShowMask;
labRegionShowMask->set_active(true);
} else {
labRegionSelected = 0;
labRegionShowMask->set_active(false);
}
labRegionPopulateList();
labRegionShow(labRegionSelected);
if (pedited) { if (pedited) {
redlow->setEditedState (pedited->colorToning.redlow ? Edited : UnEdited); redlow->setEditedState (pedited->colorToning.redlow ? Edited : UnEdited);
greenlow->setEditedState (pedited->colorToning.greenlow ? Edited : UnEdited); greenlow->setEditedState (pedited->colorToning.greenlow ? Edited : UnEdited);
@ -433,6 +559,9 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited)
lumamode->set_inconsistent (!pedited->colorToning.lumamode); lumamode->set_inconsistent (!pedited->colorToning.lumamode);
labgrid->setEdited(pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh); labgrid->setEdited(pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh);
labRegionAB->setEdited(pedited->colorToning.labregions);
labRegionShowMask->set_inconsistent(!pedited->colorToning.labregionsShowMask);
} }
redlow->setValue (pp->colorToning.redlow); redlow->setValue (pp->colorToning.redlow);
@ -464,7 +593,7 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited)
lastLumamode = pp->colorToning.lumamode; lastLumamode = pp->colorToning.lumamode;
labgrid->setParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh, false); labgrid->setParams(pp->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, pp->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX, false);
if (pedited && !pedited->colorToning.method) { if (pedited && !pedited->colorToning.method) {
method->set_active (5); method->set_active (5);
@ -480,6 +609,8 @@ void ColorToning::read (const ProcParams* pp, const ParamsEdited* pedited)
method->set_active (4); method->set_active (4);
} else if (pp->colorToning.method == "LabGrid") { } else if (pp->colorToning.method == "LabGrid") {
method->set_active(5); method->set_active(5);
} else if (pp->colorToning.method == "LabRegions") {
method->set_active(6);
} }
methodChanged(); methodChanged();
@ -533,6 +664,19 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited)
pp->colorToning.strength = strength->getIntValue(); pp->colorToning.strength = strength->getIntValue();
labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh); labgrid->getParams(pp->colorToning.labgridALow, pp->colorToning.labgridBLow, pp->colorToning.labgridAHigh, pp->colorToning.labgridBHigh);
pp->colorToning.labgridALow *= ColorToningParams::LABGRID_CORR_MAX;
pp->colorToning.labgridAHigh *= ColorToningParams::LABGRID_CORR_MAX;
pp->colorToning.labgridBLow *= ColorToningParams::LABGRID_CORR_MAX;
pp->colorToning.labgridBHigh *= ColorToningParams::LABGRID_CORR_MAX;
labRegionGet(labRegionSelected);
labRegionShow(labRegionSelected, true);
pp->colorToning.labregions = labRegionData;
if (labRegionShowMask->get_active()) {
pp->colorToning.labregionsShowMask = labRegionSelected;
} else {
pp->colorToning.labregionsShowMask = -1;
}
if (pedited) { if (pedited) {
pedited->colorToning.redlow = redlow->getEditedState (); pedited->colorToning.redlow = redlow->getEditedState ();
@ -560,6 +704,9 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited)
pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState (); pedited->colorToning.shadowsColSat = shadowsColSat->getEditedState ();
pedited->colorToning.labgridALow = pedited->colorToning.labgridBLow = pedited->colorToning.labgridAHigh = pedited->colorToning.labgridBHigh = labgrid->getEdited(); pedited->colorToning.labgridALow = pedited->colorToning.labgridBLow = pedited->colorToning.labgridAHigh = pedited->colorToning.labgridBHigh = labgrid->getEdited();
pedited->colorToning.labregions = labRegionAB->getEdited();
pedited->colorToning.labregionsShowMask = !labRegionShowMask->get_inconsistent();
} }
if (method->get_active_row_number() == 0) { if (method->get_active_row_number() == 0) {
@ -574,6 +721,8 @@ void ColorToning::write (ProcParams* pp, ParamsEdited* pedited)
pp->colorToning.method = "Splitlr"; pp->colorToning.method = "Splitlr";
} else if (method->get_active_row_number() == 5) { } else if (method->get_active_row_number() == 5) {
pp->colorToning.method = "LabGrid"; pp->colorToning.method = "LabGrid";
} else if (method->get_active_row_number() == 6) {
pp->colorToning.method = "LabRegions";
} }
if (twocolor->get_active_row_number() == 0) { if (twocolor->get_active_row_number() == 0) {
@ -630,7 +779,8 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited*
hlColSat->setDefault<int> (defParams->colorToning.hlColSat); hlColSat->setDefault<int> (defParams->colorToning.hlColSat);
shadowsColSat->setDefault<int> (defParams->colorToning.shadowsColSat); shadowsColSat->setDefault<int> (defParams->colorToning.shadowsColSat);
strength->setDefault (defParams->colorToning.strength); strength->setDefault (defParams->colorToning.strength);
labgrid->setDefault(defParams->colorToning.labgridALow, defParams->colorToning.labgridBLow, defParams->colorToning.labgridAHigh, defParams->colorToning.labgridBHigh); labgrid->setDefault(defParams->colorToning.labgridALow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBLow / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridAHigh / ColorToningParams::LABGRID_CORR_MAX, defParams->colorToning.labgridBHigh / ColorToningParams::LABGRID_CORR_MAX);
if (pedited) { if (pedited) {
redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited); redlow->setDefaultEditedState (pedited->colorToning.redlow ? Edited : UnEdited);
@ -649,6 +799,8 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited*
shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited); shadowsColSat->setDefaultEditedState (pedited->colorToning.shadowsColSat ? Edited : UnEdited);
strength->setDefaultEditedState (pedited->colorToning.strength ? Edited : UnEdited); strength->setDefaultEditedState (pedited->colorToning.strength ? Edited : UnEdited);
labgrid->setEdited((pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh) ? Edited : UnEdited); labgrid->setEdited((pedited->colorToning.labgridALow || pedited->colorToning.labgridBLow || pedited->colorToning.labgridAHigh || pedited->colorToning.labgridBHigh) ? Edited : UnEdited);
labRegionAB->setEdited(pedited->colorToning.labregions ? Edited : UnEdited);
} else { } else {
redlow->setDefaultEditedState (Irrelevant); redlow->setDefaultEditedState (Irrelevant);
greenlow->setDefaultEditedState (Irrelevant); greenlow->setDefaultEditedState (Irrelevant);
@ -666,6 +818,7 @@ void ColorToning::setDefaults (const ProcParams* defParams, const ParamsEdited*
shadowsColSat->setDefaultEditedState (Irrelevant); shadowsColSat->setDefaultEditedState (Irrelevant);
strength->setDefaultEditedState (Irrelevant); strength->setDefaultEditedState (Irrelevant);
labgrid->setEdited(Edited); labgrid->setEdited(Edited);
labRegionAB->setEdited(Edited);
} }
} }
@ -813,7 +966,8 @@ void ColorToning::methodChanged ()
{ {
if (!batchMode) { if (!batchMode) {
labgridBox->hide(); labgrid->hide();
labRegionBox->hide();
if (method->get_active_row_number() == 0) { // Lab if (method->get_active_row_number() == 0) { // Lab
colorSep->show(); colorSep->show();
@ -962,7 +1116,7 @@ void ColorToning::methodChanged ()
chanMixerBox->hide(); chanMixerBox->hide();
neutrHBox->hide(); neutrHBox->hide();
lumamode->show(); lumamode->show();
} else if (method->get_active_row_number() == 5) { // Lab Grid } else if (method->get_active_row_number() == 5 || method->get_active_row_number() == 6) { // Lab Grid or Lab Regions
colorSep->hide(); colorSep->hide();
colorCurveEditorG->hide(); colorCurveEditorG->hide();
twocolor->hide(); twocolor->hide();
@ -981,7 +1135,11 @@ void ColorToning::methodChanged ()
neutrHBox->hide(); neutrHBox->hide();
lumamode->hide(); lumamode->hide();
labgridBox->show(); if (method->get_active_row_number() == 5) {
labgrid->show();
} else {
labRegionBox->show();
}
} }
} }
@ -1038,6 +1196,17 @@ void ColorToning::colorForValue (double valX, double valY, enum ColorCaller::Ele
} }
} else if (callerId == 4) { // color curve vertical and horizontal crosshair } else if (callerId == 4) { // color curve vertical and horizontal crosshair
Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B); Color::hsv2rgb01(float(valY), 1.0f, 0.5f, R, G, B);
} else if (callerId == ID_LABREGION_HUE) {
// TODO
float x = valX - 1.f/6.f;
if (x < 0.f) {
x += 1.f;
}
x = log2lin(x, 3.f);
// float x = valX;
Color::hsv2rgb01(x, 0.5f, 0.5f, R, G, B);
} else if (callerId == ID_LABREGION_HUE+1) {
Color::hsv2rgb01(float(valY), float(valX), 0.5f, R, G, B);
} }
caller->ccRed = double(R); caller->ccRed = double(R);
@ -1057,6 +1226,12 @@ void ColorToning::curveChanged (CurveEditor* ce)
listener->panelChanged (EvColorToningCLCurve, M("HISTORY_CUSTOMCURVE")); listener->panelChanged (EvColorToningCLCurve, M("HISTORY_CUSTOMCURVE"));
} else if (ce == cl2shape) { } else if (ce == cl2shape) {
listener->panelChanged (EvColorToningLLCurve, M("HISTORY_CUSTOMCURVE")); listener->panelChanged (EvColorToningLLCurve, M("HISTORY_CUSTOMCURVE"));
} else if (ce == labRegionHueMask) {
listener->panelChanged(EvLabRegionHueMask, M("HISTORY_CUSTOMCURVE"));
} else if (ce == labRegionChromaticityMask) {
listener->panelChanged(EvLabRegionChromaticityMask, M("HISTORY_CUSTOMCURVE"));
} else if (ce == labRegionLightnessMask) {
listener->panelChanged(EvLabRegionLightnessMask, M("HISTORY_CUSTOMCURVE"));
} }
} }
} }
@ -1158,6 +1333,10 @@ void ColorToning::adjusterChanged(Adjuster* a, double newval)
listener->panelChanged (EvColorToningSatProtection, a->getTextValue()); listener->panelChanged (EvColorToningSatProtection, a->getTextValue());
} else if (a == strength) { } else if (a == strength) {
listener->panelChanged (EvColorToningStrength, a->getTextValue()); listener->panelChanged (EvColorToningStrength, a->getTextValue());
} else if (a == labRegionSaturation) {
listener->panelChanged(EvLabRegionSaturation, a->getTextValue());
} else if (a == labRegionLightness) {
listener->panelChanged(EvLabRegionLightness, a->getTextValue());
} }
} }
@ -1190,8 +1369,177 @@ void ColorToning::setBatchMode (bool batchMode)
} }
bool ColorToning::resetPressed(GdkEventButton* event)
void ColorToning::onLabRegionSelectionChanged()
{ {
labgrid->reset(event->state & GDK_CONTROL_MASK); auto s = labRegionList->get_selected();
return false; if (!s.empty()) {
// update the selected values
labRegionGet(labRegionSelected);
labRegionSelected = s[0];
labRegionShow(labRegionSelected);
if (labRegionShowMask->get_active()) {
labRegionShowMaskChanged();
}
}
}
void ColorToning::labRegionGet(int idx)
{
if (idx < 0 || size_t(idx) >= labRegionData.size()) {
return;
}
auto &r = labRegionData[idx];
double la, lb;
labRegionAB->getParams(la, lb, r.a, r.b);
r.saturation = labRegionSaturation->getValue();
r.lightness = labRegionLightness->getValue();
r.hueMask = labRegionHueMask->getCurve();
r.chromaticityMask = labRegionChromaticityMask->getCurve();
r.lightnessMask = labRegionLightnessMask->getCurve();
}
void ColorToning::labRegionAddPressed()
{
labRegionSelected = labRegionData.size();
labRegionData.push_back(rtengine::ColorToningParams::LabCorrectionRegion());
labRegionPopulateList();
labRegionShow(labRegionSelected);
if (listener) {
listener->panelChanged(EvLabRegionList, M("HISTORY_CHANGED"));
}
}
void ColorToning::labRegionRemovePressed()
{
if (labRegionList->size() > 1) {
labRegionData.erase(labRegionData.begin() + labRegionSelected);
labRegionSelected = LIM(labRegionSelected-1, 0, int(labRegionData.size()-1));
labRegionPopulateList();
labRegionShow(labRegionSelected);
if (listener) {
listener->panelChanged(EvLabRegionList, M("HISTORY_CHANGED"));
}
}
}
void ColorToning::labRegionUpPressed()
{
if (labRegionSelected > 0) {
auto r = labRegionData[labRegionSelected];
labRegionData.erase(labRegionData.begin() + labRegionSelected);
--labRegionSelected;
labRegionData.insert(labRegionData.begin() + labRegionSelected, r);
labRegionPopulateList();
if (listener) {
listener->panelChanged(EvLabRegionList, M("HISTORY_CHANGED"));
}
}
}
void ColorToning::labRegionDownPressed()
{
if (labRegionSelected < int(labRegionData.size()-1)) {
auto r = labRegionData[labRegionSelected];
labRegionData.erase(labRegionData.begin() + labRegionSelected);
++labRegionSelected;
labRegionData.insert(labRegionData.begin() + labRegionSelected, r);
labRegionPopulateList();
if (listener) {
listener->panelChanged(EvLabRegionList, M("HISTORY_CHANGED"));
}
}
}
void ColorToning::labRegionShowMaskChanged()
{
if (listener) {
listener->panelChanged(EvLabRegionShowMask, labRegionShowMask->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED"));
}
}
void ColorToning::labRegionPopulateList()
{
ConnectionBlocker b(labRegionSelectionConn);
labRegionList->clear_items();
rtengine::ColorToningParams::LabCorrectionRegion dflt;
for (size_t i = 0; i < labRegionData.size(); ++i) {
auto &r = labRegionData[i];
auto j = labRegionList->append(std::to_string(i+1));
labRegionList->set_text(j, 1, Glib::ustring::compose("a=%1 b=%2 s=%3 l=%4", round_ab(r.a), round_ab(r.b), r.saturation, r.lightness));
labRegionList->set_text(
j, 2, Glib::ustring::compose(
"%1%2%3",
hasMask(dflt.hueMask, r.hueMask) ? "H" : "",
hasMask(dflt.chromaticityMask, r.chromaticityMask) ? "C" : "",
hasMask(dflt.lightnessMask, r.lightnessMask) ? "L" : ""));
}
}
void ColorToning::labRegionShow(int idx, bool list_only)
{
const bool disable = listener;
if (disable) {
disableListener();
}
rtengine::ColorToningParams::LabCorrectionRegion dflt;
auto &r = labRegionData[idx];
if (!list_only) {
labRegionAB->setParams(0, 0, r.a, r.b, false);
labRegionSaturation->setValue(r.saturation);
labRegionLightness->setValue(r.lightness);
labRegionHueMask->setCurve(r.hueMask);
labRegionChromaticityMask->setCurve(r.chromaticityMask);
labRegionLightnessMask->setCurve(r.lightnessMask);
}
labRegionList->set_text(idx, 1, Glib::ustring::compose("a=%1 b=%2 s=%3 l=%4", round_ab(r.a), round_ab(r.b), r.saturation, r.lightness));
labRegionList->set_text(
idx, 2, Glib::ustring::compose(
"%1%2%3",
hasMask(dflt.hueMask, r.hueMask) ? "H" : "",
hasMask(dflt.chromaticityMask, r.chromaticityMask) ? "C" : "",
hasMask(dflt.lightnessMask, r.lightnessMask) ? "L" : ""));
Gtk::TreePath pth;
pth.push_back(idx);
labRegionList->get_selection()->select(pth);
if (disable) {
enableListener();
}
}
void ColorToning::setEditProvider(EditDataProvider *provider)
{
labRegionHueMask->setEditProvider(provider);
labRegionChromaticityMask->setEditProvider(provider);
labRegionLightnessMask->setEditProvider(provider);
}
float ColorToning::blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3)
{
if (ce == labRegionChromaticityMask && chan1 > 0.f) {
return lin2log(chan1, 10.f);
} else if (ce == labRegionHueMask && chan1 > 0.f) {
float x = chan1 + 1.f/6.f;
if (x > 1.f) {
x -= 1.f;
}
return lin2log(x, 3.f);
}
return CurveListener::blendPipetteValues(ce, chan1, chan2, chan3);
} }

View File

@ -58,8 +58,19 @@ public:
void setListener(ToolPanelListener *tpl); void setListener(ToolPanelListener *tpl);
void setEditProvider(EditDataProvider *provider);
float blendPipetteValues(CurveEditor *ce, float chan1, float chan2, float chan3);
private: private:
bool resetPressed(GdkEventButton* event); void onLabRegionSelectionChanged();
void labRegionAddPressed();
void labRegionRemovePressed();
void labRegionUpPressed();
void labRegionDownPressed();
void labRegionShowMaskChanged();
void labRegionPopulateList();
void labRegionShow(int idx, bool list_only=false);
void labRegionGet(int idx);
//Gtk::HSeparator* satLimiterSep; //Gtk::HSeparator* satLimiterSep;
Gtk::HSeparator* colorSep; Gtk::HSeparator* colorSep;
@ -113,9 +124,33 @@ private:
sigc::connection lumamodeConn; sigc::connection lumamodeConn;
rtengine::ProcEvent EvColorToningLabGridValue; rtengine::ProcEvent EvColorToningLabGridValue;
Gtk::Button *labgridReset;
LabGrid *labgrid; LabGrid *labgrid;
Gtk::HBox *labgridBox;
rtengine::ProcEvent EvLabRegionList;
rtengine::ProcEvent EvLabRegionAB;
rtengine::ProcEvent EvLabRegionSaturation;
rtengine::ProcEvent EvLabRegionLightness;
rtengine::ProcEvent EvLabRegionHueMask;
rtengine::ProcEvent EvLabRegionChromaticityMask;
rtengine::ProcEvent EvLabRegionLightnessMask;
rtengine::ProcEvent EvLabRegionShowMask;
Gtk::VBox *labRegionBox;
Gtk::ListViewText *labRegionList;
Gtk::Button *labRegionAdd;
Gtk::Button *labRegionRemove;
Gtk::Button *labRegionUp;
Gtk::Button *labRegionDown;
LabGrid *labRegionAB;
Adjuster *labRegionSaturation;
Adjuster *labRegionLightness;
FlatCurveEditor *labRegionHueMask;
FlatCurveEditor *labRegionChromaticityMask;
FlatCurveEditor *labRegionLightnessMask;
Gtk::CheckButton *labRegionShowMask;
std::vector<rtengine::ColorToningParams::LabCorrectionRegion> labRegionData;
int labRegionSelected;
sigc::connection labRegionSelectionConn;
IdleRegister idle_register; IdleRegister idle_register;
}; };

View File

@ -41,29 +41,40 @@
using rtengine::Color; using rtengine::Color;
bool LabGrid::notifyListener() //-----------------------------------------------------------------------------
// LabGridArea
//-----------------------------------------------------------------------------
bool LabGridArea::notifyListener()
{ {
if (listener) { if (listener) {
listener->panelChanged(evt, Glib::ustring::compose(M("TP_COLORTONING_LABGRID_VALUES"), int(low_a), int(low_b), int(high_a), int(high_b))); const auto round =
[](float v) -> float
{
return int(v * 1000) / 1000.f;
};
listener->panelChanged(evt, Glib::ustring::compose(evtMsg, round(high_a), round(high_b), round(low_a), round(low_b)));
} }
return false; return false;
} }
LabGrid::LabGrid(rtengine::ProcEvent evt): LabGridArea::LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low):
Gtk::DrawingArea(), Gtk::DrawingArea(),
evt(evt), litPoint(NONE), evt(evt), evtMsg(msg),
litPoint(NONE),
low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f), low_a(0.f), high_a(0.f), low_b(0.f), high_b(0.f),
defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f), defaultLow_a(0.f), defaultHigh_a(0.f), defaultLow_b(0.f), defaultHigh_b(0.f),
listener(nullptr), listener(nullptr),
edited(false), edited(false),
isDragged(false) isDragged(false),
low_enabled(enable_low)
{ {
set_can_focus(true); set_can_focus(true);
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK); add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK);
} }
void LabGrid::getParams(double &la, double &lb, double &ha, double &hb) const void LabGridArea::getParams(double &la, double &lb, double &ha, double &hb) const
{ {
la = low_a; la = low_a;
ha = high_a; ha = high_a;
@ -72,10 +83,10 @@ void LabGrid::getParams(double &la, double &lb, double &ha, double &hb) const
} }
void LabGrid::setParams(double la, double lb, double ha, double hb, bool notify) void LabGridArea::setParams(double la, double lb, double ha, double hb, bool notify)
{ {
const double lo = -rtengine::ColorToningParams::LABGRID_CORR_MAX; const double lo = -1.0;
const double hi = rtengine::ColorToningParams::LABGRID_CORR_MAX; const double hi = 1.0;
low_a = rtengine::LIM(la, lo, hi); low_a = rtengine::LIM(la, lo, hi);
low_b = rtengine::LIM(lb, lo, hi); low_b = rtengine::LIM(lb, lo, hi);
high_a = rtengine::LIM(ha, lo, hi); high_a = rtengine::LIM(ha, lo, hi);
@ -86,7 +97,7 @@ void LabGrid::setParams(double la, double lb, double ha, double hb, bool notify)
} }
} }
void LabGrid::setDefault (double la, double lb, double ha, double hb) void LabGridArea::setDefault (double la, double lb, double ha, double hb)
{ {
defaultLow_a = la; defaultLow_a = la;
defaultLow_b = lb; defaultLow_b = lb;
@ -95,7 +106,7 @@ void LabGrid::setDefault (double la, double lb, double ha, double hb)
} }
void LabGrid::reset(bool toInitial) void LabGridArea::reset(bool toInitial)
{ {
if (toInitial) { if (toInitial) {
setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, true); setParams(defaultLow_a, defaultLow_b, defaultHigh_a, defaultHigh_b, true);
@ -105,32 +116,32 @@ void LabGrid::reset(bool toInitial)
} }
void LabGrid::setEdited(bool yes) void LabGridArea::setEdited(bool yes)
{ {
edited = yes; edited = yes;
} }
bool LabGrid::getEdited() const bool LabGridArea::getEdited() const
{ {
return edited; return edited;
} }
void LabGrid::setListener(ToolPanelListener *l) void LabGridArea::setListener(ToolPanelListener *l)
{ {
listener = l; listener = l;
} }
void LabGrid::on_style_updated () void LabGridArea::on_style_updated ()
{ {
setDirty(true); setDirty(true);
queue_draw (); queue_draw ();
} }
bool LabGrid::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf) bool LabGridArea::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf)
{ {
Gtk::Allocation allocation = get_allocation(); Gtk::Allocation allocation = get_allocation();
allocation.set_x(0); allocation.set_x(0);
@ -170,7 +181,7 @@ bool LabGrid::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf)
cr->translate(0, height); cr->translate(0, height);
cr->scale(1., -1.); cr->scale(1., -1.);
const int cells = 8; const int cells = 8;
float step = rtengine::ColorToningParams::LABGRID_CORR_MAX / float(cells/2); float step = 12000.f / float(cells/2);
for (int j = 0; j < cells; j++) { for (int j = 0; j < cells; j++) {
for (int i = 0; i < cells; i++) { for (int i = 0; i < cells; i++) {
float R, G, B; float R, G, B;
@ -190,10 +201,10 @@ bool LabGrid::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf)
// drawing the connection line // drawing the connection line
cr->set_antialias(Cairo::ANTIALIAS_DEFAULT); cr->set_antialias(Cairo::ANTIALIAS_DEFAULT);
float loa, hia, lob, hib; float loa, hia, lob, hib;
loa = .5f * (width + width * low_a / rtengine::ColorToningParams::LABGRID_CORR_MAX); loa = .5f * (width + width * low_a);
hia = .5f * (width + width * high_a / rtengine::ColorToningParams::LABGRID_CORR_MAX); hia = .5f * (width + width * high_a);
lob = .5f * (height + height * low_b / rtengine::ColorToningParams::LABGRID_CORR_MAX); lob = .5f * (height + height * low_b);
hib = .5f * (height + height * high_b / rtengine::ColorToningParams::LABGRID_CORR_MAX); hib = .5f * (height + height * high_b);
cr->set_line_width(2.); cr->set_line_width(2.);
cr->set_source_rgb(0.6, 0.6, 0.6); cr->set_source_rgb(0.6, 0.6, 0.6);
cr->move_to(loa, lob); cr->move_to(loa, lob);
@ -201,13 +212,15 @@ bool LabGrid::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf)
cr->stroke(); cr->stroke();
// drawing points // drawing points
cr->set_source_rgb(0.1, 0.1, 0.1); if (low_enabled) {
if (litPoint == LOW) { cr->set_source_rgb(0.1, 0.1, 0.1);
cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI); if (litPoint == LOW) {
} else { cr->arc(loa, lob, 5, 0, 2. * rtengine::RT_PI);
cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI); } else {
cr->arc(loa, lob, 3, 0, 2. * rtengine::RT_PI);
}
cr->fill();
} }
cr->fill();
cr->set_source_rgb(0.9, 0.9, 0.9); cr->set_source_rgb(0.9, 0.9, 0.9);
if (litPoint == HIGH) { if (litPoint == HIGH) {
@ -223,7 +236,7 @@ bool LabGrid::on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf)
} }
bool LabGrid::on_button_press_event(GdkEventButton *event) bool LabGridArea::on_button_press_event(GdkEventButton *event)
{ {
if (event->button == 1) { if (event->button == 1) {
if (event->type == GDK_2BUTTON_PRESS) { if (event->type == GDK_2BUTTON_PRESS) {
@ -250,7 +263,7 @@ bool LabGrid::on_button_press_event(GdkEventButton *event)
} }
bool LabGrid::on_button_release_event(GdkEventButton *event) bool LabGridArea::on_button_release_event(GdkEventButton *event)
{ {
if (event->button == 1) { if (event->button == 1) {
isDragged = false; isDragged = false;
@ -260,7 +273,7 @@ bool LabGrid::on_button_release_event(GdkEventButton *event)
} }
bool LabGrid::on_motion_notify_event(GdkEventMotion *event) bool LabGridArea::on_motion_notify_event(GdkEventMotion *event)
{ {
if (isDragged && delayconn.connected()) { if (isDragged && delayconn.connected()) {
delayconn.disconnect(); delayconn.disconnect();
@ -275,30 +288,30 @@ bool LabGrid::on_motion_notify_event(GdkEventMotion *event)
const float mb = (2.0 * mouse_y - height) / (float)height; const float mb = (2.0 * mouse_y - height) / (float)height;
if (isDragged) { if (isDragged) {
if (litPoint == LOW) { if (litPoint == LOW) {
low_a = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; low_a = ma;
low_b = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; low_b = mb;
} else if (litPoint == HIGH) { } else if (litPoint == HIGH) {
high_a = ma * rtengine::ColorToningParams::LABGRID_CORR_MAX; high_a = ma;
high_b = mb * rtengine::ColorToningParams::LABGRID_CORR_MAX; high_b = mb;
} }
edited = true; edited = true;
grab_focus(); grab_focus();
if (options.adjusterMinDelay == 0) { if (options.adjusterMinDelay == 0) {
notifyListener(); notifyListener();
} else { } else {
delayconn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGrid::notifyListener), options.adjusterMinDelay); delayconn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LabGridArea::notifyListener), options.adjusterMinDelay);
} }
queue_draw(); queue_draw();
} else { } else {
litPoint = NONE; litPoint = NONE;
float la = low_a / rtengine::ColorToningParams::LABGRID_CORR_MAX; float la = low_a;
float lb = low_b / rtengine::ColorToningParams::LABGRID_CORR_MAX; float lb = low_b;
float ha = high_a / rtengine::ColorToningParams::LABGRID_CORR_MAX; float ha = high_a;
float hb = high_b / rtengine::ColorToningParams::LABGRID_CORR_MAX; float hb = high_b;
const float thrs = 0.05f; const float thrs = 0.05f;
const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb); const float distlo = (la - ma) * (la - ma) + (lb - mb) * (lb - mb);
const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb); const float disthi = (ha - ma) * (ha - ma) + (hb - mb) * (hb - mb);
if (distlo < thrs * thrs && distlo < disthi) { if (low_enabled && distlo < thrs * thrs && distlo < disthi) {
litPoint = LOW; litPoint = LOW;
} else if (disthi < thrs * thrs && disthi <= distlo) { } else if (disthi < thrs * thrs && disthi <= distlo) {
litPoint = HIGH; litPoint = HIGH;
@ -311,20 +324,66 @@ bool LabGrid::on_motion_notify_event(GdkEventMotion *event)
} }
Gtk::SizeRequestMode LabGrid::get_request_mode_vfunc() const Gtk::SizeRequestMode LabGridArea::get_request_mode_vfunc() const
{ {
return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH; return Gtk::SIZE_REQUEST_HEIGHT_FOR_WIDTH;
} }
void LabGrid::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const void LabGridArea::get_preferred_width_vfunc(int &minimum_width, int &natural_width) const
{ {
minimum_width = 50; minimum_width = 50;
natural_width = 150; // same as GRAPH_SIZE from mycurve.h natural_width = 150; // same as GRAPH_SIZE from mycurve.h
} }
void LabGrid::get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const void LabGridArea::get_preferred_height_for_width_vfunc(int width, int &minimum_height, int &natural_height) const
{ {
minimum_height = natural_height = width; minimum_height = natural_height = width;
} }
bool LabGridArea::lowEnabled() const
{
return low_enabled;
}
void LabGridArea::setLowEnabled(bool yes)
{
if (low_enabled != yes) {
low_enabled = yes;
queue_draw();
}
}
//-----------------------------------------------------------------------------
// LabGrid
//-----------------------------------------------------------------------------
LabGrid::LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low):
grid(evt, msg, enable_low)
{
Gtk::Button *reset = Gtk::manage(new Gtk::Button());
reset->set_tooltip_markup(M("ADJUSTER_RESET_TO_DEFAULT"));
reset->add(*Gtk::manage(new RTImage("undo-small.png", "redo-small.png")));
reset->signal_button_release_event().connect(sigc::mem_fun(*this, &LabGrid::resetPressed));
setExpandAlignProperties(reset, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_START);
reset->set_relief(Gtk::RELIEF_NONE);
reset->get_style_context()->add_class(GTK_STYLE_CLASS_FLAT);
reset->set_can_focus(false);
reset->set_size_request(-1, 20);
pack_start(grid, true, true);
pack_start(*reset, false, false);
show_all_children();
}
bool LabGrid::resetPressed(GdkEventButton *event)
{
grid.reset(event->state & GDK_CONTROL_MASK);
return false;
}

View File

@ -43,9 +43,11 @@
#include "toolpanel.h" #include "toolpanel.h"
class LabGrid: public Gtk::DrawingArea, public BackBuffer { class LabGridArea: public Gtk::DrawingArea, public BackBuffer {
private: private:
rtengine::ProcEvent evt; rtengine::ProcEvent evt;
Glib::ustring evtMsg;
enum State { NONE, HIGH, LOW }; enum State { NONE, HIGH, LOW };
State litPoint; State litPoint;
float low_a; float low_a;
@ -64,11 +66,14 @@ private:
sigc::connection delayconn; sigc::connection delayconn;
static const int inset = 2; static const int inset = 2;
bool grid_visible;
bool low_enabled;
bool notifyListener(); bool notifyListener();
void getLitPoint(); void getLitPoint();
public: public:
LabGrid(rtengine::ProcEvent evt); LabGridArea(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true);
void getParams(double &la, double &lb, double &ha, double &hb) const; void getParams(double &la, double &lb, double &ha, double &hb) const;
void setParams(double la, double lb, double ha, double hb, bool notify); void setParams(double la, double lb, double ha, double hb, bool notify);
@ -78,6 +83,9 @@ public:
void reset(bool toInitial); void reset(bool toInitial);
void setListener(ToolPanelListener *l); void setListener(ToolPanelListener *l);
bool lowEnabled() const;
void setLowEnabled(bool yes);
bool on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf); bool on_draw(const ::Cairo::RefPtr<Cairo::Context> &crf);
void on_style_updated (); void on_style_updated ();
bool on_button_press_event(GdkEventButton *event); bool on_button_press_event(GdkEventButton *event);
@ -88,3 +96,24 @@ public:
void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const; void get_preferred_height_for_width_vfunc (int width, int &minimum_height, int &natural_height) const;
}; };
class LabGrid: public Gtk::HBox {
private:
LabGridArea grid;
bool resetPressed(GdkEventButton *event);
public:
LabGrid(rtengine::ProcEvent evt, const Glib::ustring &msg, bool enable_low=true);
void getParams(double &la, double &lb, double &ha, double &hb) const { return grid.getParams(la, lb, ha, hb); }
void setParams(double la, double lb, double ha, double hb, bool notify) { grid.setParams(la, lb, ha, hb, notify); }
void setDefault (double la, double lb, double ha, double hb) { grid.setDefault(la, lb, ha, hb); }
void setEdited(bool yes) { grid.setEdited(yes); }
bool getEdited() const { return grid.getEdited(); }
void reset(bool toInitial) { grid.reset(toInitial); }
void setListener(ToolPanelListener *l) { grid.setListener(l); }
bool lowEnabled() const { return grid.lowEnabled(); }
void setLowEnabled(bool yes) { grid.setLowEnabled(yes); }
};

View File

@ -141,6 +141,8 @@ void ParamsEdited::set(bool v)
colorToning.labgridBLow = v; colorToning.labgridBLow = v;
colorToning.labgridAHigh = v; colorToning.labgridAHigh = v;
colorToning.labgridBHigh = v; colorToning.labgridBHigh = v;
colorToning.labregions = v;
colorToning.labregionsShowMask = v;
sharpening.enabled = v; sharpening.enabled = v;
sharpening.contrast = v; sharpening.contrast = v;
@ -703,6 +705,8 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
colorToning.labgridBLow = colorToning.labgridBLow && p.colorToning.labgridBLow == other.colorToning.labgridBLow; colorToning.labgridBLow = colorToning.labgridBLow && p.colorToning.labgridBLow == other.colorToning.labgridBLow;
colorToning.labgridAHigh = colorToning.labgridAHigh && p.colorToning.labgridAHigh == other.colorToning.labgridAHigh; colorToning.labgridAHigh = colorToning.labgridAHigh && p.colorToning.labgridAHigh == other.colorToning.labgridAHigh;
colorToning.labgridBHigh = colorToning.labgridBHigh && p.colorToning.labgridBHigh == other.colorToning.labgridBHigh; colorToning.labgridBHigh = colorToning.labgridBHigh && p.colorToning.labgridBHigh == other.colorToning.labgridBHigh;
colorToning.labregions = colorToning.labregions && p.colorToning.labregions == other.colorToning.labregions;
colorToning.labregionsShowMask = colorToning.labregionsShowMask && p.colorToning.labregionsShowMask == other.colorToning.labregionsShowMask;
sharpenEdge.enabled = sharpenEdge.enabled && p.sharpenEdge.enabled == other.sharpenEdge.enabled; sharpenEdge.enabled = sharpenEdge.enabled && p.sharpenEdge.enabled == other.sharpenEdge.enabled;
sharpenEdge.passes = sharpenEdge.passes && p.sharpenEdge.passes == other.sharpenEdge.passes; sharpenEdge.passes = sharpenEdge.passes && p.sharpenEdge.passes == other.sharpenEdge.passes;
sharpenEdge.amount = sharpenEdge.amount && p.sharpenEdge.amount == other.sharpenEdge.amount; sharpenEdge.amount = sharpenEdge.amount && p.sharpenEdge.amount == other.sharpenEdge.amount;
@ -1579,6 +1583,14 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
toEdit.colorToning.labgridBHigh = mods.colorToning.labgridBHigh; toEdit.colorToning.labgridBHigh = mods.colorToning.labgridBHigh;
} }
if (colorToning.labregions) {
toEdit.colorToning.labregions = mods.colorToning.labregions;
}
if (colorToning.labregionsShowMask) {
toEdit.colorToning.labregionsShowMask = mods.colorToning.labregionsShowMask;
}
if (sharpenEdge.enabled) { if (sharpenEdge.enabled) {
toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled; toEdit.sharpenEdge.enabled = mods.sharpenEdge.enabled;
} }

View File

@ -178,6 +178,8 @@ public:
bool labgridBLow; bool labgridBLow;
bool labgridAHigh; bool labgridAHigh;
bool labgridBHigh; bool labgridBHigh;
bool labregions;
bool labregionsShowMask;
}; };
class SharpenEdgeParamsEdited class SharpenEdgeParamsEdited