diff --git a/CMakeLists.txt b/CMakeLists.txt index 99805c216..30721a43c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ option(WITH_MYFILE_MMAP "Build using memory mapped file" ON) option(WITH_LTO "Build with link-time optimizations" OFF) option(WITH_SAN "Build with run-time sanitizer" OFF) option(WITH_PROF "Build with profiling instrumentation" OFF) +option(WITH_SYSTEM_KLT "Build using system KLT library." OFF) option(OPTION_OMP "Build with OpenMP support" ON) option(STRICT_MUTEX "True (recommended): MyMutex will behave like POSIX Mutex; False: MyMutex will behave like POSIX RecMutex; Note: forced to ON for Debug builds" ON) option(TRACE_MYRWMUTEX "Trace custom R/W Mutex (Debug builds only); redirecting std::out to a file is strongly recommended!" OFF) @@ -292,6 +293,9 @@ find_package(JPEG REQUIRED) find_package(PNG REQUIRED) find_package(TIFF REQUIRED) find_package(ZLIB REQUIRED) +if(WITH_SYSTEM_KLT) + find_package(KLT REQUIRED) +endif() # Check for libcanberra-gtk3 (sound events on Linux): if(UNIX AND(NOT APPLE)) diff --git a/cmake/modules/FindKLT.cmake b/cmake/modules/FindKLT.cmake new file mode 100644 index 000000000..f6d28d999 --- /dev/null +++ b/cmake/modules/FindKLT.cmake @@ -0,0 +1,66 @@ +# - Try to find KLT +# Once done this will define +# +# KLT_FOUND - system has KLT +# KLT_INCLUDE_DIRS - the KLT include directory +# KLT_LIBRARIES - Link these to use KLT +# KLT_DEFINITIONS - Compiler switches required for using KLT +# +# Copyright (c) 2009 Andreas Schneider +# updated for KLT by Dan HorĂ¡k +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +if(KLT_LIBRARIES AND KLT_INCLUDE_DIRS) + # in cache already + set(KLT_FOUND TRUE) +else() + find_path(KLT_INCLUDE_DIR + NAMES + klt.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ${CMAKE_INSTALL_PREFIX}/include + PATH_SUFFIXES + klt + ) + mark_as_advanced(KLT_INCLUDE_DIR) + + find_library(KLT_LIBRARY + NAMES + klt + PATHS + /usr/lib64 + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ${CMAKE_INSTALL_PREFIX}/lib + ) + mark_as_advanced(KLT_LIBRARY) + + set(KLT_INCLUDE_DIRS ${KLT_INCLUDE_DIR}) + + set(KLT_LIBRARIES ${KLT_LIBRARY}) + + if(KLT_INCLUDE_DIRS AND KLT_LIBRARIES) + set(KLT_FOUND TRUE) + endif() + + if(KLT_FOUND) + if(NOT KLT_FIND_QUIETLY) + message(STATUS "Found KLT: ${KLT_LIBRARIES}") + endif() + else() + message(STATUS "KLT not found.") + endif() + + mark_as_advanced(KLT_INCLUDE_DIRS KLT_LIBRARIES) +endif() diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index e50c7b3e5..b7a081d7c 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -112,6 +112,22 @@ set(RTENGINESOURCEFILES utils.cc ) +if(NOT WITH_SYSTEM_KLT) + set(RTENGINESOURCEFILES ${RTENGINESOURCEFILES} + klt/convolve.cc + klt/error.cc + klt/klt.cc + klt/klt_util.cc + klt/pnmio.cc + klt/pyramid.cc + klt/selectGoodFeatures.cc + klt/storeFeatures.cc + klt/trackFeatures.cc + klt/writeFeatures.cc + ) + set(KLT_LIBRARIES) +endif() + include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") add_library(rtengine ${RTENGINESOURCEFILES}) diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index 285562d17..5cbc3d140 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -3519,7 +3519,8 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat bdecomp = new wavelet_decomposition (labdn->data + 2 * datalen, labdn->W, labdn->H, levwav, 1); } } - bool autoch = dnparams.autochroma; + const bool autoch = (settings->leveldnautsimpl == 1 && (dnparams.Cmethod == "AUT" || dnparams.Cmethod == "PRE")) || (settings->leveldnautsimpl == 0 && (dnparams.C2method == "AUTO" || dnparams.C2method == "PREV")); + if (comptlevel == 0) { WaveletDenoiseAll_info( diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 330741630..d6bac40de 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -3,8 +3,11 @@ #pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Wsign-compare" #pragma GCC diagnostic ignored "-Wparentheses" -#if (__GNUC__ == 6) +#if (__GNUC__ >= 6) #pragma GCC diagnostic ignored "-Wmisleading-indentation" +#if (__GNUC__ >= 7) +#pragma GCC diagnostic ignored "-Wdangling-else" +#endif #endif #endif diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 3a455c7a2..0d98affef 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -708,10 +708,11 @@ void Crop::update (int todo) if (needstransform) parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, skips (parent->fw, skip), skips (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(), parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(), - parent->imgsrc->getMetaData()->getFocusDist(), parent->imgsrc->getRotateDegree(), false); - else { - baseCrop->copyData (transCrop); - } + parent->imgsrc->getMetaData()->getFocusDist(), + parent->imgsrc->getMetaData()->getFNumber(), + parent->imgsrc->getRotateDegree(), false); + else + baseCrop->copyData(transCrop); if (transCrop) { baseCrop = transCrop; diff --git a/rtengine/helpersse2.h b/rtengine/helpersse2.h index 23dd016fa..7e2185a7f 100644 --- a/rtengine/helpersse2.h +++ b/rtengine/helpersse2.h @@ -30,7 +30,7 @@ typedef __m128i vint2; // #ifdef __GNUC__ -#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4) && (!defined(WIN32) || defined( __x86_64__ )) +#if (!defined(WIN32) || defined( __x86_64__ )) #define LVF(x) _mm_load_ps((float*)&x) #define LVFU(x) _mm_loadu_ps(&x) #define STVF(x,y) _mm_store_ps(&x,y) diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index 4e206e3bb..49ff4790e 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -220,7 +220,7 @@ rtengine::ProfileContent::ProfileContent(const Glib::ustring& fileName) if(length > 0) { char* d = new char[length + 1]; fseek(f, 0, SEEK_SET); - length = fread(d, length, 1, f); + length = fread(d, 1, length, f); d[length] = 0; data.assign(d, length); delete[] d; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 369be2f9a..5faa6175e 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -48,6 +48,7 @@ ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataL ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed(0), aperture(0.), shutter(0.) { + memset (&time, 0, sizeof(time)); root = nullptr; iptc = nullptr; @@ -110,7 +111,6 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed( orientation = "Unknown"; expcomp = 0; focal_len = 0; - memset (&time, 0, sizeof(time)); } } diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 66d10ea5d..5303c22e2 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -479,10 +479,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if (needstransform) ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(), - imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), false); - else { - orig_prev->copyData (oprevi); - } + imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), false); + else + orig_prev->copyData(oprevi); } if ((todo & (M_TRANSFORM | M_RGBCURVE)) && params.dirpyrequalizer.cbdlMethod == "bef" && params.dirpyrequalizer.enabled && !params.colorappearance.enabled) { @@ -3074,7 +3073,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring & fname, bool if (ipf.needsTransform()) { Imagefloat* trImg = new Imagefloat (fW, fH); ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), - imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), true); delete im; im = trImg; } diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index df2587488..d8d6fa7f3 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -237,7 +237,7 @@ public: void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam); void sharpeningcam (CieImage* ncie, float** buffer); void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage); + double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage); float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh); void lab2monitorRgb (LabImage* lab, Image8* image); void resize (Image16* src, Image16* dst, float dScale); diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index c4d9a0a01..ee14c80c2 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -307,7 +307,7 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& } void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, - double focalLen, double focalLen35mm, float focusDist, int rawRotationDeg, bool fullImage) + double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage) { LCPMapper *pLCPMap = nullptr; @@ -317,7 +317,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, if (pLCPProf) { pLCPMap = new LCPMapper (pLCPProf, focalLen, focalLen35mm, - focusDist, 0, false, + focusDist, fNumber, false, params->lensProf.useDist, oW, oH, params->coarse, rawRotationDeg); } diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index ca1ab8405..554634e5f 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -410,9 +410,9 @@ LCPProfile::LCPProfile(const Glib::ustring &fname) } // Two phase filter: first filter out the very rough ones, that distord the average a lot // force it, even if there are few frames (community profiles) - filterBadFrames(2.0, 0); +// filterBadFrames(2.0, 0); // from the non-distorded, filter again on new average basis, but only if there are enough frames left - filterBadFrames(1.5, 100); +// filterBadFrames(1.5, 100); } @@ -538,55 +538,66 @@ void LCPProfile::calcParams(int mode, float focalLength, float focusDist, float float focDist = aPersModel[pm]->focDist; float focDistLog = log(focDist) + euler; double meanErr; - if (aPersModel[pm]->hasModeData(mode)) { - if (mode == 0) { + double lowMeanErr, highMeanErr; + switch (mode) { + case 0: meanErr = aPersModel[pm]->vignette.mean_error; + lowMeanErr = pLow->vignette.mean_error; + highMeanErr = pHigh->vignette.mean_error; + break; + case 1: + meanErr = aPersModel[pm]->base.mean_error; + lowMeanErr = pLow->base.mean_error; + highMeanErr = pHigh->base.mean_error; + break; + default: //case 2: + meanErr = aPersModel[pm]->chromG.mean_error; + lowMeanErr = pLow->chromG.mean_error; + highMeanErr = pHigh->chromG.mean_error; + break; + } - // by aperture (vignette), and max out focus distance - // tests showed doing this by log(aperture) is not as advisable + if (aperture > 0 && mode != 2) { if (aPersModel[pm]->focLen == bestFocLenLow && ( - (aper == aperture && pLow->vignette.mean_error > meanErr) - || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) + (aper == aperture && lowMeanErr > meanErr) + || (aper >= aperture && aper < pLow->aperture && pLow->aperture > aperture) || (aper <= aperture && (pLow->aperture > aperture || fabs(aperture - aper) < fabs(aperture - pLow->aperture))))) { pLow = aPersModel[pm]; } if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (aper == aperture && pHigh->vignette.mean_error > meanErr) - || (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture) - || (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) { + (aper == aperture && highMeanErr > meanErr) + || (aper <= aperture && aper > pHigh->aperture && pHigh->aperture < aperture) + || (aper >= aperture && (pHigh->aperture < aperture || fabs(aperture - aper) < fabs(aperture - pHigh->aperture))))) { + pHigh = aPersModel[pm]; + } + } else if (focusDist > 0 && mode != 0) { + // by focus distance + if (aPersModel[pm]->focLen == bestFocLenLow && ( + (focDist == focusDist && lowMeanErr > meanErr) + || (focDist >= focusDist && focDist < pLow->focDist && pLow->focDist > focusDist) + || (focDist <= focusDist && (pLow->focDist > focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pLow->focDist) + euler)))))) { + pLow = aPersModel[pm]; + } + + if (aPersModel[pm]->focLen == bestFocLenHigh && ( + (focDist == focusDist && highMeanErr > meanErr) + || (focDist <= focusDist && focDist > pHigh->focDist && pHigh->focDist < focusDist) + || (focDist >= focusDist && (pHigh->focDist < focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pHigh->focDist) + euler)))))) { pHigh = aPersModel[pm]; } } else { - meanErr = (mode == 1 ? aPersModel[pm]->base.mean_error : aPersModel[pm]->chromG.mean_error); + // no focus distance available, just error + if (aPersModel[pm]->focLen == bestFocLenLow && lowMeanErr > meanErr) { + pLow = aPersModel[pm]; + } - if (focusDist > 0) { - // by focus distance - if (aPersModel[pm]->focLen == bestFocLenLow && ( - (focDist == focusDist && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr) - || (focDist >= focusDist && focDist < pLow->focDist && pLow->focDist > focusDist) - || (focDist <= focusDist && (pLow->focDist > focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pLow->focDist) + euler)))))) { - pLow = aPersModel[pm]; - } - - if (aPersModel[pm]->focLen == bestFocLenHigh && ( - (focDist == focusDist && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) - || (focDist <= focusDist && focDist > pHigh->focDist && pHigh->focDist < focusDist) - || (focDist >= focusDist && (pHigh->focDist < focusDist || fabs(focusDistLog - focDistLog) < fabs(focusDistLog - (log(pHigh->focDist) + euler)))))) { - pHigh = aPersModel[pm]; - } - } else { - // no focus distance available, just error - if (aPersModel[pm]->focLen == bestFocLenLow && (mode == 1 ? pLow->base.mean_error : pLow->chromG.mean_error) > meanErr) { - pLow = aPersModel[pm]; - } - - if (aPersModel[pm]->focLen == bestFocLenHigh && (mode == 1 ? pHigh->base.mean_error : pHigh->chromG.mean_error) > meanErr) { - pHigh = aPersModel[pm]; - } + if (aPersModel[pm]->focLen == bestFocLenHigh && highMeanErr > meanErr) { + pHigh = aPersModel[pm]; } } + } } } diff --git a/rtengine/opthelper.h b/rtengine/opthelper.h index 4b34fc58f..5e9b97931 100644 --- a/rtengine/opthelper.h +++ b/rtengine/opthelper.h @@ -55,7 +55,7 @@ #define RESTRICT __restrict__ #define LIKELY(x) __builtin_expect (!!(x), 1) #define UNLIKELY(x) __builtin_expect (!!(x), 0) - #if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 9) || __GNUC__ > 4) && (!defined(WIN32) || defined( __x86_64__ )) + #if (!defined(WIN32) || defined( __x86_64__ )) #define ALIGNED64 __attribute__ ((aligned (64))) #define ALIGNED16 __attribute__ ((aligned (16))) #else // there is a bug in gcc 4.7.x when using openmp and aligned memory and -O3, also needed for WIN32 builds diff --git a/rtengine/procevents.h b/rtengine/procevents.h index a282830a2..7e8d82c8f 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -73,7 +73,7 @@ enum ProcEvent { EvLDNRadius = 43, // obsolete EvLDNEdgeTolerance = 44, // obsolete EvCDNEnabled = 45, // obsolete - EvBlendCMSMatrix = 46, + EvBlendCMSMatrix = 46, // obsolete EvDCPToneCurve = 47, EvDCPIlluminant = 48, EvSHEnabled = 49, diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 13e26c0d3..d5fbe7cee 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -593,6 +593,13 @@ void ColorToningParams::getCurves (ColorGradientCurve &colorCurveLUT, OpacityCur opacityCurveLUT.Set (oCurve, opautili); } } + +SharpeningParams::SharpeningParams() : enabled(false), radius(0.5), amount(200), threshold(20, 80, 2000, 1200, false), edgesonly(false), edges_radius(1.9), edges_tolerance(1800), halocontrol(false), halocontrol_amount(85), deconvamount(75), deconvradius(0.75), deconviter(30), deconvdamping(20) {}; + + +VibranceParams::VibranceParams() : enabled(false), pastels(0), saturated(0), psthreshold(0, 75, false), protectskins(false), avoidcolorshift(true), pastsattog(true) {}; + + //WaveletParams::WaveletParams (): hueskin(-5, 25, 170, 120, false), hueskin2(-260, -250, -130, -140, false), hllev(50, 75, 100, 98, false), bllev(0, 2, 50, 25, false), pastlev(0, 2, 30, 20, false), satlev(30, 45, 130, 100, false), edgcont(0, 20, 100, 75, false){ WaveletParams::WaveletParams (): hueskin (-5, 25, 170, 120, false), hueskin2 (-260, -250, -130, -140, false), hllev (50, 75, 100, 98, false), bllev (0, 2, 50, 25, false), @@ -827,7 +834,6 @@ void DirPyrDenoiseParams::setDefaults() enabled = false; enhance = false; median = false; - autochroma = false; perform = false; luma = 0; passes = 1; @@ -1162,7 +1168,6 @@ void RAWParams::setDefaults() void ColorManagementParams::setDefaults() { input = "(cameraICC)"; - blendCMSMatrix = false; toneCurve = false; applyLookTable = false; applyBaselineExposureOffset = true; @@ -2445,10 +2450,6 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_boolean ("Directional Pyramid Denoising", "Median", dirpyrDenoise.median); } - if (!pedited || pedited->dirpyrDenoise.autochroma) { - keyFile.set_boolean ("Directional Pyramid Denoising", "Auto", dirpyrDenoise.autochroma); - } - // if (!pedited || pedited->dirpyrDenoise.perform) keyFile.set_boolean ("Directional Pyramid Denoising", "Perform", dirpyrDenoise.perform); if (!pedited || pedited->dirpyrDenoise.luma) { keyFile.set_double ("Directional Pyramid Denoising", "Luma", dirpyrDenoise.luma); @@ -3168,10 +3169,6 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b keyFile.set_boolean ("Color Management", "ApplyHueSatMap", icm.applyHueSatMap); } - if (!pedited || pedited->icm.blendCMSMatrix) { - keyFile.set_boolean ("Color Management", "BlendCMSMatrix", icm.blendCMSMatrix); - } - if (!pedited || pedited->icm.dcpIlluminant) { keyFile.set_integer ("Color Management", "DCPIlluminant", icm.dcpIlluminant); } @@ -6283,14 +6280,6 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) } } - if (keyFile.has_key ("Directional Pyramid Denoising", "Auto")) { - dirpyrDenoise.autochroma = keyFile.get_boolean ("Directional Pyramid Denoising", "Auto"); - - if (pedited) { - pedited->dirpyrDenoise.autochroma = true; - } - } - // if (keyFile.has_key ("Directional Pyramid Denoising", "Perform")) { dirpyrDenoise.perform = keyFile.get_boolean ("Directional Pyramid Denoising", "Perform"); if (pedited) pedited->dirpyrDenoise.perform = true; } if (keyFile.has_key ("Directional Pyramid Denoising", "Luma")) { dirpyrDenoise.luma = keyFile.get_double ("Directional Pyramid Denoising", "Luma"); @@ -7145,14 +7134,6 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited) } } - if (keyFile.has_key ("Color Management", "BlendCMSMatrix")) { - icm.blendCMSMatrix = keyFile.get_boolean ("Color Management", "BlendCMSMatrix"); - - if (pedited) { - pedited->icm.blendCMSMatrix = true; - } - } - if (keyFile.has_key ("Color Management", "DCPIlluminant")) { icm.dcpIlluminant = keyFile.get_integer ("Color Management", "DCPIlluminant"); @@ -9284,7 +9265,6 @@ bool ProcParams::operator== (const ProcParams& other) && dirpyrDenoise.enabled == other.dirpyrDenoise.enabled && dirpyrDenoise.enhance == other.dirpyrDenoise.enhance && dirpyrDenoise.median == other.dirpyrDenoise.median - && dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma // && dirpyrDenoise.perform == other.dirpyrDenoise.perform && dirpyrDenoise.luma == other.dirpyrDenoise.luma && dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve @@ -9536,7 +9516,6 @@ bool ProcParams::operator== (const ProcParams& other) && icm.applyLookTable == other.icm.applyLookTable && icm.applyBaselineExposureOffset == other.icm.applyBaselineExposureOffset && icm.applyHueSatMap == other.icm.applyHueSatMap - && icm.blendCMSMatrix == other.icm.blendCMSMatrix && icm.dcpIlluminant == other.icm.dcpIlluminant && icm.working == other.icm.working && icm.output == other.icm.output diff --git a/rtengine/procparams.h b/rtengine/procparams.h index e9cf691ce..a007fc6ca 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -471,7 +471,7 @@ public: int deconviter; int deconvdamping; - SharpeningParams() : threshold (20, 80, 2000, 1200, false) {}; + SharpeningParams(); }; class SharpenEdgeParams { @@ -506,7 +506,7 @@ public: bool pastsattog; std::vector skintonescurve; - VibranceParams() : psthreshold (0, 75, false) {}; + VibranceParams(); }; /** @@ -694,7 +694,6 @@ public: bool enabled; bool enhance; bool median; - bool autochroma; bool perform; double luma; @@ -1085,7 +1084,6 @@ public: bool applyLookTable; bool applyBaselineExposureOffset; bool applyHueSatMap; - bool blendCMSMatrix; // setting no longer used int dcpIlluminant; Glib::ustring working; Glib::ustring output; diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index 0847ccfad..d593e3125 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -73,7 +73,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = { 0, // EvLDNRadius: obsolete, 0, // EvLDNEdgeTolerance: obsolete, 0, // EvCDNEnabled:obsolete, - ALL, // EvBlendCMSMatrix, + 0, // free entry RGBCURVE, // EvDCPToneCurve, ALLNORAW, // EvDCPIlluminant, RETINEX, // EvSHEnabled, diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index f163c43c2..6e5b0c9e2 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -1065,7 +1065,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei int origFH; double tscale = 0.0; getDimensions(origFW, origFH, tscale); - ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, 0, true); // Raw rotate degree not detectable here + ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, fnumber, 0, true); // Raw rotate degree not detectable here delete baseImg; baseImg = trImg; } diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index b8e0ada03..1c380fab0 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -822,7 +822,9 @@ private: if (ipf.needsTransform()) { Imagefloat* trImg = new Imagefloat (fw, fh); ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), - imgsrc->getMetaData()->getFocusDist(), imgsrc->getRotateDegree(), true); + imgsrc->getMetaData()->getFocusDist(), + imgsrc->getMetaData()->getFNumber(), + imgsrc->getRotateDegree(), true); delete baseImg; baseImg = trImg; } @@ -2289,13 +2291,7 @@ void startBatchProcessing (ProcessingJob* job, BatchProcessingListener* bpl, boo { if (bpl) -#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__) - // See Issue 2384 "Very bad response time on win7/64 using gcc 4.8 when queue is running" - Glib::Thread::create (sigc::bind (sigc::ptr_fun (batchProcessingThread), job, bpl, tunnelMetaData), 0, true, true, Glib::THREAD_PRIORITY_NORMAL); - -#else - Glib::Thread::create (sigc::bind (sigc::ptr_fun (batchProcessingThread), job, bpl, tunnelMetaData), 0, true, true, Glib::THREAD_PRIORITY_LOW); -#endif + Glib::Thread::create(sigc::bind(sigc::ptr_fun(batchProcessingThread), job, bpl, tunnelMetaData), 0, true, true, Glib::THREAD_PRIORITY_LOW); } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 4ff687502..c12f5f782 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -1085,7 +1085,7 @@ defsubdirs: // read value value = new unsigned char [valuesize]; fread (value, 1, valuesize, f); - int pos = ftell (f); + // count the number of valid subdirs int sdcount = count; @@ -1102,7 +1102,6 @@ defsubdirs: int newpos = base + toInt (j * 4, LONG); fseek (f, newpos, SEEK_SET); directory[i] = new TagDirectory (parent, f, base, attrib->subdirAttribs, order); - fseek (f, pos, SEEK_SET); } // set the terminating NULL @@ -2741,7 +2740,7 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) Tag* tmodel4 = root->getTag ("LocalizedCameraModel"); if (tmodel4) { - const char *model4 = (tmodel4) ? (const char *)tmodel4->getValue() : ""; + const char *model4 = (const char *)tmodel4->getValue(); if (strstr (model4, "Hasselblad ") == model4) { model4 = model4 + 11; @@ -2786,27 +2785,29 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) { - fseek (f, offset, SEEK_SET); - unsigned char markerl = 0xff; - unsigned char c; - fread (&c, 1, 1, f); - const char exifid[] = "Exif\0\0"; - char idbuff[8]; - int tiffbase = -1; + if(!fseek (f, offset, SEEK_SET)) { + unsigned char c; + if(fread (&c, 1, 1, f) == 1) { + constexpr unsigned char markerl = 0xff; + const char exifid[] = "Exif\0\0"; + char idbuff[8]; + int tiffbase = -1; - while (fread (&c, 1, 1, f)) { - if (c != markerl) { - continue; - } + while (fread (&c, 1, 1, f)) { + if (c != markerl) { + continue; + } - if (fread (&c, 1, 1, f) && c == 0xe1) { // APP1 marker found - if (fread (idbuff, 1, 8, f) < 8) { - return nullptr; - } + if (fread (&c, 1, 1, f) && c == 0xe1) { // APP1 marker found + if (fread (idbuff, 1, 8, f) < 8) { + return nullptr; + } - if (!memcmp (idbuff + 2, exifid, 6)) { // Exif info found - tiffbase = ftell (f); - return parse (f, tiffbase); + if (!memcmp (idbuff + 2, exifid, 6)) { // Exif info found + tiffbase = ftell (f); + return parse (f, tiffbase); + } + } } } } diff --git a/rtgui/batchqueue.cc b/rtgui/batchqueue.cc index f1d29c4d6..da042347d 100644 --- a/rtgui/batchqueue.cc +++ b/rtgui/batchqueue.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include "../rtengine/rt_math.h" #include @@ -237,7 +238,12 @@ bool BatchQueue::saveBatchQueue () const auto& saveFormat = entry->saveFormat; // Warning: for code's simplicity in loadBatchQueue, each field must end by the '|' character, safer than ';' or ',' since it can't be used in paths +#ifdef WIN32 + // on windows it crashes if we don't use c_str() and filename etc. contain special (e.g. chinese) characters, see issue 3387 + file << entry->filename.c_str() << '|' << entry->savedParamsFile.c_str() << '|' << entry->outFileName.c_str() << '|' << saveFormat.format << '|' +#else file << entry->filename << '|' << entry->savedParamsFile << '|' << entry->outFileName << '|' << saveFormat.format << '|' +#endif << saveFormat.jpegQuality << '|' << saveFormat.jpegSubSamp << '|' << saveFormat.pngBits << '|' << saveFormat.pngCompression << '|' << saveFormat.tiffBits << '|' << saveFormat.tiffUncompressed << '|' diff --git a/rtgui/coordinateadjuster.cc b/rtgui/coordinateadjuster.cc index ac8e5ea4e..c91ced052 100644 --- a/rtgui/coordinateadjuster.cc +++ b/rtgui/coordinateadjuster.cc @@ -42,13 +42,9 @@ void Axis::setValues(Glib::ustring label, unsigned int decimal, double increment CoordinateAdjuster::AxisAdjuster::AxisAdjuster(CoordinateAdjuster *parent, const Axis *axis, char index) : idx(index), parent(parent), rangeLowerBound(0.f), rangeUpperBound(0.f) { - label = Gtk::manage( new Gtk::Label(axis->label) ); - spinButton = Gtk::manage( new Gtk::SpinButton() ); - label = Gtk::manage (new Gtk::Label(axis->label)); - //label->set_alignment(Gtk::ALIGN_MIDDLE, Gtk::ALIGN_MIDDLE); - - spinButton = Gtk::manage (new Gtk::SpinButton()); + label = Gtk::manage(new Gtk::Label(axis->label)); + spinButton = Gtk::manage(new Gtk::SpinButton()); spinButton->set_name("AxisAdjuster"); spinButton->set_digits(axis->decimal); spinButton->set_increments(axis->increment, axis->pageIncrement); diff --git a/rtgui/dirpyrdenoise.cc b/rtgui/dirpyrdenoise.cc index 61b9bf55a..168a9df03 100644 --- a/rtgui/dirpyrdenoise.cc +++ b/rtgui/dirpyrdenoise.cc @@ -26,7 +26,7 @@ using namespace rtengine; using namespace rtengine::procparams; extern Options options; -DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastenhance(false), lastmedian(false), lastautochroma(false) +DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP_DIRPYRDENOISE_LABEL"), true, true), lastmedian(false) { std::vector milestones; CurveListener::setMulti(true); @@ -83,10 +83,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP Gtk::VBox *chromaVBox = Gtk::manage ( new Gtk::VBox()); chromaVBox->set_spacing(2); - autochroma = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_AUTO"))); - autochroma->set_active (true); - autochroma->set_tooltip_text (M("TP_DIRPYRDENOISE_AUTO_TOOLTIP")); - ctboxC = Gtk::manage (new Gtk::HBox ()); Gtk::Label* labmC = Gtk::manage (new Gtk::Label (M("TP_DIRPYRDENOISE_CTYPE") + ":")); ctboxC->pack_start (*labmC, Gtk::PACK_SHRINK, 1); @@ -167,7 +163,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP luma->hide(); Ldetail->show(); -// autochroma->show(); NoiseLabels->show(); TileLabels->show(); PrevLabels->show(); @@ -178,9 +173,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP gamma->show(); // perform->set_active (true); - enhance = Gtk::manage (new Gtk::CheckButton (M("TP_DIRPYRDENOISE_ENH"))); - enhance->set_active (false); - enhance->set_tooltip_text (M("TP_DIRPYRDENOISE_ENH_TOOLTIP")); // ---- Median FIltering ---- Gtk::Frame* medianFrame = Gtk::manage (new Gtk::Frame ()); @@ -193,10 +185,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP median->set_active (true); medianFrame->set_label_widget(*median); - - Gtk::HSeparator *hsep2 = Gtk::manage (new Gtk::HSeparator()); - hsep2->show (); - methodmed = Gtk::manage (new MyComboBoxText ()); methodmed->append (M("TP_DIRPYRDENOISE_LM")); methodmed->append (M("TP_DIRPYRDENOISE_ABM")); @@ -292,12 +280,10 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP pack_start (*gamma); - //pack_start (*enhance); pack_start (*hsep4); // pack_start( *hb11, Gtk::PACK_SHRINK, 4); -// pack_start (*hsep2); // pack_start (*median); ctboxm->pack_start (*methodmed); @@ -318,8 +304,6 @@ DirPyrDenoise::DirPyrDenoise () : FoldableToolPanel(this, "dirpyrdenoise", M("TP // pack_start (*perform); - enhanConn = enhance->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::enhanceChanged) ); - autochromaConn = autochroma->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::autochromaChanged) ); medianConn = median->signal_toggled().connect( sigc::mem_fun(*this, &DirPyrDenoise::medianChanged) ); ctboxrgb->hide(); @@ -475,13 +459,11 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) Cmethodconn.block(true); C2methodconn.block(true); smethodconn.block(true); - autochromaConn.block(true); medmethodconn.block(true); rgbmethodconn.block(true); methodmedconn.block(true); - autochromaChanged (); dmethod->set_active (0); if (pp->dirpyrDenoise.dmethod == "Lab") { @@ -641,7 +623,6 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) gamma->setEditedState (pedited->dirpyrDenoise.gamma ? Edited : UnEdited); passes->setEditedState (pedited->dirpyrDenoise.passes ? Edited : UnEdited); set_inconsistent (multiImage && !pedited->dirpyrDenoise.enabled); - enhance->set_inconsistent (!pedited->dirpyrDenoise.enhance); median->set_inconsistent (!pedited->dirpyrDenoise.median); ccshape->setUnChanged (!pedited->dirpyrDenoise.cccurve); @@ -650,15 +631,11 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) // perfconn.block (true); setEnabled(pp->dirpyrDenoise.enabled); - enhance->set_active (pp->dirpyrDenoise.enhance); // perform->set_active (pp->dirpyrDenoise.perform); median->set_active (pp->dirpyrDenoise.median); - autochroma->set_active (pp->dirpyrDenoise.autochroma); // perfconn.block (false); lastmedian = pp->dirpyrDenoise.median; - lastautochroma = pp->dirpyrDenoise.autochroma; - lastenhance = pp->dirpyrDenoise.enhance; // lastperform = pp->dirpyrDenoise.perform; luma->setValue (pp->dirpyrDenoise.luma); Ldetail->setValue (pp->dirpyrDenoise.Ldetail); @@ -671,7 +648,6 @@ void DirPyrDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) lshape->setCurve (pp->dirpyrDenoise.lcurve); ccshape->setCurve (pp->dirpyrDenoise.cccurve); - autochromaConn.block(false); dmethodconn.block(false); Lmethodconn.block(false); @@ -708,10 +684,8 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) pp->dirpyrDenoise.gamma = gamma->getValue (); pp->dirpyrDenoise.passes = passes->getValue (); pp->dirpyrDenoise.enabled = getEnabled(); - pp->dirpyrDenoise.enhance = enhance->get_active(); // pp->dirpyrDenoise.perform = perform->get_active(); pp->dirpyrDenoise.median = median->get_active(); - pp->dirpyrDenoise.autochroma = autochroma->get_active(); pp->dirpyrDenoise.lcurve = lshape->getCurve (); pp->dirpyrDenoise.cccurve = ccshape->getCurve (); @@ -732,9 +706,7 @@ void DirPyrDenoise::write (ProcParams* pp, ParamsEdited* pedited) pedited->dirpyrDenoise.gamma = gamma->getEditedState (); pedited->dirpyrDenoise.passes = passes->getEditedState (); pedited->dirpyrDenoise.enabled = !get_inconsistent(); - pedited->dirpyrDenoise.enhance = !enhance->get_inconsistent(); pedited->dirpyrDenoise.median = !median->get_inconsistent(); - pedited->dirpyrDenoise.autochroma = !autochroma->get_inconsistent(); pedited->dirpyrDenoise.lcurve = !lshape->isUnChanged (); pedited->dirpyrDenoise.cccurve = !ccshape->isUnChanged (); @@ -1086,32 +1058,6 @@ void DirPyrDenoise::enabledChanged () } } -void DirPyrDenoise::enhanceChanged () -{ - - if (batchMode) { - if (enhance->get_inconsistent()) { - enhance->set_inconsistent (false); - enhanConn.block (true); - enhance->set_active (false); - enhanConn.block (false); - } else if (lastenhance) { - enhance->set_inconsistent (true); - } - - lastenhance = enhance->get_active (); - } - - if (listener) { - - if (enhance->get_active ()) { - listener->panelChanged (EvDPDNenhance, M("GENERAL_ENABLED")); - } else { - listener->panelChanged (EvDPDNenhance, M("GENERAL_DISABLED")); - } - } -} - void DirPyrDenoise::medianChanged () { @@ -1138,49 +1084,6 @@ void DirPyrDenoise::medianChanged () } } -void DirPyrDenoise::autochromaChanged () -{ -// printf("Autochroma\n"); - if (batchMode) { - if (autochroma->get_inconsistent()) { - autochroma->set_inconsistent (false); - autochromaConn.block (true); - autochroma->set_active (false); - autochromaConn.block (false); - } else if (lastautochroma) { - autochroma->set_inconsistent (true); - } - - lastautochroma = autochroma->get_active (); - } - - if (autochroma->get_active ()) { - chroma->set_sensitive(false); - redchro->set_sensitive(false); - bluechro->set_sensitive(false); - } else { - chroma->set_sensitive(true); - redchro->set_sensitive(true); - bluechro->set_sensitive(true); - } - - if (listener) { - if (autochroma->get_active ()) { - listener->panelChanged (EvDPDNautochroma, M("GENERAL_ENABLED")); - // chroma->set_sensitive(false); - // redchro->set_sensitive(false); - // bluechro->set_sensitive(false); - } else { - listener->panelChanged (EvDPDNautochroma, M("GENERAL_DISABLED")); - //chroma->set_sensitive(true); - //redchro->set_sensitive(true); - //bluechro->set_sensitive(true); - } - - - } -} - /* void DirPyrDenoise::perform_toggled () { diff --git a/rtgui/dirpyrdenoise.h b/rtgui/dirpyrdenoise.h index 9745b374b..cc9a2b5bd 100644 --- a/rtgui/dirpyrdenoise.h +++ b/rtgui/dirpyrdenoise.h @@ -50,9 +50,7 @@ public: void adjusterChanged (Adjuster* a, double newval); void enabledChanged (); - void enhanceChanged (); void medianChanged (); - void autochromaChanged (); void chromaChanged (double autchroma, double autred, double autblue); bool chromaComputed_ (); void noiseChanged (double nresid, double highresid); @@ -92,13 +90,9 @@ private: FlatCurveEditor* lshape; FlatCurveEditor* ccshape; - Gtk::CheckButton* enhance; - bool lastenhance; - sigc::connection enhanConn, medianConn, autochromaConn; + sigc::connection medianConn; Gtk::CheckButton* median; bool lastmedian; - Gtk::CheckButton* autochroma; - bool lastautochroma; Gtk::Label* NoiseLabels; Gtk::Label* TileLabels; Gtk::Label* PrevLabels; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index a334c84a8..e9975196f 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -548,7 +548,6 @@ EditorPanel::EditorPanel (FilePanel* filePanel) Gtk::VSeparator* vsep1 = Gtk::manage (new Gtk::VSeparator ()); Gtk::VSeparator* vsep2 = Gtk::manage (new Gtk::VSeparator ()); - Gtk::VSeparator* vsep3 = Gtk::manage (new Gtk::VSeparator ()); iareapanel = new ImageAreaPanel (); tpc->setEditProvider (iareapanel->imageArea); @@ -681,13 +680,17 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iops->attach_next_to (*vsep2, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*progressLabel, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*vsep1, Gtk::POS_LEFT, 1, 1); - iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1); + if (!gimpPlugin) { + iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1); + } - if (!simpleEditor) { + if (!gimpPlugin) { iops->attach_next_to (*queueimg, Gtk::POS_LEFT, 1, 1); } - iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); + if (!gimpPlugin) { + iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); + } // Color management toolbar @@ -695,6 +698,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) colorMgmtToolBar->pack_right_in (iops); if (!simpleEditor && !options.tabbedUI) { + Gtk::VSeparator* vsep3 = Gtk::manage (new Gtk::VSeparator ()); iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1); iops->attach_next_to (*navPrev, Gtk::POS_RIGHT, 1, 1); iops->attach_next_to (*navSync, Gtk::POS_RIGHT, 1, 1); @@ -1579,7 +1583,9 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) return true; case GDK_KEY_s: - saveAsPressed(); + if (!gimpPlugin) { + saveAsPressed(); + } return true; case GDK_KEY_b: @@ -1590,7 +1596,9 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) return true; case GDK_KEY_e: - sendToGimpPressed(); + if (!gimpPlugin) { + sendToGimpPressed(); + } return true; case GDK_KEY_z: @@ -1889,6 +1897,30 @@ void EditorPanel::sendToGimpPressed () } +bool EditorPanel::saveImmediately(const Glib::ustring &filename, const SaveFormat &sf) +{ + rtengine::procparams::ProcParams pparams; + ipc->getParams (&pparams); + std::unique_ptr job(rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams)); + + // save immediately + rtengine::IImage16 *img = rtengine::processImage(job.get(), err, nullptr, options.tunnelMetaData, false); + + int err = 0; + if (sf.format == "tif") { + err = img->saveAsTIFF(filename, sf.tiffBits, sf.tiffUncompressed); + } else if (sf.format == "png") { + err = img->saveAsPNG(filename, sf.pngCompression, sf.pngBits); + } else if (sf.format == "jpg") { + err = img->saveAsJPEG(filename, sf.jpegQuality, sf.jpegSubSamp); + } else { + err = 1; + } + img->free(); + return !err; +} + + void EditorPanel::openPreviousEditorImage() { if (!simpleEditor && fPanel && !fname.empty()) { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 6cfedb634..050909d7d 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -131,6 +131,8 @@ public: void defaultMonitorProfileChanged(const Glib::ustring &profile_name, bool auto_monitor_profile); + bool saveImmediately(const Glib::ustring &filename, const SaveFormat &sf); + Gtk::Paned* catalogPane; private: diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 3051e6e74..34cb2c064 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -88,10 +88,6 @@ ExifPanel::ExifPanel () : idata(nullptr) pack_start (*scrolledWindow); - Gtk::Grid* buttons = Gtk::manage(new Gtk::Grid()); - buttons->set_row_homogeneous(true); - buttons->set_column_homogeneous(true); - setExpandAlignProperties(buttons, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); Gtk::Grid* buttons1 = Gtk::manage(new Gtk::Grid()); buttons1->set_row_homogeneous(true); buttons1->set_column_homogeneous(true); diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index 9bce8575a..d76870788 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -205,11 +205,7 @@ void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengi cropParams }; -#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__) - const gint priority = G_PRIORITY_DEFAULT; -#else const gint priority = G_PRIORITY_LOW; -#endif const auto func = [](gpointer data) -> gboolean { tiupdate* const params = static_cast(data); diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 1aa997095..316beb791 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -190,8 +190,12 @@ void FilePanel::init () dirBrowser->fillDirTree (); placesBrowser->refreshPlacesList (); - if (argv1 != "" && Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { - dirBrowser->open (argv1); + if (!argv1.empty() && Glib::file_test (argv1, Glib::FILE_TEST_EXISTS)) { + Glib::ustring d(argv1); + if (!Glib::file_test(d, Glib::FILE_TEST_IS_DIR)) { + d = Glib::path_get_dirname(d); + } + dirBrowser->open(d); } else { if (options.startupDir == STARTUPDIR_HOME) { dirBrowser->open (PlacesBrowser::userPicturesDir ()); diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index 91348e52f..4d9dd3c5c 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -1330,26 +1330,6 @@ BackBuffer::BackBuffer(int width, int height, Cairo::Format format) : x(0), y(0) } } -BackBuffer::BackBuffer(int width, int height, Glib::RefPtr referenceWindow) : x(0), y(0), w(width), h(height), offset(0, 0), dirty(true) -{ - if (w > 0 && h > 0 && referenceWindow) { - Cairo::RefPtr surf = referenceWindow->create_similar_image_surface(Cairo::FORMAT_RGB24, w, h, 0); - Cairo::SurfaceType type = surf->get_type(); - - if (type == Cairo::SURFACE_TYPE_IMAGE || type == Cairo::SURFACE_TYPE_WIN32) { - surface = Cairo::RefPtr::cast_static(surf); - - if (!surface || !surface->get_width() || !surface->get_height()) { - printf("ERRRROOOOORRRR!\n"); - } - } else { - printf("ERROR: wrong surface type. 0 or 7 was expected, but we've got %d instead.\n", type); - } - } else { - w = h = 0; - } -} - void BackBuffer::setDestPosition(int x, int y) { // values will be clamped when used... diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index a6ec916f0..085027577 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -509,7 +509,6 @@ protected: public: BackBuffer(); BackBuffer(int w, int h, Cairo::Format format = Cairo::FORMAT_RGB24); - BackBuffer(int w, int h, Glib::RefPtr referenceWindow); // set the destination drawing rectangle; return true if the dimensions are different // Note: newW & newH must be > 0 diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 232d626a0..e80b2028a 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -32,7 +32,7 @@ extern Options options; ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(nullptr), icmplistener(nullptr), lastRefFilename(""), camName("") { - isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = lastBlendCMSMatrix = lastgamfree = false; + isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = lastgamfree = false; ipDialog = Gtk::manage (new MyFileChooserButton (M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN)); ipDialog->set_tooltip_text (M("TP_ICM_INPUTCUSTOM_TOOLTIP")); @@ -138,12 +138,6 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch dcpFrame->set_sensitive(false); iVBox->pack_start (*dcpFrame); - ckbBlendCMSMatrix = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_BLENDCMSMATRIX"))); - ckbBlendCMSMatrix->set_sensitive (false); - ckbBlendCMSMatrix->set_tooltip_text (M("TP_ICM_BLENDCMSMATRIX_TOOLTIP")); - // blend cms matrix no longer used - //iVBox->pack_start (*ckbBlendCMSMatrix, Gtk::PACK_SHRINK, 2); - saveRef = Gtk::manage (new Gtk::Button (M("TP_ICM_SAVEREFERENCE"))); saveRef->set_image (*Gtk::manage (new RTImage ("gtk-save-large.png"))); saveRef->set_alignment (0.5f, 0.5f); @@ -318,7 +312,6 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch ltableconn = ckbApplyLookTable->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::applyLookTableChanged)); beoconn = ckbApplyBaselineExposureOffset->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::applyBaselineExposureOffsetChanged)); hsmconn = ckbApplyHueSatMap->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::applyHueSatMapChanged)); - blendcmsconn = ckbBlendCMSMatrix->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::blendCMSMatrixChanged)); icamera->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); icameraICC->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); @@ -494,7 +487,6 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) ConnectionBlocker ltableconn_(ltableconn); ConnectionBlocker beoconn_(beoconn); ConnectionBlocker hsmconn_(hsmconn); - ConnectionBlocker blendcmsconn_(blendcmsconn); ConnectionBlocker wnamesconn_(wnamesconn); ConnectionBlocker onamesconn_(onamesconn); ConnectionBlocker ointentconn_(ointentconn); @@ -507,50 +499,29 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) if (pp->icm.input == "(none)") { inone->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (false); - } updateDCP(pp->icm.dcpIlluminant, ""); } else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { iembedded->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (false); - } updateDCP(pp->icm.dcpIlluminant, ""); } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { icameraICC->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (true); - } updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); } else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() != Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { // this is the case when (cameraICC) is instructed by packaged profiles, but ICC file is not found // therefore falling back UI to explicitly reflect the (camera) option icamera->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (false); - } updateDCP(pp->icm.dcpIlluminant, ""); } else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() == Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { // If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded). iembedded->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (false); - } updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); } else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) { icamera->set_active (true); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (false); - } updateDCP(pp->icm.dcpIlluminant, ""); } else { ifromfile->set_active (true); oldip = pp->icm.input.substr(5); // cut of "file:" ipDialog->set_filename (pp->icm.input.substr(5)); - if (!batchMode) { - ckbBlendCMSMatrix->set_sensitive (true); - } updateDCP(pp->icm.dcpIlluminant, pp->icm.input.substr(5)); } @@ -578,9 +549,6 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) ckbApplyHueSatMap->set_active (pp->icm.applyHueSatMap); lastApplyHueSatMap = pp->icm.applyHueSatMap; - ckbBlendCMSMatrix->set_active (pp->icm.blendCMSMatrix); - lastBlendCMSMatrix = pp->icm.blendCMSMatrix; - freegamma->set_active (pp->icm.freegamma); lastgamfree = pp->icm.freegamma; @@ -602,7 +570,6 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) ckbApplyLookTable->set_inconsistent(!pedited->icm.applyLookTable); ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset); ckbApplyHueSatMap->set_inconsistent(!pedited->icm.applyHueSatMap); - ckbBlendCMSMatrix->set_inconsistent(!pedited->icm.blendCMSMatrix); freegamma->set_inconsistent (!pedited->icm.freegamma); if (!pedited->icm.working) { @@ -677,7 +644,6 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) pp->icm.applyLookTable = ckbApplyLookTable->get_active (); pp->icm.applyBaselineExposureOffset = ckbApplyBaselineExposureOffset->get_active (); pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active (); - pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active (); pp->icm.gampos = (double) gampos->getValue(); pp->icm.slpos = (double) slpos->getValue(); pp->icm.outputBPC = obpc->get_active (); @@ -693,7 +659,6 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent (); pedited->icm.applyBaselineExposureOffset = !ckbApplyBaselineExposureOffset->get_inconsistent (); pedited->icm.applyHueSatMap = !ckbApplyHueSatMap->get_inconsistent (); - pedited->icm.blendCMSMatrix = !ckbBlendCMSMatrix->get_inconsistent (); pedited->icm.gamma = wgamma->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.freegamma = !freegamma->get_inconsistent(); pedited->icm.gampos = gampos->getEditedState (); @@ -871,19 +836,14 @@ void ICMPanel::ipChanged () if (inone->get_active()) { profname = "(none)"; - ckbBlendCMSMatrix->set_sensitive(false); } else if (iembedded->get_active ()) { profname = "(embedded)"; - ckbBlendCMSMatrix->set_sensitive(false); } else if (icamera->get_active ()) { profname = "(camera)"; - ckbBlendCMSMatrix->set_sensitive(false); } else if (icameraICC->get_active ()) { profname = "(cameraICC)"; - ckbBlendCMSMatrix->set_sensitive(true); } else { profname = ipDialog->get_filename (); - ckbBlendCMSMatrix->set_sensitive(true); } updateDCP(-1, profname); @@ -895,32 +855,6 @@ void ICMPanel::ipChanged () oldip = profname; } -void ICMPanel::blendCMSMatrixChanged() -{ - if (multiImage) { - if (ckbBlendCMSMatrix->get_inconsistent()) { - ckbBlendCMSMatrix->set_inconsistent (false); - blendcmsconn.block (true); - ckbBlendCMSMatrix->set_active (false); - blendcmsconn.block (false); - } else if (lastBlendCMSMatrix) { - ckbBlendCMSMatrix->set_inconsistent (true); - } - - lastBlendCMSMatrix = ckbBlendCMSMatrix->get_active (); - } - - if (listener) { - if (ckbBlendCMSMatrix->get_inconsistent()) { - listener->panelChanged (EvBlendCMSMatrix, M("GENERAL_UNCHANGED")); - } else if (ckbBlendCMSMatrix->get_active()) { - listener->panelChanged (EvBlendCMSMatrix, M("GENERAL_ENABLED")); - } else { - listener->panelChanged (EvBlendCMSMatrix, M("GENERAL_DISABLED")); - } - } -} - void ICMPanel::GamChanged() { if (multiImage) { diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 846129105..0e7deefa9 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -56,9 +56,7 @@ protected: sigc::connection hsmconn; bool lastobpc; sigc::connection obpcconn; - bool lastBlendCMSMatrix; bool isBatchMode; - sigc::connection blendcmsconn; private: Gtk::VBox * iVBox; @@ -78,7 +76,6 @@ private: Gtk::CheckButton* ckbApplyLookTable; Gtk::CheckButton* ckbApplyBaselineExposureOffset; Gtk::CheckButton* ckbApplyHueSatMap; - Gtk::CheckButton* ckbBlendCMSMatrix; MyComboBoxText* wnames; sigc::connection wnamesconn; MyComboBoxText* wgamma; @@ -119,7 +116,6 @@ public: void gpChanged (); void GamChanged (); void ipSelectionChanged (); - void blendCMSMatrixChanged(); void dcpIlluminantChanged(); void toneCurveChanged(); void applyLookTableChanged(); diff --git a/rtgui/main.cc b/rtgui/main.cc index c77b0b205..d269bf948 100644 --- a/rtgui/main.cc +++ b/rtgui/main.cc @@ -60,7 +60,9 @@ Glib::ustring argv0; Glib::ustring creditsPath; Glib::ustring licensePath; Glib::ustring argv1; -bool simpleEditor; +Glib::ustring argv2; +bool simpleEditor = false; +bool gimpPlugin = false; Glib::RefPtr cssForced; Glib::RefPtr cssRT; //Glib::Threads::Thread* mainThread; @@ -292,12 +294,21 @@ int main (int argc, char **argv) #endif - simpleEditor = false; - - if ( !argv1.empty() ) - if ( Glib::file_test (argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test (argv1, Glib::FILE_TEST_IS_DIR)) { + if (!argv1.empty()) { + if( Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) && !Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { simpleEditor = true; } + } + if (gimpPlugin) { + if (!Glib::file_test(argv1, Glib::FILE_TEST_EXISTS) || Glib::file_test(argv1, Glib::FILE_TEST_IS_DIR)) { + printf("Error: argv1 doesn't exist\n"); + return 1; + } + if (argv2.empty()) { + printf("Error: -gimp requires two arguments\n"); + return 1; + } + } Gtk::Main m (&argc, &argv); @@ -390,7 +401,18 @@ int main (int argc, char **argv) // opening the main window m.run (*rtWindow); + if (gimpPlugin && rtWindow->epanel && rtWindow->epanel->isRealized()) { + SaveFormat sf; + sf.format = "tif"; + sf.tiffBits = 16; + sf.tiffUncompressed = true; + sf.saveParams = true; + + rtWindow->epanel->saveImmediately(argv2, sf); + } + gdk_threads_leave (); + delete rtWindow; rtengine::cleanup(); @@ -433,6 +455,16 @@ int processLineParams ( int argc, char **argv ) case 'w': // This case is handled outside this function break; #endif + case 'g': + if (currParam == "-gimp") { + simpleEditor = true; + gimpPlugin = true; + break; + } + // no break here on purpose + + case 'v': + return 0; case 'h': case '?': @@ -459,16 +491,24 @@ int processLineParams ( int argc, char **argv ) #ifdef WIN32 std::cout << " -w Do not open the Windows console" << std::endl; #endif - std::cout << " -h -? Display this help message" << std::endl; - return -1; - } + std::cout << " -v Print RawTherapee version number and exit" << std::endl; + std::cout << " -h -? Display this help message" << std::endl; + return -1; + } } } else { - argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); + if (argv1.empty()) { + argv1 = Glib::ustring(fname_to_utf8(argv[iArg])); #if ECLIPSE_ARGS - argv1 = argv1.substr(1, argv1.length()-2); + argv1 = argv1.substr(1, argv1.length()-2); #endif - break; + } else if (gimpPlugin) { + argv2 = Glib::ustring(fname_to_utf8(argv[iArg])); + break; + } + if (!gimpPlugin) { + break; + } } } diff --git a/rtgui/options.h b/rtgui/options.h index 6a5f2db8a..40429075e 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -363,6 +363,7 @@ extern Options options; extern Glib::ustring argv0; extern Glib::ustring argv1; extern bool simpleEditor; +extern bool gimpPlugin; extern Glib::ustring versionString; extern Glib::ustring paramFileExtension; diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index e63717f51..b55665c91 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -235,7 +235,6 @@ void ParamsEdited::set (bool v) dirpyrDenoise.lcurve = v; dirpyrDenoise.cccurve = v; dirpyrDenoise.median = v; - dirpyrDenoise.autochroma = v; dirpyrDenoise.luma = v; dirpyrDenoise.Ldetail = v; dirpyrDenoise.chroma = v; @@ -425,7 +424,6 @@ void ParamsEdited::set (bool v) icm.applyLookTable = v; icm.applyBaselineExposureOffset = v; icm.applyHueSatMap = v; - icm.blendCMSMatrix = v; icm.dcpIlluminant = v; icm.working = v; icm.output = v; @@ -835,7 +833,6 @@ void ParamsEdited::initFrom (const std::vector dirpyrDenoise.enabled = dirpyrDenoise.enabled && p.dirpyrDenoise.enabled == other.dirpyrDenoise.enabled; dirpyrDenoise.enhance = dirpyrDenoise.enhance && p.dirpyrDenoise.enhance == other.dirpyrDenoise.enhance; dirpyrDenoise.median = dirpyrDenoise.median && p.dirpyrDenoise.median == other.dirpyrDenoise.median; - dirpyrDenoise.autochroma = dirpyrDenoise.autochroma && p.dirpyrDenoise.autochroma == other.dirpyrDenoise.autochroma; // dirpyrDenoise.perform = dirpyrDenoise.perform && p.dirpyrDenoise.perform == other.dirpyrDenoise.perform; dirpyrDenoise.luma = dirpyrDenoise.luma && p.dirpyrDenoise.luma == other.dirpyrDenoise.luma; dirpyrDenoise.lcurve = dirpyrDenoise.lcurve && p.dirpyrDenoise.lcurve == other.dirpyrDenoise.lcurve; @@ -1027,7 +1024,6 @@ void ParamsEdited::initFrom (const std::vector icm.applyLookTable = icm.applyLookTable && p.icm.applyLookTable == other.icm.applyLookTable; icm.applyBaselineExposureOffset = icm.applyBaselineExposureOffset && p.icm.applyBaselineExposureOffset == other.icm.applyBaselineExposureOffset; icm.applyHueSatMap = icm.applyHueSatMap && p.icm.applyHueSatMap == other.icm.applyHueSatMap; - icm.blendCMSMatrix = icm.blendCMSMatrix && p.icm.blendCMSMatrix == other.icm.blendCMSMatrix; icm.dcpIlluminant = icm.dcpIlluminant && p.icm.dcpIlluminant == other.icm.dcpIlluminant; icm.working = icm.working && p.icm.working == other.icm.working; icm.output = icm.output && p.icm.output == other.icm.output; @@ -1976,10 +1972,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.dirpyrDenoise.median = mods.dirpyrDenoise.median; } - if (dirpyrDenoise.autochroma) { - toEdit.dirpyrDenoise.autochroma = mods.dirpyrDenoise.autochroma; - } - if (dirpyrDenoise.luma) { toEdit.dirpyrDenoise.luma = dontforceSet && options.baBehav[ADDSET_DIRPYRDN_LUMA] ? toEdit.dirpyrDenoise.luma + mods.dirpyrDenoise.luma : mods.dirpyrDenoise.luma; } @@ -2698,10 +2690,6 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten toEdit.icm.applyHueSatMap = mods.icm.applyHueSatMap; } - if (icm.blendCMSMatrix) { - toEdit.icm.blendCMSMatrix = mods.icm.blendCMSMatrix; - } - if (icm.dcpIlluminant) { toEdit.icm.dcpIlluminant = mods.icm.dcpIlluminant; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 022d54a91..b8926c30e 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -321,7 +321,6 @@ public: bool enabled; bool enhance; bool median; - bool autochroma; bool Ldetail; bool luma; bool chroma; @@ -617,7 +616,6 @@ public: bool applyLookTable; bool applyBaselineExposureOffset; bool applyHueSatMap; - bool blendCMSMatrix; bool dcpIlluminant; bool working; bool output; diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index ca1a011b9..e40d95f15 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -283,6 +283,13 @@ RTWindow::RTWindow () show_all (); bpanel->init (this); + + if (!argv1.empty()) { + Thumbnail* thm = cacheMgr->getEntry(argv1); + if (thm) { + fpanel->fileCatalog->openRequested({thm}); + } + } } if (!isSingleTabMode() && !simpleEditor) { @@ -663,6 +670,7 @@ bool RTWindow::on_delete_event(GdkEventAny* event) Options::save (); hide(); + on_delete_has_run = true; return false; } diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index d6c2acd9d..531ed8c25 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -697,10 +697,8 @@ void ThumbBrowserBase::Internal::on_realize() bgn = style->get_background_color(Gtk::STATE_FLAG_NORMAL); bgs = style->get_background_color(Gtk::STATE_FLAG_SELECTED); - Glib::RefPtr window = get_window(); set_can_focus(true); add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::SCROLL_MASK | Gdk::KEY_PRESS_MASK); - //cc = window->create_cairo_context(); set_has_tooltip (true); signal_query_tooltip().connect( sigc::mem_fun(*this, &ThumbBrowserBase::Internal::on_query_tooltip) ); } @@ -842,8 +840,6 @@ bool ThumbBrowserBase::Internal::on_draw(const ::Cairo::RefPtr< Cairo::Context> dirty = false; - Glib::RefPtr window = get_window(); - int w = get_width(); int h = get_height(); diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index 6fa8eac52..cf0ce1bb3 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -56,20 +56,12 @@ void ThumbBrowserEntryBase::updateBackBuffer () Gtk::Widget* w = parent->getDrawingArea (); - Glib::RefPtr win = w->get_window(); - - if (!win) - // Nothing to draw on, so we return - { - return; - } - if (backBuffer && (backBuffer->getWidth() != exp_width || backBuffer->getHeight() != exp_height )) { // deleting the existing BackBuffer backBuffer.reset(); } if (!backBuffer) { - backBuffer = Glib::RefPtr ( new BackBuffer (exp_width, exp_height, win) ); + backBuffer = Glib::RefPtr(new BackBuffer(exp_width, exp_height)); } // If thumbnail is hidden by a filter, drawing to it will crash diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index 95618d5ab..533967b72 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -68,11 +68,8 @@ public: inactive_waiting_(false) { int threadCount = 1; -#if !(__GNUC__ == 4 && __GNUC_MINOR__ == 8 && defined( WIN32 ) && defined(__x86_64__)) - // See Issue 2431 for explanation #ifdef _OPENMP threadCount = omp_get_num_procs(); -#endif #endif threadPool_ = new Glib::ThreadPool(threadCount, 0); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 5aa665398..323e46653 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -219,35 +219,36 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const CacheImageData* cfs = getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); const bool create = (!hasProcParams() || force); + const bool run_cpb = !options.CPBPath.empty() && !defaultPparamsPath.empty() && cfs && cfs->exifValid && create; const Glib::ustring outFName = (options.paramsLoadLocation == PLL_Input && options.saveParamsFile) ? fname + paramFileExtension : getCacheFileName("profiles", paramFileExtension); - if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { - rtengine::ImageMetaData* imageMetaData; - if (getType() == FT_Raw) { - rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); - imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); - } else { - imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + if (!run_cpb) { + if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { + rtengine::ImageMetaData* imageMetaData; + if (getType() == FT_Raw) { + rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); + imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + } else { + imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + } + PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData); + int err = pp->pparams->save(outFName); + pp->deleteInstance(); + delete pp; + if (!err) { + loadProcParams(); + } + } else if (create && defProf != DEFPROFILE_DYNAMIC) { + const PartialProfile *p = ProfileStore::getInstance()->getProfile(defProf); + if (p && !p->pparams->save(outFName)) { + loadProcParams(); + } } - PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData); - int err = pp->pparams->save(outFName); - pp->deleteInstance(); - delete pp; - if (!err) { - loadProcParams(); - } - } else if (create && defProf != DEFPROFILE_DYNAMIC) { - const PartialProfile *p = ProfileStore::getInstance()->getProfile(defProf); - if (p && !p->pparams->save(outFName)) { - loadProcParams(); - } - } - - if (!options.CPBPath.empty() && !defaultPparamsPath.empty() && create && cfs && cfs->exifValid) { + } else { // First generate the communication file, with general values and EXIF metadata rtengine::ImageMetaData* imageMetaData; diff --git a/tools/gimp-plugin/file-formats.h b/tools/gimp-plugin/file-formats.h new file mode 100644 index 000000000..b967c7cbe --- /dev/null +++ b/tools/gimp-plugin/file-formats.h @@ -0,0 +1,316 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-rawtherapee.c -- raw file format plug-in that uses rawtherapee + * Copyright (C) 2016 Tobias Ellinghaus + * Copyright (C) 2017 Alberto Griggio + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +/* These are the raw formats that file-rawtherapee will register */ + +typedef struct _FileFormat FileFormat; + +struct _FileFormat +{ + const gchar *file_type; + const gchar *mime_type; + const gchar *extensions; + const gchar *magic; + + const gchar *load_proc; + const gchar *load_blurb; + const gchar *load_help; +}; + +#define N_(s) s +#define _(s) s + +static const FileFormat file_formats[] = +{ + { + N_("Raw Canon"), + "image/x-canon-cr2,image/x-canon-crw", + "cr2,crw", + NULL, + + "file-rawtherapee-canon-load", + "Load files in the Canon raw formats via rawtherapee", + "This plug-in loads files in Canon's raw formats by calling rawtherapee." + }, + + { + N_("Raw Nikon"), + "image/x-nikon-nef,image/x-nikon-nrw", + "nef,nrw", + NULL, + + "file-rawtherapee-nikon-load", + "Load files in the Nikon raw formats via rawtherapee", + "This plug-in loads files in Nikon's raw formats by calling rawtherapee." + }, + + { + N_("Raw Hasselblad"), + "image/x-hasselblad-3fr,image/x-hasselblad-fff", + "3fr,fff", + NULL, + + "file-rawtherapee-hasselblad-load", + "Load files in the Hasselblad raw formats via rawtherapee", + "This plug-in loads files in Hasselblad's raw formats by calling rawtherapee." + }, + + { + N_("Raw Sony"), + "image/x-sony-arw,image/x-sony-srf,image/x-sony-sr2", + "arw,srf,sr2", + NULL, + + "file-rawtherapee-sony-load", + "Load files in the Sony raw formats via rawtherapee", + "This plug-in loads files in Sony's raw formats by calling rawtherapee." + }, + + { + N_("Raw Casio BAY"), + "image/x-casio-bay", + "bay", + NULL, + + "file-rawtherapee-bay-load", + "Load files in the BAY raw format via rawtherapee", + "This plug-in loads files in Casio's raw BAY format by calling rawtherapee." + }, + + { + N_("Raw Phantom Software CINE"), + "", /* FIXME: find a mime type */ + "cine,cin", + NULL, + + "file-rawtherapee-cine-load", + "Load files in the CINE raw format via rawtherapee", + "This plug-in loads files in Phantom Software's raw CINE format by calling rawtherapee." + }, + + { + N_("Raw Sinar"), + "", /* FIXME: find a mime type */ + "cs1,ia,sti", + NULL, + + "file-rawtherapee-sinar-load", + "Load files in the Sinar raw formats via rawtherapee", + "This plug-in loads files in Sinar's raw formats by calling rawtherapee." + }, + + { + N_("Raw Kodak"), + "image/x-kodak-dc2,image/x-kodak-dcr,image/x-kodak-kdc,image/x-kodak-k25,image/x-kodak-kc2", + "dc2,dcr,kdc,k25,kc2", + NULL, + + "file-rawtherapee-kodak-load", + "Load files in the Kodak raw formats via rawtherapee", + "This plug-in loads files in Kodak's raw formats by calling rawtherapee." + }, + + { + N_("Raw Adobe DNG Digital Negative"), + "image/x-adobe-dng", + "dng", + NULL, + + "file-rawtherapee-dng-load", + "Load files in the DNG raw format via rawtherapee", + "This plug-in loads files in the Adobe Digital Negative DNG format by calling rawtherapee." + }, + + { + N_("Raw Epson ERF"), + "image/x-epson-erf", + "erf", + NULL, + + "file-rawtherapee-erf-load", + "Load files in the ERF raw format via rawtherapee", + "This plug-in loads files in Epson's raw ERF format by calling rawtherapee." + }, + + { + N_("Raw Phase One"), + "image/x-phaseone-cap,image/x-phaseone-iiq", + "cap,iiq", + NULL, + + "file-rawtherapee-phaseone-load", + "Load files in the Phase One raw formats via rawtherapee", + "This plug-in loads files in Phase One's raw formats by calling rawtherapee." + }, + + { + N_("Raw Minolta"), + "image/x-minolta-mdc,image/x-minolta-mrw", + "mdc,mrw", + NULL, + + "file-rawtherapee-minolta-load", + "Load files in the Minolta raw formats via rawtherapee", + "This plug-in loads files in Minolta's raw formats by calling rawtherapee." + }, + + { + N_("Raw Mamiya MEF"), + "image/x-mamiya-mef", + "mef", NULL, + + "file-rawtherapee-mef-load", + "Load files in the MEF raw format via rawtherapee", + "This plug-in loads files in Mamiya's raw MEF format by calling rawtherapee." + }, + + { + N_("Raw Leaf MOS"), + "image/x-leaf-mos", + "mos", + NULL, + + "file-rawtherapee-mos-load", + "Load files in the MOS raw format via rawtherapee", + "This plug-in loads files in Leaf's raw MOS format by calling rawtherapee." + }, + + { + N_("Raw Olympus ORF"), + "image/x-olympus-orf", + "orf", + NULL, + + "file-rawtherapee-orf-load", + "Load files in the ORF raw format via rawtherapee", + "This plug-in loads files in Olympus' raw ORF format by calling rawtherapee." + }, + + { + N_("Raw Pentax PEF"), + "image/x-pentax-pef,image/x-pentax-raw", + "pef,raw", + NULL, + + "file-rawtherapee-pef-load", + "Load files in the PEF raw format via rawtherapee", + "This plug-in loads files in Pentax' raw PEF format by calling rawtherapee." + }, + + { + N_("Raw Logitech PXN"), + "image/x-pxn", /* FIXME: is that the correct mime type? */ + "pxn", + NULL, + + "file-rawtherapee-pxn-load", + "Load files in the PXN raw format via rawtherapee", + "This plug-in loads files in Logitech's raw PXN format by calling rawtherapee." + }, + + { + N_("Raw Apple QuickTake QTK"), + "", /* FIXME: find a mime type */ + "qtk", + NULL, + + "file-rawtherapee-qtk-load", + "Load files in the QTK raw format via rawtherapee", + "This plug-in loads files in Apple's QuickTake QTK raw format by calling rawtherapee." + }, + + { + N_("Raw Fujifilm RAF"), + "image/x-fuji-raf", + "raf", + NULL, + + "file-rawtherapee-raf-load", + "Load files in the RAF raw format via rawtherapee", + "This plug-in loads files in Fujifilm's raw RAF format by calling rawtherapee." + }, + + { + N_("Raw Panasonic"), + "image/x-panasonic-raw,image/x-panasonic-rw2", + "raw,rw2", + NULL, + + "file-rawtherapee-panasonic-load", + "Load files in the Panasonic raw formats via rawtherapee", + "This plug-in loads files in Panasonic's raw formats by calling rawtherapee." + }, + + { + N_("Raw Digital Foto Maker RDC"), + "", /* FIXME: find a mime type */ + "rdc", + NULL, + + "file-rawtherapee-rdc-load", + "Load files in the RDC raw format via rawtherapee", + "This plug-in loads files in Digital Foto Maker's raw RDC format by calling rawtherapee." + }, + + { + N_("Raw Leica RWL"), + "image/x-leica-rwl", + "rwl", + NULL, + + "file-rawtherapee-rwl-load", + "Load files in the RWL raw format via rawtherapee", + "This plug-in loads files in Leica's raw RWL format by calling rawtherapee." + }, + + { + N_("Raw Samsung SRW"), + "image/x-samsung-srw", + "srw", + NULL, + + "file-rawtherapee-srw-load", + "Load files in the SRW raw format via rawtherapee", + "This plug-in loads files in Samsung's raw SRW format by calling rawtherapee." + }, + + { + N_("Raw Sigma X3F"), + "image/x-sigma-x3f", + "x3f", + NULL, + + "file-rawtherapee-x3f-load", + "Load files in the X3F raw format via rawtherapee", + "This plug-in loads files in Sigma's raw X3F format by calling rawtherapee." + }, + + { + N_("Raw Arriflex ARI"), + "", + "ari", + NULL, + + "file-rawtherapee-ari-load", + "Load files in the ARI raw format via rawtherapee", + "This plug-in loads files in Arriflex' raw ARI format by calling rawtherapee." + } +}; diff --git a/tools/gimp-plugin/file-rawtherapee.c b/tools/gimp-plugin/file-rawtherapee.c new file mode 100644 index 000000000..92ce40f9f --- /dev/null +++ b/tools/gimp-plugin/file-rawtherapee.c @@ -0,0 +1,424 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * file-rawtherapee.c -- raw file format plug-in that uses RawTherapee + * Copyright (C) 2012 Simon Budig + * Copyright (C) 2016 Tobias Ellinghaus + * Copyright (C) 2017 Alberto Griggio + * + * This program 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. + * + * This program 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 this program. If not, see . + */ + +//#include "config.h" + +#include +#include +#include + +#include + +#include +#include + +//#include "libgimp/stdplugins-intl.h" + +#include "file-formats.h" + + +#define LOAD_THUMB_PROC "file-rawtherapee-load-thumb" + + +static void query (void); +static void run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals); +static gint32 load_image (const gchar *filename, + GimpRunMode run_mode, + GError **error); + +static gint32 load_thumbnail_image (const gchar *filename, + gint thumb_size, + GError **error); + +const GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query proc */ + run, /* run_proc */ +}; + +MAIN () + + +static void +query (void) +{ + static const GimpParamDef load_args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_STRING, "filename", "The name of the file to load." }, + { GIMP_PDB_STRING, "raw-filename", "The name entered" }, + }; + + static const GimpParamDef load_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Output image" } + }; + + static const GimpParamDef thumb_args[] = + { + { GIMP_PDB_STRING, "filename", "The name of the file to load" }, + { GIMP_PDB_INT32, "thumb-size", "Preferred thumbnail size" } + }; + + static const GimpParamDef thumb_return_vals[] = + { + { GIMP_PDB_IMAGE, "image", "Thumbnail image" } + }; + + /* check if rawtherapee is installed + * TODO: allow setting the location of the executable in preferences + */ + gchar *argv[] = { "rawtherapee", "-v", NULL }; + gchar *rawtherapee_stdout = NULL; + gboolean have_rawtherapee = FALSE; + gint i; + + if (g_spawn_sync (NULL, + argv, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + NULL)) + { + char *rtversion = NULL; + + if (sscanf (rawtherapee_stdout, + "RawTherapee, version %ms", + &rtversion) == 1) + { + have_rawtherapee = TRUE; + free(rtversion); + } + + g_free (rawtherapee_stdout); + } + + if (! have_rawtherapee) + return; + + gimp_install_procedure (LOAD_THUMB_PROC, + "Load thumbnail from a raw image via rawtherapee", + "This plug-in loads a thumbnail from a raw image by calling rawtherapee-cli.", + "Alberto Griggio", + "Alberto Griggio", + "2017", + NULL, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (thumb_args), + G_N_ELEMENTS (thumb_return_vals), + thumb_args, thumb_return_vals); + + for (i = 0; i < G_N_ELEMENTS (file_formats); i++) + { + const FileFormat *format = &file_formats[i]; + + gimp_install_procedure (format->load_proc, + format->load_blurb, + format->load_help, + "Alberto Griggio", + "Alberto Griggio", + "2017", + format->file_type, + NULL, + GIMP_PLUGIN, + G_N_ELEMENTS (load_args), + G_N_ELEMENTS (load_return_vals), + load_args, load_return_vals); + + gimp_register_file_handler_mime (format->load_proc, + format->mime_type); + gimp_register_file_handler_raw (format->load_proc); + gimp_register_magic_load_handler (format->load_proc, + format->extensions, + "", + format->magic); + + gimp_register_thumbnail_loader (format->load_proc, LOAD_THUMB_PROC); + } +} + +static void +run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[6]; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + GimpRunMode run_mode; + gint image_ID; + GError *error = NULL; + gint i; + +// INIT_I18N (); + + run_mode = param[0].data.d_int32; + + *nreturn_vals = 1; + *return_vals = values; + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR; + + /* check if the format passed is actually supported & load */ + for (i = 0; i < G_N_ELEMENTS (file_formats); i++) + { + const FileFormat *format = &file_formats[i]; + + if (format->load_proc && ! strcmp (name, format->load_proc)) + { + image_ID = load_image (param[1].data.d_string, run_mode, &error); + + if (image_ID != -1) + { + *nreturn_vals = 2; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + } + else + { + status = GIMP_PDB_EXECUTION_ERROR; + } + + break; + } + else if (! strcmp (name, LOAD_THUMB_PROC)) + { + image_ID = load_thumbnail_image (param[0].data.d_string, + param[1].data.d_int32, + &error); + + if (image_ID != -1) + { + *nreturn_vals = 4; + values[1].type = GIMP_PDB_IMAGE; + values[1].data.d_image = image_ID; + values[4].type = GIMP_PDB_INT32; + values[4].data.d_int32 = GIMP_RGB_IMAGE; + values[5].type = GIMP_PDB_INT32; + values[5].data.d_int32 = 1; /* num_layers */ + } + else + { + status = GIMP_PDB_EXECUTION_ERROR; + } + + break; + } + } + + if (i == G_N_ELEMENTS (file_formats)) + status = GIMP_PDB_CALLING_ERROR; + + if (status != GIMP_PDB_SUCCESS && error) + { + *nreturn_vals = 2; + values[1].type = GIMP_PDB_STRING; + values[1].data.d_string = error->message; + } + + values[0].data.d_status = status; +} + +static gint32 +load_image (const gchar *filename, + GimpRunMode run_mode, + GError **error) +{ + gint32 image_ID = -1; + gchar *filename_out = gimp_temp_name ("tif"); + + gchar *rawtherapee_stdout = NULL; + + /* linear sRGB for now as GIMP uses that internally in many places anyway */ + gchar *argv[] = + { + "rawtherapee", + "-gimp", + (gchar *) filename, + filename_out, + NULL + }; + + gimp_progress_init_printf (_("Opening '%s'"), + gimp_filename_to_utf8 (filename)); + + if (g_spawn_sync (NULL, + argv, + NULL, +// G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + error)) + { + image_ID = gimp_file_load (run_mode, filename_out, filename_out); + if (image_ID != -1) + gimp_image_set_filename (image_ID, filename); + } + +// if (rawtherapee_stdout) printf ("%s\n", rawtherapee_stdout); + g_free(rawtherapee_stdout); + + g_unlink (filename_out); + g_free (filename_out); + + gimp_progress_update (1.0); + + return image_ID; +} + +static gint32 +load_thumbnail_image (const gchar *filename, + gint thumb_size, + GError **error) +{ + gint32 image_ID = -1; + gchar *filename_out = gimp_temp_name ("jpg"); + gchar *thumb_pp3 = gimp_temp_name ("pp3"); + gchar *size = g_strdup_printf ("%d", thumb_size); + FILE *thumb_pp3_f = fopen(thumb_pp3, "w"); + gboolean pp3_ok = FALSE; + gchar *rawtherapee_stdout = NULL; + const char *pp3_content = + "[Version]\n" + "AppVersion=5.0\n" + "Version=326\n" + "\n" + "[Resize]\n" + "Enabled=true\n" + "AppliesTo=Cropped area\n" + "Method=Lanczos\n" + "Width=%d\n" + "Height=%d\n" + "\n" + "[Sharpening]\n" + "Enabled=false\n" + "\n" + "[SharpenEdge]\n" + "Enabled=false\n" + "\n" + "[SharpenMicro]\n" + "Enabled=false\n" + "\n" + "[Defringing]\n" + "Enabled=false\n" + "\n" + "[Directional Pyramid Equalizer]\n" + "Enabled=false\n" + "\n" + "[PostResizeSharpening]\n" + "Enabled=false\n" + "\n" + "[Directional Pyramid Denoising]\n" + "Enabled=false\n" + "\n" + "[Impulse Denoising]\n" + "Enabled=false\n" + "\n" + "[Wavelet]\n" + "Enabled=false\n" + "\n" + "[RAW Bayer]\n" + "Method=fast\n" + "\n" + "[RAW X-Trans]\n" + "Method=fast\n"; + + + gchar *argv[] = + { + "rawtherapee-cli", + "-o", filename_out, + "-d", + "-s", + "-j", + "-p", thumb_pp3, + "-f", + "-c", (char *) filename, + NULL + }; + + if (thumb_pp3_f) { + if (fprintf(thumb_pp3_f, pp3_content, thumb_size, thumb_size) < 0) { + fclose(thumb_pp3_f); + thumb_pp3_f = NULL; + } + } + + gimp_progress_init_printf (_("Opening thumbnail for '%s'"), + gimp_filename_to_utf8 (filename)); + + if (thumb_pp3_f && + g_spawn_sync (NULL, + argv, + NULL, + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + &rawtherapee_stdout, + NULL, + NULL, + error)) + { + gimp_progress_update (0.5); + + image_ID = gimp_file_load (GIMP_RUN_NONINTERACTIVE, + filename_out, + filename_out); + if (image_ID != -1) + { + /* is this needed for thumbnails? */ + gimp_image_set_filename (image_ID, filename); + } + } + + gimp_progress_update (1.0); + + if (thumb_pp3_f) { + fclose(thumb_pp3_f); + } + g_unlink (thumb_pp3); + g_free (filename_out); + g_free (thumb_pp3); + g_free (rawtherapee_stdout); + + return image_ID; +}