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/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 ca1d44cbf..1b546669a 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -539,7 +539,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 586243391..3e0433197 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/rawimage.h b/rtengine/rawimage.h index 88ef5d710..b741a7ffc 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -274,37 +274,37 @@ public: { return profile_data; } - IMFILE *get_file() + IMFILE *get_file() const { return ifp; } bool is_supportedThumb() const ; bool is_jpegThumb() const ; bool is_ppmThumb() const ; - int get_thumbOffset() + int get_thumbOffset() const { return int(thumb_offset); } - int get_thumbWidth() + int get_thumbWidth() const { return int(thumb_width); } - int get_thumbHeight() + int get_thumbHeight() const { return int(thumb_height); } - int get_thumbBPS() + int get_thumbBPS() const { return thumb_load_raw ? 16 : 8; } bool get_thumbSwap() const; - unsigned get_thumbLength() + unsigned get_thumbLength() const { return thumb_length; } - bool zeroIsBad() + bool zeroIsBad() const { - return zero_is_bad == 1 ? true : false; + return zero_is_bad == 1; } public: diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index c135acc39..77e260985 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -41,6 +41,25 @@ #include "StopWatch.h" +namespace +{ + + bool checkRawImageThumb(const rtengine::RawImage& raw_image) + { + if (!raw_image.is_supportedThumb()) { + return false; + } + + const std::size_t length = + fdata(raw_image.get_thumbOffset(), raw_image.get_file())[1] != 0xD8 && raw_image.is_ppmThumb() + ? raw_image.get_thumbWidth() * raw_image.get_thumbHeight() * (raw_image.get_thumbBPS() / 8) * 3 + : raw_image.get_thumbLength(); + + return raw_image.get_thumbOffset() + length < raw_image.get_file()->size; + } + +} + extern Options options; namespace rtengine @@ -175,8 +194,8 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL int err = 1; - // see if it is something we support - if ( ri->is_supportedThumb() && ri->get_thumbOffset() < ri->get_file()->size ) { + // See if it is something we support + if (checkRawImageThumb(*ri)) { const char* data((const char*)fdata(ri->get_thumbOffset(), ri->get_file())); if ( (unsigned char)data[1] == 0xd8 ) { @@ -491,6 +510,17 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati tmph = high; } + const bool rotate_90 = + rotate + && ( + ri->get_rotateDegree() == 90 + || ri->get_rotateDegree() == 270 + ); + + if (rotate_90) { + std::swap(tmpw, tmph); + } + if (fixwh == 1) { // fix height, scale width w = tmpw * h / tmph; } else { @@ -501,8 +531,11 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati delete tpp->thumbImg; } - tpp->thumbImg = nullptr; - tpp->thumbImg = resizeTo(w, h, TI_Bilinear, tmpImg); + if (rotate_90) { + tpp->thumbImg = resizeTo(h, w, TI_Bilinear, tmpImg); + } else { + tpp->thumbImg = resizeTo(w, h, TI_Bilinear, tmpImg); + } delete tmpImg; @@ -1057,7 +1090,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 9e7d5f58f..4fb193c2b 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -858,7 +858,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 e6a9d6e42..7ff139e81 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -2110,9 +2110,14 @@ void CropWindow::updateHoveredPicker (rtengine::Coord *imgPos) } LockableColorPicker::Validity validity = checkValidity (hoveredPicker, cropPos); hoveredPicker->setValidity (validity); - if (validity == LockableColorPicker::Validity::INSIDE) { - cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize()); - hoveredPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); + + { + 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) @@ -2477,6 +2482,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/guiutils.h b/rtgui/guiutils.h index 305ec49c0..0a7489e12 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -519,7 +519,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() {