New option [Color Management]/LCMSSafeMode (no GUI) to allow disabled multithreading on LCMS

This commit is contained in:
Oliver Duis
2011-04-14 19:54:13 +02:00
parent af91e3bfb5
commit f258169b08
10 changed files with 92 additions and 72 deletions

View File

@@ -273,8 +273,12 @@ Image16::tofloat() const
} }
// Parallized transformation; create transform with cmsFLAGS_NOCACHE! // Parallized transformation; create transform with cmsFLAGS_NOCACHE!
void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform) { void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe) {
#pragma omp parallel for if (safe) {
for (int i=0; i<height; i++) cmsDoTransform(hTransform, data, data, planestride);
cmsDoTransform(hTransform, data + 3*i*rowstride, data + 3*i*rowstride, rowstride); } else {
#pragma omp parallel for
for (int i=0; i<height; i++)
cmsDoTransform(hTransform, data + 3*i*rowstride, data + 3*i*rowstride, rowstride);
}
} }

View File

@@ -88,7 +88,7 @@ class Image16 : public ImageIO, public IImage16 {
virtual unsigned short** getGPlane () { return g; } virtual unsigned short** getGPlane () { return g; }
virtual unsigned short** getBPlane () { return b; } virtual unsigned short** getBPlane () { return b; }
void ExecCMSTransform(cmsHTRANSFORM hTransform); void ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe);
}; };
}; };
#endif #endif

View File

@@ -236,8 +236,12 @@ Imagefloat::to16() const
} }
// Parallized transformation; create transform with cmsFLAGS_NOCACHE! // Parallized transformation; create transform with cmsFLAGS_NOCACHE!
void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform) { void Imagefloat::ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe) {
#pragma omp parallel for if (safe) {
for (int i=0; i<height; i++) cmsDoTransform(hTransform, data, data, planestride);
cmsDoTransform(hTransform, data + 3*i*rowstride, data + 3*i*rowstride, rowstride); } else {
#pragma omp parallel for
for (int i=0; i<height; i++)
cmsDoTransform(hTransform, data + 3*i*rowstride, data + 3*i*rowstride, rowstride);
}
} }

View File

@@ -90,7 +90,7 @@ class Imagefloat : public ImageIO, public IImagefloat {
virtual float** getGPlane () { return g; } virtual float** getGPlane () { return g; }
virtual float** getBPlane () { return b; } virtual float** getBPlane () { return b; }
void ExecCMSTransform(cmsHTRANSFORM hTransform); void ExecCMSTransform(cmsHTRANSFORM hTransform, bool safe);
}; };
}; };
#endif #endif

View File

