diff --git a/rtdata/rt_splash_5.png b/rtdata/rt_splash_5.png
new file mode 100644
index 000000000..71486b132
Binary files /dev/null and b/rtdata/rt_splash_5.png differ
diff --git a/rtdata/rt_splash_5.svg b/rtdata/rt_splash_5.svg
new file mode 100644
index 000000000..78620dd68
--- /dev/null
+++ b/rtdata/rt_splash_5.svg
@@ -0,0 +1,1770 @@
+
+
+
+
diff --git a/rtengine/color.h b/rtengine/color.h
index e2b32e834..77db1f4f7 100644
--- a/rtengine/color.h
+++ b/rtengine/color.h
@@ -17,14 +17,16 @@
* along with RawTherapee. If not, see .
*/
-#ifndef _COLOR_H_
-#define _COLOR_H_
+#pragma once
+
+#include
#include "rt_math.h"
#include "LUT.h"
#include "labimage.h"
#include "iccmatrices.h"
#include "sleef.c"
+
#define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c)
namespace rtengine
@@ -1680,5 +1682,3 @@ public:
};
}
-
-#endif
diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc
index e308ab13b..5e3ef6991 100644
--- a/rtengine/dcrop.cc
+++ b/rtengine/dcrop.cc
@@ -751,10 +751,11 @@ void Crop::update (int todo)
DCPProfile::ApplyState as;
DCPProfile *dcpProf = parent->imgsrc->getDCP(params.icm, parent->currWB, as);
+ LUTu histToneCurve;
parent->ipf.rgbProc (baseCrop, laboCrop, this, parent->hltonecurve, parent->shtonecurve, parent->tonecurve, cshmap,
params.toneCurve.saturation, parent->rCurve, parent->gCurve, parent->bCurve, parent->colourToningSatLimit , parent->colourToningSatLimitOpacity, parent->ctColorCurve, parent->ctOpacityCurve, parent->opautili, parent->clToningcurve, parent->cl2Toningcurve,
parent->customToneCurve1, parent->customToneCurve2, parent->beforeToneCurveBW, parent->afterToneCurveBW, rrm, ggm, bbm,
- parent->bwAutoR, parent->bwAutoG, parent->bwAutoB, dcpProf, as);
+ parent->bwAutoR, parent->bwAutoG, parent->bwAutoB, dcpProf, as, histToneCurve);
}
/*xref=000;yref=000;
diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
index 4ef2c3358..c71d7f98b 100644
--- a/rtengine/dfmanager.cc
+++ b/rtengine/dfmanager.cc
@@ -598,12 +598,13 @@ std::vector *DFManager::getBadPixels ( const std::string &mak, const std
found = true;
}
- if( settings->verbose )
+ if( settings->verbose ) {
if(found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
+ }
}
@@ -617,12 +618,13 @@ std::vector *DFManager::getBadPixels ( const std::string &mak, const std
found = true;
}
- if( settings->verbose )
+ if( settings->verbose ) {
if(found) {
printf("%s.badpixels found\n", s.str().c_str());
} else {
printf("%s.badpixels not found\n", s.str().c_str());
}
+ }
}
if(!found) {
diff --git a/rtengine/iccjpeg.cc b/rtengine/iccjpeg.cc
index 21ba86f28..31aa0ec7c 100644
--- a/rtengine/iccjpeg.cc
+++ b/rtengine/iccjpeg.cc
@@ -142,7 +142,9 @@ marker_is_icc (jpeg_saved_marker_ptr marker)
GETJOCTET(marker->data[8]) == 0x49 &&
GETJOCTET(marker->data[9]) == 0x4C &&
GETJOCTET(marker->data[10]) == 0x45 &&
- GETJOCTET(marker->data[11]) == 0x0;
+ GETJOCTET(marker->data[11]) == 0x0
+ ? TRUE
+ : FALSE;
}
diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc
index d3400a8d0..f8e257ddc 100644
--- a/rtengine/imagedata.cc
+++ b/rtengine/imagedata.cc
@@ -440,6 +440,16 @@ void ImageData::extractInfo ()
}
}
} else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) {
+ // ISO at max value supported, check manufacturer specific
+ if (iso_speed == 65535 || iso_speed == 0) {
+ rtexif::Tag* baseIsoTag = mnote->getTag("ISO");
+ if (baseIsoTag) {
+ std::string isoData = baseIsoTag->valueToString();
+ if (isoData.size() > 1) {
+ iso_speed = stoi(isoData);
+ }
+ }
+ }
if (mnote->getTag ("LensType")) {
lens = mnote->getTag ("LensType")->valueToString ();
}
diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc
index f869a0f3e..e886dabce 100644
--- a/rtengine/imageio.cc
+++ b/rtengine/imageio.cc
@@ -556,11 +556,13 @@ int ImageIO::loadJPEG (Glib::ustring fname)
jpeg_read_header(&cinfo, TRUE);
//if JPEG is CMYK, then abort reading
- if (cinfo.jpeg_color_space == JCS_CMYK || cinfo.jpeg_color_space == JCS_YCCK || cinfo.jpeg_color_space == JCS_GRAYSCALE) {
+ if (cinfo.jpeg_color_space == JCS_CMYK || cinfo.jpeg_color_space == JCS_YCCK) {
jpeg_destroy_decompress(&cinfo);
return IMIO_READERROR;
}
+ cinfo.out_color_space = JCS_RGB;
+
deleteLoadedProfileData();
loadedProfileDataJpg = true;
bool hasprofile = read_icc_profile (&cinfo, (JOCTET**)&loadedProfileData, (unsigned int*)&loadedProfileLength);
@@ -677,8 +679,8 @@ int ImageIO::getTIFFSampleFormat (Glib::ustring fname, IIOSampleFormat &sFormat,
TIFFClose(in);
- if (photometric == PHOTOMETRIC_RGB) {
- if ((samplesperpixel == 3 || samplesperpixel == 4) && sampleformat == SAMPLEFORMAT_UINT) {
+ if (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK) {
+ if ((samplesperpixel == 1 || samplesperpixel == 3 || samplesperpixel == 4) && sampleformat == SAMPLEFORMAT_UINT) {
if (bitspersample == 8) {
sFormat = IIOSF_UNSIGNED_CHAR;
return IMIO_SUCCESS;
@@ -820,7 +822,7 @@ int ImageIO::loadTIFF (Glib::ustring fname)
allocate (width, height);
float minValue[3] = {0.f, 0.f, 0.f}, maxValue[3] = {0.f, 0.f, 0.f};
- unsigned char* linebuffer = new unsigned char[TIFFScanlineSize(in)];
+ unsigned char* linebuffer = new unsigned char[TIFFScanlineSize(in) * (samplesperpixel == 1 ? 3 : 1)];
for (int row = 0; row < height; row++) {
if (TIFFReadScanline(in, linebuffer, row, 0) < 0) {
@@ -829,10 +831,21 @@ int ImageIO::loadTIFF (Glib::ustring fname)
return IMIO_READERROR;
}
- if (samplesperpixel > 3)
+ if (samplesperpixel > 3) {
for (int i = 0; i < width; i++) {
memcpy (linebuffer + i * 3 * bitspersample / 8, linebuffer + i * samplesperpixel * bitspersample / 8, 3 * bitspersample / 8);
}
+ }
+ else if (samplesperpixel == 1) {
+ const size_t bytes = bitspersample / 8;
+ for (int i = width - 1; i >= 0; --i) {
+ const unsigned char* const src = linebuffer + i * bytes;
+ unsigned char* const dest = linebuffer + i * 3 * bytes;
+ memcpy(dest + 2 * bytes, src, bytes);
+ memcpy(dest + 1 * bytes, src, bytes);
+ memcpy(dest + 0 * bytes, src, bytes);
+ }
+ }
if (sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT)) {
setScanline (row, linebuffer, bitspersample, minValue, maxValue);
diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc
index afa791b4f..639841ac5 100644
--- a/rtengine/improccoordinator.cc
+++ b/rtengine/improccoordinator.cc
@@ -540,7 +540,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB, as);
ipf.rgbProc (oprevi, oprevl, nullptr, hltonecurve, shtonecurve, tonecurve, shmap, params.toneCurve.saturation,
- rCurve, gCurve, bCurve, colourToningSatLimit , colourToningSatLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, dcpProf, as);
+ rCurve, gCurve, bCurve, colourToningSatLimit , colourToningSatLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, beforeToneCurveBW, afterToneCurveBW, rrm, ggm, bbm, bwAutoR, bwAutoG, bwAutoB, params.toneCurve.expcomp, params.toneCurve.hlcompr, params.toneCurve.hlcomprthresh, dcpProf, as, histToneCurve);
if(params.blackwhite.enabled && params.blackwhite.autoc && abwListener) {
if (settings->verbose) {
diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc
index 4860648da..8cb1e77c4 100644
--- a/rtengine/improcfun.cc
+++ b/rtengine/improcfun.cc
@@ -2948,15 +2948,15 @@ filmlike_clip(float *r, float *g, float *b)
void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve,
- const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn )
+ const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve )
{
- rgbProc (working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf, asIn);
+ rgbProc (working, lab, pipetteBuffer, hltonecurve, shtonecurve, tonecurve, shmap, sat, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, params->toneCurve.expcomp, params->toneCurve.hlcompr, params->toneCurve.hlcomprthresh, dcpProf, asIn, histToneCurve);
}
// Process RGB image and convert to LAB space
void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clToningcurve, LUTf & cl2Toningcurve,
- const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn )
+ const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve )
{
BENCHFUN
Imagefloat *tmpImage = nullptr;
@@ -3030,6 +3030,9 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
{wprof[2][0], wprof[2][1], wprof[2][2]}
};
+ // For tonecurve histogram
+ float lumimulf[3] = {static_cast(lumimul[0]), static_cast(lumimul[1]), static_cast(lumimul[2])};
+
bool mixchannels = (params->chmixer.red[0] != 100 || params->chmixer.red[1] != 0 || params->chmixer.red[2] != 0 ||
params->chmixer.green[0] != 0 || params->chmixer.green[1] != 100 || params->chmixer.green[2] != 0 ||
@@ -3282,6 +3285,16 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
int W = working->width;
int H = working->height;
+ // For tonecurve histogram
+ int toneCurveHistSize = histToneCurve ? histToneCurve.getSize() : 0;
+ int histToneCurveCompression;
+
+ if(toneCurveHistSize > 0) {
+ histToneCurve.clear();
+ histToneCurveCompression = log2(65536 / toneCurveHistSize);
+ }
+
+
#define TS 112
#ifdef _OPENMP
@@ -3325,6 +3338,12 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
float out_rgbx[4 * TS] ALIGNED16; // Line buffer for CLUT
+ LUTu histToneCurveThr;
+ if(toneCurveHistSize > 0) {
+ histToneCurveThr(toneCurveHistSize);
+ histToneCurveThr.clear();
+ }
+
#ifdef _OPENMP
#pragma omp for schedule(dynamic) collapse(2)
#endif
@@ -3473,6 +3492,10 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
rtemp[ti * TS + tj] = tonecurve[ rtemp[ti * TS + tj] ];
gtemp[ti * TS + tj] = tonecurve[ gtemp[ti * TS + tj] ];
btemp[ti * TS + tj] = tonecurve[ btemp[ti * TS + tj] ];
+ if(histToneCurveThr) {
+ int y = CLIP(lumimulf[0] * Color::gamma2curve[rtemp[ti * TS + tj]] + lumimulf[1] * Color::gamma2curve[gtemp[ti * TS + tj]] + lumimulf[2] * Color::gamma2curve[btemp[ti * TS + tj]]);
+ histToneCurveThr[y>>histToneCurveCompression]++;
+ }
}
}
@@ -4398,7 +4421,14 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
if (editWhateverBuffer) {
free (editWhateverBuffer);
}
-
+#ifdef _OPENMP
+#pragma omp critical
+{
+ if(toneCurveHistSize > 0) {
+ histToneCurve += histToneCurveThr;
+ }
+}
+#endif // _OPENMP
}
// starting a new tile processing with a 'reduction' clause for the auto mixer computing
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 5af2093d9..6a182e67b 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -208,11 +208,11 @@ public:
void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck);
void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2,
- const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn );
+ const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve );
void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2,
const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob,
- double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn );
+ double expcomp, int hlcompr, int hlcomprthresh, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn, LUTu &histToneCurve);
void labtoning (float r, float g, float b, float &ro, float &go, float &bo, int algm, int metchrom, int twoc, float satLimit, float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, LUTf & clToningcurve, LUTf & cl2Toningcurve, float iplow, float iphigh, double wp[3][3], double wip[3][3] );
void toning2col (float r, float g, float b, float &ro, float &go, float &bo, float iplow, float iphigh, float rl, float gl, float bl, float rh, float gh, float bh, float SatLow, float SatHigh, float balanS, float balanH, float reducac, int mode, int preser, float strProtect);
void toningsmh (float r, float g, float b, float &ro, float &go, float &bo, float RedLow, float GreenLow, float BlueLow, float RedMed, float GreenMed, float BlueMed, float RedHigh, float GreenHigh, float BlueHigh, float reducac, int mode, int preser, float strProtect);
diff --git a/rtengine/iplab2rgb.cc b/rtengine/iplab2rgb.cc
index 6b04bb8f2..218dbf6fe 100644
--- a/rtengine/iplab2rgb.cc
+++ b/rtengine/iplab2rgb.cc
@@ -169,9 +169,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
if (icm.outputBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
- printf("lab2rgb / bpc=true\n");
}
- else printf("lab2rgb / bpc=false\n");
lcmsMutex->lock ();
cmsHPROFILE LabIProf = cmsCreateLab4Profile(nullptr);
cmsHTRANSFORM hTransform = cmsCreateTransform (LabIProf, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, icm.outputIntent, flags); // NOCACHE is important for thread safety
@@ -290,19 +288,15 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
iccStore->getGammaArray(icm, *ga);
oprof = iccStore->createGammaProfile(icm, *ga);
lcmsMutex->unlock ();
- printf("iccStore->createGammaProfile(icm, *ga);\n");
} else {
oprof = iccStore->getProfile (icm.output);
-// printf("iccStore->getProfile (%s);\n", icm.output.c_str());
}
if (oprof) {
cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
if (icm.outputBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
-// printf("lab2rgb16 / icm.outputBPC=true / outputIntent=%d\n", icm.outputIntent);
}
-// else printf("lab2rgb16 / icm.outputBPC=false / outputIntent=%d\n", icm.outputIntent);
lcmsMutex->lock ();
cmsHPROFILE iprof = cmsCreateLab4Profile(nullptr);
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, oprof, TYPE_RGB_16, icm.outputIntent, flags);
diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc
index d22fe08f2..7356231cb 100644
--- a/rtengine/iptransform.cc
+++ b/rtengine/iptransform.cc
@@ -794,12 +794,13 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
// multiplier for vignetting correction
double vignmul = 1.0;
- if (needsVignetting())
+ if (needsVignetting()) {
if(darkening) {
vignmul /= std::max(v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001);
} else {
vignmul *= (v + mul * tanh (b * (maxRadius - s * r2) / maxRadius));
}
+ }
if (needsGradient()) {
vignmul *= calcGradientFactor(gp, cx + x, cy + y);
@@ -963,12 +964,13 @@ void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transf
// multiplier for vignetting correction
double vignmul = 1.0;
- if (needsVignetting())
+ if (needsVignetting()) {
if(darkening) {
vignmul /= std::max(v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001);
} else {
vignmul = v + mul * tanh (b * (maxRadius - s * r2) / maxRadius);
}
+ }
if (needsGradient()) {
vignmul *= calcGradientFactor(gp, cx + x, cy + y);
diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc
index 0a09995fe..5fd8b17ff 100644
--- a/rtengine/procparams.cc
+++ b/rtengine/procparams.cc
@@ -1491,6 +1491,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
//save retinex
+ if (!pedited || pedited->retinex.enabled) {
+ keyFile.set_boolean ("Retinex", "Enabled", retinex.enabled);
+ }
+
if (!pedited || pedited->retinex.str) {
keyFile.set_integer ("Retinex", "Str", retinex.str);
}
@@ -1519,10 +1523,6 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_double ("Retinex", "Slope", retinex.slope);
}
- if (!pedited || pedited->retinex.enabled) {
- keyFile.set_boolean ("Retinex", "Enabled", retinex.enabled);
- }
-
if (!pedited || pedited->retinex.medianmap) {
keyFile.set_boolean ("Retinex", "Median", retinex.medianmap);
}
diff --git a/rtengine/procparams.h b/rtengine/procparams.h
index f9d6a60fd..0c06fa315 100644
--- a/rtengine/procparams.h
+++ b/rtengine/procparams.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include
#include
@@ -206,7 +207,7 @@ public:
}
}*/
- Threshold & operator= (const Threshold &rhs)
+ Threshold& operator =(const Threshold &rhs)
{
value[0] = rhs.value[0];
value[1] = rhs.value[1];
@@ -217,16 +218,34 @@ public:
return *this;
}
- bool operator== (const Threshold &rhs) const
+ template
+ typename std::enable_if::value, bool>::type operator ==(const Threshold &rhs) const
{
- if (_isDouble)
- return fabs(value[0] - rhs.value[0]) < 1e-10
- && fabs(value[1] - rhs.value[1]) < 1e-10
- && fabs(value[2] - rhs.value[2]) < 1e-10
- && fabs(value[3] - rhs.value[3]) < 1e-10;
- else
- return fabs(value[0] - rhs.value[0]) < 1e-10
- && fabs(value[1] - rhs.value[1]) < 1e-10;
+ if (_isDouble) {
+ return std::fabs(value[0] - rhs.value[0]) < 1e-10
+ && std::fabs(value[1] - rhs.value[1]) < 1e-10
+ && std::fabs(value[2] - rhs.value[2]) < 1e-10
+ && std::fabs(value[3] - rhs.value[3]) < 1e-10;
+ } else {
+ return std::fabs(value[0] - rhs.value[0]) < 1e-10
+ && std::fabs(value[1] - rhs.value[1]) < 1e-10;
+ }
+ }
+
+ template
+ typename std::enable_if::value, bool>::type operator ==(const Threshold &rhs) const
+ {
+ if (_isDouble) {
+ return
+ value[0] == rhs.value[0]
+ && value[1] == rhs.value[1]
+ && value[2] == rhs.value[2]
+ && value[3] == rhs.value[3];
+ } else {
+ return
+ value[0] == rhs.value[0]
+ && value[1] == rhs.value[1];
+ }
}
};
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index dab8e342c..36b78aa20 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1937,7 +1937,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
}
- if( totBP )
+ if( totBP ) {
if ( ri->getSensorType() == ST_BAYER ) {
if(numFrames == 4) {
for(int i = 0; i < 4; ++i) {
@@ -1951,6 +1951,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
} else {
interpolateBadPixelsNColours( *bitmapBads, ri->get_colors() );
}
+ }
if ( ri->getSensorType() == ST_BAYER && raw.bayersensor.linenoise > 0 ) {
if (plistener) {
diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc
index 9b71d2156..a5ec68433 100644
--- a/rtengine/rtthumbnail.cc
+++ b/rtengine/rtthumbnail.cc
@@ -1062,7 +1062,8 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
}
}
- ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as);
+ LUTu histToneCurve;
+ ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as, histToneCurve);
// freeing up some memory
customToneCurve1.Reset();
diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc
index 250875b6a..0cc10ad63 100644
--- a/rtengine/simpleprocess.cc
+++ b/rtengine/simpleprocess.cc
@@ -859,7 +859,9 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
DCPProfile::ApplyState as;
DCPProfile *dcpProf = imgsrc->getDCP(params.icm, currWB, as);
- ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as);
+ LUTu histToneCurve;
+
+ ipf.rgbProc (baseImg, labView, nullptr, curve1, curve2, curve, shmap, params.toneCurve.saturation, rCurve, gCurve, bCurve, satLimit , satLimitOpacity, ctColorCurve, ctOpacityCurve, opautili, clToningcurve, cl2Toningcurve, customToneCurve1, customToneCurve2, customToneCurvebw1, customToneCurvebw2, rrm, ggm, bbm, autor, autog, autob, expcomp, hlcompr, hlcomprthresh, dcpProf, as, histToneCurve);
if (settings->verbose) {
printf("Output image / Auto B&W coefs: R=%.2f G=%.2f B=%.2f\n", autor, autog, autob);
diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc
index 10b188a21..20dd3eb9d 100644
--- a/rtgui/cropwindow.cc
+++ b/rtgui/cropwindow.cc
@@ -2083,10 +2083,15 @@ void CropWindow::updateHoveredPicker (rtengine::Coord *imgPos)
}
LockableColorPicker::Validity validity = checkValidity (hoveredPicker, cropPos);
hoveredPicker->setValidity (validity);
+
+ {
+ MyMutex::MyLock lock(cropHandler.cimg);
+
if (validity == LockableColorPicker::Validity::INSIDE) {
cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize());
hoveredPicker->setRGB (r, g, b, rpreview, gpreview, bpreview);
}
+ }
}
void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery)
{
@@ -2450,6 +2455,7 @@ void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, in
void CropWindow::cropImageUpdated ()
{
+ MyMutex::MyLock lock(cropHandler.cimg);
for (auto colorPicker : colorPickers) {
Coord imgPos, cropPos;
diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc
index 88d0a062b..2decd48eb 100644
--- a/rtgui/exifpanel.cc
+++ b/rtgui/exifpanel.cc
@@ -430,7 +430,7 @@ void ExifPanel::addPressed ()
} else {
tcombo->set_active_text (sel);
- if (tcombo->get_active () < 0) {
+ if (!tcombo->get_active ()) {
tcombo->append_text (sel);
tcombo->set_active_text (sel);
}
diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h
index 38f5297eb..b8e058eb4 100644
--- a/rtgui/guiutils.h
+++ b/rtgui/guiutils.h
@@ -437,7 +437,7 @@ public:
// you have to check if the surface is created thanks to surfaceCreated before starting to draw on it
bool surfaceCreated()
{
- return surface;
+ return static_cast(surface);
}
Cairo::RefPtr getSurface()
{
diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc
index 32df9f8f6..a8bee4fb3 100644
--- a/rtgui/imagearea.cc
+++ b/rtgui/imagearea.cc
@@ -149,16 +149,43 @@ void ImageArea::setInfoText (Glib::ustring text)
infotext = text;
Glib::RefPtr context = get_pango_context () ;
- Pango::FontDescription fontd = context->get_font_description ();
+ Pango::FontDescription fontd(get_default_style()->get_font());
+
+ // update font
fontd.set_weight (Pango::WEIGHT_BOLD);
fontd.set_size (9 * Pango::SCALE);
context->set_font_description (fontd);
- ilayout = create_pango_layout("");
+
+ // create text layout
+ Glib::RefPtr ilayout = create_pango_layout("");
ilayout->set_markup(text);
+
+ // get size of the text block
int iw, ih;
ilayout->get_pixel_size (iw, ih);
- ipixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, true, 8, iw + 8, ih + 8);
- ipixbuf->fill (128);
+
+ // create BackBuffer
+ iBackBuffer.setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, iw + 16, ih + 16, true);
+ iBackBuffer.setDestPosition(8, 8);
+
+ Cairo::RefPtr cr = iBackBuffer.getContext();
+
+ // cleaning the back buffer (make it full transparent)
+ cr->set_source_rgba (0., 0., 0., 0.);
+ cr->set_operator (Cairo::OPERATOR_CLEAR);
+ cr->paint ();
+ cr->set_operator (Cairo::OPERATOR_OVER);
+
+ // paint transparent black background
+ cr->set_source_rgba (0., 0., 0., 0.5);
+ cr->paint ();
+
+ // paint text
+ cr->set_source_rgb (1.0, 1.0, 1.0);
+ cr->move_to (8, 8);
+ ilayout->add_to_cairo_context (cr);
+ cr->fill ();
+
}
void ImageArea::infoEnabled (bool e)
@@ -206,7 +233,6 @@ bool ImageArea::on_expose_event(GdkEventExpose* event)
return true;
}
- Glib::RefPtr window = get_window();
Cairo::RefPtr cr = get_window()->create_cairo_context();
if (mainCropWindow) {
@@ -214,13 +240,7 @@ bool ImageArea::on_expose_event(GdkEventExpose* event)
}
if (options.showInfo && infotext != "") {
- int fnw, fnh;
- ilayout->get_pixel_size (fnw, fnh);
- window->draw_pixbuf (get_style()->get_base_gc (Gtk::STATE_NORMAL), ipixbuf, 0, 0, 4, 4, fnw + 8, fnh + 8, Gdk::RGB_DITHER_NONE, 0, 0);
- cr->set_source_rgb (1.0, 1.0, 1.0);
- cr->move_to (8, 8);
- ilayout->add_to_cairo_context (cr);
- cr->fill ();
+ iBackBuffer.copySurface(cr);
}
for (std::list::reverse_iterator i = cropWins.rbegin(); i != cropWins.rend(); ++i) {
diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h
index dcdc4f3ec..24a296913 100644
--- a/rtgui/imagearea.h
+++ b/rtgui/imagearea.h
@@ -41,9 +41,8 @@ class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public Edi
protected:
Glib::ustring infotext;
- Glib::RefPtr ilayout;
Glib::RefPtr deglayout;
- Glib::RefPtr ipixbuf;
+ BackBuffer iBackBuffer;
bool showClippedH, showClippedS;
ImageAreaPanel* parent;
diff --git a/rtgui/thresholdselector.cc b/rtgui/thresholdselector.cc
index 34d5bf14a..59320dd2a 100644
--- a/rtgui/thresholdselector.cc
+++ b/rtgui/thresholdselector.cc
@@ -17,9 +17,11 @@
* along with RawTherapee. If not, see .
*/
+#include
+#include
+
#include "thresholdselector.h"
#include "multilangmgr.h"
-#include
#include "mycurve.h"
ThresholdSelector::ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom,
@@ -551,7 +553,7 @@ void ThresholdSelector::findLitCursor(int posX, int posY)
// we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same
double cursorX = (posX - hb) * (maxValTop - minValTop) / (w - 2 * hb) + minValTop;
- if (cursorX > positions[TS_TOPRIGHT] || abs(cursorX - positions[TS_TOPRIGHT]) < abs(cursorX - positions[TS_TOPLEFT])) {
+ if (cursorX > positions[TS_TOPRIGHT] || std::fabs(cursorX - positions[TS_TOPRIGHT]) < std::fabs(cursorX - positions[TS_TOPLEFT])) {
litCursor = TS_TOPRIGHT;
}
}
@@ -564,7 +566,7 @@ void ThresholdSelector::findLitCursor(int posX, int posY)
// we use minValTop since if this block is executed, it means that we are in a simple Threshold where both bottom and top range are the same
double cursorX = (posX - hb) * (maxValTop - minValTop) / (w - 2 * hb) + minValTop;
- if (cursorX > positions[TS_BOTTOMRIGHT] || abs(cursorX - positions[TS_BOTTOMRIGHT]) < abs(cursorX - positions[TS_BOTTOMLEFT])) {
+ if (cursorX > positions[TS_BOTTOMRIGHT] || std::fabs(cursorX - positions[TS_BOTTOMRIGHT]) < std::fabs(cursorX - positions[TS_BOTTOMLEFT])) {
litCursor = TS_BOTTOMRIGHT;
}
}
diff --git a/rtgui/windirmonitor.h b/rtgui/windirmonitor.h
index c3278c931..b9be67a5a 100644
--- a/rtgui/windirmonitor.h
+++ b/rtgui/windirmonitor.h
@@ -24,8 +24,9 @@
class WinDirChangeListener
{
-
public:
+ virtual ~WinDirChangeListener() = default;
+
virtual void winDirChanged () {}
};