Merge branch 'master' into gtk3

This commit is contained in:
Morgan Hardwood 2016-10-16 23:26:51 +02:00
commit 4efae5c764
53 changed files with 4404 additions and 857 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

View File

@ -632,6 +632,7 @@ HISTORY_MSG_403;O - NB - Sensibilité des bords
HISTORY_MSG_404;O - NB - Base amplification HISTORY_MSG_404;O - NB - Base amplification
HISTORY_MSG_405;O - Débruitage - Niveau 4 HISTORY_MSG_405;O - Débruitage - Niveau 4
HISTORY_MSG_406;O - NB - Pixels voisins HISTORY_MSG_406;O - NB - Pixels voisins
HISTORY_MSG_443;Compensation du Point Noir de Sortie
HISTORY_NEWSNAPSHOT;Ajouter HISTORY_NEWSNAPSHOT;Ajouter
HISTORY_NEWSNAPSHOT_TOOLTIP;Raccourci: <b>Alt-s</b> HISTORY_NEWSNAPSHOT_TOOLTIP;Raccourci: <b>Alt-s</b>
HISTORY_SNAPSHOT;Capture HISTORY_SNAPSHOT;Capture
@ -953,6 +954,7 @@ PREFERENCES_MENUGROUPPROFILEOPERATIONS;Opérations sur les profils
PREFERENCES_MENUGROUPRANK;Classement PREFERENCES_MENUGROUPRANK;Classement
PREFERENCES_MENUOPTIONS;Options du menu PREFERENCES_MENUOPTIONS;Options du menu
PREFERENCES_METADATA;Metadonnées PREFERENCES_METADATA;Metadonnées
PREFERENCES_MONBPC;Compensation du Point Noir pour la transformation L*a*b*->Moniteur
PREFERENCES_MIN;Mini (100x115) PREFERENCES_MIN;Mini (100x115)
PREFERENCES_MULTITAB;Éditeurs multiple PREFERENCES_MULTITAB;Éditeurs multiple
PREFERENCES_MULTITABDUALMON;Éditeurs multiple, si possible sur un second moniteur PREFERENCES_MULTITABDUALMON;Éditeurs multiple, si possible sur un second moniteur
@ -1083,6 +1085,8 @@ SAVEDLG_SUBSAMP_3;Meilleure qualité
SAVEDLG_TIFFUNCOMPRESSED;TIFF non compressé SAVEDLG_TIFFUNCOMPRESSED;TIFF non compressé
SAVEDLG_WARNFILENAME;Le fichier sera nommé SAVEDLG_WARNFILENAME;Le fichier sera nommé
SHCSELECTOR_TOOLTIP;Cliquez le bouton droit de la souris\npour réinitialiser la position de ces 3 curseurs SHCSELECTOR_TOOLTIP;Cliquez le bouton droit de la souris\npour réinitialiser la position de ces 3 curseurs
SOFTPROOF_GAMUTCHECK_TOOLTIP;Si activé, indique en gris les pixels dont la couleurs est en dehors du gamut du profile de sortie
SOFTPROOF_TOOLTIP;Épreuvage écran\nSi activé, simule le rendu généré par le profiles de sortie de l'outil ICM. Particulièrement utile pour simuler le rendu en sortie d'imprimante.
THRESHOLDSELECTOR_B;Bas THRESHOLDSELECTOR_B;Bas
THRESHOLDSELECTOR_BL;Bas-gauche THRESHOLDSELECTOR_BL;Bas-gauche
THRESHOLDSELECTOR_BR;Bas-droite THRESHOLDSELECTOR_BR;Bas-droite
@ -1456,6 +1460,8 @@ TP_ICM_APPLYLOOKTABLE;Table de recherche
TP_ICM_APPLYLOOKTABLE_TOOLTIP;Utilise la table de recherche (LUT) contenu dans le profil DCP. Ce réglage n'est possible que si le profil DCP sélectionné en contient une. TP_ICM_APPLYLOOKTABLE_TOOLTIP;Utilise la table de recherche (LUT) contenu dans le profil DCP. Ce réglage n'est possible que si le profil DCP sélectionné en contient une.
TP_ICM_BLENDCMSMATRIX;Mélange des hautes lumières\ndu profil ICC avec la matrice TP_ICM_BLENDCMSMATRIX;Mélange des hautes lumières\ndu profil ICC avec la matrice
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Activer la récupération des zones brûlées lorsque les profils ICC basés sur la LUT sont utilisés TP_ICM_BLENDCMSMATRIX_TOOLTIP;Activer la récupération des zones brûlées lorsque les profils ICC basés sur la LUT sont utilisés
TP_ICM_BPC;Compensation du Point Noir
TP_ICM_BPC_TOOLTIP;Activez ceci pour faire correspondre le canal Luminosité à l'espace couleur de sortie avec un Point Blanc fixe
TP_ICM_DCPILLUMINANT;Illuminant TP_ICM_DCPILLUMINANT;Illuminant
TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolé TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolé
TP_ICM_DCPILLUMINANT_TOOLTIP;Sélectionne quel illuminant DCP inclus utiliser. La valeur par défaut est "Interpolé", qui est un mix entre les 2 profils inclus basé sur la Balance des Blancs choisie. Ce paramètre n'est actif que si un fichier DCP Bi-Illuminant avec support de l'interpolation est choisi. TP_ICM_DCPILLUMINANT_TOOLTIP;Sélectionne quel illuminant DCP inclus utiliser. La valeur par défaut est "Interpolé", qui est un mix entre les 2 profils inclus basé sur la Balance des Blancs choisie. Ce paramètre n'est actif que si un fichier DCP Bi-Illuminant avec support de l'interpolation est choisi.

View File

@ -674,6 +674,7 @@ HISTORY_MSG_439;Retinex - Process
HISTORY_MSG_440;CbDL - Method HISTORY_MSG_440;CbDL - Method
HISTORY_MSG_441;Retinex - Gain transmission HISTORY_MSG_441;Retinex - Gain transmission
HISTORY_MSG_442;Retinex - Scale HISTORY_MSG_442;Retinex - Scale
HISTORY_MSG_443;Output Black Point Compensation
HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: <b>Alt-s</b> HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: <b>Alt-s</b>
HISTORY_SNAPSHOT;Snapshot HISTORY_SNAPSHOT;Snapshot
@ -1000,6 +1001,7 @@ PREFERENCES_MENUGROUPRANK;Group "Rank"
PREFERENCES_MENUOPTIONS;Context Menu Options PREFERENCES_MENUOPTIONS;Context Menu Options
PREFERENCES_METADATA;Metadata PREFERENCES_METADATA;Metadata
PREFERENCES_MIN;Mini (100x115) PREFERENCES_MIN;Mini (100x115)
PREFERENCES_MONBPC;Black Point Compensation for the L*a*b*->Monitor transform
PREFERENCES_MONINTENT;Default monitor intent PREFERENCES_MONINTENT;Default monitor intent
PREFERENCES_MONPROFILE;Default monitor profile PREFERENCES_MONPROFILE;Default monitor profile
PREFERENCES_MULTITAB;Multiple Editor Tabs Mode PREFERENCES_MULTITAB;Multiple Editor Tabs Mode
@ -1136,6 +1138,8 @@ SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved h
SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF
SAVEDLG_WARNFILENAME;File will be named SAVEDLG_WARNFILENAME;File will be named
SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders.
SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile.
SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs.
THRESHOLDSELECTOR_B;Bottom THRESHOLDSELECTOR_B;Bottom
THRESHOLDSELECTOR_BL;Bottom-left THRESHOLDSELECTOR_BL;Bottom-left
THRESHOLDSELECTOR_BR;Bottom-right THRESHOLDSELECTOR_BR;Bottom-right
@ -1523,6 +1527,8 @@ TP_ICM_APPLYLOOKTABLE;Look table
TP_ICM_APPLYLOOKTABLE_TOOLTIP;Employ the embedded DCP look table. The setting is only enabled if the selected DCP has one. TP_ICM_APPLYLOOKTABLE_TOOLTIP;Employ the embedded DCP look table. The setting is only enabled if the selected DCP has one.
TP_ICM_BLENDCMSMATRIX;Blend ICC highlights with matrix TP_ICM_BLENDCMSMATRIX;Blend ICC highlights with matrix
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Enable to recover clipped highlights when using LUT-based ICC profiles. TP_ICM_BLENDCMSMATRIX_TOOLTIP;Enable to recover clipped highlights when using LUT-based ICC profiles.
TP_ICM_BPC;Black Point Compensation
TP_ICM_BPC_TOOLTIP;Enable this to fit the Luminosity channel to the output color space with a fix White Point
TP_ICM_DCPILLUMINANT;Illuminant TP_ICM_DCPILLUMINANT;Illuminant
TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolated TP_ICM_DCPILLUMINANT_INTERPOLATED;Interpolated
TP_ICM_DCPILLUMINANT_TOOLTIP;Select which embedded DCP illuminant to employ. Default is "interpolated" which is a mix between the two based on white balance. The setting is only enabled if a Dual-Illuminant DCP with interpolation support is selected. TP_ICM_DCPILLUMINANT_TOOLTIP;Select which embedded DCP illuminant to employ. Default is "interpolated" which is a mix between the two based on white balance. The setting is only enabled if a Dual-Illuminant DCP with interpolation support is selected.

View File

@ -37,6 +37,7 @@
#include "opthelper.h" #include "opthelper.h"
#include "cplx_wavelet_dec.h" #include "cplx_wavelet_dec.h"
#include "median.h" #include "median.h"
#include "iccstore.h"
#ifdef _OPENMP #ifdef _OPENMP
#include <omp.h> #include <omp.h>
#endif #endif

View File

@ -23,6 +23,7 @@
#include "mytime.h" #include "mytime.h"
#include "sleef.c" #include "sleef.c"
#include "opthelper.h" #include "opthelper.h"
#include "iccstore.h"
#define pow_F(a,b) (xexpf(b*xlogf(a))) #define pow_F(a,b) (xexpf(b*xlogf(a)))
@ -1647,7 +1648,7 @@ void Color::interpolateRGBColor (float realL, float iplow, float iphigh, int alg
Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut Color::xyz2rgb(X, Y, Z, ro, go, bo, rgb_xyz);// ro go bo in gamut
} }
void Color::calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5) void Color::calcGamma (double pwr, double ts, int mode, int imax, GammaValues &gamma)
{ {
//from Dcraw (D.Coffin) //from Dcraw (D.Coffin)
int i; int i;
@ -1683,12 +1684,13 @@ void Color::calcGamma (double pwr, double ts, int mode, int imax, double &gamma0
} }
if (!mode--) { if (!mode--) {
gamma0 = g[0]; gamma[0] = g[0];
gamma1 = g[1]; gamma[1] = g[1];
gamma2 = g[2]; gamma[2] = g[2];
gamma3 = g[3]; gamma[3] = g[3];
gamma4 = g[4]; gamma[4] = g[4];
gamma5 = g[5]; gamma[5] = g[5];
gamma[6] = 0.;
return; return;
} }
} }

View File