@@ -32,7 +32,6 @@
#include <imagesource.h> #include <imagesource.h>
#include <rtthumbnail.h> #include <rtthumbnail.h>
#include <utils.h> #include <utils.h>
#include <iccmatrices.h> #include <iccmatrices.h>
#ifdef _OPENMP #ifdef _OPENMP
@@ -165,7 +164,7 @@ void ImProcFunctions::firstAnalysis (Imagefloat* original, const ProcParams* par
cmsHPROFILE iprof = iccStore->getXYZProfile (); cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock (); lcmsMutex->lock ();
monitorTransform = cmsCreateTransform (iprof, TYPE_RGB_FLT, monitor, TYPE_RGB_8, settings->colorimetricIntent, monitorTransform = cmsCreateTransform (iprof, TYPE_RGB_FLT, monitor, TYPE_RGB_8, settings->colorimetricIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety settings->LCMSSafeMode ? cmsFLAGS_NOOPTIMIZE : cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety
lcmsMutex->unlock (); lcmsMutex->unlock ();
} }

View File

@@ -150,7 +150,7 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
cmsHPROFILE iprof = iccStore->getXYZProfile (); cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_8, settings->colorimetricIntent, cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_8, settings->colorimetricIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety settings->LCMSSafeMode ? cmsFLAGS_NOOPTIMIZE : cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety
lcmsMutex->unlock (); lcmsMutex->unlock ();
// cmsDoTransform is relatively expensive // cmsDoTransform is relatively expensive
@@ -180,7 +180,9 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
buffer[iy++] = CLIP((int)z_); buffer[iy++] = CLIP((int)z_);
} }
if (settings->LCMSSafeMode) lcmsMutex->lock ();
cmsDoTransform (hTransform, buffer, image->data + ix, cw); cmsDoTransform (hTransform, buffer, image->data + ix, cw);
if (settings->LCMSSafeMode) lcmsMutex->unlock ();
} }
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
@@ -265,10 +267,12 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
za[j-cx] = CLIP((int)z_); za[j-cx] = CLIP((int)z_);
} }
} }
cmsHPROFILE iprof = iccStore->getXYZProfile (); cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16_PLANAR, oprof, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE); cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16_PLANAR, oprof, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOOPTIMIZE);
lcmsMutex->unlock (); lcmsMutex->unlock ();
cmsDoTransform (hTransform, image->data, image->data, image->planestride); cmsDoTransform (hTransform, image->data, image->data, image->planestride);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
} else { } else {

View File

@@ -30,6 +30,7 @@
#include <ffmanager.h> #include <ffmanager.h>
#include <slicer.h> #include <slicer.h>
#include <iostream> #include <iostream>
#include <options.h>
#include <improcfun.h> #include <improcfun.h>
@@ -1603,7 +1604,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (in, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent, cmsHTRANSFORM hTransform = cmsCreateTransform (in, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent,
cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety settings->LCMSSafeMode ? 0 : cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety
lcmsMutex->unlock (); lcmsMutex->unlock ();
if (hTransform) { if (hTransform) {
@@ -1622,15 +1623,15 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
} }
} }
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
} else { } else {
// create the profile from camera // create the profile from camera
lcmsMutex->lock (); lcmsMutex->lock ();
hTransform = cmsCreateTransform (camprofile, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent, hTransform = cmsCreateTransform (camprofile, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety settings->LCMSSafeMode ? cmsFLAGS_NOOPTIMIZE : cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety
lcmsMutex->unlock (); lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
} }
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
@@ -1688,7 +1689,7 @@ void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams
cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); //cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT);//cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT); cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); //cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT);//cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT);
lcmsMutex->unlock (); lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
*/ */
// in this case we avoid using the slllllooooooowwww lcms // in this case we avoid using the slllllooooooowwww lcms
@@ -1716,7 +1717,8 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
out = iccStore->workingSpace (cmp.working); out = iccStore->workingSpace (cmp.working);
// out = iccStore->workingSpaceGamma (wProfile); // out = iccStore->workingSpaceGamma (wProfile);
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); // NOCACHE is important for thread safety cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent,
settings->LCMSSafeMode ? 0 : cmsFLAGS_NOCACHE); // NOCACHE is important for thread safety
lcmsMutex->unlock (); lcmsMutex->unlock ();
if (hTransform) { if (hTransform) {
@@ -1733,14 +1735,15 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
} }
} }
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
} }
else { else {
lcmsMutex->lock (); lcmsMutex->lock ();
hTransform = cmsCreateTransform (camprofile, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); hTransform = cmsCreateTransform (camprofile, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent,
settings->LCMSSafeMode ? 0 : cmsFLAGS_NOCACHE);
lcmsMutex->unlock (); lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
} }
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);

View File