@ -23,7 +23,6 @@
#include "rt_math.h" #include "rt_math.h"
#include "LUT.h" #include "LUT.h"
#include "labimage.h" #include "labimage.h"
#include "iccstore.h"
#include "iccmatrices.h" #include "iccmatrices.h"
#include "sleef.c" #include "sleef.c"
#define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c) #define SAT(a,b,c) ((float)max(a,b,c)-(float)min(a,b,c))/(float)max(a,b,c)
@ -31,6 +30,8 @@
namespace rtengine namespace rtengine
{ {
typedef std::array<double, 7> GammaValues;
#ifdef _DEBUG #ifdef _DEBUG
class MunsellDebugInfo class MunsellDebugInfo
@ -47,6 +48,7 @@ public:
#endif #endif
class Color class Color
{ {
@ -880,21 +882,21 @@ public:
return h; return h;
} }
/** /**
* @brief Get the gamma curves' parameters used by LCMS2 * @brief Get the gamma curves' parameters used by LCMS2
* @param pwr gamma value [>1] * @param pwr gamma value [>1]
* @param ts slope [0 ; 20] * @param ts slope [0 ; 20]
* @param mode [always 0] * @param mode [always 0]
* @imax imax [always 0] * @imax imax [always 0]
* @param gamma0 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) * @param gamma a pointer to an array of 6 double gamma values:
* @param gamma1 used in ip2Lab2rgb [0 ; 20], can be superior to 20, but it's quite unusual(return value) * gamma0 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value)
* @param gamma2 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) * gamma1 used in ip2Lab2rgb [0 ; 20], can be superior to 20, but it's quite unusual(return value)
* @param gamma3 used in ip2Lab2rgb [0 ; 1], usually near 0.003(return value) * gamma2 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value)
* @param gamma4 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value) * gamma3 used in ip2Lab2rgb [0 ; 1], usually near 0.003(return value)
* @param gamma5 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value) * gamma4 used in ip2Lab2rgb [0 ; 1], usually near 0.03(return value)
* gamma5 used in ip2Lab2rgb [0 ; 1], usually near 0.5 (return value)
*/ */
static void calcGamma (double pwr, double ts, int mode, int imax, double &gamma0, double &gamma1, double &gamma2, double &gamma3, double &gamma4, double &gamma5); static void calcGamma (double pwr, double ts, int mode, int imax, GammaValues &gamma);
/** /**

View File

@ -36,6 +36,7 @@
#include "opthelper.h" #include "opthelper.h"
#include "ciecam02.h" #include "ciecam02.h"
#include "color.h" #include "color.h"
#include "iccstore.h"
#undef CLIPD #undef CLIPD
#define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f) #define CLIPD(a) ((a)>0.0f?((a)<1.0f?(a):1.0f):0.0f)

View File

@ -962,24 +962,14 @@ void Crop::update (int todo)
// all pipette buffer processing should be finished now // all pipette buffer processing should be finished now
PipetteBuffer::setReady(); PipetteBuffer::setReady();
// switch back to rgb // Computing the preview image, i.e. converting from lab->Monitor color space (soft-proofing disabled) or lab->Output profile->Monitor color space (soft-proofing enabled)
parent->ipf.lab2monitorRgb (labnCrop, cropImg); parent->ipf.lab2monitorRgb (labnCrop, cropImg);
if (cropImageListener) { if (cropImageListener) {
// this in output space held in parallel to allow analysis like shadow/highlight // Computing the internal image for analysis, i.e. conversion from lab->Output profile (rtSettings.HistogramWorking disabled) or lab->WCS (rtSettings.HistogramWorking enabled)
Glib::ustring outProfile = params.icm.output;
Glib::ustring workProfile = params.icm.working;
Image8 *cropImgtrue;
if(settings->HistogramWorking) { // internal image in output color space for analysis
cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, workProfile, RI_RELATIVE, false); // HOMBRE: was RELATIVE by default in lab2rgb, is it safe to assume we have to use it again ? Image8 *cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, params.icm);
} else {
if (params.icm.output == "" || params.icm.output == ColorManagementParams::NoICMString) {
outProfile = "sRGB";
}
cropImgtrue = parent->ipf.lab2rgb (labnCrop, 0, 0, cropw, croph, outProfile, params.icm.outputIntent, false);
}
int finalW = rqcropw; int finalW = rqcropw;

View File

@ -44,7 +44,7 @@ protected:
Imagefloat* origCrop; // "one chunk" allocation Imagefloat* origCrop; // "one chunk" allocation
LabImage* laboCrop; // "one chunk" allocation LabImage* laboCrop; // "one chunk" allocation
LabImage* labnCrop; // "one chunk" allocation LabImage* labnCrop; // "one chunk" allocation
Image8* cropImg; // "one chunk" allocation Image8* cropImg; // "one chunk" allocation ; displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
float * cbuf_real; // "one chunk" allocation float * cbuf_real; // "one chunk" allocation
SHMap* cshmap; // per line allocation SHMap* cshmap; // per line allocation

View File

@ -32,14 +32,15 @@
#include "../rtgui/options.h" #include "../rtgui/options.h"
namespace namespace rtengine
{ {
extern const Settings* settings;
void loadProfiles (const Glib::ustring& dirName, void loadProfiles (const Glib::ustring& dirName,
std::map<Glib::ustring, cmsHPROFILE>* profiles, std::map<Glib::ustring, cmsHPROFILE>* profiles,
std::map<Glib::ustring, rtengine::ProfileContent>* profileContents, std::map<Glib::ustring, ProfileContent>* profileContents,
std::map<Glib::ustring, Glib::ustring>* profileNames, std::map<Glib::ustring, Glib::ustring>* profileNames,
bool nameUpper, bool onlyRgb) bool nameUpper)
{ {
if (dirName.empty ()) { if (dirName.empty ()) {
return; return;
@ -76,10 +77,10 @@ void loadProfiles (const Glib::ustring& dirName,
} }
if (profiles) { if (profiles) {
const rtengine::ProfileContent content (filePath); const ProfileContent content (filePath);
const cmsHPROFILE profile = content.toProfile (); const cmsHPROFILE profile = content.toProfile ();
if (profile && (!onlyRgb || cmsGetColorSpace (profile) == cmsSigRgbData)) { if (profile) {
profiles->insert (std::make_pair (name, profile)); profiles->insert (std::make_pair (name, profile));
if (profileContents) { if (profileContents) {
@ -95,20 +96,20 @@ void loadProfiles (const Glib::ustring& dirName,
} catch (Glib::Exception&) {} } catch (Glib::Exception&) {}
} }
inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, std::uint8_t& result) inline void getSupportedIntent (cmsHPROFILE profile, cmsUInt32Number intent, cmsUInt32Number direction, uint8_t& result)
{ {
if (cmsIsIntentSupported (profile, intent, direction)) { if (cmsIsIntentSupported (profile, intent, direction)) {
result |= 1 << intent; result |= 1 << intent;
} }
} }
inline std::uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number direction) inline uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number direction)
{ {
if (!profile) { if (!profile) {
return 0; return 0;
} }
std::uint8_t result = 0; uint8_t result = 0;
getSupportedIntent (profile, INTENT_PERCEPTUAL, direction, result); getSupportedIntent (profile, INTENT_PERCEPTUAL, direction, result);
getSupportedIntent (profile, INTENT_RELATIVE_COLORIMETRIC, direction, result); getSupportedIntent (profile, INTENT_RELATIVE_COLORIMETRIC, direction, result);
@ -121,7 +122,7 @@ inline std::uint8_t getSupportedIntents (cmsHPROFILE profile, cmsUInt32Number di
inline cmsHPROFILE createXYZProfile () inline cmsHPROFILE createXYZProfile ()
{ {
double mat[3][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0} }; double mat[3][3] = { {1.0, 0, 0}, {0, 1.0, 0}, {0, 0, 1.0} };
return rtengine::ICCStore::createFromMatrix (mat, false, "XYZ"); return ICCStore::createFromMatrix (mat, false, "XYZ");
} }
const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best, xyz_rec2020}; const double (*wprofiles[])[3] = {xyz_sRGB, xyz_adobe, xyz_prophoto, xyz_widegamut, xyz_bruce, xyz_beta, xyz_best, xyz_rec2020};
@ -164,7 +165,7 @@ std::vector<Glib::ustring> getWorkingProfiles ()
return res; return res;
} }
std::vector<Glib::ustring> ICCStore::getProfiles () const std::vector<Glib::ustring> ICCStore::getProfiles (const bool onlyRgb) const
{ {
MyMutex::MyLock lock (mutex_); MyMutex::MyLock lock (mutex_);
@ -172,6 +173,7 @@ std::vector<Glib::ustring> ICCStore::getProfiles () const
std::vector<Glib::ustring> res; std::vector<Glib::ustring> res;
for (ProfileMap::const_iterator profile = fileProfiles.begin (); profile != fileProfiles.end (); ++profile) { for (ProfileMap::const_iterator profile = fileProfiles.begin (); profile != fileProfiles.end (); ++profile) {
if (!onlyRgb || (onlyRgb && cmsGetColorSpace (profile->second) == cmsSigRgbData))
res.push_back (profile->first); res.push_back (profile->first);
} }
@ -187,8 +189,8 @@ std::vector<Glib::ustring> ICCStore::getProfilesFromDir (const Glib::ustring& di
ProfileMap profiles; ProfileMap profiles;
loadProfiles (profilesDir, &profiles, NULL, NULL, false, true); loadProfiles (profilesDir, &profiles, nullptr, nullptr, false);
loadProfiles (dirName, &profiles, NULL, NULL, false, true); loadProfiles (dirName, &profiles, nullptr, nullptr, false);
for (ProfileMap::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) { for (ProfileMap::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) {
res.push_back (profile->first); res.push_back (profile->first);
@ -201,14 +203,14 @@ cmsHPROFILE ICCStore::makeStdGammaProfile (cmsHPROFILE iprof)
{ {
// forgive me for the messy code, quick hack to change gamma of an ICC profile to the RT standard gamma // forgive me for the messy code, quick hack to change gamma of an ICC profile to the RT standard gamma
if (!iprof) { if (!iprof) {
return NULL; return nullptr;
} }
cmsUInt32Number bytesNeeded = 0; cmsUInt32Number bytesNeeded = 0;
cmsSaveProfileToMem (iprof, 0, &bytesNeeded); cmsSaveProfileToMem (iprof, 0, &bytesNeeded);
if (bytesNeeded == 0) { if (bytesNeeded == 0) {
return NULL; return nullptr;
} }
uint8_t *data = new uint8_t[bytesNeeded + 1]; uint8_t *data = new uint8_t[bytesNeeded + 1];
@ -362,6 +364,312 @@ cmsHPROFILE ICCStore::workingSpaceGamma (const Glib::ustring& name) const
} }
} }
void ICCStore::getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga)
{
const double eps = 0.000000001; // not divide by zero
if (!icm.freegamma) {//if Free gamma not selected
// gamma : ga[0],ga[1],ga[2],ga[3],ga[4],ga[5] by calcul
if(icm.gamma == "BT709_g2.2_s4.5") {
ga[0] = 2.22; //BT709 2.2 4.5 - my preferred as D.Coffin
ga[1] = 0.909995;
ga[2] = 0.090005;
ga[3] = 0.222222;
ga[4] = 0.081071;
} else if (icm.gamma == "sRGB_g2.4_s12.92") {
ga[0] = 2.40; //sRGB 2.4 12.92 - RT default as Lightroom
ga[1] = 0.947858;
ga[2] = 0.052142;
ga[3] = 0.077399;
ga[4] = 0.039293;
} else if (icm.gamma == "High_g1.3_s3.35") {
ga[0] = 1.3 ; //for high dynamic images
ga[1] = 0.998279;
ga[2] = 0.001721;
ga[3] = 0.298507;
ga[4] = 0.005746;
} else if (icm.gamma == "Low_g2.6_s6.9") {
ga[0] = 2.6 ; //gamma 2.6 variable : for low contrast images
ga[1] = 0.891161;
ga[2] = 0.108839;
ga[3] = 0.144928;
ga[4] = 0.076332;
} else if (icm.gamma == "standard_g2.2") {
ga[0] = 2.2; //gamma=2.2 (as gamma of Adobe, Widegamut...)
ga[1] = 1.;
ga[2] = 0.;
ga[3] = 1. / eps;
ga[4] = 0.;
} else if (icm.gamma == "standard_g1.8") {
ga[0] = 1.8; //gamma=1.8 (as gamma of Prophoto)
ga[1] = 1.;
ga[2] = 0.;
ga[3] = 1. / eps;
ga[4] = 0.;
} else /* if (icm.gamma == "linear_g1.0") */ {
ga[0] = 1.0; //gamma=1 linear : for high dynamic images (cf : D.Coffin...)
ga[1] = 1.;
ga[2] = 0.;
ga[3] = 1. / eps;
ga[4] = 0.;
}
ga[5] = 0.0;
ga[6] = 0.0;
} else { //free gamma selected
GammaValues g_a; //gamma parameters
double pwr = 1.0 / icm.gampos;
double ts = icm.slpos;
double slope = icm.slpos == 0 ? eps : icm.slpos;
int mode = 0, imax = 0;
Color::calcGamma(pwr, ts, mode, imax, g_a); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
ga[4] = g_a[3] * ts;
//printf("g_a.gamma0=%f g_a.gamma1=%f g_a.gamma2=%f g_a.gamma3=%f g_a.gamma4=%f\n", g_a.gamma0,g_a.gamma1,g_a.gamma2,g_a.gamma3,g_a.gamma4);
ga[0] = icm.gampos;
ga[1] = 1. / (1.0 + g_a[4]);
ga[2] = g_a[4] / (1.0 + g_a[4]);
ga[3] = 1. / slope;
ga[5] = 0.0;
ga[6] = 0.0;
//printf("ga[0]=%f ga[1]=%f ga[2]=%f ga[3]=%f ga[4]=%f\n", ga[0],ga[1],ga[2],ga[3],ga[4]);
}
}
// WARNING: the caller must lock lcmsMutex
cmsHPROFILE ICCStore::createGammaProfile (const procparams::ColorManagementParams &icm, GammaValues &ga) {
float p[6]; //primaries
ga[6] = 0.0;
enum class ColorTemp {
D50 = 5003, // for Widegamut, Prophoto Best, Beta -> D50
D65 = 6504 // for sRGB, AdobeRGB, Bruce Rec2020 -> D65
};
ColorTemp temp = ColorTemp::D50;
//primaries for 7 working profiles ==> output profiles
// eventually to adapt primaries if RT used special profiles !
if (icm.output == "WideGamut") {
p[0] = 0.7350; //Widegamut primaries
p[1] = 0.2650;
p[2] = 0.1150;
p[3] = 0.8260;
p[4] = 0.1570;
p[5] = 0.0180;
} else if (icm.output == "Adobe RGB") {
p[0] = 0.6400; //Adobe primaries
p[1] = 0.3300;
p[2] = 0.2100;
p[3] = 0.7100;
p[4] = 0.1500;
p[5] = 0.0600;
temp = ColorTemp::D65;
} else if (icm.output == "sRGB") {
p[0] = 0.6400; // sRGB primaries
p[1] = 0.3300;
p[2] = 0.3000;
p[3] = 0.6000;
p[4] = 0.1500;
p[5] = 0.0600;
temp = ColorTemp::D65;
} else if (icm.output == "BruceRGB") {
p[0] = 0.6400; // Bruce primaries
p[1] = 0.3300;
p[2] = 0.2800;
p[3] = 0.6500;
p[4] = 0.1500;
p[5] = 0.0600;
temp = ColorTemp::D65;
} else if (icm.output == "Beta RGB") {
p[0] = 0.6888; // Beta primaries
p[1] = 0.3112;
p[2] = 0.1986;
p[3] = 0.7551;
p[4] = 0.1265;
p[5] = 0.0352;
} else if (icm.output == "BestRGB") {
p[0] = 0.7347; // Best primaries
p[1] = 0.2653;
p[2] = 0.2150;
p[3] = 0.7750;
p[4] = 0.1300;
p[5] = 0.0350;
} else if (icm.output == "Rec2020") {
p[0] = 0.7080; // Rec2020 primaries
p[1] = 0.2920;
p[2] = 0.1700;
p[3] = 0.7970;
p[4] = 0.1310;
p[5] = 0.0460;
temp = ColorTemp::D65;
} else {
p[0] = 0.7347; //ProPhoto and default primaries
p[1] = 0.2653;
p[2] = 0.1596;
p[3] = 0.8404;
p[4] = 0.0366;
p[5] = 0.0001;
}
cmsCIExyY xyD;
cmsCIExyYTRIPLE Primaries = {
{p[0], p[1], 1.0}, // red
{p[2], p[3], 1.0}, // green
{p[4], p[5], 1.0} // blue
};
cmsToneCurve* GammaTRC[3];
// 7 parameters for smoother curves
cmsFloat64Number Parameters[7] = { ga[0], ga[1], ga[2], ga[3], ga[4], ga[5], ga[6] } ;
//lcmsMutex->lock (); Mutex acquired by the caller
cmsWhitePointFromTemp(&xyD, (double)temp);
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters); //5 = smoother than 4
cmsHPROFILE oprofdef = cmsCreateRGBProfile(&xyD, &Primaries, GammaTRC); //oprofdef become Outputprofile
cmsFreeToneCurve(GammaTRC[0]);
//lcmsMutex->unlock ();
return oprofdef;
}
// WARNING: the caller must lock lcmsMutex
cmsHPROFILE ICCStore::createCustomGammaOutputProfile (const procparams::ColorManagementParams &icm, GammaValues &ga) {
bool pro = false;
Glib::ustring outProfile;
cmsHPROFILE outputProfile = nullptr;
if (icm.freegamma && icm.gampos < 1.35) {
pro = true; //select profil with gammaTRC modified :
} else if (icm.gamma == "linear_g1.0" || (icm.gamma == "High_g1.3_s3.35")) {
pro = true; //pro=0 RT_sRGB || Prophoto
}
// Check that output profiles exist, otherwise use LCMS2
// Use the icc/icm profiles associated to possible working profiles, set in "options"
if (icm.working == "ProPhoto" && iccStore->outputProfileExist(options.rtSettings.prophoto) && !pro) {
outProfile = options.rtSettings.prophoto;
} else if (icm.working == "Adobe RGB" && iccStore->outputProfileExist(options.rtSettings.adobe) ) {
outProfile = options.rtSettings.adobe;
} else if (icm.working == "WideGamut" && iccStore->outputProfileExist(options.rtSettings.widegamut) ) {
outProfile = options.rtSettings.widegamut;
} else if (icm.working == "Beta RGB" && iccStore->outputProfileExist(options.rtSettings.beta) ) {
outProfile = options.rtSettings.beta;
} else if (icm.working == "BestRGB" && iccStore->outputProfileExist(options.rtSettings.best) ) {
outProfile = options.rtSettings.best;
} else if (icm.working == "BruceRGB" && iccStore->outputProfileExist(options.rtSettings.bruce) ) {
outProfile = options.rtSettings.bruce;
} else if (icm.working == "sRGB" && iccStore->outputProfileExist(options.rtSettings.srgb) && !pro) {
outProfile = options.rtSettings.srgb;
} else if (icm.working == "sRGB" && iccStore->outputProfileExist(options.rtSettings.srgb10) && pro) {
outProfile = options.rtSettings.srgb10;
} else if (icm.working == "ProPhoto" && iccStore->outputProfileExist(options.rtSettings.prophoto10) && pro) {
outProfile = options.rtSettings.prophoto10;
} else if (icm.working == "Rec2020" && iccStore->outputProfileExist(options.rtSettings.rec2020) ) {
outProfile = options.rtSettings.rec2020;
} else {
// Should not occurs
if (settings->verbose) {
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", icm.working.c_str() );
}
return nullptr;
}
//begin adaptation rTRC gTRC bTRC
//"outputProfile" profile has the same characteristics than RGB values, but TRC are adapted... for applying profile
if (settings->verbose) {
printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str()
}
outputProfile = iccStore->getProfile(outProfile); //get output profile
if (outputProfile == nullptr) {
if (settings->verbose) {
printf("\"%s\" ICC output profile not found!\n", outProfile.c_str());
}
return nullptr;
}
// 7 parameters for smoother curves
cmsFloat64Number Parameters[7] = { ga[0], ga[1], ga[2], ga[3], ga[4], ga[5], ga[6] };
//change desc Tag , to "free gamma", or "BT709", etc.
cmsMLU *mlu;
cmsContext ContextID = cmsGetProfileContextID(outputProfile); // create context to modify some TAGs
mlu = cmsMLUalloc(ContextID, 1);
// instruction with //ICC are used to generate ICC profile
if (mlu == nullptr) {
printf("Description error\n");
} else {
// Description TAG : selection of gamma and Primaries
if (!icm.freegamma) {
std::wstring gammaStr;
if(icm.gamma == "High_g1.3_s3.35") {
gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35");
} else if (icm.gamma == "Low_g2.6_s6.9") {
gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9");
} else if (icm.gamma == "sRGB_g2.4_s12.92") {
gammaStr = std::wstring(L"GammaTRC: sRGB g=2.4 s=12.92");
} else if (icm.gamma == "BT709_g2.2_s4.5") {
gammaStr = std::wstring(L"GammaTRC: BT709 g=2.2 s=4.5");
} else if (icm.gamma == "linear_g1.0") {
gammaStr = std::wstring(L"GammaTRC: Linear g=1.0");
} else if (icm.gamma == "standard_g2.2") {
gammaStr = std::wstring(L"GammaTRC: g=2.2");
} else if (icm.gamma == "standard_g1.8") {
gammaStr = std::wstring(L"GammaTRC: g=1.8");
}
cmsMLUsetWide(mlu, "en", "US", gammaStr.c_str());
} else {
// create description with gamma + slope + primaries
std::wostringstream gammaWs;
gammaWs.precision(2);
gammaWs << "Manual GammaTRC: g=" << (float)icm.gampos << " s=" << (float)icm.slpos;
cmsMLUsetWide(mlu, "en", "US", gammaWs.str().c_str());
}
cmsWriteTag(outputProfile, cmsSigProfileDescriptionTag, mlu);//desc changed
/*
cmsMLUsetWide(mlu, "en", "US", L"General Public License - AdobeRGB compatible");//adapt to profil
cmsWriteTag(outputProfile, cmsSigCopyrightTag, mlu);
cmsMLUsetWide(mlu, "en", "US", L"RawTherapee");
cmsWriteTag(outputProfile, cmsSigDeviceMfgDescTag, mlu);
cmsMLUsetWide(mlu, "en", "US", L"RTMedium"); //adapt to profil
cmsWriteTag(outputProfile, cmsSigDeviceModelDescTag, mlu);
*/
cmsMLUfree (mlu);
}
// Calculate output profile's rTRC gTRC bTRC
cmsToneCurve* GammaTRC = nullptr;
GammaTRC = cmsBuildParametricToneCurve(nullptr, 5, Parameters);
cmsWriteTag(outputProfile, cmsSigRedTRCTag, (void*)GammaTRC );
cmsWriteTag(outputProfile, cmsSigGreenTRCTag, (void*)GammaTRC );
cmsWriteTag(outputProfile, cmsSigBlueTRCTag, (void*)GammaTRC );
if (GammaTRC) {
cmsFreeToneCurve(GammaTRC);
}
return outputProfile;
}
bool ICCStore::outputProfileExist (const Glib::ustring& name) const
{
MyMutex::MyLock lock(mutex_);
return fileProfiles.find(name) != fileProfiles.end();
}
cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const cmsHPROFILE ICCStore::getProfile (const Glib::ustring& name) const
{ {
@ -407,7 +715,7 @@ cmsHPROFILE ICCStore::getStdProfile (const Glib::ustring& name) const
// profile does not exist // profile does not exist
if (f == fileStdProfilesFileNames.end ()) { if (f == fileStdProfilesFileNames.end ()) {
return NULL; return nullptr;
} }
// but there exists one => load it // but there exists one => load it
@ -433,21 +741,21 @@ ProfileContent ICCStore::getContent (const Glib::ustring& name) const
return r != fileProfileContents.end () ? r->second : ProfileContent(); return r != fileProfileContents.end () ? r->second : ProfileContent();
} }
std::uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const uint8_t ICCStore::getInputIntents (cmsHPROFILE profile) const
{ {
MyMutex::MyLock lock (mutex_); MyMutex::MyLock lock (mutex_);
return getSupportedIntents (profile, LCMS_USED_AS_INPUT); return getSupportedIntents (profile, LCMS_USED_AS_INPUT);
} }
std::uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const uint8_t ICCStore::getOutputIntents (cmsHPROFILE profile) const
{ {
MyMutex::MyLock lock (mutex_); MyMutex::MyLock lock (mutex_);
return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT); return getSupportedIntents (profile, LCMS_USED_AS_OUTPUT);
} }
std::uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const uint8_t ICCStore::getProofIntents (cmsHPROFILE profile) const
{ {
MyMutex::MyLock lock (mutex_); MyMutex::MyLock lock (mutex_);
@ -464,15 +772,15 @@ void ICCStore::init (const Glib::ustring& usrICCDir, const Glib::ustring& rtICCD
profilesDir = Glib::build_filename (rtICCDir, "output"); profilesDir = Glib::build_filename (rtICCDir, "output");
fileProfiles.clear(); fileProfiles.clear();
fileProfileContents.clear(); fileProfileContents.clear();
loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, NULL, false, true); loadProfiles (profilesDir, &fileProfiles, &fileProfileContents, nullptr, false);
loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, NULL, false, true); loadProfiles (usrICCDir, &fileProfiles, &fileProfileContents, nullptr, false);
// Input profiles // Input profiles
// Load these to different areas, since the short name (e.g. "NIKON D700" may overlap between system/user and RT dir) // Load these to different areas, since the short name (e.g. "NIKON D700" may overlap between system/user and RT dir)
stdProfilesDir = Glib::build_filename (rtICCDir, "input"); stdProfilesDir = Glib::build_filename (rtICCDir, "input");
fileStdProfiles.clear(); fileStdProfiles.clear();
fileStdProfilesFileNames.clear(); fileStdProfilesFileNames.clear();
loadProfiles (stdProfilesDir, NULL, NULL, &fileStdProfilesFileNames, true, false); loadProfiles (stdProfilesDir, nullptr, nullptr, &fileStdProfilesFileNames, true);
} }
// Determine the first monitor default profile of operating system, if selected // Determine the first monitor default profile of operating system, if selected
@ -515,7 +823,7 @@ void ICCStore::findDefaultMonitorProfile ()
} }
} }
ProfileContent::ProfileContent (const Glib::ustring& fileName) : data (NULL), length (0) ProfileContent::ProfileContent (const Glib::ustring& fileName) : data(nullptr), length(0)
{ {
FILE* f = g_fopen (fileName.c_str (), "rb"); FILE* f = g_fopen (fileName.c_str (), "rb");
@ -542,14 +850,14 @@ ProfileContent::ProfileContent (const ProfileContent& other)
data = new char[length + 1]; data = new char[length + 1];
memcpy (data, other.data, length + 1); memcpy (data, other.data, length + 1);
} else { } else {
data = NULL; data = nullptr;
} }
} }
ProfileContent::ProfileContent (cmsHPROFILE hProfile) : data (NULL), length (0) ProfileContent::ProfileContent (cmsHPROFILE hProfile) : data(nullptr), length(0)
{ {
if (hProfile != NULL) { if (hProfile != nullptr) {
cmsUInt32Number bytesNeeded = 0; cmsUInt32Number bytesNeeded = 0;
cmsSaveProfileToMem (hProfile, 0, &bytesNeeded); cmsSaveProfileToMem (hProfile, 0, &bytesNeeded);
@ -573,7 +881,7 @@ ProfileContent& ProfileContent::operator= (const ProfileContent& other)
data = new char[length + 1]; data = new char[length + 1];
memcpy (data, other.data, length + 1); memcpy (data, other.data, length + 1);
} else { } else {
data = NULL; data = nullptr;
} }
return *this; return *this;
@ -585,7 +893,7 @@ cmsHPROFILE ProfileContent::toProfile () const
if (data) { if (data) {
return cmsOpenProfileFromMem (data, length); return cmsOpenProfileFromMem (data, length);
} else { } else {
return NULL; return nullptr;
} }
} }

View File

@ -23,6 +23,9 @@
#include <glibmm.h> #include <glibmm.h>
#include <map> #include <map>
#include <string> #include <string>
#include <cstdint>
#include "procparams.h"
#include "color.h"
#include "../rtgui/threadutils.h" #include "../rtgui/threadutils.h"
namespace rtengine namespace rtengine
@ -85,8 +88,11 @@ public:
void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir); void init (const Glib::ustring& usrICCDir, const Glib::ustring& stdICCDir);
static void getGammaArray(const procparams::ColorManagementParams &icm, GammaValues &ga);
static cmsHPROFILE makeStdGammaProfile (cmsHPROFILE iprof); static cmsHPROFILE makeStdGammaProfile (cmsHPROFILE iprof);
static cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring()); static cmsHPROFILE createFromMatrix (const double matrix[3][3], bool gamma = false, const Glib::ustring& name = Glib::ustring());
static cmsHPROFILE createGammaProfile (const procparams::ColorManagementParams &icm, GammaValues &ga);
static cmsHPROFILE createCustomGammaOutputProfile (const procparams::ColorManagementParams &icm, GammaValues &ga);
// Main monitors standard profile name, from OS // Main monitors standard profile name, from OS
void findDefaultMonitorProfile (); void findDefaultMonitorProfile ();
@ -98,29 +104,30 @@ public:
TMatrix workingSpaceMatrix (const Glib::ustring& name) const; TMatrix workingSpaceMatrix (const Glib::ustring& name) const;
TMatrix workingSpaceInverseMatrix (const Glib::ustring& name) const; TMatrix workingSpaceInverseMatrix (const Glib::ustring& name) const;
cmsHPROFILE getProfile (const Glib::ustring& name) const; bool outputProfileExist (const Glib::ustring& name) const;
cmsHPROFILE getStdProfile (const Glib::ustring& name) const; cmsHPROFILE getProfile (const Glib::ustring& name) const;
ProfileContent getContent (const Glib::ustring& name) const; cmsHPROFILE getStdProfile (const Glib::ustring& name) const;
ProfileContent getContent (const Glib::ustring& name) const;
cmsHPROFILE getXYZProfile () const; cmsHPROFILE getXYZProfile () const;
cmsHPROFILE getsRGBProfile () const; cmsHPROFILE getsRGBProfile () const;
std::vector<Glib::ustring> getProfiles () const; std::vector<Glib::ustring> getProfiles (const bool onlyRgb = false) const;
std::vector<Glib::ustring> getProfilesFromDir (const Glib::ustring& dirName) const; std::vector<Glib::ustring> getProfilesFromDir (const Glib::ustring& dirName) const;
std::uint8_t getInputIntents (cmsHPROFILE profile) const; uint8_t getInputIntents (cmsHPROFILE profile) const;
std::uint8_t getOutputIntents (cmsHPROFILE profile) const; uint8_t getOutputIntents (cmsHPROFILE profile) const;
std::uint8_t getProofIntents (cmsHPROFILE profile) const; uint8_t getProofIntents (cmsHPROFILE profile) const;
std::uint8_t getInputIntents (const Glib::ustring& name) const; uint8_t getInputIntents (const Glib::ustring& name) const;
std::uint8_t getOutputIntents (const Glib::ustring& name) const; uint8_t getOutputIntents (const Glib::ustring& name) const;
std::uint8_t getProofIntents (const Glib::ustring& name) const; uint8_t getProofIntents (const Glib::ustring& name) const;
}; };
#define iccStore ICCStore::getInstance() #define iccStore ICCStore::getInstance()
inline ProfileContent::ProfileContent () : inline ProfileContent::ProfileContent () :
data(NULL), data(nullptr),
length(0) length(0)
{ {
} }
@ -140,17 +147,17 @@ inline Glib::ustring ICCStore::getDefaultMonitorProfileName () const
return defaultMonitorProfile; return defaultMonitorProfile;
} }
inline std::uint8_t ICCStore::getInputIntents (const Glib::ustring &name) const inline uint8_t ICCStore::getInputIntents (const Glib::ustring &name) const
{ {
return getInputIntents (getProfile (name)); return getInputIntents (getProfile (name));
} }
inline std::uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) const inline uint8_t ICCStore::getOutputIntents (const Glib::ustring &name) const
{ {
return getOutputIntents (getProfile (name)); return getOutputIntents (getProfile (name));
} }
inline std::uint8_t ICCStore::getProofIntents (const Glib::ustring &name) const inline uint8_t ICCStore::getProofIntents (const Glib::ustring &name) const
{ {
return getProofIntents (getProfile (name)); return getProofIntents (getProfile (name));
} }

View File

@ -326,43 +326,48 @@ Image16::tofloat()
} }
// Parallized transformation; create transform with cmsFLAGS_NOCACHE! // Parallized transformation; create transform with cmsFLAGS_NOCACHE!
void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform) void Image16::ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy)
{ {
//cmsDoTransform(hTransform, data, data, planestride); // LittleCMS cannot parallelize planar Lab float images
// LittleCMS cannot parallelize planar setups -- Hombre: LCMS2.4 can! But it we use this new feature, memory allocation have to be modified too
// so build temporary buffers to allow multi processor execution // so build temporary buffers to allow multi processor execution
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif #endif
{ {
AlignedBuffer<unsigned short> buffer(width * 3); AlignedBuffer<float> bufferLab(width * 3);
AlignedBuffer<unsigned short> bufferRGB(width * 3);
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp for schedule(static) #pragma omp for schedule(static)
#endif #endif
for (int y = 0; y < height; y++) for (int y = cy; y < cy + height; y++)
{ {
unsigned short *p = buffer.data, *pR = r(y), *pG = g(y), *pB = b(y); unsigned short *pRGB, *pR, *pG, *pB;
float *pLab, *pL, *pa, *pb;
pLab= bufferLab.data;
pL = labImage.L[y] + cx;
pa = labImage.a[y] + cx;
pb = labImage.b[y] + cx;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
*(p++) = *(pR++); *(pLab++) = *(pL++) / 327.68f;
*(p++) = *(pG++); *(pLab++) = *(pa++) / 327.68f;
*(p++) = *(pB++); *(pLab++) = *(pb++) / 327.68f;
} }
cmsDoTransform (hTransform, buffer.data, buffer.data, width); cmsDoTransform (hTransform, bufferLab.data, bufferRGB.data, width);
p = buffer.data; pRGB = bufferRGB.data;
pR = r(y); pR = r(y - cy);
pG = g(y); pG = g(y - cy);
pB = b(y); pB = b(y - cy);
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
*(pR++) = *(p++); *(pR++) = *(pRGB++);
*(pG++) = *(p++); *(pG++) = *(pRGB++);
*(pB++) = *(p++); *(pB++) = *(pRGB++);
} }
} // End of parallelization } // End of parallelization
} }

View File

@ -96,7 +96,7 @@ public:
delete this; delete this;
} }
void ExecCMSTransform(cmsHTRANSFORM hTransform); void ExecCMSTransform(cmsHTRANSFORM hTransform, const LabImage &labImage, int cx, int cy);
}; };
} }

View File

@ -771,39 +771,39 @@ int ImageIO::loadTIFF (Glib::ustring fname)
* We could use the min/max values set in TIFFTAG_SMINSAMPLEVALUE and * We could use the min/max values set in TIFFTAG_SMINSAMPLEVALUE and
* TIFFTAG_SMAXSAMPLEVALUE, but for now, we normalize the image to the * TIFFTAG_SMAXSAMPLEVALUE, but for now, we normalize the image to the
* effective minimum and maximum values * effective minimum and maximum values
* */
printf("Informations de \"%s\":\n", fname.c_str()); if (options.rtSettings.verbose) {
uint16 tiffDefaultScale, tiffBaselineExposure, tiffLinearResponseLimit; printf("Informations of \"%s\":\n", fname.c_str());
if (TIFFGetField(in, TIFFTAG_DEFAULTSCALE, &tiffDefaultScale)) { uint16 tiffDefaultScale, tiffBaselineExposure, tiffLinearResponseLimit;
printf(" DefaultScale: %d\n", tiffDefaultScale); if (TIFFGetField(in, TIFFTAG_DEFAULTSCALE, &tiffDefaultScale)) {
} printf(" DefaultScale: %d\n", tiffDefaultScale);
else }
printf(" No DefaultScale value!\n"); else
if (TIFFGetField(in, TIFFTAG_BASELINEEXPOSURE, &tiffBaselineExposure)) { printf(" No DefaultScale value!\n");
printf(" BaselineExposure: %d\n", tiffBaselineExposure); if (TIFFGetField(in, TIFFTAG_BASELINEEXPOSURE, &tiffBaselineExposure)) {
} printf(" BaselineExposure: %d\n", tiffBaselineExposure);
else }
printf(" No BaselineExposure value!\n"); else
if (TIFFGetField(in, TIFFTAG_LINEARRESPONSELIMIT, &tiffLinearResponseLimit)) { printf(" No BaselineExposure value!\n");
printf(" LinearResponseLimit: %d\n", tiffLinearResponseLimit); if (TIFFGetField(in, TIFFTAG_LINEARRESPONSELIMIT, &tiffLinearResponseLimit)) {
} printf(" LinearResponseLimit: %d\n", tiffLinearResponseLimit);
else }
printf(" No LinearResponseLimit value!\n"); else
printf(" No LinearResponseLimit value!\n");
uint16 tiffMinValue, tiffMaxValue; uint16 tiffMinValue, tiffMaxValue;
if (TIFFGetField(in, TIFFTAG_SMINSAMPLEVALUE, &tiffMinValue)) { if (TIFFGetField(in, TIFFTAG_SMINSAMPLEVALUE, &tiffMinValue)) {
printf(" MinValue: %d\n", tiffMinValue); printf(" MinValue: %d\n", tiffMinValue);
}
else
printf(" No minimum value!\n");
if (TIFFGetField(in, TIFFTAG_SMAXSAMPLEVALUE, &tiffMaxValue)) {
printf(" MaxValue: %d\n\n", tiffMaxValue);
}
else
printf(" No maximum value!\n\n");
printf(" Those values are not taken into account, the image data are normalized to a [0;1] range\n\n");
} }
else
printf(" No minimum value!\n");
if (TIFFGetField(in, TIFFTAG_SMAXSAMPLEVALUE, &tiffMaxValue)) {
printf(" MaxValue: %d\n\n", tiffMaxValue);
}
else
printf(" No maximum value!\n\n");
printf("\n");
*/
char* profdata; char* profdata;
deleteLoadedProfileData(); deleteLoadedProfileData();
@ -811,30 +811,8 @@ int ImageIO::loadTIFF (Glib::ustring fname)
if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &loadedProfileLength, &profdata)) { if (TIFFGetField(in, TIFFTAG_ICCPROFILE, &loadedProfileLength, &profdata)) {
embProfile = cmsOpenProfileFromMem (profdata, loadedProfileLength); embProfile = cmsOpenProfileFromMem (profdata, loadedProfileLength);
loadedProfileData = new char [loadedProfileLength];
// For 32 bits floating point images, gamma is forced to linear in embedded ICC profiles memcpy (loadedProfileData, profdata, loadedProfileLength);
if ( sampleFormat & (IIOSF_LOGLUV24 | IIOSF_LOGLUV32 | IIOSF_FLOAT) ) {
// Modifying the gammaTRG tags
cmsWriteTag(embProfile, cmsSigGreenTRCTag, (void*)Color::linearGammaTRC );
cmsWriteTag(embProfile, cmsSigRedTRCTag, (void*)Color::linearGammaTRC );
cmsWriteTag(embProfile, cmsSigBlueTRCTag, (void*)Color::linearGammaTRC );
// Saving the profile in the memory
cmsUInt32Number bytesNeeded = 0;
cmsSaveProfileToMem(embProfile, 0, &bytesNeeded);
if (bytesNeeded > 0) {
loadedProfileData = new char[bytesNeeded + 1];
cmsSaveProfileToMem(embProfile, loadedProfileData, &bytesNeeded);
}
loadedProfileLength = (int)bytesNeeded;
} else {
// Saving the profile in the memory as is
loadedProfileData = new char [loadedProfileLength];
memcpy (loadedProfileData, profdata, loadedProfileLength);
}
} else { } else {
embProfile = NULL; embProfile = NULL;
} }

View File

@ -23,6 +23,7 @@
#include "../rtgui/ppversion.h" #include "../rtgui/ppversion.h"
#include "colortemp.h" #include "colortemp.h"
#include "improcfun.h" #include "improcfun.h"
#include "iccstore.h"
#ifdef _OPENMP #ifdef _OPENMP
#include <omp.h> #include <omp.h>
#endif #endif
@ -33,9 +34,9 @@ extern const Settings* settings;
ImProcCoordinator::ImProcCoordinator () ImProcCoordinator::ImProcCoordinator ()
: orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL), : orig_prev(NULL), oprevi(NULL), oprevl(NULL), nprevl(NULL), previmg(NULL), workimg(NULL),
ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(&params, true), monitorIntent(RI_RELATIVE), scale(10), ncie(NULL), imgsrc(NULL), shmap(NULL), lastAwbEqual(0.), ipf(&params, true), monitorIntent(RI_RELATIVE),
highDetailPreprocessComputed(false), highDetailRawComputed(false), allocated(false), softProof(false), gamutCheck(false), scale(10), highDetailPreprocessComputed(false), highDetailRawComputed(false),
bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(NAN), allocated(false), bwAutoR(-9000.f), bwAutoG(-9000.f), bwAutoB(-9000.f), CAMMean(NAN),
hltonecurve(65536), hltonecurve(65536),
shtonecurve(65536), shtonecurve(65536),
@ -87,7 +88,7 @@ ImProcCoordinator::ImProcCoordinator ()
fullw(1), fullh(1), fullw(1), fullh(1),
pW(-1), pH(-1), pW(-1), pH(-1),
plistener(NULL), imageListener(NULL), aeListener(NULL), acListener(NULL), abwListener(NULL), actListener(NULL), adnListener(NULL), awavListener(NULL), dehaListener(NULL), hListener(NULL), plistener(NULL), imageListener(NULL), aeListener(NULL), acListener(NULL), abwListener(NULL), actListener(NULL), adnListener(NULL), awavListener(NULL), dehaListener(NULL), hListener(NULL),
resultValid(false), changeSinceLast(0), updaterRunning(false), destroying(false), utili(false), autili(false), wavcontlutili(false), resultValid(false), lastOutputProfile("BADFOOD"), lastOutputIntent(RI__COUNT), lastOutputBPC(false), changeSinceLast(0), updaterRunning(false), destroying(false), utili(false), autili(false), wavcontlutili(false),
butili(false), ccutili(false), cclutili(false), clcutili(false), opautili(false), conversionBuffer(1, 1) butili(false), ccutili(false), cclutili(false), clcutili(false), opautili(false), conversionBuffer(1, 1)
{} {}
@ -778,8 +779,11 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
} }
// Update the monitor color transform if necessary // Update the monitor color transform if necessary
if (todo & M_MONITOR) { if ((todo & M_MONITOR) || (lastOutputProfile!=params.icm.output) || lastOutputIntent!=params.icm.outputIntent || lastOutputBPC!=params.icm.outputBPC) {
ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent); lastOutputProfile = params.icm.output;
lastOutputIntent = params.icm.outputIntent;
lastOutputBPC = params.icm.outputBPC;
ipf.updateColorProfiles(params.icm, monitorProfile, monitorIntent, softProof, gamutCheck);
} }
// process crop, if needed // process crop, if needed
@ -794,20 +798,12 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
MyMutex::MyLock prevImgLock(previmg->getMutex()); MyMutex::MyLock prevImgLock(previmg->getMutex());
try { try {
// Computing the preview image, i.e. converting from WCS->Monitor color space (soft-proofing disabled) or WCS->Output profile->Monitor color space (soft-proofing enabled)
ipf.lab2monitorRgb (nprevl, previmg); ipf.lab2monitorRgb (nprevl, previmg);
// Computing the internal image for analysis, i.e. conversion from WCS->Output profile
delete workimg; delete workimg;
Glib::ustring outProfile = params.icm.output; workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, params.icm);
if(settings->HistogramWorking) {
Glib::ustring workProfile = params.icm.working;
workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, workProfile, RI_RELATIVE, true); // HOMBRE: was RELATIVE by default in lab2rgb, is it safe to assume we have to use it again ?
} else {
if (params.icm.output.empty() || params.icm.output == ColorManagementParams::NoICMString) {
outProfile = "sRGB";
}
workimg = ipf.lab2rgb (nprevl, 0, 0, pW, pH, outProfile, params.icm.outputIntent, false);
}
} catch(char * str) { } catch(char * str) {
progress ("Error converting file...", 0); progress ("Error converting file...", 0);
return; return;
@ -1134,6 +1130,18 @@ void ImProcCoordinator::getMonitorProfile (Glib::ustring& profile, RenderingInte
intent = monitorIntent; intent = monitorIntent;
} }
void ImProcCoordinator::setSoftProofing (bool softProof, bool gamutCheck)
{
this->softProof = softProof;
this->gamutCheck = gamutCheck;
}
void ImProcCoordinator::getSoftProofing (bool &softProof, bool &gamutCheck)
{
softProof = this->softProof;
gamutCheck = this->gamutCheck;
}
void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb) void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname, bool apply_wb)
{ {

View File

@ -57,8 +57,8 @@ protected:
Imagefloat *oprevi; Imagefloat *oprevi;
LabImage *oprevl; LabImage *oprevl;
LabImage *nprevl; LabImage *nprevl;
Image8 *previmg; Image8 *previmg; // displayed image in monitor color space, showing the output profile as well (soft-proofing enabled, which then correspond to workimg) or not
Image8 *workimg; Image8 *workimg; // internal image in output color space for analysis
CieImage *ncie; CieImage *ncie;
ImageSource* imgsrc; ImageSource* imgsrc;
@ -73,8 +73,9 @@ protected:
ImProcFunctions ipf; ImProcFunctions ipf;
Glib::ustring monitorProfile; Glib::ustring monitorProfile;
RenderingIntent monitorIntent; RenderingIntent monitorIntent;
bool softProof;
bool gamutCheck;
int scale; int scale;
bool highDetailPreprocessComputed; bool highDetailPreprocessComputed;
@ -179,6 +180,13 @@ protected:
MyMutex mProcessing; MyMutex mProcessing;
ProcParams params; ProcParams params;
// for optimization purpose, the output profile, output rendering intent and
// output BPC will trigger a regeneration of the profile on parameter change only
// and automatically
Glib::ustring lastOutputProfile;
RenderingIntent lastOutputIntent;
bool lastOutputBPC;
// members of the updater: // members of the updater:
Glib::Thread* thread; Glib::Thread* thread;
MyMutex updaterThreadStart; MyMutex updaterThreadStart;
@ -256,6 +264,8 @@ public:
void setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent); void setMonitorProfile (const Glib::ustring& profile, RenderingIntent intent);
void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const; void getMonitorProfile (Glib::ustring& profile, RenderingIntent& intent) const;
void setSoftProofing (bool softProof, bool gamutCheck);
void getSoftProofing (bool &softProof, bool &gamutCheck);
bool updateTryLock () bool updateTryLock ()
{ {

View File

@ -61,14 +61,6 @@ ImProcFunctions::~ImProcFunctions ()
if (monitorTransform) { if (monitorTransform) {
cmsDeleteTransform (monitorTransform); cmsDeleteTransform (monitorTransform);
} }
if (output2monitorTransform) {
cmsDeleteTransform (output2monitorTransform);
}
if (lab2outputTransform) {
cmsDeleteTransform (lab2outputTransform);
}
} }
void ImProcFunctions::setScale (double iscale) void ImProcFunctions::setScale (double iscale)
@ -76,24 +68,14 @@ void ImProcFunctions::setScale (double iscale)
scale = iscale; scale = iscale;
} }
void ImProcFunctions::updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent) void ImProcFunctions::updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck)
{ {
// set up monitor transform // set up monitor transform
if (monitorTransform) { if (monitorTransform) {
cmsDeleteTransform (monitorTransform); cmsDeleteTransform (monitorTransform);
} }
if (output2monitorTransform) {
cmsDeleteTransform (output2monitorTransform);
}
if (lab2outputTransform) {
cmsDeleteTransform (lab2outputTransform);
}
monitorTransform = nullptr; monitorTransform = nullptr;
output2monitorTransform = nullptr;
lab2outputTransform = nullptr;
#if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB #if !defined(__APPLE__) // No support for monitor profiles on OS X, all data is sRGB
@ -101,20 +83,57 @@ void ImProcFunctions::updateColorProfiles (const ColorManagementParams& icm, con
if (monitor) { if (monitor) {
MyMutex::MyLock lcmsLock (*lcmsMutex); MyMutex::MyLock lcmsLock (*lcmsMutex);
cmsUInt32Number flags;
cmsHPROFILE iprof = cmsCreateLab4Profile(nullptr); cmsHPROFILE iprof = cmsCreateLab4Profile(nullptr);
monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent,
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is for thread safety, NOOPTIMIZE for precision
Glib::ustring outputProfile; bool softProofCreated = false;
if (!icm.output.empty() && icm.output != ColorManagementParams::NoICMString) { if (softProof) {
outputProfile = icm.output; cmsHPROFILE oprof = nullptr;
cmsHPROFILE jprof = iccStore->getProfile(outputProfile); if(icm.gamma != "default" || icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
GammaValues ga;
if (jprof) { iccStore->getGammaArray(icm, ga);
lab2outputTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, jprof, TYPE_RGB_FLT, icm.outputIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); oprof = iccStore->createGammaProfile (icm, ga);
output2monitorTransform = cmsCreateTransform (jprof, TYPE_RGB_FLT, monitor, TYPE_RGB_8, monitorIntent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE );
} }
else if (!icm.output.empty() && icm.output != ColorManagementParams::NoICMString) {
if(icm.gamma != "default" || icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
GammaValues ga;
iccStore->getGammaArray(icm, ga);
oprof = iccStore->createCustomGammaOutputProfile (icm, ga);
} else {
oprof = iccStore->getProfile(icm.output);
}
}
if (oprof) {
// NOCACHE is for thread safety, NOOPTIMIZE for precision
flags = cmsFLAGS_SOFTPROOFING | cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
if (icm.outputBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
if (gamutCheck) {
flags |= cmsFLAGS_GAMUTCHECK;
}
monitorTransform = cmsCreateProofingTransform(
iprof, TYPE_Lab_FLT,
monitor, TYPE_RGB_8,
oprof,
monitorIntent, icm.outputIntent,
flags
);
if (monitorTransform) {
softProofCreated = true;
}
}
}
if (!softProofCreated) {
flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
if (settings->monitorBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
}
monitorTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, monitor, TYPE_RGB_8, monitorIntent, flags);
} }
cmsCloseProfile(iprof); cmsCloseProfile(iprof);

View File

@ -223,7 +223,7 @@ public:
bool needsPCVignetting (); bool needsPCVignetting ();
void firstAnalysis (const Imagefloat* const working, const ProcParams &params, LUTu & vhist16); void firstAnalysis (const Imagefloat* const working, const ProcParams &params, LUTu & vhist16);
void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent); void updateColorProfiles (const ColorManagementParams& icm, const Glib::ustring& monitorProfile, RenderingIntent monitorIntent, bool softProof, bool gamutCheck);
void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve, void rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer *pipetteBuffer, LUTf & hltonecurve, LUTf & shtonecurve, LUTf & tonecurve,
SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2, SHMap* shmap, int sat, LUTf & rCurve, LUTf & gCurve, LUTf & bCurve, float satLimit , float satLimitOpacity, const ColorGradientCurve & ctColorCurve, const OpacityCurve & ctOpacityCurve, bool opautili, LUTf & clcurve, LUTf & cl2curve, const ToneCurve & customToneCurve1, const ToneCurve & customToneCurve2,
const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn ); const ToneCurve & customToneCurvebw1, const ToneCurve & customToneCurvebw2, double &rrm, double &ggm, double &bbm, float &autor, float &autog, float &autob, DCPProfile *dcpProf, const DCPProfile::ApplyState &asIn );
@ -361,9 +361,8 @@ public:
void Badpixelscam(CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad); void Badpixelscam(CieImage * src, CieImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom, int hotbad);
void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom); void BadpixelsLab(LabImage * src, LabImage * dst, double radius, int thresh, int mode, float b_l, float t_l, float t_r, float b_r, float skinprot, float chrom);
Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool standard_gamma); Image8* lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm);
Image16* lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw);// for gamma output Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga=NULL);
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool bw);//without gamma ==>default
// CieImage *ciec; // CieImage *ciec;
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = NULL); bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = NULL);

View File