@@ -1,47 +1,48 @@
/* /*
* This file is part of RawTherapee. * This file is part of RawTherapee.
* *
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com> * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
* *
* RawTherapee is free software: you can redistribute it and/or modify * RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* RawTherapee is distributed in the hope that it will be useful, * RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _RTSETTINGS_ #ifndef _RTSETTINGS_
#define _RTSETTINGS_ #define _RTSETTINGS_
namespace rtengine { namespace rtengine {
/** This structure holds the global parameters used by the RT engine. */ /** This structure holds the global parameters used by the RT engine. */
class Settings { class Settings {
public: public:
bool dualThreadEnabled; ///< If true, the image processing operations with utilize two processor cores (if possible) bool dualThreadEnabled; ///< If true, the image processing operations with utilize two processor cores (if possible)
Glib::ustring iccDirectory; ///< The directory containing the possible output icc profiles Glib::ustring iccDirectory; ///< The directory containing the possible output icc profiles
int colorimetricIntent; ///< Colorimetric intent used at color space conversions int colorimetricIntent; ///< Colorimetric intent used at color space conversions
Glib::ustring monitorProfile; ///< ICC profile of the monitor (full path recommended) Glib::ustring monitorProfile; ///< ICC profile of the monitor (full path recommended)
bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile
bool verbose; bool verbose;
Glib::ustring darkFramesPath; ///< The default directory for dark frames Glib::ustring darkFramesPath; ///< The default directory for dark frames
Glib::ustring flatFieldsPath; ///< The default directory for flat fields Glib::ustring flatFieldsPath; ///< The default directory for flat fields
bool LCMSSafeMode; // If true, not OMP
/** Creates a new instance of Settings.
* @return a pointer to the new Settings instance. */ /** Creates a new instance of Settings.
static Settings* create (); * @return a pointer to the new Settings instance. */
/** Destroys an instance of Settings. static Settings* create ();
* @param s a pointer to the Settings instance to destroy. */ /** Destroys an instance of Settings.
static void destroy (Settings* s); * @param s a pointer to the Settings instance to destroy. */
}; static void destroy (Settings* s);
} };
}
#endif
#endif

View File

@@ -328,10 +328,10 @@ void StdImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
if (cmp.input!="(none)") { if (cmp.input!="(none)") {
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (in, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent, cmsHTRANSFORM hTransform = cmsCreateTransform (in, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); settings->LCMSSafeMode ? cmsFLAGS_NOOPTIMIZE : cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
lcmsMutex->unlock (); lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
} }
@@ -365,10 +365,11 @@ void StdImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams
if (cmp.input!="(none)") { if (cmp.input!="(none)") {
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent,
settings->LCMSSafeMode ? 0 : cmsFLAGS_NOCACHE);
lcmsMutex->unlock (); lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform); im->ExecCMSTransform(hTransform, settings->LCMSSafeMode);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
} }

View File

@@ -151,6 +151,7 @@ void Options::setDefaults () {
rtSettings.colorimetricIntent = 1; rtSettings.colorimetricIntent = 1;
rtSettings.monitorProfile = ""; rtSettings.monitorProfile = "";
rtSettings.autoMonitorProfile = false; rtSettings.autoMonitorProfile = false;
rtSettings.LCMSSafeMode = false;
rtSettings.verbose = false; rtSettings.verbose = false;
} }
@@ -312,6 +313,8 @@ if (keyFile.has_group ("Color Management")) {
if (keyFile.has_key ("Color Management", "AutoMonitorProfile")) rtSettings.autoMonitorProfile = keyFile.get_boolean ("Color Management", "AutoMonitorProfile"); if (keyFile.has_key ("Color Management", "AutoMonitorProfile")) rtSettings.autoMonitorProfile = keyFile.get_boolean ("Color Management", "AutoMonitorProfile");
if (keyFile.has_key ("Color Management", "Intent")) rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent"); if (keyFile.has_key ("Color Management", "Intent")) rtSettings.colorimetricIntent = keyFile.get_integer("Color Management", "Intent");
if (keyFile.has_key ("Color Management", "LCMSSafeMode")) rtSettings.LCMSSafeMode = keyFile.get_boolean ("Color Management", "LCMSSafeMode");
} }
if (keyFile.has_group ("Batch Processing")) { if (keyFile.has_group ("Batch Processing")) {
@@ -453,6 +456,7 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_string ("Color Management", "MonitorProfile", rtSettings.monitorProfile); keyFile.set_string ("Color Management", "MonitorProfile", rtSettings.monitorProfile);
keyFile.set_boolean ("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile); keyFile.set_boolean ("Color Management", "AutoMonitorProfile", rtSettings.autoMonitorProfile);
keyFile.set_integer ("Color Management", "Intent", rtSettings.colorimetricIntent); keyFile.set_integer ("Color Management", "Intent", rtSettings.colorimetricIntent);
keyFile.set_boolean ("Color Management", "LCMSSafeMode", rtSettings.LCMSSafeMode);
Glib::ArrayHandle<int> bab = baBehav; Glib::ArrayHandle<int> bab = baBehav;
keyFile.set_integer_list ("Batch Processing", "AdjusterBehavior", bab); keyFile.set_integer_list ("Batch Processing", "AdjusterBehavior", bab);