@ -32,6 +32,12 @@ namespace rtengine
extern const Settings* settings; extern const Settings* settings;
// Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc)
// Crop::update (rtengine/dcrop.cc)
// Thumbnail::processImage (rtengine/rtthumbnail.cc)
//
// If monitorTransform, divide by 327.68 then apply monitorTransform (which can integrate soft-proofing)
// otherwise divide by 327.68, convert to xyz and apply the sRGB transform, before converting with gamma2curve
void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image) void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
{ {
if (monitorTransform) { if (monitorTransform) {
@ -61,21 +67,13 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
float* ra = lab->a[i]; float* ra = lab->a[i];
float* rb = lab->b[i]; float* rb = lab->b[i];
float fy, fx, fz, x_, y_, z_, LL;
for (int j = 0; j < W; j++) { for (int j = 0; j < W; j++) {
buffer[iy++] = rL[j] / 327.68f; buffer[iy++] = rL[j] / 327.68f;
buffer[iy++] = ra[j] / 327.68f; buffer[iy++] = ra[j] / 327.68f;
buffer[iy++] = rb[j] / 327.68f; buffer[iy++] = rb[j] / 327.68f;
} }
if (!settings->HistogramWorking && output2monitorTransform && lab2outputTransform) { cmsDoTransform (monitorTransform, buffer, data + ix, W);
AlignedBuffer<float> buf(3 * W);
cmsDoTransform (lab2outputTransform, buffer, buf.data, W);
cmsDoTransform (output2monitorTransform, buf.data, data + ix, W);
} else {
cmsDoTransform (monitorTransform, buffer, data + ix, W);
}
} }
} // End of parallelization } // End of parallelization
} else { } else {
@ -115,8 +113,18 @@ void ImProcFunctions::lab2monitorRgb (LabImage* lab, Image8* image)
} }
} }
Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool standard_gamma)
// Used in ImProcCoordinator::updatePreviewImage (rtengine/improccoordinator.cc)
// Crop::update (rtengine/dcrop.cc)
//
// Generate an Image8
//
// If output profile used, divide by 327.68 then apply the "profile" profile (eventually with a standard gamma)
// otherwise divide by 327.68, convert to xyz and apply the RGB transform, before converting with gamma2curve
Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm)
{ {
//gamutmap(lab);
if (cx < 0) { if (cx < 0) {
cx = 0; cx = 0;
@ -135,9 +143,22 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
} }
Image8* image = new Image8 (cw, ch); Image8* image = new Image8 (cw, ch);
Glib::ustring profile;
cmsHPROFILE oprof = iccStore->getProfile (profile); cmsHPROFILE oprof = iccStore->getProfile (profile);
bool standard_gamma;
if(settings->HistogramWorking) {
profile = icm.working;
standard_gamma = true;
} else {
profile = icm.output;
if (icm.output.empty() || icm.output == ColorManagementParams::NoICMString) {
profile = "sRGB";
}
standard_gamma = false;
}
if (oprof) { if (oprof) {
cmsHPROFILE oprofG = oprof; cmsHPROFILE oprofG = oprof;
@ -145,11 +166,16 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
oprofG = ICCStore::makeStdGammaProfile(oprof); oprofG = ICCStore::makeStdGammaProfile(oprof);
} }
cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
if (icm.outputBPC) {
flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
printf("lab2rgb / bpc=true\n");
}
else printf("lab2rgb / bpc=false\n");
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHPROFILE hLab = cmsCreateLab4Profile(NULL); cmsHPROFILE LabIProf = cmsCreateLab4Profile(NULL);
cmsHTRANSFORM hTransform = cmsCreateTransform (hLab, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, intent, cmsHTRANSFORM hTransform = cmsCreateTransform (LabIProf, TYPE_Lab_DBL, oprofG, TYPE_RGB_8, icm.outputIntent, flags); // NOCACHE is important for thread safety
cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE ); // NOCACHE is important for thread safety cmsCloseProfile(LabIProf);
cmsCloseProfile(hLab);
lcmsMutex->unlock (); lcmsMutex->unlock ();
unsigned char *data = image->data; unsigned char *data = image->data;
@ -220,8 +246,24 @@ Image8* ImProcFunctions::lab2rgb (LabImage* lab, int cx, int cy, int cw, int ch,
return image; return image;
} }
// for default (not gamma)
Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, bool bw)
/** @brief Convert the final Lab image to the output RGB color space
*
* Used in processImage (rtengine/simpleprocess.cc)
*
* Provide a pointer to a 7 floats array for "ga" (uninitialized ; this array will be filled with the gamma values) if you want
* to use the custom gamma scenario. Thoses gamma values will correspond to the ones of the chosen standard output profile
* (Prophoto if non standard output profile given)
*
* If "ga" is NULL, then we're considering standard gamma with the chosen output profile.
*
* Generate an Image16
*
* If a custom gamma profile can be created, divide by 327.68, convert to xyz and apply the custom gamma transform
* otherwise divide by 327.68, convert to xyz and apply the sRGB transform, before converting with gamma2curve
*/
Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga)
{ {
if (cx < 0) { if (cx < 0) {
@ -241,49 +283,37 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
} }
Image16* image = new Image16 (cw, ch); Image16* image = new Image16 (cw, ch);
cmsHPROFILE oprof = iccStore->getProfile (profile);
cmsHPROFILE oprof = NULL;
if (ga) {
lcmsMutex->lock ();
iccStore->getGammaArray(icm, *ga);
oprof = iccStore->createGammaProfile(icm, *ga);
lcmsMutex->unlock ();
printf("iccStore->createGammaProfile(icm, *ga);\n");
} else {
oprof = iccStore->getProfile (icm.output);
printf("iccStore->getProfile (%s);\n", icm.output.c_str());
}
if (oprof) { if (oprof) {
#ifdef _OPENMP cmsUInt32Number flags = cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE;
#pragma omp parallel for if (multiThread) if (icm.outputBPC) {
#endif flags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
printf("lab2rgb16 / icm.outputBPC=true / outputIntent=%d\n", icm.outputIntent);
for (int i = cy; i < cy + ch; i++) {
float* rL = lab->L[i];
float* ra = lab->a[i];
float* rb = lab->b[i];
short* xa = (short*)image->r(i - cy);
short* ya = (short*)image->g(i - cy);
short* za = (short*)image->b(i - cy);
for (int j = cx; j < cx + cw; j++) {
float x_, y_, z_;
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
xa[j - cx] = float2uint16range(x_);
ya[j - cx] = float2uint16range(y_);
za[j - cx] = float2uint16range(z_);
if(bw && y_ < 65535.f ) { //force Bw value and take highlight into account
xa[j - cx] = float2uint16range(y_ * Color::D50x);
za[j - cx] = float2uint16range(y_ * Color::D50z);
}
}
} }
else printf("lab2rgb16 / icm.outputBPC=false / outputIntent=%d\n", icm.outputIntent);
cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock (); lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprof, TYPE_RGB_16, intent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE); cmsHPROFILE iprof = cmsCreateLab4Profile(nullptr);
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_Lab_FLT, oprof, TYPE_RGB_16, icm.outputIntent, flags);
lcmsMutex->unlock (); lcmsMutex->unlock ();
image->ExecCMSTransform(hTransform); image->ExecCMSTransform(hTransform, *lab, cx, cy);
cmsDeleteTransform(hTransform); cmsDeleteTransform(hTransform);
} else { } else {
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel for if (multiThread) #pragma omp parallel for schedule(dynamic,16) if (multiThread)
#endif #endif
for (int i = cy; i < cy + ch; i++) { for (int i = cy; i < cy + ch; i++) {
float R, G, B; float R, G, B;
float* rL = lab->L[i]; float* rL = lab->L[i];
@ -297,279 +327,10 @@ Image16* ImProcFunctions::lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int
float fz = fy - (0.005f * rb[j]) / 327.68f; float fz = fy - (0.005f * rb[j]) / 327.68f;
float LL = rL[j] / 327.68f; float LL = rL[j] / 327.68f;
float x_ = 65535.0f * (float) Color::f2xyz(fx) * Color::D50x; float x_ = 65535.0f * Color::f2xyz(fx) * Color::D50x;
//float y_ = 65535.0 * Color::f2xyz(fy); //float y_ = 65535.0 * Color::f2xyz(fy);
float z_ = 65535.0f * (float) Color::f2xyz(fz) * Color::D50z; float z_ = 65535.0f * Color::f2xyz(fz) * Color::D50z;
float y_ = (LL > Color::epskap) ? (float) 65535.0f * fy * fy * fy : 65535.0f * LL / Color::kappa; float y_ = (LL > (float)Color::epskap) ? 65535.0f * fy * fy * fy : 65535.0f * LL / (float)Color::kappa;
Color::xyz2srgb(x_, y_, z_, R, G, B);
image->r(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(R)];
image->g(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(G)];
image->b(i - cy, j - cx) = (int)Color::gamma2curve[CLIP(B)];
}
}
}
return image;
}
// for gamma options (BT709...sRGB linear...)
Image16* ImProcFunctions::lab2rgb16b (LabImage* lab, int cx, int cy, int cw, int ch, Glib::ustring profile, RenderingIntent intent, Glib::ustring profi, Glib::ustring gam, bool freegamma, double gampos, double slpos, double &ga0, double &ga1, double &ga2, double &ga3, double &ga4, double &ga5, double &ga6, bool bw)
{
if (cx < 0) {
cx = 0;
}
if (cy < 0) {
cy = 0;
}
if (cx + cw > lab->W) {
cw = lab->W - cx;
}
if (cy + ch > lab->H) {
ch = lab->H - cy;
}
Image16* image = new Image16 (cw, ch);
float p1, p2, p3, p4, p5, p6; //primaries
double pwr;
double ts;
ga6 = 0.0;
pwr = 1.0 / gampos;
ts = slpos;
int t50;
int select_temp = 1; //5003K
const double eps = 0.000000001; // not divide by zero
//primaries for 7 working profiles ==> output profiles
// eventually to adapt primaries if RT used special profiles !
if (profi == "WideGamut") {
p1 = 0.7350; //Widegamut primaries
p2 = 0.2650;
p3 = 0.1150;
p4 = 0.8260;
p5 = 0.1570;
p6 = 0.0180;
select_temp = 1;
} else if (profi == "Adobe RGB") {
p1 = 0.6400; //Adobe primaries
p2 = 0.3300;
p3 = 0.2100;
p4 = 0.7100;
p5 = 0.1500;
p6 = 0.0600;
select_temp = 2;
} else if (profi == "sRGB") {
p1 = 0.6400; // sRGB primaries
p2 = 0.3300;
p3 = 0.3000;
p4 = 0.6000;
p5 = 0.1500;
p6 = 0.0600;
select_temp = 2;
} else if (profi == "BruceRGB") {
p1 = 0.6400; // Bruce primaries
p2 = 0.3300;
p3 = 0.2800;
p4 = 0.6500;
p5 = 0.1500;
p6 = 0.0600;
select_temp = 2;
} else if (profi == "Beta RGB") {
p1 = 0.6888; // Beta primaries
p2 = 0.3112;
p3 = 0.1986;
p4 = 0.7551;
p5 = 0.1265;
p6 = 0.0352;
select_temp = 1;
} else if (profi == "BestRGB") {
p1 = 0.7347; // Best primaries
p2 = 0.2653;
p3 = 0.2150;
p4 = 0.7750;
p5 = 0.1300;
p6 = 0.0350;
select_temp = 1;
} else if (profi == "Rec2020") {
p1 = 0.7080; // Rec2020 primaries
p2 = 0.2920;
p3 = 0.1700;
p4 = 0.7970;
p5 = 0.1310;
p6 = 0.0460;
select_temp = 2;
} else {
p1 = 0.7347; //ProPhoto and default primaries
p2 = 0.2653;
p3 = 0.1596;
p4 = 0.8404;
p5 = 0.0366;
p6 = 0.0001;
select_temp = 1;
}
if (!freegamma) {//if Free gamma not selected
// gamma : ga0,ga1,ga2,ga3,ga4,ga5 by calcul
if(gam == "BT709_g2.2_s4.5") {
ga0 = 2.22; //BT709 2.2 4.5 - my prefered as D.Coffin
ga1 = 0.909995;
ga2 = 0.090005;
ga3 = 0.222222;
ga4 = 0.081071;
ga5 = 0.0;
} else if (gam == "sRGB_g2.4_s12.92") {
ga0 = 2.40; //sRGB 2.4 12.92 - RT default as Lightroom
ga1 = 0.947858;
ga2 = 0.052142;
ga3 = 0.077399;
ga4 = 0.039293;
ga5 = 0.0;
} else if (gam == "High_g1.3_s3.35") {
ga0 = 1.3 ; //for high dynamic images
ga1 = 0.998279;
ga2 = 0.001721;
ga3 = 0.298507;
ga4 = 0.005746;
ga5 = 0.0;
} else if (gam == "Low_g2.6_s6.9") {
ga0 = 2.6 ; //gamma 2.6 variable : for low contrast images
ga1 = 0.891161;
ga2 = 0.108839;
ga3 = 0.144928;
ga4 = 0.076332;
ga5 = 0.0;
} else if (gam == "linear_g1.0") {
ga0 = 1.0; //gamma=1 linear : for high dynamic images (cf : D.Coffin...)
ga1 = 1.;
ga2 = 0.;
ga3 = 1. / eps;
ga4 = 0.;
ga5 = 0.0;
} else if (gam == "standard_g2.2") {
ga0 = 2.2; //gamma=2.2 (as gamma of Adobe, Widegamut...)
ga1 = 1.;
ga2 = 0.;
ga3 = 1. / eps;
ga4 = 0.;
ga5 = 0.0;
} else if (gam == "standard_g1.8") {
ga0 = 1.8; //gamma=1.8 (as gamma of Prophoto)
ga1 = 1.;
ga2 = 0.;
ga3 = 1. / eps;
ga4 = 0.;
ga5 = 0.0;
}
} else { //free gamma selected
if(slpos == 0) {
slpos = eps;
}
double g_a0, g_a1, g_a2, g_a3, g_a4, g_a5; //gamma parameters
int mode = 0, imax = 0;
Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope : return parameters for LCMS2
ga4 = g_a3 * ts;
ga0 = gampos;
ga1 = 1. / (1.0 + g_a4);
ga2 = g_a4 / (1.0 + g_a4);
ga3 = 1. / slpos;
ga5 = 0.0;
}
if(select_temp == 1) {
t50 = 5003; // for Widegamut, Prophoto Best, Beta D50
} else if (select_temp == 2) {
t50 = 6504; // for sRGB, AdobeRGB, Bruce Rec2020 D65
}
cmsCIExyY xyD;
cmsCIExyYTRIPLE Primaries = {{p1, p2, 1.0},//red primaries
{p3, p4, 1.0}, // green
{p5, p6, 1.0} //blue
};
cmsToneCurve* GammaTRC[3];
cmsFloat64Number Parameters[7];
Parameters[0] = ga0;
Parameters[1] = ga1;
Parameters[2] = ga2;
Parameters[3] = ga3;
Parameters[4] = ga4;
Parameters[5] = ga5;
Parameters[6] = ga6;
// 7 parameters for smoother curves
cmsWhitePointFromTemp(&xyD, t50);
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters);//5 = more smoother than 4
cmsHPROFILE oprofdef = cmsCreateRGBProfileTHR(NULL, &xyD, &Primaries, GammaTRC); //oprofdef becomes Outputprofile
cmsFreeToneCurve(GammaTRC[0]);
if (oprofdef) {
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int i = cy; i < cy + ch; i++) {
float* rL = lab->L[i];
float* ra = lab->a[i];
float* rb = lab->b[i];
short* xa = (short*)image->r(i - cy);
short* ya = (short*)image->g(i - cy);
short* za = (short*)image->b(i - cy);
for (int j = cx; j < cx + cw; j++) {
float x_, y_, z_;
Color::Lab2XYZ(rL[j], ra[j], rb[j], x_, y_, z_);
xa[j - cx] = float2uint16range(x_);
ya[j - cx] = float2uint16range(y_);
za[j - cx] = float2uint16range(z_);
if(bw && y_ < 65535.f) { //force Bw value and take highlight into account
xa[j - cx] = float2uint16range(y_ * Color::D50x);
za[j - cx] = float2uint16range(y_ * Color::D50z);
}
}
}
cmsHPROFILE iprof = iccStore->getXYZProfile ();
lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (iprof, TYPE_RGB_16, oprofdef, TYPE_RGB_16, intent, cmsFLAGS_NOOPTIMIZE | cmsFLAGS_NOCACHE);
lcmsMutex->unlock ();
image->ExecCMSTransform(hTransform);
cmsDeleteTransform(hTransform);
} else {
#ifdef _OPENMP
#pragma omp parallel for if (multiThread)
#endif
for (int i = cy; i < cy + ch; i++) {
float R, G, B;
float* rL = lab->L[i];
float* ra = lab->a[i];
float* rb = lab->b[i];
for (int j = cx; j < cx + cw; j++) {
float fy = (0.0086206897f * rL[j]) / 327.68f + 0.1379310345f; // (L+16)/116
float fx = (0.002f * ra[j]) / 327.68f + fy;
float fz = fy - (0.005f * rb[j]) / 327.68f;
float LL = rL[j] / 327.68f;
float x_ = 65535.0f * (float) Color::f2xyz(fx) * Color::D50x;
//float y_ = 65535.0 * Color::f2xyz(fy);
float z_ = 65535.0f * (float) Color::f2xyz(fz) * Color::D50z;
float y_ = (LL > Color::epskap) ? (float) 65535.0 * fy * fy * fy : 65535.0f * LL / Color::kappa;
Color::xyz2srgb(x_, y_, z_, R, G, B); Color::xyz2srgb(x_, y_, z_, R, G, B);

View File

@ -39,6 +39,7 @@
#include "opthelper.h" #include "opthelper.h"
#include "median.h" #include "median.h"
#include "EdgePreservingDecomposition.h" #include "EdgePreservingDecomposition.h"
#include "iccstore.h"
#ifdef _OPENMP #ifdef _OPENMP
#include <omp.h> #include <omp.h>

View File

@ -469,6 +469,7 @@ enum ProcEvent {
EvcbdlMethod = 439, EvcbdlMethod = 439,
EvRetinexgaintransmission = 440, EvRetinexgaintransmission = 440,
EvLskal = 441, EvLskal = 441,
EvOBPCompens = 442,
NUMOFEVENTS NUMOFEVENTS
}; };

View File

@ -927,6 +927,7 @@ void ColorManagementParams::setDefaults()
working = "ProPhoto"; working = "ProPhoto";
output = "RT_sRGB"; output = "RT_sRGB";
outputIntent = RI_RELATIVE; outputIntent = RI_RELATIVE;
outputBPC = true;
gamma = "default"; gamma = "default";
gampos = 2.22; gampos = 2.22;
slpos = 4.5; slpos = 4.5;
@ -2662,6 +2663,10 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_string ("Color Management", "OutputProfileIntent", intent); keyFile.set_string ("Color Management", "OutputProfileIntent", intent);
} }
if (!pedited || pedited->icm.outputBPC) {
keyFile.set_boolean ("Color Management", "OutputBPC", icm.outputBPC);
}
if (!pedited || pedited->icm.gamma) { if (!pedited || pedited->icm.gamma) {
keyFile.set_string ("Color Management", "Gammafree", icm.gamma); keyFile.set_string ("Color Management", "Gammafree", icm.gamma);
} }
@ -5921,6 +5926,14 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
} }
} }
if (keyFile.has_key ("Color Management", "OutputBPC")) {
icm.outputBPC = keyFile.get_boolean ("Color Management", "OutputBPC");
if (pedited) {
pedited->icm.outputBPC = true;
}
}
if (keyFile.has_key ("Color Management", "Gammafree")) { if (keyFile.has_key ("Color Management", "Gammafree")) {
icm.gamma = keyFile.get_string ("Color Management", "Gammafree"); icm.gamma = keyFile.get_string ("Color Management", "Gammafree");

View File

@ -969,6 +969,7 @@ public:
Glib::ustring working; Glib::ustring working;
Glib::ustring output; Glib::ustring output;
RenderingIntent outputIntent; RenderingIntent outputIntent;
bool outputBPC;
static const Glib::ustring NoICMString; static const Glib::ustring NoICMString;
Glib::ustring gamma; Glib::ustring gamma;

View File

@ -1973,7 +1973,7 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
} else if(retinexParams.gammaretinex == "hig") { } else if(retinexParams.gammaretinex == "hig") {
retinexgamtab = &(Color::gammatab_145_3); retinexgamtab = &(Color::gammatab_145_3);
} else if(retinexParams.gammaretinex == "fre") { } else if(retinexParams.gammaretinex == "fre") {
double g_a0, g_a1, g_a2, g_a3, g_a4, g_a5; GammaValues g_a;
double pwr = 1.0 / retinexParams.gam; double pwr = 1.0 / retinexParams.gam;
double gamm = retinexParams.gam; double gamm = retinexParams.gam;
double ts = retinexParams.slope; double ts = retinexParams.slope;
@ -1984,21 +1984,21 @@ void RawImageSource::retinexPrepareBuffers(ColorManagementParams cmp, RetinexPar
} }
int mode = 0, imax = 0; int mode = 0, imax = 0;
Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope Color::calcGamma(pwr, ts, mode, imax, g_a); // call to calcGamma with selected gamma and slope
// printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4); // printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4);
double start; double start;
double add; double add;
if(gamm2 < 1.) { if(gamm2 < 1.) {
start = g_a2; start = g_a[2];
add = g_a4; add = g_a[4];
} else { } else {
start = g_a3; start = g_a[3];
add = g_a4; add = g_a[4];
} }
double mul = 1. + g_a4; double mul = 1. + g_a[4];
lutTonereti(65536); lutTonereti(65536);
@ -2245,7 +2245,7 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
} else if(deh.gammaretinex == "hig") { } else if(deh.gammaretinex == "hig") {
retinexigamtab = &(Color::igammatab_145_3); retinexigamtab = &(Color::igammatab_145_3);
} else if(deh.gammaretinex == "fre") { } else if(deh.gammaretinex == "fre") {
double g_a0, g_a1, g_a2, g_a3, g_a4, g_a5; GammaValues g_a;
double pwr = 1.0 / deh.gam; double pwr = 1.0 / deh.gam;
double gamm = deh.gam; double gamm = deh.gam;
double gamm2 = gamm; double gamm2 = gamm;
@ -2256,18 +2256,18 @@ void RawImageSource::retinex(ColorManagementParams cmp, RetinexParams deh, ToneC
std::swap(pwr, gamm); std::swap(pwr, gamm);
} }
Color::calcGamma(pwr, ts, mode, imax, g_a0, g_a1, g_a2, g_a3, g_a4, g_a5); // call to calcGamma with selected gamma and slope Color::calcGamma(pwr, ts, mode, imax, g_a); // call to calcGamma with selected gamma and slope
double mul = 1. + g_a4; double mul = 1. + g_a[4];
double add; double add;
double start; double start;
if(gamm2 < 1.) { if(gamm2 < 1.) {
start = g_a3; start = g_a[3];
add = g_a3; add = g_a[3];
} else { } else {
add = g_a4; add = g_a[4];
start = g_a2; start = g_a[2];
} }
// printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4); // printf("g_a0=%f g_a1=%f g_a2=%f g_a3=%f g_a4=%f\n", g_a0,g_a1,g_a2,g_a3,g_a4);

View File

@ -119,8 +119,8 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
ALLNORAW, // EvDPDNLuma, ALLNORAW, // EvDPDNLuma,
ALLNORAW, // EvDPDNChroma, ALLNORAW, // EvDPDNChroma,
ALLNORAW, // EvDPDNGamma, ALLNORAW, // EvDPDNGamma,
ALLNORAW, // EvDirPyrEqualizer, ALLNORAW, // EvDirPyrEqualizer,
ALLNORAW, // EvDirPyrEqlEnabled, ALLNORAW, // EvDirPyrEqlEnabled,
LUMINANCECURVE, // EvLSaturation, LUMINANCECURVE, // EvLSaturation,
LUMINANCECURVE, // EvLaCurve, LUMINANCECURVE, // EvLaCurve,
LUMINANCECURVE, // EvLbCurve, LUMINANCECURVE, // EvLbCurve,
@ -275,12 +275,12 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
LUMINANCECURVE, // EvLCLCurve LUMINANCECURVE, // EvLCLCurve
LUMINANCECURVE, // EvLLHCurve LUMINANCECURVE, // EvLLHCurve
LUMINANCECURVE, // EvLHHCurve LUMINANCECURVE, // EvLHHCurve
ALLNORAW, // EvDirPyrEqualizerThreshold ALLNORAW, // EvDirPyrEqualizerThreshold
ALLNORAW, // EvDPDNenhance ALLNORAW, // EvDPDNenhance
RGBCURVE, // EvBWMethodalg RGBCURVE, // EvBWMethodalg
ALLNORAW, // EvDirPyrEqualizerSkin ALLNORAW, // EvDirPyrEqualizerSkin
ALLNORAW, // EvDirPyrEqlgamutlab ALLNORAW, // EvDirPyrEqlgamutlab
ALLNORAW, // EvDirPyrEqualizerHueskin ALLNORAW, // EvDirPyrEqualizerHueskin
ALLNORAW, // EvDPDNmedian ALLNORAW, // EvDPDNmedian
ALLNORAW, // EvDPDNmedmet ALLNORAW, // EvDPDNmedmet
RGBCURVE, // EvColorToningEnabled RGBCURVE, // EvColorToningEnabled
@ -453,7 +453,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
RETINEX, // EvLhighl RETINEX, // EvLhighl
DEMOSAIC, // EvLbaselog DEMOSAIC, // EvLbaselog
DEMOSAIC, // EvRetinexlhcurve DEMOSAIC, // EvRetinexlhcurve
ALLNORAW, // EvOIntent OUTPUTPROFILE, // EvOIntent
MONITORTRANSFORM, // EvMonitorTransform: no history message MONITORTRANSFORM, // EvMonitorTransform: no history message
RETINEX, // EvLiter RETINEX, // EvLiter
RETINEX, // EvLgrad RETINEX, // EvLgrad
@ -465,10 +465,11 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
RETINEX, // EvLradius RETINEX, // EvLradius
RETINEX, // EvmapMethod RETINEX, // EvmapMethod
DEMOSAIC, // EvRetinexmapcurve DEMOSAIC, // EvRetinexmapcurve
DEMOSAIC, // EvviewMethod DEMOSAIC, // EvviewMethod
ALLNORAW, // EvcbdlMethod ALLNORAW, // EvcbdlMethod
RETINEX, // EvRetinexgaintransmission RETINEX, // EvRetinexgaintransmission
RETINEX //EvLskal RETINEX, // EvLskal
OUTPUTPROFILE // EvOBPCompens
}; };

View File

@ -46,7 +46,7 @@
// Bitfield of functions to do to the preview image when an event occurs // Bitfield of functions to do to the preview image when an event occurs
// Use those or create new ones for your new events // Use those or create new ones for your new events
#define FIRST (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL #define FIRST (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_MONITOR) // without HIGHQUAL
#define ALL (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL #define ALL (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) #define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_LINDENOISE|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
@ -61,7 +61,7 @@
#define DEFRINGE (M_LUMINANCE|M_COLOR) #define DEFRINGE (M_LUMINANCE|M_COLOR)
#define DIRPYRDENOISE (M_LUMINANCE|M_COLOR) #define DIRPYRDENOISE (M_LUMINANCE|M_COLOR)
#define DIRPYREQUALIZER (M_LUMINANCE|M_COLOR) #define DIRPYREQUALIZER (M_LUMINANCE|M_COLOR)
#define GAMMA (M_LUMINANCE|M_COLOR) #define GAMMA M_MONITOR
#define CROP M_CROP #define CROP M_CROP
#define RESIZE M_VOID #define RESIZE M_VOID
#define EXIF M_VOID #define EXIF M_VOID
@ -69,7 +69,7 @@
#define MINUPDATE M_MINUPDATE #define MINUPDATE M_MINUPDATE
#define RETINEX (M_RETINEX|ALLNORAW) #define RETINEX (M_RETINEX|ALLNORAW)
#define MONITORTRANSFORM M_MONITOR #define MONITORTRANSFORM M_MONITOR
#define OUTPUTPROFILE (ALLNORAW|MONITORTRANSFORM) #define OUTPUTPROFILE M_MONITOR
extern int refreshmap[]; extern int refreshmap[];
#endif #endif

View File

@ -418,6 +418,8 @@ public:
virtual void setMonitorProfile (const Glib::ustring& monitorProfile, RenderingIntent intent) = 0; virtual void setMonitorProfile (const Glib::ustring& monitorProfile, RenderingIntent intent) = 0;
virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0; virtual void getMonitorProfile (Glib::ustring& monitorProfile, RenderingIntent& intent) const = 0;
virtual void setSoftProofing (bool softProof, bool gamutCheck) = 0;
virtual void getSoftProofing (bool &softProof, bool &gamutCheck) = 0;
virtual ~StagedImageProcessor () {} virtual ~StagedImageProcessor () {}

View File

@ -908,7 +908,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
ImProcFunctions ipf (&params, false); ImProcFunctions ipf (&params, false);
ipf.setScale (sqrt(double(fw * fw + fh * fh)) / sqrt(double(thumbImg->width * thumbImg->width + thumbImg->height * thumbImg->height))*scale); ipf.setScale (sqrt(double(fw * fw + fh * fh)) / sqrt(double(thumbImg->width * thumbImg->width + thumbImg->height * thumbImg->height))*scale);
ipf.updateColorProfiles (params.icm, options.rtSettings.monitorProfile, options.rtSettings.monitorIntent); ipf.updateColorProfiles (params.icm, options.rtSettings.monitorProfile, options.rtSettings.monitorIntent, false, false);
LUTu hist16 (65536); LUTu hist16 (65536);

View File

@ -40,6 +40,7 @@ public:
Glib::ustring monitorProfile; ///< ICC profile name used for the monitor Glib::ustring monitorProfile; ///< ICC profile name used for the monitor
RenderingIntent monitorIntent; ///< Colorimetric intent used with the above profile RenderingIntent monitorIntent; ///< Colorimetric intent used with the above profile
bool monitorBPC; ///< Black Point Compensation for the Labimage->Monitor transform (directly, i.e. not soft-proofing and no WCS in between)
bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile bool autoMonitorProfile; ///< Try to auto-determine the correct monitor color profile
bool autocielab; bool autocielab;
bool rgbcurveslumamode_gamut;// controls gamut enforcement for RGB curves in lumamode bool rgbcurveslumamode_gamut;// controls gamut enforcement for RGB curves in lumamode

View File

@ -1151,213 +1151,27 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
cmsHPROFILE jprof = NULL; cmsHPROFILE jprof = NULL;
bool customGamma = false; bool customGamma = false;
bool useLCMS = false; bool useLCMS = false;
bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled && !autili && !butili ;
if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8 if(params.icm.gamma != "default" || params.icm.freegamma) { // if select gamma output between BT709, sRGB, linear, low, high, 2.2 , 1.8
double ga0, ga1, ga2, ga3, ga4, ga5, ga6; GammaValues ga;
// if(params.blackwhite.enabled) params.toneCurve.hrenabled=false; // if(params.blackwhite.enabled) params.toneCurve.hrenabled=false;
readyImg = ipf.lab2rgb16b (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, params.icm.working, params.icm.gamma, params.icm.freegamma, params.icm.gampos, params.icm.slpos, ga0, ga1, ga2, ga3, ga4, ga5, ga6, params.blackwhite.enabled ); readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly, &ga);
customGamma = true; customGamma = true;
//or selected Free gamma //or selected Free gamma
useLCMS = false; useLCMS = false;
bool pro = false;
Glib::ustring chpro, outProfile;
bool present_space[10] = {false, false, false, false, false, false, false, false, false, false};
std::vector<Glib::ustring> opnames = iccStore->getProfiles ();
//test if files are in system
for (int j = 0; j < 10; j++) {
// one can modify "option" [Color Management] to adapt the profile's name if they are different for windows, MacOS, Linux ??
// some of them are actually provided by RT, thanks to Jacques Desmis
if (j == 0) {
chpro = options.rtSettings.prophoto;
} else if(j == 1) {
chpro = options.rtSettings.adobe;
} else if(j == 2) {
chpro = options.rtSettings.widegamut;
} else if(j == 3) {
chpro = options.rtSettings.beta;
} else if(j == 4) {
chpro = options.rtSettings.best;
} else if(j == 5) {
chpro = options.rtSettings.bruce;
} else if(j == 6) {
chpro = options.rtSettings.srgb;
} else if(j == 7) {
chpro = options.rtSettings.srgb10; //gamma 1.0
} else if(j == 8) {
chpro = options.rtSettings.prophoto10; //gamma 1.0
} else if(j == 9) {
chpro = options.rtSettings.rec2020;
}
for (unsigned int i = 0; i < opnames.size(); i++) {
if(chpro.compare(opnames[i]) == 0) {
present_space[j] = true;
}
}
if (!present_space[j] && settings->verbose) {
printf("Missing file: %s\n", chpro.c_str());
}
}
if (params.icm.freegamma && params.icm.gampos < 1.35) {
pro = true; //select profil with gammaTRC modified :
} else if (params.icm.gamma == "linear_g1.0" || (params.icm.gamma == "High_g1.3_s3.35")) {
pro = true; //pro=0 RT_sRGB || Prophoto
}
// Check that output profiles exist, otherwise use LCMS2
// Use the icc/icm profiles associated to possible working profiles, set in "options"
if (params.icm.working == "ProPhoto" && present_space[0] && !pro) {
outProfile = options.rtSettings.prophoto;
} else if (params.icm.working == "Adobe RGB" && present_space[1] ) {
outProfile = options.rtSettings.adobe;
} else if (params.icm.working == "WideGamut" && present_space[2] ) {
outProfile = options.rtSettings.widegamut;
} else if (params.icm.working == "Beta RGB" && present_space[3] ) {
outProfile = options.rtSettings.beta;
} else if (params.icm.working == "BestRGB" && present_space[4] ) {
outProfile = options.rtSettings.best;
} else if (params.icm.working == "BruceRGB" && present_space[5] ) {
outProfile = options.rtSettings.bruce;
} else if (params.icm.working == "sRGB" && present_space[6] && !pro) {
outProfile = options.rtSettings.srgb;
} else if (params.icm.working == "sRGB" && present_space[7] && pro) {
outProfile = options.rtSettings.srgb10;
} else if (params.icm.working == "ProPhoto" && present_space[8] && pro) {
outProfile = options.rtSettings.prophoto10;
} else if (params.icm.working == "Rec2020" && present_space[9]) {
outProfile = options.rtSettings.rec2020;
} else {
// Should not occurs
if (settings->verbose) {
printf("\"%s\": unknown working profile! - use LCMS2 substitution\n", params.icm.working.c_str() );
}
if ((jprof = iccStore->createCustomGammaOutputProfile (params.icm, ga)) == NULL) {
useLCMS = true; useLCMS = true;
} }
//begin adaptation rTRC gTRC bTRC
//"jprof" profile has the same characteristics than RGB values, but TRC are adapted... for applying profile
if (!useLCMS) {
if (settings->verbose) {
printf("Output Gamma - profile: \"%s\"\n", outProfile.c_str() ); //c_str()
}
jprof = iccStore->getProfile(outProfile); //get output profile
if (jprof == NULL) {
useLCMS = true;
if (settings->verbose) {
printf("\"%s\" ICC output profile not found!\n", outProfile.c_str());
}
} else {
cmsToneCurve* GammaTRC[3] = { NULL, NULL, NULL };
cmsFloat64Number Parameters[7];
Parameters[0] = ga0;
Parameters[1] = ga1;
Parameters[2] = ga2;
Parameters[3] = ga3;
Parameters[4] = ga4;
Parameters[5] = ga5;
Parameters[6] = ga6;
// 7 parameters for smoother curves
//change desc Tag , to "free gamma", or "BT709", etc.
cmsMLU *DescriptionMLU, *CopyrightMLU, *DmndMLU, *DmddMLU;// for modification TAG
cmsContext ContextID = cmsGetProfileContextID(jprof);//modification TAG
DescriptionMLU = cmsMLUalloc(ContextID, 1);
CopyrightMLU = cmsMLUalloc(ContextID, 1);//for ICC
DmndMLU = cmsMLUalloc(ContextID, 1); //for ICC
DmddMLU = cmsMLUalloc(ContextID, 1); // for ICC
// instruction with //ICC are used for generate icc profile
if (DescriptionMLU == NULL) {
printf("Description error\n");
}
cmsMLUsetWide(CopyrightMLU, "en", "US", L"General Public License - AdobeRGB compatible") ;//adapt to profil
cmsMLUsetWide(DmndMLU, "en", "US", L"RawTherapee") ;
cmsMLUsetWide(DmddMLU, "en", "US", L"RTMedium") ; //adapt to profil
//display Tag desc with : selection of gamma and Primaries
if (!params.icm.freegamma) {
std::wstring gammaStr;
if(params.icm.gamma == "High_g1.3_s3.35") {
gammaStr = std::wstring(L"GammaTRC: High g=1.3 s=3.35");
} else if (params.icm.gamma == "Low_g2.6_s6.9") {
gammaStr = std::wstring(L"GammaTRC: Low g=2.6 s=6.9");
} else if (params.icm.gamma == "sRGB_g2.4_s12.92") {
gammaStr = std::wstring(L"GammaTRC: sRGB g=2.4 s=12.92");
} else if (params.icm.gamma == "BT709_g2.2_s4.5") {
gammaStr = std::wstring(L"GammaTRC: BT709 g=2.2 s=4.5");
} else if (params.icm.gamma == "linear_g1.0") {
gammaStr = std::wstring(L"GammaTRC: Linear g=1.0");
} else if (params.icm.gamma == "standard_g2.2") {
gammaStr = std::wstring(L"GammaTRC: g=2.2");
} else if (params.icm.gamma == "standard_g1.8") {
gammaStr = std::wstring(L"GammaTRC: g=1.8");
}
cmsMLUsetWide(DescriptionMLU, "en", "US", gammaStr.c_str());
//for elaboration ICC profiles
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Medium gamma sRGB(AdobeRGB compatible)");
// else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma BT709(IEC61966 equivalent)");
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma sRGB(IEC61966 equivalent)");
// else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_sRGB gamma Linear1.0(IEC61966 equivalent)");
//else if (params.icm.gamma== "BT709_g2.2_s4.5" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma BT709(Prophoto compatible)");
// else if (params.icm.gamma== "sRGB_g2.4_s12.92" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma sRGB(Prophoto compatible)");
// else if (params.icm.gamma== "linear_g1.0" && !params.icm.freegamma) cmsMLUsetWide(DescriptionMLU, "en", "US", L"RT_Large gamma Linear1.0(Prophoto compatible)");
} else {
// create description with gamma + slope + primaries
std::wostringstream gammaWs;
gammaWs.precision(2);
gammaWs << "Manual GammaTRC: g=" << (float)params.icm.gampos << " s=" << (float)params.icm.slpos;
cmsMLUsetWide(DescriptionMLU, "en", "US", gammaWs.str().c_str());
}
cmsWriteTag(jprof, cmsSigProfileDescriptionTag, DescriptionMLU);//desc changed
// cmsWriteTag(jprof, cmsSigCopyrightTag, CopyrightMLU);
// cmsWriteTag(jprof, cmsSigDeviceMfgDescTag, DmndMLU);
// cmsWriteTag(jprof, cmsSigDeviceModelDescTag, DmddMLU);
// Calculate output profile's rTRC bTRC gTRC
GammaTRC[0] = GammaTRC[1] = GammaTRC[2] = cmsBuildParametricToneCurve(NULL, 5, Parameters);
cmsWriteTag(jprof, cmsSigGreenTRCTag, (void*)GammaTRC[1] );
cmsWriteTag(jprof, cmsSigRedTRCTag, (void*)GammaTRC[0] );
cmsWriteTag(jprof, cmsSigBlueTRCTag, (void*)GammaTRC[2] );
//for generation ICC profiles : here Prophoto ==> Large
// if(params.icm.gamma== "BT709_g2.2_s4.5") cmsSaveProfileToFile(jprof, "RT_sRGB_gBT709.icm");
// else if (params.icm.gamma== "sRGB_g2.4_s12.92") cmsSaveProfileToFile(jprof, "RT_Medium_gsRGB.icc");
// else if (params.icm.gamma== "linear_g1.0") cmsSaveProfileToFile(jprof, "RT_Large_g10.icc");
if (GammaTRC[0]) {
cmsFreeToneCurve(GammaTRC[0]);
}
}
}
} else { } else {
// if Default gamma mode: we use the profile selected in the "Output profile" combobox; // if Default gamma mode: we use the profile selected in the "Output profile" combobox;
// gamma come from the selected profile, otherwise it comes from "Free gamma" tool // gamma come from the selected profile, otherwise it comes from "Free gamma" tool
// readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.blackwhite.enabled); readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm, bwonly);
bool bwonly = params.blackwhite.enabled && !params.colorToning.enabled ;
if(autili || butili ) {
bwonly = false;
}
readyImg = ipf.lab2rgb16 (labView, cx, cy, cw, ch, params.icm.output, params.icm.outputIntent, bwonly);
if (settings->verbose) { if (settings->verbose) {
printf("Output profile_: \"%s\"\n", params.icm.output.c_str()); printf("Output profile_: \"%s\"\n", params.icm.output.c_str());
@ -1369,17 +1183,15 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
if(!autili && !butili ) { if(bwonly) { //force BW r=g=b
if(params.blackwhite.enabled && !params.colorToning.enabled ) {//force BW r=g=b if (settings->verbose) {
if (settings->verbose) { printf("Force BW\n");
printf("Force BW\n"); }
}
for (int ccw = 0; ccw < cw; ccw++) { for (int ccw = 0; ccw < cw; ccw++) {
for (int cch = 0; cch < ch; cch++) { for (int cch = 0; cch < ch; cch++) {
readyImg->r(cch, ccw) = readyImg->g(cch, ccw); readyImg->r(cch, ccw) = readyImg->g(cch, ccw);
readyImg->b(cch, ccw) = readyImg->g(cch, ccw); readyImg->b(cch, ccw) = readyImg->g(cch, ccw);
}
} }
} }
} }
@ -1405,37 +1217,28 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
// Setting the output curve to readyImg // Setting the output curve to readyImg
if (customGamma) { if (customGamma) {
if (!useLCMS) { if (!useLCMS) {
// use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16b // use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16 w/ gamma
ProfileContent pc(jprof); ProfileContent pc(jprof);
readyImg->setOutputProfile (pc.data, pc.length); readyImg->setOutputProfile (pc.data, pc.length);
} }
} else { } else {
// use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma
Glib::ustring outputProfile;
if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) { if (params.icm.output != "" && params.icm.output != ColorManagementParams::NoICMString) {
outputProfile = params.icm.output;
/* if we'd wanted the RT_sRGB profile we would have selected it
else {
// use RT_sRGB.icm profile if present, otherwise use LCMS2 profile generate by lab2rgb16b
if (settings->verbose) printf("No output profiles set ; looking for the default sRGB profile (\"%s\")...\n", options.rtSettings.srgb.c_str());
outputProfile = options.rtSettings.srgb;
}*/
// if iccStore->getProfile send back an object, then iccStore->getContent will do too // if iccStore->getProfile send back an object, then iccStore->getContent will do too
cmsHPROFILE jprof = iccStore->getProfile(outputProfile); //get outProfile cmsHPROFILE jprof = iccStore->getProfile(params.icm.output); //get outProfile
if (jprof == NULL) { if (jprof == NULL) {
if (settings->verbose) { if (settings->verbose) {
printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", outputProfile.c_str()); printf("\"%s\" ICC output profile not found!\n - use LCMS2 substitution\n", params.icm.output.c_str());
} }
} else { } else {
if (settings->verbose) { if (settings->verbose) {
printf("Using \"%s\" output profile\n", outputProfile.c_str()); printf("Using \"%s\" output profile\n", params.icm.output.c_str());
} }
ProfileContent pc = iccStore->getContent (outputProfile); ProfileContent pc = iccStore->getContent (params.icm.output);
readyImg->setOutputProfile (pc.data, pc.length); readyImg->setOutputProfile (pc.data, pc.length);
} }
} else { } else {

View File

@ -354,7 +354,7 @@ void CurveEditorGroup::setTooltip( Glib::ustring ttip)
void CurveEditorGroup::setBatchMode (bool batchMode) void CurveEditorGroup::setBatchMode (bool batchMode)
{ {
for (std::vector<CurveEditor*>::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) { for (std::vector<CurveEditor*>::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) {
(*i)->curveType->addEntry("curveType-unchanged.png", M("GENERAL_UNCHANGED")); (*i)->curveType->addEntry("unchanged-18.png", M("GENERAL_UNCHANGED"));
(*i)->curveType->show(); (*i)->curveType->show();
} }
} }

View File

@ -35,11 +35,13 @@
using namespace rtengine::procparams; using namespace rtengine::procparams;
class EditorPanel::MonitorProfileSelector class EditorPanel::ColorManagementToolbar
{ {
private: private:
MyComboBoxText profileBox; MyComboBoxText profileBox;
PopUpButton intentBox; PopUpButton intentBox;
Gtk::ToggleButton softProof;
Gtk::ToggleButton spGamutCheck;
sigc::connection profileConn, intentConn; sigc::connection profileConn, intentConn;
rtengine::StagedImageProcessor* const& processor; rtengine::StagedImageProcessor* const& processor;
@ -61,29 +63,51 @@ private:
profileBox.set_active (0); profileBox.set_active (0);
#endif #endif
const std::vector<Glib::ustring> profiles = rtengine::iccStore->getProfiles (); const std::vector<Glib::ustring> profiles = rtengine::iccStore->getProfiles (true);
for (std::vector<Glib::ustring>::const_iterator iterator = profiles.begin (); iterator != profiles.end (); ++iterator) { for (std::vector<Glib::ustring>::const_iterator iterator = profiles.begin (); iterator != profiles.end (); ++iterator) {
profileBox.append (*iterator); profileBox.append (*iterator);
} }
profileBox.set_tooltip_text (profileBox.get_active_text ());
} }
void prepareIntentBox () void prepareIntentBox ()
{ {
intentBox.addEntry ("intent-relative.png", M ("PREFERENCES_INTENT_RELATIVE")); // same order as the enum
intentBox.addEntry ("intent-perceptual.png", M ("PREFERENCES_INTENT_PERCEPTUAL")); intentBox.addEntry ("intent-perceptual.png", M ("PREFERENCES_INTENT_PERCEPTUAL"));
intentBox.addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE"));
intentBox.addEntry ("intent-absolute.png", M ("PREFERENCES_INTENT_ABSOLUTE")); intentBox.addEntry ("intent-absolute.png", M ("PREFERENCES_INTENT_ABSOLUTE"));
setExpandAlignProperties (intentBox.buttonGroup, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); setExpandAlignProperties (intentBox.buttonGroup, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
intentBox.setSelected (0); intentBox.setSelected(1);
intentBox.show (); intentBox.show ();
} }
void prepareSoftProofingBox ()
{
Gtk::Image *softProofImage = Gtk::manage (new RTImage ("softProof.png"));
softProofImage->set_padding(0, 0);
softProof.add(*softProofImage);
softProof.set_relief(Gtk::RELIEF_NONE);
softProof.set_tooltip_markup(M("SOFTPROOF_TOOLTIP"));
softProof.set_active(false);
softProof.show ();
Gtk::Image *spGamutCheckImage = Gtk::manage (new RTImage ("spGamutCheck.png"));
spGamutCheckImage->set_padding(0, 0);
spGamutCheck.add(*spGamutCheckImage);
spGamutCheck.set_relief(Gtk::RELIEF_NONE);
spGamutCheck.set_tooltip_markup(M("SOFTPROOF_GAMUTCHECK_TOOLTIP"));
spGamutCheck.set_active(false);
spGamutCheck.set_sensitive(false);
spGamutCheck.show ();
}
void profileBoxChanged () void profileBoxChanged ()
{ {
updateParameters (); updateParameters ();
profileBox.set_tooltip_text (profileBox.get_active_text ());
} }
void intentBoxChanged (int) void intentBoxChanged (int)
@ -91,7 +115,17 @@ private:
updateParameters (); updateParameters ();
} }
void updateParameters () void softProofToggled ()
{
updateSoftProofParameters ();
}
void spGamutCheckToggled ()
{
updateSoftProofParameters ();
}
void updateParameters (bool noEvent = false)
{ {
ConnectionBlocker profileBlocker (profileConn); ConnectionBlocker profileBlocker (profileConn);
ConnectionBlocker intentBlocker (intentConn); ConnectionBlocker intentBlocker (intentConn);
@ -123,23 +157,36 @@ private:
profile.clear (); profile.clear ();
intentBox.set_sensitive (false); intentBox.set_sensitive (false);
intentBox.setSelected (0); intentBox.setSelected (1);
softProof.set_sensitive(false);
spGamutCheck.set_sensitive(false);
profileBox.set_tooltip_text ("");
} else { } else {
const std::uint8_t supportedIntents = rtengine::iccStore->getProofIntents (profile); const uint8_t supportedIntents = rtengine::iccStore->getProofIntents (profile);
const bool supportsRelativeColorimetric = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC; const bool supportsRelativeColorimetric = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC;
const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL; const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL;
const bool supportsAbsoluteColorimetric = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC; const bool supportsAbsoluteColorimetric = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC;
if (supportsPerceptual || supportsRelativeColorimetric || supportsAbsoluteColorimetric) { if (supportsPerceptual || supportsRelativeColorimetric || supportsAbsoluteColorimetric) {
intentBox.set_sensitive (true); intentBox.set_sensitive (true);
intentBox.setItemSensitivity (0, supportsRelativeColorimetric); intentBox.setItemSensitivity(0, supportsPerceptual);
intentBox.setItemSensitivity (1, supportsPerceptual); intentBox.setItemSensitivity(1, supportsRelativeColorimetric);
intentBox.setItemSensitivity (2, supportsAbsoluteColorimetric); intentBox.setItemSensitivity(2, supportsAbsoluteColorimetric);
softProof.set_sensitive(true);
spGamutCheck.set_sensitive(true);
} else { } else {
intentBox.setItemSensitivity(0, true);
intentBox.setItemSensitivity(1, true);
intentBox.setItemSensitivity(2, true);
intentBox.set_sensitive (false); intentBox.set_sensitive (false);
intentBox.setSelected (0); intentBox.setSelected (1);
softProof.set_sensitive(false);
spGamutCheck.set_sensitive(false);
} }
profileBox.set_tooltip_text (profileBox.get_active_text ());
} }
rtengine::RenderingIntent intent; rtengine::RenderingIntent intent;
@ -147,11 +194,11 @@ private:
switch (intentBox.getSelected ()) { switch (intentBox.getSelected ()) {
default: default:
case 0: case 0:
intent = rtengine::RI_RELATIVE; intent = rtengine::RI_PERCEPTUAL;
break; break;
case 1: case 1:
intent = rtengine::RI_PERCEPTUAL; intent = rtengine::RI_RELATIVE;
break; break;
case 2: case 2:
@ -163,29 +210,61 @@ private:
return; return;
} }
processor->beginUpdateParams (); if (!noEvent) {
processor->beginUpdateParams ();
}
processor->setMonitorProfile (profile, intent); processor->setMonitorProfile (profile, intent);
processor->endUpdateParams (rtengine::EvMonitorTransform); processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_sensitive() && spGamutCheck.get_active());
if (!noEvent) {
processor->endUpdateParams (rtengine::EvMonitorTransform);
}
}
void updateSoftProofParameters (bool noEvent = false)
{
spGamutCheck.set_sensitive(softProof.get_active());
if (profileBox.get_active_row_number () > 0) {
if (!noEvent) {
processor->beginUpdateParams ();
}
processor->setSoftProofing (softProof.get_sensitive() && softProof.get_active(), spGamutCheck.get_sensitive() && spGamutCheck.get_active());
if (!noEvent) {
processor->endUpdateParams (rtengine::EvMonitorTransform);
}
}
} }
public: public:
explicit MonitorProfileSelector (rtengine::StagedImageProcessor* const& ipc) : explicit ColorManagementToolbar (rtengine::StagedImageProcessor* const& ipc) :
intentBox (Glib::ustring (), true), intentBox (Glib::ustring (), true),
processor (ipc) processor (ipc)
{ {
prepareProfileBox (); prepareProfileBox ();
prepareIntentBox (); prepareIntentBox ();
prepareSoftProofingBox ();
reset (); reset ();
profileConn = profileBox.signal_changed ().connect (sigc::mem_fun (this, &MonitorProfileSelector::profileBoxChanged)); softProof.signal_toggled().connect(sigc::mem_fun (this, &ColorManagementToolbar::softProofToggled));
intentConn = intentBox.signal_changed ().connect (sigc::mem_fun (this, &MonitorProfileSelector::intentBoxChanged)); spGamutCheck.signal_toggled().connect(sigc::mem_fun (this, &ColorManagementToolbar::spGamutCheckToggled));;
profileConn = profileBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::profileBoxChanged));
intentConn = intentBox.signal_changed ().connect (sigc::mem_fun (this, &ColorManagementToolbar::intentBoxChanged));
} }
void pack_right_in (Gtk::Grid* grid) void pack_right_in (Gtk::Grid* grid)
{ {
grid->attach_next_to (profileBox, Gtk::POS_RIGHT, 1, 1); grid->attach_next_to (profileBox, Gtk::POS_RIGHT, 1, 1);
grid->attach_next_to (*intentBox.buttonGroup, Gtk::POS_RIGHT, 1, 1); grid->attach_next_to (*intentBox.buttonGroup, Gtk::POS_RIGHT, 1, 1);
grid->attach_next_to (softProof, Gtk::POS_RIGHT, 1, 1);
grid->attach_next_to (spGamutCheck, Gtk::POS_RIGHT, 1, 1);
}
void updateProcessor()
{
if (processor) {
updateParameters(true);
}
} }
void reset () void reset ()
@ -207,11 +286,11 @@ public:
switch (options.rtSettings.monitorIntent) { switch (options.rtSettings.monitorIntent) {
default: default:
case rtengine::RI_RELATIVE: case rtengine::RI_PERCEPTUAL:
intentBox.setSelected (0); intentBox.setSelected (0);
break; break;
case rtengine::RI_PERCEPTUAL: case rtengine::RI_RELATIVE:
intentBox.setSelected (1); intentBox.setSelected (1);
break; break;
@ -418,8 +497,6 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
tbShowHideSidePanels->set_image (*iShowHideSidePanels); tbShowHideSidePanels->set_image (*iShowHideSidePanels);
setExpandAlignProperties (tbShowHideSidePanels, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER); setExpandAlignProperties (tbShowHideSidePanels, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
monitorProfile.reset (new MonitorProfileSelector (ipc));
navPrev = navNext = navSync = NULL; navPrev = navNext = navSync = NULL;
if (!simpleEditor && !options.tabbedUI) { if (!simpleEditor && !options.tabbedUI) {
@ -452,6 +529,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
// ================== PACKING THE BOTTOM WIDGETS ================= // ================== PACKING THE BOTTOM WIDGETS =================
// Adding widgets from center to the left, on the left side (using Gtk::POS_LEFT) // Adding widgets from center to the left, on the left side (using Gtk::POS_LEFT)
iops->attach_next_to (*vsep2, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to (*progressLabel, 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 (*vsep1, Gtk::POS_LEFT, 1, 1);
iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*sendtogimp, Gtk::POS_LEFT, 1, 1);
@ -462,9 +540,10 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1); iops->attach_next_to (*saveimgas, Gtk::POS_LEFT, 1, 1);
// Adding widgets from center to the right, on the right side (using Gtk::POS_RIGHT)
iops->attach_next_to (*vsep2, Gtk::POS_RIGHT, 1, 1); // Color management toolbar
monitorProfile->pack_right_in (iops); colorMgmtToolBar.reset (new ColorManagementToolbar (ipc));
colorMgmtToolBar->pack_right_in (iops);
if (!simpleEditor && !options.tabbedUI) { if (!simpleEditor && !options.tabbedUI) {
iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1); iops->attach_next_to (*vsep3, Gtk::POS_RIGHT, 1, 1);
@ -736,6 +815,7 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc)
this->isrc = isrc; this->isrc = isrc;
ipc = rtengine::StagedImageProcessor::create (isrc); ipc = rtengine::StagedImageProcessor::create (isrc);
ipc->setProgressListener (this); ipc->setProgressListener (this);
colorMgmtToolBar->updateProcessor();
ipc->setPreviewImageListener (previewHandler); ipc->setPreviewImageListener (previewHandler);
ipc->setPreviewScale (10); // Important ipc->setPreviewScale (10); // Important
tpc->initImage (ipc, tmb->getType() == FT_Raw); tpc->initImage (ipc, tmb->getType() == FT_Raw);
@ -784,8 +864,6 @@ void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc)
} }
history->resetSnapShotNumber(); history->resetSnapShotNumber();
monitorProfile->reset ();
} }
void EditorPanel::close () void EditorPanel::close ()

View File

@ -85,8 +85,8 @@ protected:
Gtk::Button* navNext; Gtk::Button* navNext;
Gtk::Button* navPrev; Gtk::Button* navPrev;
class MonitorProfileSelector; class ColorManagementToolbar;
std::unique_ptr<MonitorProfileSelector> monitorProfile; std::unique_ptr<ColorManagementToolbar> colorMgmtToolBar;
ImageAreaPanel* iareapanel; ImageAreaPanel* iareapanel;
PreviewHandler* previewHandler; PreviewHandler* previewHandler;

View File

@ -1185,6 +1185,7 @@ void FileCatalog::developRequested (std::vector<FileBrowserEntry*> tbe, bool fas
params.icm.working = options.fastexport_icm_working ; params.icm.working = options.fastexport_icm_working ;
params.icm.output = options.fastexport_icm_output ; params.icm.output = options.fastexport_icm_output ;
params.icm.outputIntent = options.fastexport_icm_outputIntent ; params.icm.outputIntent = options.fastexport_icm_outputIntent ;
params.icm.outputBPC = options.fastexport_icm_outputBPC ;
params.icm.gamma = options.fastexport_icm_gamma ; params.icm.gamma = options.fastexport_icm_gamma ;
params.resize.enabled = options.fastexport_resize_enabled ; params.resize.enabled = options.fastexport_resize_enabled ;
params.resize.scale = options.fastexport_resize_scale ; params.resize.scale = options.fastexport_resize_scale ;

View File

@ -26,6 +26,7 @@
#include "../rtengine/improccoordinator.h" #include "../rtengine/improccoordinator.h"
#include "../rtengine/color.h" #include "../rtengine/color.h"
#include "../rtengine/opthelper.h" #include "../rtengine/opthelper.h"
#include "../rtengine/iccstore.h"
using namespace rtengine; using namespace rtengine;
extern Options options; extern Options options;

View File

@ -205,15 +205,21 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
Gtk::HBox *riHBox = Gtk::manage ( new Gtk::HBox()); Gtk::HBox *riHBox = Gtk::manage ( new Gtk::HBox());
Gtk::Label* outputIntentLbl = Gtk::manage (new Gtk::Label(M("TP_ICM_PROFILEINTENT")+":")); Gtk::Label* outputIntentLbl = Gtk::manage (new Gtk::Label(M("TP_ICM_PROFILEINTENT")+":"));
riHBox->pack_start (*outputIntentLbl, Gtk::PACK_SHRINK); riHBox->pack_start (*outputIntentLbl, Gtk::PACK_SHRINK);
ointent = Gtk::manage (new MyComboBoxText ()); ointent = Gtk::manage (new PopUpButton ());
riHBox->pack_start (*ointent, Gtk::PACK_EXPAND_WIDGET); ointent->addEntry("intent-perceptual.png", M("PREFERENCES_INTENT_PERCEPTUAL"));
ointent->append (M("PREFERENCES_INTENT_PERCEPTUAL")); ointent->addEntry("intent-relative.png", M("PREFERENCES_INTENT_RELATIVE"));
ointent->append (M("PREFERENCES_INTENT_RELATIVE")); ointent->addEntry("intent-saturation.png", M("PREFERENCES_INTENT_SATURATION"));
ointent->append (M("PREFERENCES_INTENT_SATURATION")); ointent->addEntry("intent-absolute.png", M("PREFERENCES_INTENT_ABSOLUTE"));
ointent->append (M("PREFERENCES_INTENT_ABSOLUTE")); ointent->setSelected (1);
ointent->set_active (1); ointent->show();
riHBox->pack_start (*ointent->buttonGroup, Gtk::PACK_EXPAND_PADDING);
oVBox->pack_start(*riHBox, Gtk::PACK_SHRINK); oVBox->pack_start(*riHBox, Gtk::PACK_SHRINK);
// Black Point Compensation
obpc = Gtk::manage(new Gtk::CheckButton((M("TP_ICM_BPC"))));
obpc->set_active (true);
oVBox->pack_start(*obpc, Gtk::PACK_SHRINK);
// Output gamma // Output gamma
Gtk::HBox* gaHBox = Gtk::manage (new Gtk::HBox ()); Gtk::HBox* gaHBox = Gtk::manage (new Gtk::HBox ());
@ -306,6 +312,7 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
wgamma->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::gpChanged) ); wgamma->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::gpChanged) );
dcpIll->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::dcpIlluminantChanged) ); dcpIll->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::dcpIlluminantChanged) );
obpcconn = obpc->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::oBPCChanged) );
gamcsconn = freegamma->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::GamChanged)); gamcsconn = freegamma->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::GamChanged));
tcurveconn = ckbToneCurve->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::toneCurveChanged)); tcurveconn = ckbToneCurve->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::toneCurveChanged));
ltableconn = ckbApplyLookTable->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::applyLookTableChanged)); ltableconn = ckbApplyLookTable->signal_toggled().connect ( sigc::mem_fun(*this, &ICMPanel::applyLookTableChanged));
@ -324,6 +331,31 @@ ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunch
show_all (); show_all ();
} }
void ICMPanel::updateRenderingIntent (const Glib::ustring &profile) {
const uint8_t supportedIntents = rtengine::iccStore->getOutputIntents (profile);
const bool supportsPerceptual = supportedIntents & 1 << INTENT_PERCEPTUAL;
const bool supportsRelative = supportedIntents & 1 << INTENT_RELATIVE_COLORIMETRIC;
const bool supportsSaturation = supportedIntents & 1 << INTENT_SATURATION;
const bool supportsAbsolute = supportedIntents & 1 << INTENT_ABSOLUTE_COLORIMETRIC;
//printf("Intents: %d / Perceptual: %d Relative: %d Saturation: %d Absolute: %d\n", supportedIntents, supportsPerceptual, supportsRelative, supportsSaturation, supportsAbsolute);
if (!profile.empty() && (supportsPerceptual || supportsRelative || supportsSaturation || supportsAbsolute)) {
ointent->set_sensitive (true);
ointent->setItemSensitivity(0, supportsPerceptual);
ointent->setItemSensitivity(1, supportsRelative);
ointent->setItemSensitivity(2, supportsSaturation);
ointent->setItemSensitivity(3, supportsAbsolute);
} else {
ointent->setItemSensitivity(0, true);
ointent->setItemSensitivity(1, true);
ointent->setItemSensitivity(2, true);
ointent->setItemSensitivity(3, true);
ointent->set_sensitive (false);
ointent->setSelected (1);
}
}
void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name) void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name)
{ {
@ -466,6 +498,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
disableListener (); disableListener ();
obpcconn.block (true);
ipc.block (true); ipc.block (true);
gamcsconn.block (true); gamcsconn.block (true);
tcurveconn.block(true); tcurveconn.block(true);
@ -480,36 +513,50 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
if (pp->icm.input == "(none)") { if (pp->icm.input == "(none)") {
inone->set_active (true); inone->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (false);
}
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "");
} else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() == Gtk::STATE_INSENSITIVE)) { } else if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() == Gtk::STATE_INSENSITIVE)) {
iembedded->set_active (true); iembedded->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (false);
}
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "");
} else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) {
icameraICC->set_active (true); icameraICC->set_active (true);
ckbBlendCMSMatrix->set_sensitive (true); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (true);
}
updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)");
} else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() != Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { } 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 // 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 // therefore falling back UI to explicitly reflect the (camera) option
icamera->set_active (true); icamera->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (false);
}
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "");
} else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() == Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { } 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). // If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded).
iembedded->set_active (true); iembedded->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (false);
}
updateDCP(pp->icm.dcpIlluminant, "(cameraICC)"); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)");
} else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) { } else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) {
icamera->set_active (true); icamera->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (false);
}
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "");
} else { } else {
ifromfile->set_active (true); ifromfile->set_active (true);
oldip = pp->icm.input.substr(5); // cut of "file:" oldip = pp->icm.input.substr(5); // cut of "file:"
ipDialog->set_filename (pp->icm.input.substr(5)); ipDialog->set_filename (pp->icm.input.substr(5));
ckbBlendCMSMatrix->set_sensitive (true); if (!batchMode) {
ckbBlendCMSMatrix->set_sensitive (true);
}
updateDCP(pp->icm.dcpIlluminant, pp->icm.input.substr(5)); updateDCP(pp->icm.dcpIlluminant, pp->icm.input.substr(5));
} }
@ -525,8 +572,9 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
if (onames->get_active_row_number() == -1) { if (onames->get_active_row_number() == -1) {
onames->set_active_text (M("TP_ICM_NOICM")); onames->set_active_text (M("TP_ICM_NOICM"));
} }
ointent->set_active(pp->icm.outputIntent); ointent->setSelected (pp->icm.outputIntent);
obpc->set_active (pp->icm.outputBPC);
ckbToneCurve->set_active (pp->icm.toneCurve); ckbToneCurve->set_active (pp->icm.toneCurve);
lastToneCurve = pp->icm.toneCurve; lastToneCurve = pp->icm.toneCurve;
ckbApplyLookTable->set_active (pp->icm.applyLookTable); ckbApplyLookTable->set_active (pp->icm.applyLookTable);
@ -539,22 +587,29 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
ckbBlendCMSMatrix->set_active (pp->icm.blendCMSMatrix); ckbBlendCMSMatrix->set_active (pp->icm.blendCMSMatrix);
lastBlendCMSMatrix = pp->icm.blendCMSMatrix; lastBlendCMSMatrix = pp->icm.blendCMSMatrix;
onames->set_sensitive(wgamma->get_active_row_number() == 0 || freegamma->get_active()); //"default"
wgamma->set_sensitive(!freegamma->get_active());
freegamma->set_active (pp->icm.freegamma); freegamma->set_active (pp->icm.freegamma);
lastgamfree = pp->icm.freegamma; lastgamfree = pp->icm.freegamma;
if (!batchMode) {
onames->set_sensitive(wgamma->get_active_row_number() == 0 && !pp->icm.freegamma); //"default"
wgamma->set_sensitive(!pp->icm.freegamma);
gampos->set_sensitive(pp->icm.freegamma);
slpos->set_sensitive(pp->icm.freegamma);
updateRenderingIntent(pp->icm.output);
}
gampos->setValue (pp->icm.gampos); gampos->setValue (pp->icm.gampos);
slpos->setValue (pp->icm.slpos); slpos->setValue (pp->icm.slpos);
if (pedited) { if (pedited) {
iunchanged->set_active (!pedited->icm.input); iunchanged->set_active (!pedited->icm.input);
obpc->set_inconsistent(!pedited->icm.outputBPC);
ckbToneCurve->set_inconsistent(!pedited->icm.toneCurve); ckbToneCurve->set_inconsistent(!pedited->icm.toneCurve);
ckbApplyLookTable->set_inconsistent(!pedited->icm.applyLookTable); ckbApplyLookTable->set_inconsistent(!pedited->icm.applyLookTable);
ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset); ckbApplyBaselineExposureOffset->set_inconsistent(!pedited->icm.applyBaselineExposureOffset);
ckbApplyHueSatMap->set_inconsistent(!pedited->icm.applyHueSatMap); ckbApplyHueSatMap->set_inconsistent(!pedited->icm.applyHueSatMap);
ckbBlendCMSMatrix->set_inconsistent(!pedited->icm.blendCMSMatrix); ckbBlendCMSMatrix->set_inconsistent(!pedited->icm.blendCMSMatrix);
freegamma->set_inconsistent (!pedited->icm.freegamma);
if (!pedited->icm.working) { if (!pedited->icm.working) {
wnames->set_active_text(M("GENERAL_UNCHANGED")); wnames->set_active_text(M("GENERAL_UNCHANGED"));
@ -565,7 +620,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
} }
if (!pedited->icm.outputIntent) { if (!pedited->icm.outputIntent) {
ointent->set_active_text(M("GENERAL_UNCHANGED")); ointent->setSelected (4);
} }
if (!pedited->icm.dcpIlluminant) { if (!pedited->icm.dcpIlluminant) {
@ -589,6 +644,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
hsmconn.block(false); hsmconn.block(false);
gamcsconn.block (false); gamcsconn.block (false);
ipc.block (false); ipc.block (false);
obpcconn.block (false);
enableListener (); enableListener ();
} }
@ -628,7 +684,7 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited)
pp->icm.output = onames->get_active_text(); pp->icm.output = onames->get_active_text();
} }
int ointentVal = ointent->get_active_row_number(); int ointentVal = ointent->getSelected ();
if (ointentVal >= 0 && ointentVal < RI__COUNT) { if (ointentVal >= 0 && ointentVal < RI__COUNT) {
pp->icm.outputIntent = static_cast<RenderingIntent>(ointentVal); pp->icm.outputIntent = static_cast<RenderingIntent>(ointentVal);
} else { } else {
@ -666,12 +722,14 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited)
pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active (); pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active ();
pp->icm.gampos = (double) gampos->getValue(); pp->icm.gampos = (double) gampos->getValue();
pp->icm.slpos = (double) slpos->getValue(); pp->icm.slpos = (double) slpos->getValue();
pp->icm.outputBPC = obpc->get_active ();
if (pedited) { if (pedited) {
pedited->icm.input = !iunchanged->get_active (); pedited->icm.input = !iunchanged->get_active ();
pedited->icm.working = wnames->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.working = wnames->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.output = onames->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.output = onames->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.outputIntent = ointent->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.outputIntent = ointent->getSelected () < 4;
pedited->icm.outputBPC = !obpc->get_inconsistent ();
pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED"); pedited->icm.dcpIlluminant = dcpIll->get_active_text() != M("GENERAL_UNCHANGED");
pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent (); pedited->icm.toneCurve = !ckbToneCurve->get_inconsistent ();
pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent (); pedited->icm.applyLookTable = !ckbApplyLookTable->get_inconsistent ();
@ -708,7 +766,7 @@ void ICMPanel::setAdjusterBehavior (bool gammaadd, bool slopeadd)
void ICMPanel::adjusterChanged (Adjuster* a, double newval) void ICMPanel::adjusterChanged (Adjuster* a, double newval)
{ {
if (listener && freegamma->get_active()) { if (listener && (freegamma->get_active() || batchMode)) {
Glib::ustring costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), newval); Glib::ustring costr = Glib::ustring::format (std::setw(3), std::fixed, std::setprecision(2), newval);
@ -746,7 +804,7 @@ void ICMPanel::dcpIlluminantChanged()
void ICMPanel::toneCurveChanged() void ICMPanel::toneCurveChanged()
{ {
if (batchMode) { if (multiImage) {
if (ckbToneCurve->get_inconsistent()) { if (ckbToneCurve->get_inconsistent()) {
ckbToneCurve->set_inconsistent (false); ckbToneCurve->set_inconsistent (false);
tcurveconn.block (true); tcurveconn.block (true);
@ -760,13 +818,19 @@ void ICMPanel::toneCurveChanged()
} }
if (listener) { if (listener) {
listener->panelChanged (EvDCPToneCurve, ckbToneCurve->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); if (ckbToneCurve->get_inconsistent()) {
listener->panelChanged (EvDCPToneCurve, M("GENERAL_UNCHANGED"));
} else if (ckbToneCurve->get_active()) {
listener->panelChanged (EvDCPToneCurve, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (EvDCPToneCurve, M("GENERAL_DISABLED"));
}
} }
} }
void ICMPanel::applyLookTableChanged() void ICMPanel::applyLookTableChanged()
{ {
if (batchMode) { if (multiImage) {
if (ckbApplyLookTable->get_inconsistent()) { if (ckbApplyLookTable->get_inconsistent()) {
ckbApplyLookTable->set_inconsistent (false); ckbApplyLookTable->set_inconsistent (false);
ltableconn.block (true); ltableconn.block (true);
@ -780,13 +844,19 @@ void ICMPanel::applyLookTableChanged()
} }
if (listener) { if (listener) {
listener->panelChanged (EvDCPApplyLookTable, ckbApplyLookTable->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); if (ckbApplyLookTable->get_inconsistent()) {
listener->panelChanged (EvDCPApplyLookTable, M("GENERAL_UNCHANGED"));
} else if (ckbApplyLookTable->get_active()) {
listener->panelChanged (EvDCPApplyLookTable, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (EvDCPApplyLookTable, M("GENERAL_DISABLED"));
}
} }
} }
void ICMPanel::applyBaselineExposureOffsetChanged() void ICMPanel::applyBaselineExposureOffsetChanged()
{ {
if (batchMode) { if (multiImage) {
if (ckbApplyBaselineExposureOffset->get_inconsistent()) { if (ckbApplyBaselineExposureOffset->get_inconsistent()) {
ckbApplyBaselineExposureOffset->set_inconsistent (false); ckbApplyBaselineExposureOffset->set_inconsistent (false);
beoconn.block (true); beoconn.block (true);
@ -800,13 +870,19 @@ void ICMPanel::applyBaselineExposureOffsetChanged()
} }
if (listener) { if (listener) {
listener->panelChanged (EvDCPApplyBaselineExposureOffset, ckbApplyBaselineExposureOffset->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); if (ckbApplyBaselineExposureOffset->get_inconsistent()) {
listener->panelChanged (EvDCPApplyBaselineExposureOffset, M("GENERAL_UNCHANGED"));
} else if (ckbApplyBaselineExposureOffset->get_active()) {
listener->panelChanged (EvDCPApplyBaselineExposureOffset, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (EvDCPApplyBaselineExposureOffset, M("GENERAL_DISABLED"));
}
} }
} }
void ICMPanel::applyHueSatMapChanged() void ICMPanel::applyHueSatMapChanged()
{ {
if (batchMode) { if (multiImage) {
if (ckbApplyHueSatMap->get_inconsistent()) { if (ckbApplyHueSatMap->get_inconsistent()) {
ckbApplyHueSatMap->set_inconsistent (false); ckbApplyHueSatMap->set_inconsistent (false);
hsmconn.block (true); hsmconn.block (true);
@ -820,7 +896,13 @@ void ICMPanel::applyHueSatMapChanged()
} }
if (listener) { if (listener) {
listener->panelChanged (EvDCPApplyHueSatMap, ckbApplyHueSatMap->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); if (ckbApplyHueSatMap->get_inconsistent()) {
listener->panelChanged (EvDCPApplyHueSatMap, M("GENERAL_UNCHANGED"));
} else if (ckbApplyHueSatMap->get_active()) {
listener->panelChanged (EvDCPApplyHueSatMap, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (EvDCPApplyHueSatMap, M("GENERAL_DISABLED"));
}
} }
} }
@ -857,7 +939,7 @@ void ICMPanel::ipChanged ()
void ICMPanel::blendCMSMatrixChanged() void ICMPanel::blendCMSMatrixChanged()
{ {
if (batchMode) { if (multiImage) {
if (ckbBlendCMSMatrix->get_inconsistent()) { if (ckbBlendCMSMatrix->get_inconsistent()) {
ckbBlendCMSMatrix->set_inconsistent (false); ckbBlendCMSMatrix->set_inconsistent (false);
blendcmsconn.block (true); blendcmsconn.block (true);
@ -871,13 +953,19 @@ void ICMPanel::blendCMSMatrixChanged()
} }
if (listener) { if (listener) {
listener->panelChanged (EvBlendCMSMatrix, ckbBlendCMSMatrix->get_active() ? M("GENERAL_ENABLED") : M("GENERAL_DISABLED")); 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() void ICMPanel::GamChanged()
{ {
if (batchMode) { if (multiImage) {
if (freegamma->get_inconsistent()) { if (freegamma->get_inconsistent()) {
freegamma->set_inconsistent (false); freegamma->set_inconsistent (false);
gamcsconn.block (true); gamcsconn.block (true);
@ -891,31 +979,90 @@ void ICMPanel::GamChanged()
} }
if (listener) { if (listener) {
if (freegamma->get_active()) { if (freegamma->get_inconsistent()) {
listener->panelChanged (EvGAMFREE, M("GENERAL_UNCHANGED"));
}
else if (freegamma->get_active()) {
listener->panelChanged (EvGAMFREE, M("GENERAL_ENABLED")); listener->panelChanged (EvGAMFREE, M("GENERAL_ENABLED"));
onames->set_sensitive(!freegamma->get_active());//disabled choice if (!batchMode) {
wgamma->set_sensitive(!freegamma->get_active()); onames->set_sensitive(false);//disabled choice
wgamma->set_sensitive(false);
gampos->set_sensitive(true);
slpos->set_sensitive(true);
}
} else { } else {
listener->panelChanged (EvGAMFREE, M("GENERAL_DISABLED")); listener->panelChanged (EvGAMFREE, M("GENERAL_DISABLED"));
onames->set_sensitive(!freegamma->get_active() && wgamma->get_active_row_number() == 0); if (!batchMode) {
wgamma->set_sensitive(!freegamma->get_active()); onames->set_sensitive(wgamma->get_active_row_number() == 0);
wgamma->set_sensitive(true);
gampos->set_sensitive(false);
slpos->set_sensitive(false);
}
} }
} }
} }
void ICMPanel::opChanged () void ICMPanel::opChanged ()
{ {
if (!batchMode) {
updateRenderingIntent(onames->get_active_text());
}
if (listener) { if (listener) {
listener->panelChanged (EvOProfile, onames->get_active_text()); listener->panelChanged (EvOProfile, onames->get_active_text());
} }
} }
void ICMPanel::oiChanged () void ICMPanel::oiChanged (int n)
{ {
if (listener) { if (listener) {
listener->panelChanged (EvOIntent, ointent->get_active_text()); Glib::ustring str;
switch (n) {
case 0:
str = M("PREFERENCES_INTENT_PERCEPTUAL");
break;
case 1:
str = M("PREFERENCES_INTENT_RELATIVE");
break;
case 2:
str = M("PREFERENCES_INTENT_SATURATION");
break;
case 3:
str = M("PREFERENCES_INTENT_ABSOLUTE");
break;
case 4:
default:
str = M("GENERAL_UNCHANGED");
break;
}
listener->panelChanged (EvOIntent, str);
}
}
void ICMPanel::oBPCChanged ()
{
if (multiImage) {
if (obpc->get_inconsistent()) {
obpc->set_inconsistent (false);
obpcconn.block (true);
obpc->set_active (false);
obpcconn.block (false);
} else if (lastobpc) {
obpc->set_inconsistent (true);
}
lastobpc = obpc->get_active ();
}
if (listener) {
if (obpc->get_inconsistent()) {
listener->panelChanged (EvOBPCompens, M("GENERAL_UNCHANGED"));
} else if (obpc->get_active()) {
listener->panelChanged (EvOBPCompens, M("GENERAL_ENABLED"));
} else {
listener->panelChanged (EvOBPCompens, M("GENERAL_DISABLED"));
}
} }
} }
@ -1017,6 +1164,8 @@ void ICMPanel::setBatchMode (bool batchMode)
iVBox->reorder_child (*iunchanged, 5); iVBox->reorder_child (*iunchanged, 5);
removeIfThere (this, saveRef); removeIfThere (this, saveRef);
onames->append (M("GENERAL_UNCHANGED")); onames->append (M("GENERAL_UNCHANGED"));
ointent->addEntry("unchanged-22.png", M("GENERAL_UNCHANGED"));
ointent->show();
wnames->append (M("GENERAL_UNCHANGED")); wnames->append (M("GENERAL_UNCHANGED"));
wgamma->append (M("GENERAL_UNCHANGED")); wgamma->append (M("GENERAL_UNCHANGED"));
dcpIll->append (M("GENERAL_UNCHANGED")); dcpIll->append (M("GENERAL_UNCHANGED"));

View File

@ -25,6 +25,7 @@
#include "guiutils.h" #include "guiutils.h"
#include "toolpanel.h" #include "toolpanel.h"
#include "popupbutton.h"
#include "../rtengine/imagedata.h" #include "../rtengine/imagedata.h"
class ICMPanelListener class ICMPanelListener
@ -53,6 +54,8 @@ protected:
sigc::connection beoconn; sigc::connection beoconn;
bool lastApplyHueSatMap; bool lastApplyHueSatMap;
sigc::connection hsmconn; sigc::connection hsmconn;
bool lastobpc;
sigc::connection obpcconn;
bool lastBlendCMSMatrix; bool lastBlendCMSMatrix;
bool isBatchMode; bool isBatchMode;
sigc::connection blendcmsconn; sigc::connection blendcmsconn;
@ -60,6 +63,7 @@ protected:
private: private:
Gtk::VBox * iVBox; Gtk::VBox * iVBox;
Gtk::CheckButton* obpc;
Gtk::CheckButton* freegamma; Gtk::CheckButton* freegamma;
Gtk::RadioButton* inone; Gtk::RadioButton* inone;
@ -78,7 +82,7 @@ private:
MyComboBoxText* wgamma; MyComboBoxText* wgamma;
MyComboBoxText* onames; MyComboBoxText* onames;
MyComboBoxText* ointent; PopUpButton* ointent;
Gtk::RadioButton* ofromdir; Gtk::RadioButton* ofromdir;
Gtk::RadioButton* ofromfile; Gtk::RadioButton* ofromfile;
Gtk::RadioButton* iunchanged; Gtk::RadioButton* iunchanged;
@ -95,6 +99,7 @@ private:
Glib::ustring lastRefFilename; Glib::ustring lastRefFilename;
Glib::ustring camName; Glib::ustring camName;
void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); void updateDCP(int dcpIlluminant, Glib::ustring dcp_name);
void updateRenderingIntent (const Glib::ustring &profile);
public: public:
ICMPanel (); ICMPanel ();
@ -107,7 +112,8 @@ public:
void wpChanged (); void wpChanged ();
void opChanged (); void opChanged ();
void oiChanged (); void oiChanged (int n);
void oBPCChanged ();
void ipChanged (); void ipChanged ();
void gpChanged (); void gpChanged ();
void GamChanged (); void GamChanged ();

View File

@ -471,6 +471,7 @@ void Options::setDefaults ()
fastexport_icm_working = "ProPhoto"; fastexport_icm_working = "ProPhoto";
fastexport_icm_output = "RT_sRGB"; fastexport_icm_output = "RT_sRGB";
fastexport_icm_outputIntent = rtengine::RI_RELATIVE; fastexport_icm_outputIntent = rtengine::RI_RELATIVE;
fastexport_icm_outputBPC = true;
fastexport_icm_gamma = "default"; fastexport_icm_gamma = "default";
fastexport_resize_enabled = true; fastexport_resize_enabled = true;
fastexport_resize_scale = 1; fastexport_resize_scale = 1;
@ -636,6 +637,7 @@ void Options::setDefaults ()
rtSettings.monitorProfile = Glib::ustring(); rtSettings.monitorProfile = Glib::ustring();
rtSettings.monitorIntent = rtengine::RI_RELATIVE; rtSettings.monitorIntent = rtengine::RI_RELATIVE;
rtSettings.monitorBPC = true;
rtSettings.autoMonitorProfile = false; rtSettings.autoMonitorProfile = false;
rtSettings.adobe = "RT_Medium_gsRGB"; // put the name of yours profiles (here windows) rtSettings.adobe = "RT_Medium_gsRGB"; // put the name of yours profiles (here windows)
rtSettings.prophoto = "RT_Large_gBT709"; // these names appear in the menu "output profile" rtSettings.prophoto = "RT_Large_gBT709"; // these names appear in the menu "output profile"
@ -1471,6 +1473,10 @@ int Options::readFromFile (Glib::ustring fname)
rtSettings.monitorIntent = static_cast<rtengine::RenderingIntent> (keyFile.get_integer ("Color Management", "Intent")); rtSettings.monitorIntent = static_cast<rtengine::RenderingIntent> (keyFile.get_integer ("Color Management", "Intent"));
} }
if (keyFile.has_key ("Color Management", "MonitorBPC")) {
rtSettings.monitorBPC = keyFile.get_boolean("Color Management", "MonitorBPC");
}
if (keyFile.has_key ("Color Management", "CRI")) { if (keyFile.has_key ("Color Management", "CRI")) {
rtSettings.CRI_color = keyFile.get_integer ("Color Management", "CRI"); rtSettings.CRI_color = keyFile.get_integer ("Color Management", "CRI");
} }
@ -1727,6 +1733,10 @@ int Options::readFromFile (Glib::ustring fname)
fastexport_icm_outputIntent = static_cast<rtengine::RenderingIntent> (keyFile.get_integer ("Fast Export", "fastexport_icm_output_intent" )); fastexport_icm_outputIntent = static_cast<rtengine::RenderingIntent> (keyFile.get_integer ("Fast Export", "fastexport_icm_output_intent" ));
} }
if (keyFile.has_key ("Fast Export", "fastexport_icm_output_bpc" )) {
fastexport_icm_outputBPC = keyFile.get_boolean ("Fast Export", "fastexport_icm_output_bpc" );
}
if (keyFile.has_key ("Fast Export", "fastexport_icm_gamma" )) { if (keyFile.has_key ("Fast Export", "fastexport_icm_gamma" )) {
fastexport_icm_gamma = keyFile.get_string ("Fast Export", "fastexport_icm_gamma" ); fastexport_icm_gamma = keyFile.get_string ("Fast Export", "fastexport_icm_gamma" );
} }
@ -1803,7 +1813,7 @@ bool Options::safeDirGet (const Glib::KeyFile& keyFile, const Glib::ustring& sec
const Glib::ustring& entryName, Glib::ustring& destination) const Glib::ustring& entryName, Glib::ustring& destination)
{ {
try { try {
if (keyFile.has_key (section, entryName) && !keyFile.get_string (section, entryName).empty ()) { if (keyFile.has_key (section, entryName) && !keyFile.get_string (section, entryName).empty ()) {
destination = keyFile.get_string (section, entryName); destination = keyFile.get_string (section, entryName);
return true; return true;
@ -2034,6 +2044,7 @@ int Options::saveToFile (Glib::ustring fname)
keyFile.set_boolean ("Color Management", "Autocielab", rtSettings.autocielab); keyFile.set_boolean ("Color Management", "Autocielab", rtSettings.autocielab);
keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut); keyFile.set_boolean ("Color Management", "RGBcurvesLumamode_Gamut", rtSettings.rgbcurveslumamode_gamut);
keyFile.set_integer ("Color Management", "Intent", rtSettings.monitorIntent); keyFile.set_integer ("Color Management", "Intent", rtSettings.monitorIntent);
keyFile.set_boolean ("Color Management", "MonitorBPC", rtSettings.monitorBPC);
keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice); keyFile.set_integer ("Color Management", "view", rtSettings.viewingdevice);
keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey); keyFile.set_integer ("Color Management", "grey", rtSettings.viewingdevicegrey);
keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc); keyFile.set_integer ("Color Management", "greySc", rtSettings.viewinggreySc);
@ -2102,6 +2113,7 @@ int Options::saveToFile (Glib::ustring fname)
keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working ); keyFile.set_string ("Fast Export", "fastexport_icm_working" , fastexport_icm_working );
keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output ); keyFile.set_string ("Fast Export", "fastexport_icm_output" , fastexport_icm_output );
keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent ); keyFile.set_integer ("Fast Export", "fastexport_icm_output_intent" , fastexport_icm_outputIntent );
keyFile.set_boolean ("Fast Export", "fastexport_icm_output_bpc" , fastexport_icm_outputBPC );
keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma ); keyFile.set_string ("Fast Export", "fastexport_icm_gamma" , fastexport_icm_gamma );
keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled ); keyFile.set_boolean ("Fast Export", "fastexport_resize_enabled" , fastexport_resize_enabled );
keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale ); keyFile.set_double ("Fast Export", "fastexport_resize_scale" , fastexport_resize_scale );

View File

@ -269,6 +269,7 @@ public:
Glib::ustring fastexport_icm_working; Glib::ustring fastexport_icm_working;
Glib::ustring fastexport_icm_output; Glib::ustring fastexport_icm_output;
rtengine::RenderingIntent fastexport_icm_outputIntent; rtengine::RenderingIntent fastexport_icm_outputIntent;
bool fastexport_icm_outputBPC;
Glib::ustring fastexport_icm_gamma; Glib::ustring fastexport_icm_gamma;
bool fastexport_resize_enabled; bool fastexport_resize_enabled;
double fastexport_resize_scale; double fastexport_resize_scale;

View File

@ -353,8 +353,9 @@ void ParamsEdited::set (bool v)
icm.working = v; icm.working = v;
icm.output = v; icm.output = v;
icm.outputIntent = v; icm.outputIntent = v;
icm.outputBPC = v;
icm.gamma = v; icm.gamma = v;
icm.freegamma = v; icm.freegamma = v;
icm.gampos = v; icm.gampos = v;
icm.slpos = v; icm.slpos = v;
raw.bayersensor.method = v; raw.bayersensor.method = v;
@ -847,6 +848,7 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
icm.working = icm.working && p.icm.working == other.icm.working; icm.working = icm.working && p.icm.working == other.icm.working;
icm.output = icm.output && p.icm.output == other.icm.output; icm.output = icm.output && p.icm.output == other.icm.output;
icm.outputIntent = icm.outputIntent && p.icm.outputIntent == other.icm.outputIntent; icm.outputIntent = icm.outputIntent && p.icm.outputIntent == other.icm.outputIntent;
icm.outputBPC = icm.outputBPC && p.icm.outputBPC == other.icm.outputBPC ;
icm.gamma = icm.gamma && p.icm.gamma == other.icm.gamma; icm.gamma = icm.gamma && p.icm.gamma == other.icm.gamma;
icm.freegamma = icm.freegamma && p.icm.freegamma == other.icm.freegamma; icm.freegamma = icm.freegamma && p.icm.freegamma == other.icm.freegamma;
icm.gampos = icm.gampos && p.icm.gampos == other.icm.gampos; icm.gampos = icm.gampos && p.icm.gampos == other.icm.gampos;
@ -2210,8 +2212,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
toEdit.icm.outputIntent = mods.icm.outputIntent; toEdit.icm.outputIntent = mods.icm.outputIntent;
} }
//if (icm.gampos) toEdit.icm.gampos = mods.icm.gampos; if (icm.outputBPC) {
//if (icm.slpos) toEdit.icm.slpos = mods.icm.slpos; toEdit.icm.outputBPC = mods.icm.outputBPC;
}
if (icm.gampos) { if (icm.gampos) {
toEdit.icm.gampos = dontforceSet && options.baBehav[ADDSET_FREE_OUPUT_GAMMA] ? toEdit.icm.gampos + mods.icm.gampos : mods.icm.gampos; toEdit.icm.gampos = dontforceSet && options.baBehav[ADDSET_FREE_OUPUT_GAMMA] ? toEdit.icm.gampos + mods.icm.gampos : mods.icm.gampos;
} }

View File

@ -544,6 +544,7 @@ public:
bool working; bool working;
bool output; bool output;
bool outputIntent; bool outputIntent;
bool outputBPC;
bool gamma; bool gamma;
bool gampos; bool gampos;
bool slpos; bool slpos;

View File

@ -680,15 +680,19 @@ Gtk::Widget* Preferences::getColorManagementPanel ()
monProfile->append (M("PREFERENCES_PROFILE_NONE")); monProfile->append (M("PREFERENCES_PROFILE_NONE"));
monProfile->set_active (0); monProfile->set_active (0);
const std::vector<Glib::ustring> profiles = rtengine::ICCStore::getInstance ()->getProfiles (); const std::vector<Glib::ustring> profiles = rtengine::ICCStore::getInstance ()->getProfiles (true);
for (std::vector<Glib::ustring>::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile) for (std::vector<Glib::ustring>::const_iterator profile = profiles.begin (); profile != profiles.end (); ++profile)
monProfile->append (*profile); monProfile->append (*profile);
monIntent->append (M("PREFERENCES_INTENT_RELATIVE")); // same order as the enum
monIntent->append (M("PREFERENCES_INTENT_PERCEPTUAL")); monIntent->append (M("PREFERENCES_INTENT_PERCEPTUAL"));
monIntent->append (M("PREFERENCES_INTENT_RELATIVE"));
monIntent->append (M("PREFERENCES_INTENT_ABSOLUTE")); monIntent->append (M("PREFERENCES_INTENT_ABSOLUTE"));
monIntent->set_active (1); monIntent->set_active (1);
monBPC = Gtk::manage (new Gtk::CheckButton (M("PREFERENCES_MONBPC")));
monBPC->set_active (true);
iccDir->signal_selection_changed ().connect (sigc::mem_fun (this, &Preferences::iccDirChanged)); iccDir->signal_selection_changed ().connect (sigc::mem_fun (this, &Preferences::iccDirChanged));
#if defined(WIN32) // Auto-detection not implemented for Linux, see issue 851 #if defined(WIN32) // Auto-detection not implemented for Linux, see issue 851
@ -698,22 +702,24 @@ Gtk::Widget* Preferences::getColorManagementPanel ()
Gtk::Table* colt = Gtk::manage (new Gtk::Table (3, 2)); Gtk::Table* colt = Gtk::manage (new Gtk::Table (3, 2));
int row = 0; int row = 0;
colt->attach (*pdlabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2); colt->attach (*pdlabel, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2);
colt->attach (*iccDir, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); colt->attach (*iccDir, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2);
#if !defined(__APPLE__) // monitor profile not supported on apple #if !defined(__APPLE__) // monitor profile not supported on apple
++row; ++row;
colt->attach (*mplabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2); colt->attach (*mplabel, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2);
colt->attach (*monProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); colt->attach (*monProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2);
#if defined(WIN32) #if defined(WIN32)
++row; ++row;
colt->attach (*cbAutoMonProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); colt->attach (*cbAutoMonProfile, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2);
#endif #endif
#endif #endif
++row; ++row;
colt->attach (*milabel, 0, 1, row, row + 1, Gtk::FILL, Gtk::SHRINK, 2, 2); colt->attach (*milabel, 0, 1, row, row + 1, Gtk::SHRINK, Gtk::SHRINK, 2, 2);
colt->attach (*monIntent, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL | Gtk::SHRINK, Gtk::SHRINK, 2, 2); colt->attach (*monIntent, 1, 2, row, row + 1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK, 2, 2);
mvbcm->pack_start (*colt, Gtk::PACK_SHRINK, 4); mvbcm->pack_start (*colt, Gtk::PACK_SHRINK, 4);
mvbcm->pack_start (*monBPC, Gtk::PACK_SHRINK, 4);
#if defined(WIN32) #if defined(WIN32)
autoMonProfileToggled(); autoMonProfileToggled();
#endif #endif
@ -1450,15 +1456,16 @@ void Preferences::storePreferences ()
switch (monIntent->get_active_row_number ()) { switch (monIntent->get_active_row_number ()) {
default: default:
case 0: case 0:
moptions.rtSettings.monitorIntent = rtengine::RI_RELATIVE; moptions.rtSettings.monitorIntent = rtengine::RI_PERCEPTUAL;
break; break;
case 1: case 1:
moptions.rtSettings.monitorIntent = rtengine::RI_PERCEPTUAL; moptions.rtSettings.monitorIntent = rtengine::RI_RELATIVE;
break; break;
case 2: case 2:
moptions.rtSettings.monitorIntent = rtengine::RI_ABSOLUTE; moptions.rtSettings.monitorIntent = rtengine::RI_ABSOLUTE;
break; break;
} }
moptions.rtSettings.monitorBPC = monBPC->get_active ();
#if defined(WIN32) #if defined(WIN32)
moptions.rtSettings.autoMonitorProfile = cbAutoMonProfile->get_active (); moptions.rtSettings.autoMonitorProfile = cbAutoMonProfile->get_active ();
#endif #endif
@ -1579,16 +1586,17 @@ void Preferences::fillPreferences ()
setActiveTextOrIndex (*monProfile, moptions.rtSettings.monitorProfile, 0); setActiveTextOrIndex (*monProfile, moptions.rtSettings.monitorProfile, 0);
switch (moptions.rtSettings.monitorIntent) { switch (moptions.rtSettings.monitorIntent) {
default: default:
case rtengine::RI_RELATIVE: case rtengine::RI_PERCEPTUAL:
monIntent->set_active (0); monIntent->set_active (0);
break; break;
case rtengine::RI_PERCEPTUAL: case rtengine::RI_RELATIVE:
monIntent->set_active (1); monIntent->set_active (1);
break; break;
case rtengine::RI_ABSOLUTE: case rtengine::RI_ABSOLUTE:
monIntent->set_active (2); monIntent->set_active (2);
break; break;
} }
monBPC->set_active (moptions.rtSettings.monitorBPC);
#if defined(WIN32) #if defined(WIN32)
cbAutoMonProfile->set_active(moptions.rtSettings.autoMonitorProfile); cbAutoMonProfile->set_active(moptions.rtSettings.autoMonitorProfile);
#endif #endif

View File

@ -97,6 +97,7 @@ protected:
Gtk::FileChooserButton* iccDir; Gtk::FileChooserButton* iccDir;
Gtk::ComboBoxText* monProfile; Gtk::ComboBoxText* monProfile;
Gtk::ComboBoxText* monIntent; Gtk::ComboBoxText* monIntent;
Gtk::CheckButton* monBPC;
Gtk::CheckButton* cbAutoMonProfile; Gtk::CheckButton* cbAutoMonProfile;
//Gtk::CheckButton* cbAutocielab; //Gtk::CheckButton* cbAutocielab;
Gtk::CheckButton* cbciecamfloat; Gtk::CheckButton* cbciecamfloat;

655
tools/color_management.svg Normal file
View File

@ -0,0 +1,655 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="297mm"
height="210mm"
viewBox="0 0 1052.3622 744.09448"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="color_management.svg">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker10113"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path10115"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#b049e1;stroke-width:1pt;stroke-opacity:1;fill:#b049e1;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker9939"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path9941"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#b049e1;stroke-width:1pt;stroke-opacity:1;fill:#b049e1;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker9189"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Send"
inkscape:collect="always">
<path
transform="scale(0.2) rotate(180) translate(6,0)"
style="fill-rule:evenodd;stroke:#b049e1;stroke-width:1pt;stroke-opacity:1;fill:#b049e1;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path9191" />
</marker>
<marker
inkscape:isstock="true"
style="overflow:visible;"
id="marker4296"
refX="0.0"
refY="0.0"
orient="auto"
inkscape:stockid="Arrow1Send">
<path
transform="scale(0.2) rotate(180) translate(6,0)"
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
id="path4298" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker5710"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path5712"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#dd8a7e;stroke-width:1pt;stroke-opacity:1;fill:#dd8a7e;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Mend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4281"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#dd8a7e;stroke-width:1pt;stroke-opacity:1;fill:#dd8a7e;fill-opacity:1"
transform="scale(0.4) rotate(180) translate(10,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker5062"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path5064"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4998"
style="overflow:visible;"
inkscape:isstock="true"
inkscape:collect="always">
<path
id="path5000"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Send"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Send"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4287"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#add352;stroke-width:1pt;stroke-opacity:1;fill:#add352;fill-opacity:1"
transform="scale(0.2) rotate(180) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4756"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4758"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#439872;stroke-opacity:1;fill:#439872;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4272"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4293"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#439872;stroke-opacity:1;fill:#439872;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) rotate(180) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="marker4574"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4576"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow2Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow2Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path4290"
style="fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#439872;stroke-opacity:1;fill:#439872;fill-opacity:1"
d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
transform="scale(1.1) translate(1,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;"
inkscape:isstock="true">
<path
id="path4275"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#439872;stroke-width:1pt;stroke-opacity:1;fill:#439872;fill-opacity:1"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="489.45925"
inkscape:cy="597.68828"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1018"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-308.26772)">
<path
style="fill:none;fill-rule:evenodd;stroke:#b049e1;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker10113)"
d="m 871.82971,670.64952 0,50.45433"
id="path10111"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path9187"
d="m 548.40112,670.64952 0,50.45433"
style="fill:none;fill-rule:evenodd;stroke:#b049e1;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9189)" />
<path
sodipodi:nodetypes="csc"
inkscape:connector-curvature="0"
id="path4996"
d="m 666.10066,635.08041 c 31.37496,-1.49737 37.63639,-52.56259 42.33564,-92.54896 4.49653,-38.26138 50.69343,-47.46535 84.39106,-0.36174"
style="fill:none;fill-rule:evenodd;stroke:#439872;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:28, 7;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker5062)" />
<rect
y="579.82043"
x="423.40112"
height="92.857147"
width="250"
id="rect5442"
style="opacity:1;fill:#8bd8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#439872;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:28, 7;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker4998)"
d="m 492.32787,440.64952 c 16.21054,39.59059 30.90653,57.74251 30.90653,98.45433"
id="path4200"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
inkscape:connector-curvature="0"
id="path4218"
d="m 534.03112,397.20982 c 130.59165,0 248.85289,32.24077 287.24555,140.161"
style="fill:none;fill-rule:evenodd;stroke:#add352;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Send)" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:0.71270716;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect10399"
width="169.52106"
height="31.025021"
x="599.28571"
y="405.36221" />
<path
style="fill:none;fill-rule:evenodd;stroke:#dd8a7e;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5710)"
d="m 394.53933,434.19203 c -31.92389,48.56808 -43.48293,40.68411 -98.97824,105.07044"
id="path4202"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<rect
style="opacity:1;fill:#ffffff;fill-opacity:0.71270716;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect7950"
width="167.56383"
height="42.952511"
x="236.2933"
y="459.36221" />
<rect
style="opacity:1;fill:#e1f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4190"
width="250"
height="29.285715"
x="423.40112"
y="550.53473" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="436.6803"
y="569.3158"
id="text4146"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
x="436.6803"
y="569.3158"
id="tspan4180"
style="font-size:15px">Output ICC profile &amp; intent</tspan></text>
<rect
style="opacity:1;fill:#8bd8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5444"
width="250"
height="92.857147"
x="746.82971"
y="579.82043" />
<rect
y="550.53473"
x="746.82971"
height="29.285715"
width="250"
id="rect5408"
style="opacity:1;fill:#e1f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="762.99524"
y="569.3158"
id="text4152"
sodipodi:linespacing="125%"><tspan
id="tspan4270"
sodipodi:role="line"
x="762.99524"
y="569.3158"
style="font-size:15px">Monitor ICC profile &amp; intent</tspan></text>
<g
id="g9171"
transform="translate(65.286377,16)">
<rect
y="713.55499"
x="731.54333"
height="80"
width="150"
id="rect4196"
style="opacity:1;fill:#dcb7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text4158"
y="761.94305"
x="762.66943"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="761.94305"
x="762.66943"
id="tspan4160"
sodipodi:role="line">Monitor</tspan></text>
</g>
<g
id="g9176"
transform="translate(68.218231,40)">
<rect
y="832.55505"
x="395.18289"
height="80"
width="170"
id="rect4198"
style="opacity:1;fill:#dcb7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
sodipodi:linespacing="125%"
id="text4162"
y="880.94312"
x="441.62637"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="880.94312"
x="441.62637"
id="tspan4164"
sodipodi:role="line">Printer</tspan></text>
</g>
<g
id="g9166"
transform="translate(71.411163,20)">
<rect
style="opacity:1;fill:#dcb7e7;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4210"
width="200"
height="80"
x="376.98996"
y="711.33673" />
<text
sodipodi:linespacing="125%"
id="text4170"
y="757.54401"
x="417.12546"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="757.54401"
x="417.12546"
id="tspan4172"
sodipodi:role="line">Output file</tspan></text>
</g>
<rect
y="457.36221"
x="469.28571"
height="31.025021"
width="82.14286"
id="rect7952"
style="opacity:1;fill:#ffffff;fill-opacity:0.71270716;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="471.19366"
y="469.87708"
id="text4182"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan4184"
x="471.19366"
y="469.87708"
style="font-size:10px">Soft-proofing path</tspan><tspan
sodipodi:role="line"
x="471.19366"
y="482.37708"
style="font-size:10px"
id="tspan10377">(Output Black Point Compensation)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4204"
y="471.25275"
x="318.36606"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="471.25275"
x="318.36606"
id="tspan4206"
sodipodi:role="line"
style="font-size:10px;text-align:center;text-anchor:middle">Only if</tspan><tspan
y="483.75275"
x="318.36606"
sodipodi:role="line"
style="font-size:10px;text-align:center;text-anchor:middle"
id="tspan5382">options.rtSettings.HistogramWorking = 1</tspan><tspan
y="496.25275"
x="318.36606"
sodipodi:role="line"
style="font-size:10px;text-align:center;text-anchor:middle"
id="tspan10383">(Output Black Point Compensation)</tspan></text>
<rect
style="opacity:1;fill:#8bd8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect4186"
width="180"
height="80"
x="359.46707"
y="361.55499" />
<g
id="g4220"
transform="translate(322.64831,127.10442)">
<text
sodipodi:linespacing="125%"
id="text4142"
y="271.17874"
x="56.132729"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="271.17874"
x="56.132729"
id="tspan4144"
sodipodi:role="line">L*a*b image</tspan></text>
<text
sodipodi:linespacing="125%"
id="text4214"
y="291.69702"
x="56.868813"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="291.69702"
x="56.868813"
id="tspan4216"
sodipodi:role="line">End of pipeline</tspan></text>
</g>
<text
sodipodi:linespacing="125%"
id="text5364"
y="417.30566"
x="599.33655"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="417.30566"
x="599.33655"
id="tspan5366"
sodipodi:role="line"
style="font-size:10px">Normal path</tspan><tspan
y="429.80566"
x="599.33655"
sodipodi:role="line"
style="font-size:10px"
id="tspan10375">(Monitor Black Point Compensation)</tspan></text>
<rect
style="opacity:1;fill:#8bd8d8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect5378"
width="300"
height="92.857147"
x="89.115433"
y="579.82043" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="100.83148"
y="648.47211"
id="text5374"
sodipodi:linespacing="125%"><tspan
style="font-size:10px"
sodipodi:role="line"
id="tspan5376"
x="100.83148"
y="648.47211">Used fo image analysis <tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold'"
id="tspan7948">only</tspan> with</tspan><tspan
style="font-size:10px"
sodipodi:role="line"
x="100.83148"
y="660.97211"
id="tspan5380">options.rtSettings.HistogramWorking = 1</tspan></text>
<text
sodipodi:linespacing="125%"
id="text5394"
y="648.47211"
x="436.97083"
style="font-style:normal;font-weight:normal;font-size:15px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
y="648.47211"
x="436.97083"
id="tspan5396"
sodipodi:role="line"
style="font-size:10px">Used fo image analysis with</tspan><tspan
id="tspan5398"
y="660.97211"
x="436.97083"
sodipodi:role="line"
style="font-size:10px">options.rtSettings.HistogramWorking = 0</tspan></text>
<rect
y="550.53473"
x="89.115433"
height="29.285715"
width="300"
id="rect5406"
style="opacity:1;fill:#e1f5f5;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:10;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="100.88519"
y="569.3158"
id="text4136"
sodipodi:linespacing="125%"><tspan
id="tspan4266"
sodipodi:role="line"
x="100.88519"
y="569.3158"
style="font-size:15px">Working space profile (output intent)</tspan></text>
<text
sodipodi:linespacing="125%"
id="text6976"
y="609.3158"
x="99.218933"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:22.5px"
y="609.3158"
x="99.218933"
sodipodi:role="line"
id="tspan6980">&quot;Working&quot; image</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="436.25916"
y="609.3158"
id="text6982"
sodipodi:linespacing="125%"><tspan
id="tspan6986"
sodipodi:role="line"
x="436.25916"
y="609.3158"
style="font-size:22.5px">Output image *</tspan></text>
<text
sodipodi:linespacing="125%"
id="text7002"
y="609.3158"
x="762.25916"
style="font-style:normal;font-weight:normal;font-size:22.5px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
xml:space="preserve"><tspan
style="font-size:22.5px"
y="609.3158"
x="762.25916"
sodipodi:role="line"
id="tspan7004">Preview image</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#b049e1;stroke-width:7;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker-end:url(#marker9939)"
d="m 548.40112,810.64952 0,50.45433"
id="path9937"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:20px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="69.700523"
y="1008.9257"
id="text10389"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan10391"
x="69.700523"
y="1008.9257"
style="font-size:12.5px">* When options.rtSettings.HistogramWorking = 1 and soft-proofing is enabled, the Output image does not really exist,</tspan><tspan
sodipodi:role="line"
x="69.700523"
y="1024.5508"
style="font-size:12.5px"
id="tspan10393"> i.e. no memory is allocated, the CMM only makes a double conversion of each pixel of the Lab image</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1 @@
spGamutCheck.png,w22,actions

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,2 @@
unchanged-22.png,w22,actions
unchanged-18.png,w18,actions

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 45 KiB