diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..6ef54e62a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,41 @@ +sudo: required +dist: trusty + +language: cpp + +compiler: + - gcc + +os: + - linux + +branches: + only: + - master + +notifications: + irc: + channels: + - "chat.freenode.net#rawtherapee" + template: + - "%{repository}/%{branch} (%{commit} - %{author}): %{build_url}: %{message}" + email: + on_success: change + on_failure: always + +env: + global: + - OMP_NUM_THREADS=4 + +before_install: + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + - sudo apt-get -qq update + - sudo apt-get install build-essential cmake curl g++-6 gcc-6 git libbz2-dev libcanberra-gtk-dev libexiv2-dev libexpat-dev libfftw3-dev libglibmm-2.4-dev libgtk2.0-dev libgtkmm-2.4-dev libiptcdata0-dev libjpeg8-dev liblcms2-dev libpng12-dev libsigc++-2.0-dev libtiff5-dev zlib1g-dev + - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6 + +before_script: + - mkdir build + - cd build + - cmake -DCMAKE_CXX_FLAGS="-Wno-deprecated-declarations" -DWITH_LTO="OFF" -DPROC_TARGET_NUMBER="2" .. + +script: make diff --git a/clean.sh b/clean.sh deleted file mode 100755 index 5500bf28e..000000000 --- a/clean.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -find -name CMakeCache.txt -delete -rm install_manifest.txt - -rm -r ./CMakeFiles -rm -r ./rtengine/CMakeFiles -rm -r ./rtexif/CMakeFiles -rm -r ./rtgui/CMakeFiles -rm -r ./rtdata/CMakeFiles - -rm ./cmake* -rm ./rtengine/cmake* -rm ./rtexif/cmake* -rm ./rtgui/cmake* -rm ./rtdata/cmake* - -rm ./Makefile -rm ./rtengine/Makefile -rm ./rtexif/Makefile -rm ./rtgui/Makefile -rm ./rtdata/Makefile - -rm ./rtengine/librtengine.so -rm ./rtengine/librtengine.a -rm ./rtgui/rawtherapee -rm ./rtexif/librtexif.so -rm ./rtexif/librtexif.a -exit 0 diff --git a/rtdata/images/Dark/actions/colorPickers-hide.png b/rtdata/images/Dark/actions/colorPickers-hide.png new file mode 100644 index 000000000..54b33a7fb Binary files /dev/null and b/rtdata/images/Dark/actions/colorPickers-hide.png differ diff --git a/rtdata/images/Dark/actions/colorPickers-show.png b/rtdata/images/Dark/actions/colorPickers-show.png new file mode 100644 index 000000000..d9d039c2b Binary files /dev/null and b/rtdata/images/Dark/actions/colorPickers-show.png differ diff --git a/rtdata/images/Dark/actions/gtk-color-picker-add.png b/rtdata/images/Dark/actions/gtk-color-picker-add.png new file mode 100644 index 000000000..77a30c250 Binary files /dev/null and b/rtdata/images/Dark/actions/gtk-color-picker-add.png differ diff --git a/rtdata/images/Light/actions/colorPickers-hide.png b/rtdata/images/Light/actions/colorPickers-hide.png new file mode 100644 index 000000000..434087f1c Binary files /dev/null and b/rtdata/images/Light/actions/colorPickers-hide.png differ diff --git a/rtdata/images/Light/actions/colorPickers-show.png b/rtdata/images/Light/actions/colorPickers-show.png new file mode 100644 index 000000000..d93deb3eb Binary files /dev/null and b/rtdata/images/Light/actions/colorPickers-show.png differ diff --git a/rtdata/images/Light/actions/gtk-color-picker-add.png b/rtdata/images/Light/actions/gtk-color-picker-add.png new file mode 100644 index 000000000..01d2b6a0b Binary files /dev/null and b/rtdata/images/Light/actions/gtk-color-picker-add.png differ diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 4dd5ff360..deca1cdd2 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -990,7 +990,8 @@ PREFERENCES_REMEMBERZOOMPAN;Se souvenir de niveau de zoom et de la position de l PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Retient le niveau de zoom et la position de l'image courante lors de l'ouverture d'une nouvelle image.\n\nCette option ne fonctionne que dans le mode "Éditeur unique" et quand "Méthode de dématriçage utilisé pour l'aperçu à un zoom <100%" is set to "Idem PP3". PREFERENCES_RGBDTL_LABEL;Nombre maximum d'unités de calcul pour la Réduction du bruit PREFERENCES_RGBDTL_TOOLTIP;La réduction du bruit nécessite un minimum d'à peu près 128Mo de RAM pour une image de 10MPix ou 512Mo pour une image de 40MPix, ainsi que 128Mo de RAM supplémentaire par unité de calcul. Plus il y aura d'unités de calcul travaillant en parallèle, plus ce sera rapide. Laissez la valeur à "0" pour utiliser automatiquement autant d'unités de calcul que possible. -PREFERENCES_SELECTFONT;Police de caractère +PREFERENCES_SELECTFONT;Police générale +PREFERENCES_SELECTFONT_COLPICKER;Police des pipette à couleur PREFERENCES_SELECTLANG;Choix de la langue PREFERENCES_SELECTTHEME;Choisissez un thème PREFERENCES_SERIALIZE_TIFF_READ;Réglage de lecture des images TIFF @@ -1093,6 +1094,7 @@ THRESHOLDSELECTOR_HINT;Maintenez la touche Shift appuyée pour déplacer THRESHOLDSELECTOR_T;Haut THRESHOLDSELECTOR_TL;Haut-Gauche THRESHOLDSELECTOR_TR;Haut-droite +TOOLBAR_TOOLTIP_COLORPICKER;Ancre de Vérification Couleur\n\nLorque activé:\nCliquez la zone d'image avec le bouton gauche de la souris pour ajouter une ancre\nDéplacez-le en le "tirant" avec le bouton gauche de la souris\nSupprimez une ancre en cliquant dessus avec le bouton droit de la souris\nSupprimez toutes les ancres avec Shift + click avec le bouton droit\nCliquez avec le bouton droit de la souris en dehors de toute ancre pour revenir au mode Déplacement TOOLBAR_TOOLTIP_CROP;Sélection du recadrage\nRaccourci: c\nDéplacez le recadrage en utilisant Shift + Glisser TOOLBAR_TOOLTIP_HAND;Outil de navigation\nRaccourci: h TOOLBAR_TOOLTIP_STRAIGHTEN;Sélection de la ligne d'horizon\nRaccourci: s\n\nIndiquez la verticale ou l'horizontale en dessinant une ligne à travers l'image de prévisualisation. L'angle de rotation sera affiché près de la ligne guide. Le centre de rotation est le centre géométrique de l'image. diff --git a/rtdata/languages/default b/rtdata/languages/default index 69988b905..605c2ea63 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1041,7 +1041,8 @@ PREFERENCES_REMEMBERZOOMPAN;Remember zoom % and pan offset PREFERENCES_REMEMBERZOOMPAN_TOOLTIP;Remember the zoom % and pan offset of the current image when opening a new image.\n\nThis option only works in "Single Editor Tab Mode" and when "Demosaicing method used for the preview at <100% zoom" is set to "As in PP3". PREFERENCES_RGBDTL_LABEL;Max number of threads for Noise Reduction and Wavelet Levels PREFERENCES_RGBDTL_TOOLTIP;Leave the setting at "0" to automatically use as many threads as possible. The more threads run in parallel, the faster the computation. Refer to RawPedia for memory requirements. -PREFERENCES_SELECTFONT;Select font +PREFERENCES_SELECTFONT;Select global font +PREFERENCES_SELECTFONT_COLPICKER;Select Color Picker's font PREFERENCES_SELECTLANG;Select language PREFERENCES_SELECTTHEME;Select theme PREFERENCES_SERIALIZE_TIFF_READ;Tiff Read Settings @@ -1146,6 +1147,7 @@ THRESHOLDSELECTOR_HINT;Hold the Shift key to move individual control poin THRESHOLDSELECTOR_T;Top THRESHOLDSELECTOR_TL;Top-left THRESHOLDSELECTOR_TR;Top-right +TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool TOOLBAR_TOOLTIP_CROP;Crop selection.\nShortcut: c\nMove the crop area using Shift-mouse drag TOOLBAR_TOOLTIP_HAND;Hand tool.\nShortcut: h TOOLBAR_TOOLTIP_STRAIGHTEN;Straighten / fine rotation.\nShortcut: s\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Center of rotation is the geometrical center of the image. diff --git a/rtengine/EdgePreserveLab.cc b/rtengine/EdgePreserveLab.cc deleted file mode 100644 index 1f063ec0c..000000000 --- a/rtengine/EdgePreserveLab.cc +++ /dev/null @@ -1,264 +0,0 @@ -#include "EdgePreserveLab.h" -#include "boxblur.h" -#include - -#ifdef _OPENMP -#include -#endif - -//#define MAX(a,b) ((a)<(b)?(b):(a)) -//#define MIN(a,b) ((a)>(b)?(b):(a)) - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - -EdgePreserveLab::EdgePreserveLab(unsigned int width, unsigned int height) -{ - w = width; - h = height; - n = w * h; - - //Initialize the matrix just once at construction. - A = new MultiDiagonalSymmetricMatrix(n, 5); - - if(!( - A->CreateDiagonal(0, 0) && - A->CreateDiagonal(1, 1) && - A->CreateDiagonal(2, w - 1) && - A->CreateDiagonal(3, w) && - A->CreateDiagonal(4, w + 1))) { - delete A; - A = NULL; - printf("Error in EdgePreserveLab construction: out of memory.\n"); - } else { - a0 = A->Diagonals[0]; - a_1 = A->Diagonals[1]; - a_w1 = A->Diagonals[2]; - a_w = A->Diagonals[3]; - a_w_1 = A->Diagonals[4]; - } -} - -EdgePreserveLab::~EdgePreserveLab() -{ - delete A; -} - -float *EdgePreserveLab::CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur, bool UseBlurForEdgeStop) -{ - if(Blur == NULL) - UseBlurForEdgeStop = false, //Use source if there's no supplied Blur. - Blur = new float[3 * n]; - - if(LScale == 0.0f) { - memcpy(Blur, Source, 3 * n * sizeof(float)); - return Blur; - } - - //Create the edge stopping function a, rotationally symmetric and just one instead of (ax, ay). Maybe don't need Blur yet, so use its memory. - float *a, *b, *g; - - if(UseBlurForEdgeStop) { - a = new float[n], g = Blur; - } else { - a = Blur, g = Source; - } - - //b = new float[n]; - - unsigned int x, y, i; - unsigned int w1 = w - 1, h1 = h - 1; - float eps = 0.0001f; - float scL = powf(100.0f, LScale); - float scab = powf(200.0f, abScale); - - float * var = new float[w * h]; - rtengine::boxvar(g, var, 1, 1, w, h); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(y = 0; y < h1; y++) { - float *rg = &g[w * y]; - - for(x = 0; x < w1; x++) { - //Estimate the central difference gradient in the center of a four pixel square. (gx, gy) is actually 2*gradient. - /*float gx = (fabs((rg[x + 1] - rg[x]) + (rg[x + w + 1] - rg[x + w]))); - float gy = (fabs((rg[x + w] - rg[x]) + (rg[x + w + 1] - rg[x + 1]))); - - //TODO: combine this with gx, gy if not needing separate quantities - float hx = (fabs((rg[x + 1 + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + w + n])) + \ - fabs((rg[x + 1 + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + w + 2*n]))); - float hy = (fabs((rg[x + w + n] - rg[x + n]) + (rg[x + w + 1 + n] - rg[x + 1 + n])) + \ - fabs((rg[x + w + 2*n] - rg[x + 2*n]) + (rg[x + w + 1 + 2*n] - rg[x + 1 + 2*n]))); - */ - //float gradtot = (gx+gy+hx+hy); - //gradhisto[MAX(0,MIN(32767,(int)gradtot))] ++; - - //Apply power to the magnitude of the gradient to get the edge stopping function. - //a[x + w*y] = scL*expf(-100.0f*(gx + gy + hx + hy)/(EdgeStoppingLuma)); - //a[x + w*y] = scL*expf(-var[y*w+x]/SQR(0.02*EdgeStoppingLuma));///(0.1+rg[x]); - a[x + w * y] = scL * expf(-50.0f * sqrt(var[y * w + x]) / (EdgeStoppingLuma + eps)); ///(0.1+rg[x]); - - //b[x + w*y] = (scab)*expf(-20.0f*(gx + gy + Lave*(hx + hy))/(EdgeStoppingChroma)); - //b[x + w*y] = (scab)*expf(-400.0f*SQR(gx + gy + Lave*(hx + hy))/SQR(EdgeStoppingChroma));; - - } - } - - /* Now setup the linear problem. I use the Maxima CAS, here's code for making an FEM formulation for the smoothness term: - p(x, y) := (1 - x)*(1 - y); - P(m, n) := A[m][n]*p(x, y) + A[m + 1][n]*p(1 - x, y) + A[m + 1][n + 1]*p(1 - x, 1 - y) + A[m][n + 1]*p(x, 1 - y); - Integrate(f) := integrate(integrate(f, x, 0, 1), y, 0, 1); - - Integrate(diff(P(u, v), x)*diff(p(x, y), x) + diff(P(u, v), y)*diff(p(x, y), y)); - Integrate(diff(P(u - 1, v), x)*diff(p(1 - x, y), x) + diff(P(u - 1, v), y)*diff(p(1 - x, y), y)); - Integrate(diff(P(u - 1, v - 1), x)*diff(p(1 - x, 1 - y), x) + diff(P(u - 1, v - 1), y)*diff(p(1 - x, 1 - y), y)); - Integrate(diff(P(u, v - 1), x)*diff(p(x, 1 - y), x) + diff(P(u, v - 1), y)*diff(p(x, 1 - y), y)); - So yeah. Use the numeric results of that to fill the matrix A.*/ - memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); - memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); - memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); - memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); - -//TODO: OMP here? - for(i = y = 0; y != h; y++) { - for(x = 0; x != w; x++, i++) { - float ac; - a0[i] = 1.0; - - //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. - if(x > 0 && y > 0) - ac = a[i - w - 1] / 6.0f, - a_w_1[i - w - 1] -= 2.0f * ac, a_w[i - w] -= ac, - a_1[i - 1] -= ac, a0[i] += 4.0f * ac; - - if(x < w1 && y > 0) - ac = a[i - w] / 6.0f, - a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f * ac, - a0[i] += 4.0f * ac; - - if(x > 0 && y < h1) - ac = a[i - 1] / 6.0f, - a_1[i - 1] -= ac, a0[i] += 4.0f * ac; - - if(x < w1 && y < h1) { - a0[i] += 4.0f * a[i] / 6.0f; - } - } - } - - if(UseBlurForEdgeStop) { - delete[] a; - } - - - //Solve & return. - A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). - - if(!UseBlurForEdgeStop) { - memcpy(Blur, Source, 3 * n * sizeof(float)); - } - - // blur L channel - SparseConjugateGradient(A->PassThroughVectorProduct, Source, n, false, Blur, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - - //reset A for ab channels - /*memset(a_1, 0, A->DiagonalLength(1)*sizeof(float)); - memset(a_w1, 0, A->DiagonalLength(w - 1)*sizeof(float)); - memset(a_w, 0, A->DiagonalLength(w)*sizeof(float)); - memset(a_w_1, 0, A->DiagonalLength(w + 1)*sizeof(float)); - for(i = y = 0; y != h; y++){ - for(x = 0; x != w; x++, i++){ - float ac; - a0[i] = 1.0; - - //Remember, only fill the lower triangle. Memory for upper is never made. It's symmetric. Trust. - if(x > 0 && y > 0) - ac = b[i - w - 1]/6.0f, - a_w_1[i - w - 1] -= 2.0f*ac, a_w[i - w] -= ac, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; - - if(x < w1 && y > 0) - ac = b[i - w]/6.0f, - a_w[i - w] -= ac, a_w1[i - w + 1] -= 2.0f*ac, - a0[i] += 4.0f*ac; - - if(x > 0 && y < h1) - ac = b[i - 1]/6.0f, - a_1[i - 1] -= ac, a0[i] += 4.0f*ac; - - if(x < w1 && y < h1) - a0[i] += 4.0f*b[i]/6.0f; - } - }*/ - /*if(UseBlurForEdgeStop)*/ //delete[] b; - - // blur ab channels - //A->CreateIncompleteCholeskyFactorization(1); //Fill-in of 1 seems to work really good. More doesn't really help and less hurts (slightly). - //SparseConjugateGradient(A->PassThroughVectorProduct, Source+n, n, false, Blur+n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - //SparseConjugateGradient(A->PassThroughVectorProduct, Source+2*n, n, false, Blur+2*n, 0.0f, (void *)A, Iterates, A->PassThroughCholeskyBackSolve); - - A->KillIncompleteCholeskyFactorization(); - return Blur; -} - -float *EdgePreserveLab::CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur) -{ - //Simpler outcome? - if(Reweightings == 0) { - return CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur); - } - - //Create a blur here, initialize. - if(Blur == NULL) { - Blur = new float[3 * n]; - } - - memcpy(Blur, Source, 3 * n * sizeof(float)); - - //Iteratively improve the blur. - Reweightings++; - - for(unsigned int i = 0; i != Reweightings; i++) { - CreateBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Blur, true); - } - - return Blur; -} - -float *EdgePreserveLab::CompressDynamicRange(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, float CompressionExponent, float DetailBoost, unsigned int Iterates, unsigned int Reweightings, float *Compressed) -{ - //We're working with luminance, which does better logarithmic. - unsigned int i; - //for(i = 0; i != n; i++) - // Source[i] = logf(Source[i] + 0.0001f); - - //Blur. Also setup memory for Compressed (we can just use u since each element of u is used in one calculation). - float *u = CreateIteratedBlur(Source, LScale, abScale, EdgeStoppingLuma, EdgeStoppingChroma, Iterates, Reweightings); - - if(Compressed == NULL) { - Compressed = u; - } - - //Apply compression, detail boost, unlogging. Compression is done on the logged data and detail boost on unlogged. - for(i = 0; i != n; i++) { - //float ce = expf(Source[i] + u[i]*(CompressionExponent - 1.0f)) - 0.0001f; - //float ue = expf(u[i]) - 0.0001f; - //Source[i] = expf(Source[i]) - 0.0001f; - //Compressed[i] = ce + DetailBoost*(Source[i] - ue); - Compressed[i] = u[i];//ue;//for testing, to display blur - } - - if(Compressed != u) { - delete[] u; - } - - return Compressed; -} - - - - diff --git a/rtengine/EdgePreserveLab.h b/rtengine/EdgePreserveLab.h deleted file mode 100644 index e365956c5..000000000 --- a/rtengine/EdgePreserveLab.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once -/* -The EdgePreserveLab files contain standard C++ (standard except the first line) code for creating and, to a -limited extent (create your own uses!), messing with multi scale edge preserving decompositions of a 32 bit single channel -image. As a byproduct it contains a lot of linear algebra which can be useful for optimization problems that -you want to solve in rectangles on rectangular grids. - -Anyway. Basically, this is an implementation of what's presented in the following papers: - Edge-Preserving Decompositions for Multi-Scale Tone and Detail Manipulation - An Iterative Solution Method for Linear Systems of Which the Coefficient Matrix is a Symetric M-Matrix - Color correction for tone mapping - Wikipedia, the free encyclopedia - -First one is most of what matters, next two are details, last everything else. I did a few things differently, especially: - Reformulated the minimization with finite elements instead of finite differences. This results in better conditioning, - slightly better accuracy (less artifacts), the possibility of a better picked edge stopping function, but more memory consumption. - - A single rotationally invariant edge stopping function is used instead of two non-invariant ones. - - Incomplete Cholseky factorization instead of Szeliski's LAHBF. Slower, but not subject to any patents. - - For tone mapping, original images are decomposed instead of their logarithms, and just one decomposition is made; - I find that this way works plenty good (theirs isn't better or worse... just different) and is simpler. - -Written by ben_pcc in Portland, Oregon, USA; code modified by Emil Martinec. - - // EdgePreserveLab.h and EdgePreserveLab.cpp are free software: - // you can redistribute it and/or modify it - // under the terms of the GNU General Public License as published by - // the Free Software Foundation, either version 3 of the License, or - // (at your option) any later version. - // - // This program is distributed in the hope that it will be useful, - // but WITHOUT ANY WARRANTY; without even the implied warranty of - // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - // GNU General Public License for more details. - // - // You should have received a copy of the GNU General Public License - // along with this program. If not, see . - -*/ - - - -#include -#include -#include -#include "EdgePreservingDecomposition.h" - -class EdgePreserveLab -{ -public: - EdgePreserveLab(unsigned int width, unsigned int height); - ~EdgePreserveLab(); - - //Create an edge preserving blur of Source. Will create and return, or fill into Blur if not NULL. In place not ok. - //If UseBlurForEdgeStop is true, supplied not NULL Blur is used to calculate the edge stopping function instead of Source. - float *CreateBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, float *Blur = NULL, bool UseBlurForEdgeStop = false); - - //Iterates CreateBlur such that the smoothness term approaches a specific norm via iteratively reweighted least squares. In place not ok. - float *CreateIteratedBlur(float *Source, float LScale, float abScale, float EdgeStoppingLuma, float EdgeStoppingChroma, unsigned int Iterates, unsigned int Reweightings, float *Blur = NULL); - - /*Lowers global contrast while preserving or boosting local contrast. Can fill into Compressed. The smaller Compression - the more compression is applied, with Compression = 1 giving no effect and above 1 the opposite effect. You can totally - use Compression = 1 and play with DetailBoost for some really sweet unsharp masking. If working on luma/grey, consider giving it a logarithm. - In place calculation to save memory (Source == Compressed) is totally ok. Reweightings > 0 invokes CreateIteratedBlur instead of CreateBlur. */ - float *CompressDynamicRange(float *Source, float LScale = 1.0f, float abScale = 5.0f, float EdgeStoppingLuma = 1.0f, float EdgeStoppingChroma = 1.0f, - float CompressionExponent = 0.8f, float DetailBoost = 0.1f, unsigned int Iterates = 20, - unsigned int Reweightings = 0, float *Compressed = NULL); - -private: - MultiDiagonalSymmetricMatrix *A; //The equations are simple enough to not mandate a matrix class, but fast solution NEEDS a complicated preconditioner. - unsigned int w, h, n; - - //Convenient access to the data in A. - float *a0, *a_1, *a_w, *a_w_1, *a_w1; -}; diff --git a/rtengine/EdgePreservingDecomposition.h b/rtengine/EdgePreservingDecomposition.h index 04ebfe3b6..a15cacb62 100644 --- a/rtengine/EdgePreservingDecomposition.h +++ b/rtengine/EdgePreservingDecomposition.h @@ -67,13 +67,16 @@ ben_s or nonbasketless. Enjoy! #include #include #include + #include "opthelper.h" +#include "noncopyable.h" //This is for solving big symmetric positive definite linear problems. float *SparseConjugateGradient(void Ax(float *Product, float *x, void *Pass), float *b, int n, bool OkToModify_b = true, float *x = NULL, float RMSResidual = 0.0f, void *Pass = NULL, int MaximumIterates = 0, void Preconditioner(float *Product, float *x, void *Pass) = NULL); //Storage and use class for symmetric matrices, the nonzero contents of which are confined to diagonals. -class MultiDiagonalSymmetricMatrix +class MultiDiagonalSymmetricMatrix : + public rtengine::NonCopyable { public: MultiDiagonalSymmetricMatrix(int Dimension, int NumberOfDiagonalsInLowerTriangle); @@ -131,7 +134,8 @@ public: }; -class EdgePreservingDecomposition +class EdgePreservingDecomposition : + public rtengine::NonCopyable { public: EdgePreservingDecomposition(int width, int height); diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc index d9a15e4ab..6bb0c4c3c 100644 --- a/rtengine/FTblockDN.cc +++ b/rtengine/FTblockDN.cc @@ -109,7 +109,7 @@ void ImProcFunctions::Median_Denoise(float **src, float **dst, const int width, medBuffer[0] = src; // we need a buffer if src == dst or if (src != dst && iterations > 1) - if (src == dst || (src != dst && iterations > 1)) { + if (src == dst || iterations > 1) { if (buffer == nullptr) { // we didn't get a buufer => create one allocBuffer = new float*[height]; @@ -854,7 +854,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef const float noisevarab_b = SQR(realblue); //input L channel - array2D *Lin; + array2D *Lin = nullptr; //wavelet denoised image LabImage * labdn = new LabImage(width, height); @@ -1678,10 +1678,7 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagef } delete labdn; - - if (denoiseLuminance) { - delete Lin; - } + delete Lin; }//end of tile row }//end of tile loop @@ -2251,7 +2248,6 @@ SSEFUNCTION bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposit float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); if (lvl == maxlvl - 1) { - float vari[4]; int edge = 0; ShrinkAllL(WaveletCoeffs_L, buffer, lvl, dir, noisevarlum, madL[lvl], nullptr, edge); } else { @@ -2614,7 +2610,7 @@ SSEFUNCTION void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeff // printf("OK lev=%d\n",level); float mad_L = madL[dir - 1] ; - if (edge == 1) { + if (edge == 1 && vari) { noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer for (int i = 0; i < W_L * H_L; ++i) { @@ -3045,7 +3041,7 @@ void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int l delta *= 0.15f; } else if (chaut < 650.f) { delta *= 0.1f; - } else if (chaut >= 650.f) { + } else /*if (chaut >= 650.f)*/ { delta *= 0.07f; } @@ -3083,7 +3079,7 @@ void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int l delta *= 0.3f; } else if (chaut < 650.f) { delta *= 0.2f; - } else if (chaut >= 650.f) { + } else /*if (chaut >= 650.f)*/ { delta *= 0.15f; } @@ -3108,7 +3104,7 @@ void ImProcFunctions::calcautodn_info (float &chaut, float &delta, int Nb, int l } -SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread) +SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread) { if ((settings->leveldnautsimpl == 1 && dnparams.Cmethod == "MAN") || (settings->leveldnautsimpl == 0 && dnparams.C2method == "MANU")) { //nothing to do @@ -3547,9 +3543,6 @@ SSEFUNCTION void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat } comptlevel += 1; - float chresid, chmaxredresid, chmaxblueresid; - nresi = chresid; - highresi = chresid + 0.66f * (max(chmaxredresid, chmaxblueresid) - chresid); //evaluate sigma delete adecomp; delete bdecomp; delete labdn; diff --git a/rtengine/LUT.h b/rtengine/LUT.h index 24f883766..2d3d91ed5 100644 --- a/rtengine/LUT.h +++ b/rtengine/LUT.h @@ -61,13 +61,16 @@ #include #include +#include + #ifndef NDEBUG #include #include #endif + #include "opthelper.h" -#include #include "rt_math.h" +#include "noncopyable.h" // Bit representations of flags enum { @@ -85,7 +88,8 @@ using LUTd = LUT; using LUTuc = LUT; template -class LUT +class LUT : + public rtengine::NonCopyable { protected: // list of variables ordered to improve cache speed diff --git a/rtengine/StopWatch.h b/rtengine/StopWatch.h index 2b3ff1baf..9e4400b94 100644 --- a/rtengine/StopWatch.h +++ b/rtengine/StopWatch.h @@ -26,18 +26,17 @@ #ifdef BENCHMARK #define BENCHFUN StopWatch StopFun(__func__); + #define BENCHFUNMICRO StopWatch StopFun(__func__, true); #else #define BENCHFUN + #define BENCHFUNMICRO #endif class StopWatch { public: - StopWatch( ) - { - stopped = false; - } - StopWatch( const char* msg) + + explicit StopWatch( const char* msg, bool microseconds = false ) : microseconds(microseconds) { message = msg; start(); @@ -56,8 +55,13 @@ public: void stop() { stopTime.set(); - long elapsedTime = stopTime.etime(startTime) / 1000; - std::cout << message << " took " << elapsedTime << " ms" << std::endl; + if(!microseconds) { + long elapsedTime = stopTime.etime(startTime) / 1000; + std::cout << message << " took " << elapsedTime << " ms" << std::endl; + } else { + long elapsedTime = stopTime.etime(startTime); + std::cout << message << " took " << elapsedTime << " us" << std::endl; + } stopped = true; } void stop(const char *msg) @@ -66,6 +70,7 @@ public: stop(); }; private: + bool microseconds; MyTime startTime; MyTime stopTime; const char *message; diff --git a/rtengine/alignedbuffer.h b/rtengine/alignedbuffer.h index ac8471b7e..652bfe8cf 100644 --- a/rtengine/alignedbuffer.h +++ b/rtengine/alignedbuffer.h @@ -93,7 +93,15 @@ public: // we're freeing the memory and allocate it again if the new size is bigger. if (allocatedSize < oldAllocatedSize) { - real = realloc(real, allocatedSize + alignment); + void *temp = realloc(real, allocatedSize + alignment); + if (temp) { // realloc succeeded + real = temp; + } else { // realloc failed => free old buffer and allocate new one + if (real) { + free (real); + } + real = malloc(allocatedSize + alignment); + } } else { if (real) { free (real); @@ -143,7 +151,7 @@ private: size_t size; public: - AlignedBufferMP(size_t sizeP) + explicit AlignedBufferMP(size_t sizeP) { size = sizeP; } diff --git a/rtengine/array2D.h b/rtengine/array2D.h index f9d92ac36..db44fcfc8 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -66,8 +66,11 @@ #include #include +#include "noncopyable.h" + template -class array2D +class array2D : + public rtengine::NonCopyable { private: diff --git a/rtengine/cache.h b/rtengine/cache.h index f14d7c6d9..ea567542c 100644 --- a/rtengine/cache.h +++ b/rtengine/cache.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (C) 2016 Floessie + * Copyright (C) 2016 Flössie * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/rtengine/cieimage.h b/rtengine/cieimage.h index a97622325..23b080ae3 100644 --- a/rtengine/cieimage.h +++ b/rtengine/cieimage.h @@ -20,11 +20,13 @@ #define _CIEIMAGE_H_ #include "image16.h" +#include "noncopyable.h" namespace rtengine { -class CieImage +class CieImage : + public NonCopyable { private: bool fromImage; diff --git a/rtengine/clutstore.h b/rtengine/clutstore.h index 7383b597f..5e4930fa1 100644 --- a/rtengine/clutstore.h +++ b/rtengine/clutstore.h @@ -7,16 +7,16 @@ #include "cache.h" #include "alignedbuffer.h" +#include "noncopyable.h" namespace rtengine { -class HaldCLUT +class HaldCLUT final : + public NonCopyable { public: HaldCLUT(); - HaldCLUT(const HaldCLUT& other) = delete; - HaldCLUT& operator =(const HaldCLUT& other) = delete; ~HaldCLUT(); bool load(const Glib::ustring& filename); @@ -51,14 +51,12 @@ private: Glib::ustring clut_profile; }; -class CLUTStore +class CLUTStore final : + public NonCopyable { public: static CLUTStore& getInstance(); - CLUTStore(const CLUTStore& other) = delete; - CLUTStore& operator =(const CLUTStore& other) = delete; - std::shared_ptr getClut(const Glib::ustring& filename); void clearCache(); diff --git a/rtengine/color.cc b/rtengine/color.cc index 95c9cf499..0743949e8 100644 --- a/rtengine/color.cc +++ b/rtengine/color.cc @@ -23,6 +23,7 @@ #include "mytime.h" #include "sleef.c" #include "opthelper.h" +#include "iccstore.h" #define pow_F(a,b) (xexpf(b*xlogf(a))) @@ -361,6 +362,153 @@ void Color::cleanup () } } +void Color::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b, bool workingSpace) +{ + double xyz_rgb[3][3]; + const double ep = 216.0 / 24389.0; + const double ka = 24389.0 / 27.0; + + double var_R = r / 65535.0; + double var_G = g / 65535.0; + double var_B = b / 65535.0; + + Glib::ustring profileCalc; + profileCalc = "sRGB"; //default + + if (workingSpace) { + profileCalc = profileW; //display working + } + + else {// if you want display = output space + if (profile == "RT_sRGB" || profile == "RT_sRGB_gBT709" || profile == "RT_sRGB_g10") { + profileCalc = "sRGB"; + } + + if (profile == "ProPhoto" || profile == "RT_Large_gBT709" || profile == "RT_Large_g10" || profile == "RT_Large_gsRGB") { + profileCalc = "ProPhoto"; + } + + if (profile == "AdobeRGB1998" || profile == "RT_Medium_gsRGB") { + profileCalc = "Adobe RGB"; + } + + if (profile == "WideGamutRGB") { + profileCalc = "WideGamut"; + } + } + + if (workingSpace) {//display working + if (profileW == "sRGB") { //apply sRGB inverse gamma + + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } else if (profileW == "ProPhoto") { // apply inverse gamma 1.8 + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else { // apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } else { //display outout profile + + if (profile == "RT_sRGB" || profile == "RT_Large_gsRGB" || profile == "RT_Medium_gsRGB") { //apply sRGB inverse gamma + if ( var_R > 0.04045 ) { + var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_R = var_R / 12.92; + } + + if ( var_G > 0.04045 ) { + var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_G = var_G / 12.92; + } + + if ( var_B > 0.04045 ) { + var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); + } else { + var_B = var_B / 12.92; + } + } + + else if (profile == "RT_sRGB_gBT709" || profile == "RT_Large_gBT709") { // + if ( var_R > 0.0795 ) { + var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_R = var_R / 4.5; + } + + if ( var_G > 0.0795 ) { + var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_G = var_G / 4.5; + } + + if ( var_B > 0.0795 ) { + var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2); + } else { + var_B = var_B / 4.5; + } + + } else if (profile == "ProPhoto") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.8); + var_G = pow ( var_G, 1.8); + var_B = pow ( var_B, 1.8); + } else if (profile == "RT_sRGB_g10" || profile == "RT_Large_g10") { // apply inverse gamma 1.8 + + var_R = pow ( var_R, 1.); + var_G = pow ( var_G, 1.); + var_B = pow ( var_B, 1.); + } + + else {// apply inverse gamma 2.2 + var_R = pow ( var_R, 2.2); + var_G = pow ( var_G, 2.2); + var_B = pow ( var_B, 2.2); + } + } + + // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); + + TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileCalc); + + for (int m = 0; m < 3; m++) + for (int n = 0; n < 3; n++) { + xyz_rgb[m][n] = wprof[m][n]; + } + + double varxx, varyy, varzz; + double var_X = ( xyz_rgb[0][0] * var_R + xyz_rgb[0][1] * var_G + xyz_rgb[0][2] * var_B ) / Color::D50x; + double var_Y = ( xyz_rgb[1][0] * var_R + xyz_rgb[1][1] * var_G + xyz_rgb[1][2] * var_B ) ; + double var_Z = ( xyz_rgb[2][0] * var_R + xyz_rgb[2][1] * var_G + xyz_rgb[2][2] * var_B ) / Color::D50z; + + varxx = var_X > ep ? cbrt(var_X) : ( ka * var_X + 16.0) / 116.0 ; + varyy = var_Y > ep ? cbrt(var_Y) : ( ka * var_Y + 16.0) / 116.0 ; + varzz = var_Z > ep ? cbrt(var_Z) : ( ka * var_Z + 16.0) / 116.0 ; + LAB_l = ( 116 * varyy ) - 16; + LAB_a = 500 * ( varxx - varyy ); + LAB_b = 200 * ( varyy - varzz ); + +} + void Color::rgb2hsl(float r, float g, float b, float &h, float &s, float &l) { diff --git a/rtengine/color.h b/rtengine/color.h index a221a998b..e2b32e834 100644 --- a/rtengine/color.h +++ b/rtengine/color.h @@ -177,6 +177,22 @@ public: } + /** + * @brief Convert red/green/blue to L*a*b + * @brief Convert red/green/blue to hue/saturation/luminance + * @param profile output profile name + * @param profileW working profile name + * @param r red channel [0 ; 65535] + * @param g green channel [0 ; 65535] + * @param b blue channel [0 ; 65535] + * @param L Lab L channel [0 ; 1] (return value) + * @param a Lab a channel [0 ; 1] (return value) + * @param b Lab b channel [0; 1] (return value) + * @param workingSpace true: compute the Lab value using the Working color space ; false: use the Output color space + */ + static void rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b, bool workingSpace); + + /** * @brief Convert red/green/blue to hue/saturation/luminance * @param r red channel [0 ; 65535] diff --git a/rtengine/colortemp.cc b/rtengine/colortemp.cc index 7b271960d..5cf880b41 100644 --- a/rtengine/colortemp.cc +++ b/rtengine/colortemp.cc @@ -34,7 +34,7 @@ namespace rtengine extern const Settings* settings; -static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 2 degree Standard Observer. +static const double cie_colour_match_jd[97][3] = {//350nm to 830nm 5 nm J.Desmis 2° Standard Observer. {0.0000000, 0.000000, 0.000000}, {0.0000000, 0.000000, 0.000000}, {0.0001299, 0.0003917, 0.0006061}, {0.0002321, 0.000006965, 0.001086}, {0.0004149, 0.00001239, 0.001946}, {0.0007416, 0.00002202, 0.003846}, {0.001368, 0.000039, 0.006450001}, {0.002236, 0.000064, 0.01054999}, {0.004243, 0.000120, 0.02005001}, @@ -295,7 +295,7 @@ const double ColorTemp::Solux4100_spect[97] = { 62.40, 61.373, 59.75, 58.1810, 56.25, 54.395, 51.90, 49.496, 47.05, 44.620 }; -//spectral data for Solux lamp : near Daylight (for example "Musee d'Orsay") - 4700K +//spectral data for Solux lamp : near Daylight (for example "Musée d'Orsay") - 4700K const double ColorTemp::Solux4700_spect[97] = { 0.4590, 0.83, 1.2011, 1.53, 1.8647, 2.15, 2.5338, 3.06, 3.5809, 3.99, 4.4137, 4.82, 5.2228, 5.63, 6.0387, 6.53, 6.9944, 7.55, 8.0266, 8.475, 8.9276, 8.90, 9.7840, 10.20, 10.6390, 11.00, 11.3600, 11.75, 12.1340, 12.36, 12.5880, 12.74, 12.8790, 13.07, 13.2560, 13.38, 13.5220, 13.41, 13.3070, 13.35, 13.3990, 13.37, 13.3420, 13.39, 13.4220, 13.65, 13.2710, 13.25, 13.2330, 13.12, 13.0110, 12.93, 12.8470, 12.805, 12.7630, 12.66, 12.5760, 12.563, 12.5490, @@ -1025,7 +1025,7 @@ void ColorTemp::cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, dou } -void ColorTemp::temp2mulxyz (double tem, double gree, std::string method , double &Xxyz, double &Zxyz) +void ColorTemp::temp2mulxyz (double tem, double gree, const std::string &method, double &Xxyz, double &Zxyz) { double xD, yD, x_D, y_D, interm; double x, y, z; @@ -1100,7 +1100,7 @@ void ColorTemp::temp2mulxyz (double tem, double gree, std::string method , doubl x_D = -4.6070e9 / (tem * tem * tem) + 2.9678e6 / (tem * tem) + 0.09911e3 / tem + 0.244063; } else if (tem <= 25000) { x_D = -2.0064e9 / (tem * tem * tem) + 1.9018e6 / (tem * tem) + 0.24748e3 / tem + 0.237040; - } else if (tem > 25000) { + } else /*if (tem > 25000)*/ { x_D = -2.0064e9 / (tem * tem * tem) + 1.9018e6 / (tem * tem) + 0.24748e3 / tem + 0.237040 - ((tem - 25000) / 25000) * 0.025; //Jacques empirical adjustemnt for very high temp (underwater !) } @@ -1135,12 +1135,10 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, //printf("temp=%d green=%.3f equal=%.3f\n", (int)temp, (float) green, (float) equal); //variables for CRI and display Lab, and palette - bool CRI_type = false; double xD, yD, x_D, y_D, interm; double m1, m2; - double xp, yp; - double x, y, z, xx, yy, zz; + double x, y, z; double Xchk[50], Ychk[50], Zchk[50]; //50 : I think it's a good limit for number of color : for CRI and Palette double Xcam02[50], Ycam02[50], Zcam02[50]; double Xcam02pal[50], Ycam02pal[50], Zcam02pal[50]; @@ -1148,16 +1146,12 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, double XchkLamp[50], YchkLamp[50], ZchkLamp[50]; double Xcam02Lamp[50], Ycam02Lamp[50], Zcam02Lamp[50]; double Xpal[50], Ypal[50], Zpal[50]; - double tempw; const double epsilon = 0.008856; //Lab const double whiteD50[3] = {0.9646019585, 1.0, 0.8244507152}; //calculate with this tool : spect 5nm double CAM02BB00, CAM02BB01, CAM02BB02, CAM02BB10, CAM02BB11, CAM02BB12, CAM02BB20, CAM02BB21, CAM02BB22; //for CIECAT02 double xr[50], yr[50], zr[50]; double fx[50], fy[50], fz[50]; - double Llamp[50], alamp[50], blamp[50]; - double Lbb[50], abb[50], bbb[50]; - double Lpal[50], apal[50], bpal[50]; int palet = -1; bool palette = false; @@ -1263,7 +1257,7 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, x_D = -4.6070e9 / (temp * temp * temp) + 2.9678e6 / (temp * temp) + 0.09911e3 / temp + 0.244063; } else if (temp <= 25000) { x_D = -2.0064e9 / (temp * temp * temp) + 1.9018e6 / (temp * temp) + 0.24748e3 / temp + 0.237040; - } else if (temp > 25000) { // above 25000 it's unknown..then I have modified to adjust for underwater + } else /*if (temp > 25000)*/ { // above 25000 it's unknown..then I have modified to adjust for underwater x_D = -2.0064e9 / (temp * temp * temp) + 1.9018e6 / (temp * temp) + 0.24748e3 / temp + 0.237040 - ((temp - 25000) / 25000) * 0.025; //Jacques empirical adjustemnt for very high temp (underwater !) } @@ -1291,8 +1285,6 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, double Xwb = xD / yD; double Ywb = 1.0; double Zwb = (1.0 - xD - yD) / yD; - double correl_temp; - if (settings->verbose) { // double u=4*xD/(-2*xD+12*yD+3); @@ -1335,11 +1327,6 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, { double x_x, y_y, z_z; // illuminants - const double* spect_illummax[] = { - Daylight5300_spect, Cloudy6200_spect, Shade7600_spect, A2856_spect, FluoF1_spect, FluoF2_spect, FluoF3_spect, FluoF4_spect, FluoF5_spect, FluoF6_spect, FluoF7_spect, - FluoF8_spect, FluoF9_spect, FluoF10_spect, FluoF11_spect, FluoF12_spect, HMI_spect, GTI_spect, JudgeIII_spect, Solux3500_spect, Solux4100_spect, Solux4700_spect, NG_Solux4700_spect, NG_CRSSP12WWMR16_spect, NG_CRSSP12WWMR16_spect, - Flash5500_spect, Flash6000_spect, Flash6500_spect - }; // color const double* spec_colorpalet[] = { ColabSkin98_m2_10_spect, ColabSkin95_0_4_spect, ColabSkin91_4_14_spect, ColabSkin90_m1_20_spect, @@ -1359,13 +1346,18 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, int N_col = sizeof(spec_colorpalet) / sizeof(spec_colorpalet[0]); //number of color if(palet < 28) { + const double* spect_illummax[] = { + Daylight5300_spect, Cloudy6200_spect, Shade7600_spect, A2856_spect, FluoF1_spect, FluoF2_spect, FluoF3_spect, FluoF4_spect, FluoF5_spect, FluoF6_spect, FluoF7_spect, + FluoF8_spect, FluoF9_spect, FluoF10_spect, FluoF11_spect, FluoF12_spect, HMI_spect, GTI_spect, JudgeIII_spect, Solux3500_spect, Solux4100_spect, Solux4700_spect, NG_Solux4700_spect, NG_CRSSP12WWMR16_spect, NG_CRSSP12WWMR16_spect, + Flash5500_spect, Flash6000_spect, Flash6500_spect + }; for(int i = 0; i < N_col; i++) { spectrum_to_color_xyz_preset(spec_colorpalet[i], spect_illummax[palet], x_x, y_y, z_z); Xpal[i] = x_x; Ypal[i] = y_y; Zpal[i] = z_z; } - } else if(palet >= 28) { + } else /*if(palet >= 28)*/ { if(temp < INITIALBLACKBODY) { for(int i = 0; i < N_col; i++) { spectrum_to_color_xyz_blackbody(spec_colorpalet[i], temp, x_x, y_y, z_z); @@ -1387,8 +1379,8 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, } } - xp = xD; - yp = yD; + double xp = xD; + double yp = yD; double Xwbpal = xp / yp; //white balance double Ywbpal = 1.0; double Zwbpal = (1.0 - xp - yp) / yp; @@ -1433,6 +1425,8 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, //Lab values in function of color and illuminant //these values can be compared to preview values when using white-balance (skin / sky / BW) + double Lpal[50], apal[50], bpal[50]; + for(int i = 0; i < N_col; i++) { Lpal[i] = 116.0 * fy[i] - 16.0; apal[i] = 500.0 * (fx[i] - fy[i]); @@ -1464,12 +1458,6 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, int numero_color = settings->CRI_color - 1; //spectral data illuminant (actually 21): only those necessary (lamp, fluorescent, LED) others CRI=100 (not Flash...) - const double* spect_illum[] = { - Daylight5300_spect, Cloudy6200_spect, Shade7600_spect, A2856_spect, FluoF1_spect, FluoF2_spect, FluoF3_spect, - FluoF4_spect, FluoF5_spect, FluoF6_spect, FluoF7_spect, FluoF8_spect, FluoF9_spect, FluoF10_spect, FluoF11_spect, - FluoF12_spect, HMI_spect, GTI_spect, JudgeIII_spect, Solux3500_spect, Solux4100_spect, Solux4700_spect, - NG_Solux4700_spect, NG_CRSSP12WWMR16_spect, NG_CRSSP12WWMR16_spect - }; const double* spec_color[] = { ColorchechredC3_spect, ColorchechOraA2_spect, ColorchechYelD3_spect, ColorchechGreE2_spect, ColorchechGreB3_spect, ColorchechCyaF3_spect, ColorchechPurD2_spect, ColorchechMagE3_spect, ColorchechSkiA138_13_14_spect, ColorchechGraC4_67_spect, @@ -1480,6 +1468,9 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, int N_c = sizeof(spec_color) / sizeof(spec_color[0]); //number of color + bool CRI_type = false; + double tempw; + if (method == "Fluo F1") { CRI_type = true; tempw = 6430; @@ -1569,25 +1560,26 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, } if (CRI_type) { + const double* spect_illum[] = { + Daylight5300_spect, Cloudy6200_spect, Shade7600_spect, A2856_spect, FluoF1_spect, FluoF2_spect, FluoF3_spect, + FluoF4_spect, FluoF5_spect, FluoF6_spect, FluoF7_spect, FluoF8_spect, FluoF9_spect, FluoF10_spect, FluoF11_spect, + FluoF12_spect, HMI_spect, GTI_spect, JudgeIII_spect, Solux3500_spect, Solux4100_spect, Solux4700_spect, + NG_Solux4700_spect, NG_CRSSP12WWMR16_spect, NG_CRSSP12WWMR16_spect + }; + float DeltaE[50], DeltaEs[8]; float quadCRI = 0.0f, quadCRIs = 0.0f; float CRI_RT = 0.0, CRI[50]; float CRI_RTs = 0.0, CRIs[8]; for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], xx, yy, zz); - XchkLamp[i] = xx; - YchkLamp[i] = yy; - ZchkLamp[i] = zz; + spectrum_to_color_xyz_preset(spec_color[i], spect_illum[illum + 3], XchkLamp[i], YchkLamp[i], ZchkLamp[i]); } //calculate XYZ for each color : for Blackbody and Daylight at tempw if(tempw <= INITIALBLACKBODY) { for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_blackbody(spec_color[i], tempw, xx, yy, zz); - Xchk[i] = xx; - Ychk[i] = yy; - Zchk[i] = zz; + spectrum_to_color_xyz_blackbody(spec_color[i], tempw, Xchk[i], Ychk[i], Zchk[i]); } spectrum_to_xyz_blackbody(tempw, x, y, z);//for white point @@ -1608,18 +1600,15 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, m22 = (0.03 - 31.4424 * x_DD + 30.0717 * y_DD) / interm2; for(int i = 0; i < N_c; i++) { - spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, xx, yy, zz); - Xchk[i] = xx; - Ychk[i] = yy; - Zchk[i] = zz; + spectrum_to_color_xyz_daylight(spec_color[i], m11, m22, Xchk[i], Ychk[i], Zchk[i]); } spectrum_to_xyz_daylight(m11, m22, x, y, z); } - XYZtoCorColorTemp(Xwb, Ywb, Zwb, correl_temp); - if (settings->verbose) { + double correl_temp; + XYZtoCorColorTemp(Xwb, Ywb, Zwb, correl_temp); printf("Correlated temperature (lamp)=%i\n", (int) correl_temp); //use only for lamp...otherwise It give an information!! } @@ -1680,6 +1669,7 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, } } + double Llamp[50], alamp[50], blamp[50]; for(int i = 0; i < N_c; i++) { Llamp[i] = 116.0 * fy[i] - 16.0; alamp[i] = 500.0 * (fx[i] - fy[i]); @@ -1712,6 +1702,8 @@ void ColorTemp::temp2mul (double temp, double green, double equal, double& rmul, } } + double Lbb[50], abb[50], bbb[50]; + for(int i = 0; i < N_c; i++) { Lbb[i] = 116.*fy[i] - 16.; abb[i] = 500.*(fx[i] - fy[i]); @@ -1797,7 +1789,7 @@ The next 3 methods are inspired from: this values are often called xBar yBar zBar and are characteristics of a color / illuminant -values cie_colour_match[][3] = Observer 2 degree Standard Observer x2, y2, z2 +values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2 E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above I have increase precision used by J.Walker and pass to 350nm to 830nm */ @@ -1855,7 +1847,7 @@ void ColorTemp::spectrum_to_xyz_preset(const double* spec_intens, double &x, dou this values are often called xBar yBar zBar and are characteristics of a color / illuminant - values cie_colour_match[][3] = 2 degree Standard Observer x2, y2, z2 + values cie_colour_match[][3] = 2° Standard Observer x2, y2, z2 E.g. for 380nm: x2=0.001368 y2=0.000039 z2=0.006451 round in J.Walker to 0.0014 0.0000 0.0065 above I have increased the precision used by J.Walker and pass from 350nm to 830nm */ diff --git a/rtengine/colortemp.h b/rtengine/colortemp.h index a1a805092..33a2b1b04 100644 --- a/rtengine/colortemp.h +++ b/rtengine/colortemp.h @@ -53,7 +53,7 @@ private: public: ColorTemp () : temp(-1.), green(-1.), equal (1.), method("Custom") {} - ColorTemp (double e) : temp(-1.), green(-1.), equal (e), method("Custom") {} + explicit ColorTemp (double e) : temp(-1.), green(-1.), equal (e), method("Custom") {} ColorTemp (double t, double g, double e, const Glib::ustring &m); ColorTemp (double mulr, double mulg, double mulb, double e); @@ -92,7 +92,7 @@ public: } void mul2temp (const double rmul, const double gmul, const double bmul, const double equal, double& temp, double& green) const; - static void temp2mulxyz (double tem, double gree, std::string method, double &Xxyz, double &Zxyz); + static void temp2mulxyz (double tem, double gree, const std::string &method, double &Xxyz, double &Zxyz); static void cieCAT02(double Xw, double Yw, double Zw, double &CAM02BB00, double &CAM02BB01, double &CAM02BB02, double &CAM02BB10, double &CAM02BB11, double &CAM02BB12, double &CAM02BB20, double &CAM02BB21, double &CAM02BB22, double adap ); //static void CAT02 (Imagefloat* baseImg, const ProcParams* params); diff --git a/rtengine/coord.h b/rtengine/coord.h index 2242cec1e..2f1325434 100644 --- a/rtengine/coord.h +++ b/rtengine/coord.h @@ -35,7 +35,7 @@ struct Coord Coord () = default; Coord (const int x, const int y); Coord (const Coord& other) = default; - Coord (const PolarCoord& other); + explicit Coord (const PolarCoord& other); Coord& operator= (const Coord& other) = default; Coord& operator= (const PolarCoord& other); @@ -48,7 +48,10 @@ struct Coord Coord& operator+= (const Coord& other); Coord& operator-= (const Coord& other); Coord& operator*= (const double scale); - + bool operator< (const Coord& rhs) const; + bool operator> (const Coord& rhs) const; + bool operator<=(const Coord& rhs) const; + bool operator>=(const Coord& rhs) const; }; bool operator== (const Coord& lhs, const Coord& rhs); @@ -66,7 +69,7 @@ struct PolarCoord PolarCoord () = default; PolarCoord (const double radius, const double angle); PolarCoord (const PolarCoord& other) = default; - PolarCoord (const Coord& other); + explicit PolarCoord (const Coord& other); PolarCoord& operator= (const PolarCoord& other) = default; PolarCoord& operator= (const Coord& other); @@ -130,6 +133,26 @@ inline Coord& Coord::operator*= (const double scale) return *this; } +inline bool Coord::operator< (const Coord& rhs) const +{ + return x < rhs.x && y < rhs.y; +} + +inline bool Coord::operator> (const Coord& rhs) const +{ + return x > rhs.x && y > rhs.y; +} + +inline bool Coord::operator<=(const Coord& rhs) const +{ + return x <= rhs.x && y <= rhs.y; +} + +inline bool Coord::operator>=(const Coord& rhs) const +{ + return x >= rhs.x && y >= rhs.y; +} + inline bool operator== (const Coord& lhs, const Coord& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; diff --git a/rtengine/cplx_wavelet_dec.h b/rtengine/cplx_wavelet_dec.h index 0ab01be57..bc8b7bdd3 100644 --- a/rtengine/cplx_wavelet_dec.h +++ b/rtengine/cplx_wavelet_dec.h @@ -22,15 +22,17 @@ #define CPLX_WAVELET_DEC_H_INCLUDED #include -#include +#include #include "cplx_wavelet_level.h" #include "cplx_wavelet_filter_coeffs.h" +#include "noncopyable.h" namespace rtengine { -class wavelet_decomposition +class wavelet_decomposition : + public NonCopyable { public: diff --git a/rtengine/dcp.h b/rtengine/dcp.h index 11e368b80..8b781ce6b 100644 --- a/rtengine/dcp.h +++ b/rtengine/dcp.h @@ -26,11 +26,12 @@ #include +#include "../rtgui/threadutils.h" + #include "imagefloat.h" #include "curves.h" #include "colortemp.h" - -#include "../rtgui/threadutils.h" +#include "noncopyable.h" namespace rtengine { @@ -63,7 +64,7 @@ public: using Triple = std::array; using Matrix = std::array; - DCPProfile(const Glib::ustring& filename); + explicit DCPProfile(const Glib::ustring& filename); ~DCPProfile(); explicit operator bool() const; @@ -145,14 +146,12 @@ private: AdobeToneCurve tone_curve; }; -class DCPStore final +class DCPStore final : + public NonCopyable { public: static DCPStore* getInstance(); - DCPStore(const DCPStore& other) = delete; - DCPStore& operator =(const DCPStore& other) = delete; - void init(const Glib::ustring& rt_profile_dir); bool isValidDCPFileName(const Glib::ustring& filename) const; diff --git a/rtengine/dcrop.cc b/rtengine/dcrop.cc index 7f48bc5d2..9906ea103 100644 --- a/rtengine/dcrop.cc +++ b/rtengine/dcrop.cc @@ -33,7 +33,7 @@ extern const Settings* settings; Crop::Crop (ImProcCoordinator* parent, EditDataProvider *editDataProvider, bool isDetailWindow) : PipetteBuffer(editDataProvider), origCrop(NULL), laboCrop(NULL), labnCrop(NULL), cropImg(NULL), cbuf_real(NULL), cshmap(NULL), transCrop(NULL), cieCrop(NULL), cbuffer(NULL), - updating(false), newUpdatePending(false), skip(10), + updating(false), newUpdatePending(false), skip(10), padding(0), cropx(0), cropy(0), cropw(-1), croph(-1), trafx(0), trafy(0), trafw(-1), trafh(-1), rqcropx(0), rqcropy(0), rqcropw(-1), rqcroph(-1), @@ -321,7 +321,7 @@ void Crop::update (int todo) float maxr = 0.f; float maxb = 0.f; - float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; int Nb; chaut = 0.f; @@ -334,7 +334,7 @@ void Crop::update (int todo) LUTf gamcurve(65536, 0); float gam, gamthresh, gamslope; parent->ipf.RGB_denoise_infoGamCurve(params.dirpyrDenoise, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope); - parent->ipf.RGB_denoise_info(origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true); + parent->ipf.RGB_denoise_info(origCrop, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc, true); // printf("redy=%f skin=%f pcskin=%f\n",redyel, skinc,nsknc); // printf("DCROP skip=%d cha=%4.0f Nb=%d red=%4.0f bl=%4.0f redM=%4.0f bluM=%4.0f L=%4.0f sigL=%4.0f Ch=%4.0f Si=%4.0f\n",skip, chaut,Nb, redaut,blueaut, maxredaut, maxblueaut, lumema, sigma_L, chromina, sigma); float multip = 1.f; @@ -453,9 +453,9 @@ void Crop::update (int todo) parent->imgsrc->convertColorSpace(provicalc, params.icm, parent->currWB);//for denoise luminance curve float pondcorrec = 1.0f; - float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, nresi = 0.f, highresi = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; + float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; int nb = 0; - parent->ipf.RGB_denoise_info(origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + parent->ipf.RGB_denoise_info(origCropPart, provicalc, parent->imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, parent->imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); //printf("DCROP skip=%d cha=%f red=%f bl=%f redM=%f bluM=%f chrom=%f sigm=%f lum=%f\n",skip, chaut,redaut,blueaut, maxredaut, maxblueaut, chromina, sigma, lumema); Nb[hcr * 3 + wcr] = nb; diff --git a/rtengine/dirpyrLab_equalizer.cc b/rtengine/dirpyrLab_equalizer.cc deleted file mode 100644 index fc5fc70a0..000000000 --- a/rtengine/dirpyrLab_equalizer.cc +++ /dev/null @@ -1,521 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - * - * (C) 2010 Emil Martinec - * - */ - -#include -#include -#include "curves.h" -#include "labimage.h" -#include "improcfun.h" -#include "rawimagesource.h" -#include "rt_math.h" - -#ifdef _OPENMP -#include -#endif - -#define CLIPC(a) ((a)>-32000?((a)<32000?(a):32000):-32000) - -#define DIRWT(i1,j1,i,j) (rangefn[abs((int)data_fine->L[i1][j1]-data_fine->L[i][j])+abs((int)data_fine->a[i1][j1]-data_fine->a[i][j])+abs((int)data_fine->b[i1][j1]-data_fine->b[i][j])] ) - -namespace rtengine -{ - -static const int maxlevel = 4; - -//sequence of scales -static const int scales[8] = {1, 2, 4, 8, 16, 32, 64, 128}; -//sequence of pitches -static const int pitches[8] = {1, 1, 1, 1, 1, 1, 1, 1}; - -//sequence of scales -//static const int scales[8] = {1,1,1,1,1,1,1,1}; -//sequence of pitches -//static const int pitches[8] = {2,2,2,2,2,2,2,2}; - -//sequence of scales -//static const int scales[8] = {1,3,6,10,15,21,28,36}; -//sequence of pitches -//static const int pitches[8] = {1,1,1,1,1,1,1,1}; - -//sequence of scales -//static const int scales[8] = {1,1,2,4,8,16,32,64}; -//sequence of pitches -//static const int pitches[8] = {2,1,1,1,1,1,1,1}; - -//pitch is spacing of subsampling -//scale is spacing of directional averaging weights -//example 1: no subsampling at any level -- pitch=1, scale=2^n -//example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level -//example 3: no subsampling at first level, subsampling by 2 thereafter -- -// pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - - -void ImProcFunctions :: dirpyrLab_equalizer(LabImage * src, LabImage * dst, /*float luma, float chroma, float gamma*/ const double * mult ) -{ - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - LUTf rangefn(0x20000); - - - //set up weights - float noise = 1500; - - - //set up range functions - - for (int i = 0; i < 0x20000; i++) { - rangefn[i] = (int)((noise / ((double)i + noise))); - } - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - int level; - int ** buffer[3]; - - - LabImage * dirpyrLablo[maxlevel]; - - int w = src->W; - int h = src->H; - - buffer[0] = allocArray (w + 128, h + 128); - buffer[1] = allocArray (w + 128, h + 128); - buffer[2] = allocArray (w + 128, h + 128); - - for (int i = 0; i < h + 128; i++) - for (int j = 0; j < w + 128; j++) { - for (int c = 0; c < 3; c++) { - buffer[c][i][j] = 0; - } - } - - w = (int)((w - 1) / pitches[0]) + 1; - h = (int)((h - 1) / pitches[0]) + 1; - - dirpyrLablo[0] = new LabImage(w, h); - - for (level = 1; level < maxlevel; level++) { - w = (int)((w - 1) / pitches[level]) + 1; - h = (int)((h - 1) / pitches[level]) + 1; - dirpyrLablo[level] = new LabImage(w, h); - }; - - ////////////////////////////////////////////////////////////////////////////// - - - // c[0] = luma = noise_L - // c[1] = chroma = noise_ab - // c[2] decrease of noise var with scale - // c[3] radius of domain blur at each level - // c[4] shadow smoothing - // c[5] edge preservation - - level = 0; - - int scale = scales[level]; - - int pitch = pitches[level]; - - //int thresh = 10 * c[8]; - //impulse_nr (src, src, m_w1, m_h1, thresh, noisevar); - - dirpyr_eq(src, dirpyrLablo[0], rangefn, 0, pitch, scale, mult ); - - level = 1; - - int totalpitch = pitches[0]; - - while(level < maxlevel) { - scale = scales[level]; - pitch = pitches[level]; - - dirpyr_eq(dirpyrLablo[level - 1], dirpyrLablo[level], rangefn, level, pitch, scale, mult ); - - level ++; - totalpitch *= pitch; - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //initiate buffer for final image - for(int i = 0, i1 = 0; i < src->H; i += totalpitch, i1++) - for(int j = 0, j1 = 0; j < src->W; j += totalpitch, j1++) { - - //copy pixels - buffer[0][i][j] = dirpyrLablo[maxlevel - 1]->L[i1][j1]; - buffer[1][i][j] = dirpyrLablo[maxlevel - 1]->a[i1][j1]; - buffer[2][i][j] = dirpyrLablo[maxlevel - 1]->b[i1][j1]; - - } - - //if we are not subsampling, this is lots faster but does the typecasting work??? - //memcpy(buffer[0],dirpyrLablo[maxlevel-1]->L,sizeof(buffer[0])); - //memcpy(buffer[1],dirpyrLablo[maxlevel-1]->a,sizeof(buffer[1])); - //memcpy(buffer[2],dirpyrLablo[maxlevel-1]->b,sizeof(buffer[2])); - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - for(int level = maxlevel - 1; level > 0; level--) { - - //int scale = scales[level]; - int pitch = pitches[level]; - - totalpitch /= pitch; - - idirpyr_eq(dirpyrLablo[level], dirpyrLablo[level - 1], buffer, level, pitch, totalpitch, mult ); - - } - - - scale = scales[0]; - pitch = pitches[0]; - totalpitch /= pitch; - - idirpyr_eq(dirpyrLablo[0], dst, buffer, 0, pitch, totalpitch, mult ); - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for (int i = 0; i < dst->H; i++) - for (int j = 0; j < dst->W; j++) { - - // TODO: Is integer cast necessary here? - dst->L[i][j] = CLIP((int)( buffer[0][i][j] )); - dst->a[i][j] = CLIPC((int)( buffer[1][i][j] )); - dst->b[i][j] = CLIPC((int)( buffer[2][i][j] )); - - } - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - for(int i = 0; i < maxlevel; i++) { - delete dirpyrLablo[i]; - } - - for (int c = 0; c < 3; c++) { - freeArray(buffer[c], h + 128); - } - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -} - -void ImProcFunctions::dirpyr_eq(LabImage* data_fine, LabImage* data_coarse, LUTf & rangefn, int level, int pitch, int scale, const double * mult ) -{ - - //pitch is spacing of subsampling - //scale is spacing of directional averaging weights - //example 1: no subsampling at any level -- pitch=1, scale=2^n - //example 2: subsampling by 2 every level -- pitch=2, scale=1 at each level - //example 3: no subsampling at first level, subsampling by 2 thereafter -- - // pitch =1, scale=1 at first level; pitch=2, scale=2 thereafter - - - //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // calculate weights, compute directionally weighted average - - int width = data_fine->W; - int height = data_fine->H; - - - - //generate domain kernel - int halfwin = 1;//min(ceil(2*sig),3); - int scalewin = halfwin * scale; - - -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(int i = 0; i < height; i += pitch) { - int i1 = i / pitch; - - for(int j = 0, j1 = 0; j < width; j += pitch, j1++) { - float Lout, aout, bout; - float norm; - norm = 0;//if we do want to include the input pixel in the sum - Lout = 0; - aout = 0; - bout = 0; - - for(int inbr = max(0, i - scalewin); inbr <= min(height - 1, i + scalewin); inbr += scale) { - for (int jnbr = max(0, j - scalewin); jnbr <= min(width - 1, j + scalewin); jnbr += scale) { - float dirwt = DIRWT(inbr, jnbr, i, j); - Lout += dirwt * data_fine->L[inbr][jnbr]; - aout += dirwt * data_fine->a[inbr][jnbr]; - bout += dirwt * data_fine->b[inbr][jnbr]; - norm += dirwt; - } - } - - data_coarse->L[i1][j1] = Lout / norm; //low pass filter - data_coarse->a[i1][j1] = aout / norm; - data_coarse->b[i1][j1] = bout / norm; - } - } - - - - -} - -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -void ImProcFunctions::idirpyr_eq(LabImage* data_coarse, LabImage* data_fine, int *** buffer, int level, int pitch, int scale, const double * mult ) -{ - - int width = data_fine->W; - int height = data_fine->H; - - float lumamult[4], chromamult[4]; - - for (int i = 0; i < 4; i++) { - lumamult[i] = mult[i]; - chromamult[i] = mult[i + 4]; - } - - float wtdsum[6], norm, dirwt; - float hipass[3]; - int i1, j1; - - - // for coarsest level, take non-subsampled lopass image and subtract from lopass_fine to generate hipass image - - // denoise hipass image, add back into lopass_fine to generate denoised image at fine scale - - // now iterate: - // (1) take denoised image at level n, expand and smooth using gradient weights from lopass image at level n-1 - // the result is the smoothed image at level n-1 - // (2) subtract smoothed image at level n-1 from lopass image at level n-1 to make hipass image at level n-1 - // (3) denoise the hipass image at level n-1 - // (4) add the denoised image at level n-1 to the smoothed image at level n-1 to make the denoised image at level n-1 - - // note that the coarsest level amounts to skipping step (1) and doing (2,3,4). - // in other words, skip step one if pitch=1 - - - - if (pitch == 1) { - // step (1-2-3-4) -#ifdef _OPENMP - #pragma omp parallel for -#endif - - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - //luma - float hipass0 = (float)data_fine->L[i][j] - data_coarse->L[i][j]; - buffer[0][i * scale][j * scale] += hipass0 * lumamult[level]; //*luma; - - //chroma - float hipass1 = data_fine->a[i][j] - data_coarse->a[i][j]; - float hipass2 = data_fine->b[i][j] - data_coarse->b[i][j]; - buffer[1][i * scale][j * scale] += hipass1 * chromamult[level]; //*chroma; - buffer[2][i * scale][j * scale] += hipass2 * chromamult[level]; //*chroma; - } - - } else { - - // step (1) - //if (pitch>1), pitch=2; expand coarse image, fill in missing data - - LabImage* smooth; - smooth = new LabImage(width, height); -#ifdef _OPENMP - #pragma omp parallel -#endif - - { -#ifdef _OPENMP - #pragma omp for -#endif - - for(int i = 0; i < height; i += pitch) { - int i2 = i / pitch; - - for(int j = 0, j2 = 0; j < width; j += pitch, j2++) { - - //copy common pixels - smooth->L[i][j] = data_coarse->L[i2][j2]; - smooth->a[i][j] = data_coarse->a[i2][j2]; - smooth->b[i][j] = data_coarse->b[i2][j2]; - } - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for(int i = 0; i < height - 1; i += 2) - for(int j = 0; j < width - 1; j += 2) { - //do midpoint first - norm = dirwt = 0; - wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; - - for(i1 = i; i1 < min(height, i + 3); i1 += 2) - for (j1 = j; j1 < min(width, j + 3); j1 += 2) { - dirwt = 1;//IDIRWT(i1, j1, i, j); - wtdsum[0] += dirwt * smooth->L[i1][j1]; - wtdsum[1] += dirwt * smooth->a[i1][j1]; - wtdsum[2] += dirwt * smooth->b[i1][j1]; - wtdsum[3] += dirwt * buffer[0][i1 * scale][j1 * scale]; // not completely right if j1*scale or i1*scale is out of bounds of original image ??? - wtdsum[4] += dirwt * buffer[1][i1 * scale][j1 * scale]; // also should we use directional average? - wtdsum[5] += dirwt * buffer[2][i1 * scale][j1 * scale]; - norm += dirwt; - } - - norm = 1 / norm; - smooth->L[i + 1][j + 1] = wtdsum[0] * norm; - smooth->a[i + 1][j + 1] = wtdsum[1] * norm; - smooth->b[i + 1][j + 1] = wtdsum[2] * norm; - buffer[0][(i + 1)*scale][(j + 1)*scale] = wtdsum[3] * norm; - buffer[1][(i + 1)*scale][(j + 1)*scale] = wtdsum[4] * norm; - buffer[2][(i + 1)*scale][(j + 1)*scale] = wtdsum[5] * norm; - } - -#ifdef _OPENMP - #pragma omp for -#endif - - for(int i = 0; i < height - 1; i += 2) - for(int j = 0; j < width - 1; j += 2) { - //now right neighbor - if (j + 1 == width) { - continue; - } - - norm = dirwt = 0; - wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; - - for (j1 = j; j1 < min(width, j + 3); j1 += 2) { - dirwt = 1;//IDIRWT(i, j1, i, j); - wtdsum[0] += dirwt * smooth->L[i][j1]; - wtdsum[1] += dirwt * smooth->a[i][j1]; - wtdsum[2] += dirwt * smooth->b[i][j1]; - wtdsum[3] += dirwt * buffer[0][i * scale][j1 * scale]; - wtdsum[4] += dirwt * buffer[1][i * scale][j1 * scale]; - wtdsum[5] += dirwt * buffer[2][i * scale][j1 * scale]; - norm += dirwt; - } - - for (i1 = max(0, i - 1); i1 < min(height, i + 2); i1 += 2) { - dirwt = 1;//IDIRWT(i1, j+1, i, j); - wtdsum[0] += dirwt * smooth->L[i1][j + 1]; - wtdsum[1] += dirwt * smooth->a[i1][j + 1]; - wtdsum[2] += dirwt * smooth->b[i1][j + 1]; - wtdsum[3] += dirwt * buffer[0][i1 * scale][(j + 1) * scale]; - wtdsum[4] += dirwt * buffer[1][i1 * scale][(j + 1) * scale]; - wtdsum[5] += dirwt * buffer[2][i1 * scale][(j + 1) * scale]; - norm += dirwt; - } - - norm = 1 / norm; - smooth->L[i][j + 1] = wtdsum[0] * norm; - smooth->a[i][j + 1] = wtdsum[1] * norm; - smooth->b[i][j + 1] = wtdsum[2] * norm; - buffer[0][i][(j + 1)*scale] = wtdsum[3] * norm; - buffer[1][i][(j + 1)*scale] = wtdsum[4] * norm; - buffer[2][i][(j + 1)*scale] = wtdsum[5] * norm; - - //now down neighbor - if (i + 1 == height) { - continue; - } - - norm = 0; - wtdsum[0] = wtdsum[1] = wtdsum[2] = wtdsum[3] = wtdsum[4] = wtdsum[5] = 0.0; - - for (i1 = i; i1 < min(height, i + 3); i1 += 2) { - dirwt = 1;//IDIRWT(i1, j, i, j); - wtdsum[0] += dirwt * smooth->L[i1][j]; - wtdsum[1] += dirwt * smooth->a[i1][j]; - wtdsum[2] += dirwt * smooth->b[i1][j]; - wtdsum[3] += dirwt * buffer[0][i1 * scale][j * scale]; - wtdsum[4] += dirwt * buffer[1][i1 * scale][j * scale]; - wtdsum[5] += dirwt * buffer[2][i1 * scale][j * scale]; - norm += dirwt; - } - - for (j1 = max(0, j - 1); j1 < min(width, j + 2); j1 += 2) { - dirwt = 1;//IDIRWT(i+1, j1, i, j); - wtdsum[0] += dirwt * smooth->L[i + 1][j1]; - wtdsum[1] += dirwt * smooth->a[i + 1][j1]; - wtdsum[2] += dirwt * smooth->b[i + 1][j1]; - wtdsum[3] += dirwt * buffer[0][(i + 1) * scale][j1 * scale]; - wtdsum[4] += dirwt * buffer[1][(i + 1) * scale][j1 * scale]; - wtdsum[5] += dirwt * buffer[2][(i + 1) * scale][j1 * scale]; - norm += dirwt; - } - - norm = 1 / norm; - smooth->L[i + 1][j] = wtdsum[0] * norm; - smooth->a[i + 1][j] = wtdsum[1] * norm; - smooth->b[i + 1][j] = wtdsum[2] * norm; - buffer[0][(i + 1)*scale][j * scale] = wtdsum[3] * norm; - buffer[1][(i + 1)*scale][j * scale] = wtdsum[4] * norm; - buffer[2][(i + 1)*scale][j * scale] = wtdsum[5] * norm; - - } - - - // step (2-3-4) -#ifdef _OPENMP - #pragma omp for -#endif - - for(int i = 0; i < height; i++) - for(int j = 0; j < width; j++) { - - //luma - hipass[0] = (float)data_fine->L[i][j] - smooth->L[i][j]; - buffer[0][i * scale][j * scale] += hipass[0] * lumamult[level]; //*luma; - - //chroma - hipass[1] = data_fine->a[i][j] - smooth->a[i][j]; - hipass[2] = data_fine->b[i][j] - smooth->b[i][j]; - buffer[1][i * scale][j * scale] += hipass[1] * chromamult[level]; //*chroma; - buffer[2][i * scale][j * scale] += hipass[2] * chromamult[level]; //*chroma; - } - } // end parallel - delete smooth; - - } -} - - -#undef DIRWT_L -#undef DIRWT_AB - -#undef NRWT_L -#undef NRWT_AB - -} - diff --git a/rtengine/ex2simple.cc b/rtengine/ex2simple.cc deleted file mode 100644 index 1a83526e7..000000000 --- a/rtengine/ex2simple.cc +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include "rtengine.h" -#include -//#include -#include - -class PListener : public rtengine::ProgressListener -{ - -public: - void setProgressStr (Glib::ustring str) - { - std::cout << str << std::endl; - } - void setProgress (double p) - { - std::cout << p << std::endl; - } -}; - -class MyPrevImgListener : public rtengine::PreviewImageListener -{ - - IImage8* i; - -public: - // this method is called when the staged image processor creates a new image to store the resulting preview image (this does not happen too often) - // usually you just have to store it - void setImage (IImage8* img, double scale, procparams::CropParams cp) - { - i = img; - } - // if the staged image processor wants to delete the image that stores the preview image, it calls this method. You have to destroy the image. - void delImage (IImage8* img) - { - if (img) { - // make sure we dont use this image in an other thread - IImage8* temp = i; - i->getMutex().lock (); - i = NULL; - temp->getMutex().unlock (); - // free it - img->free (); - } - } - // if the preview image changes, this method is called - void imageReady (procparams::CropParams cp) - { - // initiate a redraw in the background and return as fast as possible - } - // a possible redraw function: - //void redraw () { - // if (i) { - // i->lock (); - // int w = i->getWidth (); - // int h = i->getHeigt (); - // const char* data = i->getData (); - // ... draw it ... - // i->unlock (); - // } - // } -}; - -int main (int argc, char* argv[]) -{ - - if (argc < 4) { - std::cout << "Usage: rtcmd " << std::endl; - exit(1); - } - - Glib::thread_init (); - - // create and fill settings - rtengine::Settings* s = rtengine::Settings::create (); - s->demosaicMethod = "hphd"; - s->colorCorrectionSteps = 2; - s->iccDirectory = ""; - s->colorimetricIntent = 1; - s->monitorProfile = ""; - // init rtengine - rtengine::init (s); - // the settings can be modified later through the "s" pointer without calling any api function - - // Create a listener object. Any class is appropriate that inherits from rtengine::ProgressListener - PListener pl; - - // Load the image given in the first command line parameter - rtengine::InitialImage* ii; - int errorCode; - ii = rtengine::InitialImage::load (argv[1], true, errorCode, &pl); - - if (!ii) { - ii = rtengine::InitialImage::load (argv[1], false, errorCode, &pl); - } - - if (!ii) { - std::cout << "Input file not supported." << std::endl; - exit(2); - } - - /* Second scenario. Create a stagedimageprocessor with a preview scale of 1:5 and change few things */ - MyPrevImgListener myPrevImgListener; - - StagedImageProcessor* ipc = StagedImageProcessor::create (ii); - ipc->setProgressListener (&pl); - ipc->setPreviewImageListener (&myPrevImgListener); - ipc->setPreviewScale (5); // preview scale = 1:5 - // you can add a histogram listener, too, that is notified when the histogram changes - // ipc->setHistogramListener (...); - // you can add autoexplistener that is notified about the exposure settings when the auto exp algorithm finishes - // ipc->setAutoExpListener (curve); - // you can add sizelistener if you want to be notified when the size of the final image changes (due to rotation/resize/etc) - // ipc->setSizeListener (crop); - - // if you want to change the settings you have to ask for the procparams structure of the staged image processor - // you have to tell it what has changed. At the first time tell it EvPhotoLoaded so a full processing will be performed - rtengine::procparams::ProcParams* params = ipc->beginUpdateParams (); - // change this and that... - params->toneCurve.brightness = 1.0; - // you can load it, too, from a file: params->load (argv[2]); - // finally you have to call this non-blocking method, and the image processing starts in the background. When finished, the preview image listener will be notified - ipc->endUpdateParams (rtengine::EvPhotoLoaded); - // you can go on with changing of the settings, following the gui actions - // now we know that only the brightness has changed compared to the previous settings, to only a part of the processing has to be repeated - params = ipc->beginUpdateParams (); - params->toneCurve.brightness = 1.2; - ipc->endUpdateParams (rtengine::EvBrightness); - - // ... and so on. If you dont need it any more, you can destroy it (make sure that no processing is happening when you destroy it!) - StagedImageProcessor::destroy (ipc); -} - diff --git a/rtengine/hlmultipliers.cc b/rtengine/hlmultipliers.cc deleted file mode 100644 index 35e1d3e87..000000000 --- a/rtengine/hlmultipliers.cc +++ /dev/null @@ -1,441 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include -#include -#include "rawimagesource.h" -#include "rawimagesource_i.h" -#include "jaggedarray.h" -#include "../rtgui/options.h" - -namespace rtengine -{ - -// computes highlight recovery multipliers. Needs a possibly downscaled image where -// the highlights are indicated by INT_MAX -void hlmultipliers (int** rec[3], int max_3[3], int dh, int dw) -{ - - // STEP I. recover color with two-color information - int phase = -1; - int k = 0; - - for (k = 0; k < 1000; k++) { - int changed = 0; - - for (int i = 1; i < dh - 1; i++) - for (int j = 1; j < dw - 1; j++) { - int co, c1, c2; - -// if (phase==2) -// phase++; -// if (phase>0)// && phase!=4) -// continue; - if (phase == -1 || phase == 0 || phase == 2) { - if (rec[0][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { - co = 0; - c1 = 1; - c2 = 2; - } else if (rec[1][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0 && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { - co = 1; - c1 = 0; - c2 = 2; - } else if (rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0 && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0) { - co = 2; - c1 = 1; - c2 = 0; - } else { - continue; - } - - double ratio[2] = {0.0, 0.0}; - int count = 0; - double rato = (double)rec[c1][i][j] / rec[c2][i][j]; - double arato = 0.0; - - if (phase == 2) { - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) { - // average m/c color ratios in the surrounding pixels - if (rec[co][i + x][j + y] >= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { - double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; - - if (ratt > rato * 1.2 || ratt < rato / 1.2 || rec[co][i + x][j + y] < max_3[co] * 1 / 2) { - continue; - } - - ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; - ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; - count++; - } - } - } else if (phase == -1) { - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) { - // average m/c color ratios in the surrounding pixels - if (rec[co][i + x][j + y] >= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { - double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; - - if (ratt > rato * 1.05 || ratt < rato / 1.05 || rec[co][i + x][j + y] < max_3[co] * 4 / 5) { - continue; - } - - arato += ratt; - ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; - ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; - - count++; - } - } - } else { - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) { - // average m/c color ratios in the surrounding pixels - if (rec[co][i + x][j + y] >= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] >= 0 && rec[c1][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { - double ratt = (double)rec[c1][i + x][j + y] / rec[c2][i + x][j + y]; - - if (ratt > rato * 1.1 || ratt < rato / 1.1 || rec[co][i + x][j + y] < max_3[co] * 3 / 4) { - continue; - } - - arato += ratt; - ratio[0] += (double)rec[c1][i + x][j + y] / rec[co][i + x][j + y]; - ratio[1] += (double)rec[c2][i + x][j + y] / rec[co][i + x][j + y]; - - count++; - } - } - } - - // compute new pixel values from the surrounding color ratios - if (count > 1) { //(phase==0 && count>1) || (phase==2 && count>1)) { - rec[co][i][j] = -(int)((rec[c1][i][j] / ratio[0] * count + rec[c2][i][j] / ratio[1] * count) / 2); - changed++; - } - } else if (phase == 1 || phase == 3) { - if (rec[0][i][j] == INT_MAX && rec[1][i][j] == INT_MAX && rec[2][i][j] != INT_MAX && rec[2][i][j] >= 0) { - co = 2; - c1 = 0; - c2 = 1; - } else if (rec[0][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[1][i][j] != INT_MAX && rec[1][i][j] >= 0) { - co = 1; - c1 = 0; - c2 = 2; - } else if (rec[1][i][j] == INT_MAX && rec[2][i][j] == INT_MAX && rec[0][i][j] != INT_MAX && rec[0][i][j] >= 0) { - co = 0; - c1 = 1; - c2 = 2; - } else { - continue; - } - - double ratio[2] = {0.0, 0.0}; - int count[2] = {0, 0}; - - for (int x = -1; x <= 1; x++) - for (int y = -1; y <= 1; y++) { - // average m/c color ratios in the surrounding pixels - if (rec[co][i + x][j + y] >= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c1][i + x][j + y] > 0 && rec[c1][i + x][j + y] != INT_MAX) { - if ((phase == 1 && rec[c1][i + x][j + y] < max_3[c1] * 3 / 4) || (phase == 3 && rec[c1][i + x][j + y] < max_3[c1] * 1 / 2)) { - continue; - } - - ratio[0] += (double)rec[co][i + x][j + y] / rec[c1][i + x][j + y]; - count[0] ++; - } - - if (rec[co][i + x][j + y] >= 0 && rec[co][i + x][j + y] != INT_MAX && rec[c2][i + x][j + y] > 0 && rec[c2][i + x][j + y] != INT_MAX) { - if ((phase == 1 && rec[c2][i + x][j + y] < max_3[c2] * 3 / 4) || (phase == 3 && rec[c2][i + x][j + y] < max_3[c2] * 1 / 2)) -// if (/*phase!=3 && */rec[c2][i+x][j+y] 2) || (phase == 3 && count[0] > 1)) { - rec[c1][i][j] = - (int) ((double)rec[co][i][j] / ratio[0] * count[0]); - changed++; - } - - if ((phase == 1 && count[1] > 2) || (phase == 3 && count[1] > 1)) { - rec[c2][i][j] = - (int) ((double)rec[co][i][j] / ratio[1] * count[1]); - changed++; - } - } else { - int val = 0; - int num = 0; - - for (int c = 0; c < 3; c++) - if (rec[c][i][j] != INT_MAX) { - val += rec[c][i][j]; - num++; - } - - if (num < 3 && num > 0) { - for (int c = 0; c < 3; c++) { - rec[c][i][j] = val / num; - } - } - } - } - - - bool change = false; - - for (int i = 1; i < dh - 1; i++) - for (int j = 1; j < dw - 1; j++) - for (int c = 0; c < 3; c++) { - if (rec[c][i][j] < 0) { - rec[c][i][j] = -rec[c][i][j]; - change = true; - } - } - - if (!change && phase < 4) { - phase++; - - if( options.rtSettings.verbose ) { - printf ("phc %d: %d\n", phase, k); - } - } else if (!change) { - break; - } - - if (k % 20 == 0 && options.rtSettings.verbose ) { - printf ("changed %d\n", changed); - } - } - - if( options.rtSettings.verbose ) { - printf ("Highlight recovery ends in %d iterations\n", k); - } - - int maxval = max(max_3[0], max_3[1], max_3[2]); - - for (int i = 0; i < dh; i++) - for (int j = 0; j < dw; j++) - if (rec[0][i][j] == INT_MAX || rec[1][i][j] == INT_MAX || rec[2][i][j] == INT_MAX) { - rec[0][i][j] = maxval; - rec[1][i][j] = maxval; - rec[2][i][j] = maxval; - - } -} - -void RawImageSource::HLRecovery_ColorPropagation (float* red, float* green, float* blue, int i, int sx1, int width, int skip) -{ - - int blr = (i + HR_SCALE / 2) / HR_SCALE - 1; - - if (blr < 0 || blr >= H / HR_SCALE - 2) { - return; - } - - double mr1 = 1.0 - ((double)((i + HR_SCALE / 2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); - int maxcol = W / HR_SCALE - 2; - - for (int j = sx1, jx = 0; jx < width; j += skip, jx++) { - if (needhr[i][j]) { - int blc = (j + HR_SCALE / 2) / HR_SCALE - 1; - - if (blc < 0 || blc >= maxcol) { - continue; - } - - double mc1 = 1.0 - ((double)((j + HR_SCALE / 2) % HR_SCALE) / HR_SCALE + 0.5 / HR_SCALE); - double mulr = mr1 * mc1 * hrmap[0][blr][blc] + mr1 * (1.0 - mc1) * hrmap[0][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[0][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[0][blr + 1][blc + 1]; - double mulg = mr1 * mc1 * hrmap[1][blr][blc] + mr1 * (1.0 - mc1) * hrmap[1][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[1][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[1][blr + 1][blc + 1]; - double mulb = mr1 * mc1 * hrmap[2][blr][blc] + mr1 * (1.0 - mc1) * hrmap[2][blr][blc + 1] + (1.0 - mr1) * mc1 * hrmap[2][blr + 1][blc] + (1.0 - mr1) * (1.0 - mc1) * hrmap[2][blr + 1][blc + 1]; - red[jx] = (red[jx] * mulr); - green[jx] = (green[jx] * mulg); - blue[jx] = (blue[jx] * mulb); - } else { - red[jx] = (red[jx]); - green[jx] = (green[jx]); - blue[jx] = (blue[jx]); - } - } -} - -void RawImageSource::updateHLRecoveryMap_ColorPropagation () -{ - - // detect maximal pixel values - float* red = new float[W]; - float* blue = new float[W]; - int maxr = 0, maxg = 0, maxb = 0; - - for (int i = 32; i < H - 32; i++) { - interpolate_row_rb (red, blue, green[i - 1], green[i], green[i + 1], i); - - for (int j = 32; j < W - 32; j++) { - if ((ri->ISRED(i, j) || ri->getSensorType() != ST_BAYER) && red[j] > maxr) { - maxr = red[j]; - } - - if ((ri->ISGREEN(i, j) || ri->getSensorType() != ST_BAYER) && green[i][j] > maxg) { - maxg = green[i][j]; - } - - if ((ri->ISBLUE(i, j) || ri->getSensorType() != ST_BAYER) && blue[j] > maxb) { - maxb = blue[j]; - } - } - } - - delete [] red; - delete [] blue; - - maxr = maxr * 19 / 20; - maxg = maxg * 19 / 20; - maxb = maxb * 19 / 20; - max_3[0] = maxr; - max_3[1] = maxg; - max_3[2] = maxb; - - // downscale image - int dw = W / HR_SCALE; - int dh = H / HR_SCALE; - Image16* ds = new Image16 (dw, dh); - - // overburnt areas - int** rec[3]; - - for (int i = 0; i < 3; i++) { - rec[i] = allocJaggedArray (dw, dh); - } - - float* reds[HR_SCALE]; - float* blues[HR_SCALE]; - - for (int i = 0; i < HR_SCALE; i++) { - reds[i] = new float[W]; - blues[i] = new float[W]; - } - - if (needhr) { - freeJaggedArray(needhr); - } - - needhr = allocJaggedArray (W, H); - - for (int i = 0; i < dh; i++) { - for (int j = 0; j < HR_SCALE; j++) { - interpolate_row_rb (reds[j], blues[j], green[HR_SCALE * i + j - 1], green[HR_SCALE * i + j], green[HR_SCALE * i + j + 1], HR_SCALE * i + j); - - for (int k = 0; k < W; k++) - if (reds[j][k] >= max_3[0] || green[HR_SCALE * i + j][k] >= max_3[1] || blues[j][k] >= max_3[2]) { - needhr[HR_SCALE * i + j][k] = 1; - } else { - needhr[HR_SCALE * i + j][k] = 0; - } - } - - for (int j = 0; j < dw; j++) { - int sumr = 0; - int cr = 0; - int sumg = 0; - int cg = 0; - int sumb = 0; - int cb = 0; - - for (int x = 0; x < HR_SCALE; x++) - for (int y = 0; y < HR_SCALE; y++) { - int ix = HR_SCALE * i + x; - int jy = HR_SCALE * j + y; - sumr += reds[x][jy]; - - if (reds[x][jy] < maxr) { - cr++; - } - - sumg += green[ix][jy]; - - if (green[ix][jy] < maxg) { - cg++; - } - - sumb += blues[x][jy]; - - if (blues[x][jy] < maxb) { - cb++; - } - } - - if (cr < HR_SCALE * HR_SCALE) { - rec[0][i][j] = INT_MAX; - } else { - rec[0][i][j] = sumr / HR_SCALE / HR_SCALE; - } - - if (cg < HR_SCALE * HR_SCALE) { - rec[1][i][j] = INT_MAX; - } else { - rec[1][i][j] = sumg / HR_SCALE / HR_SCALE; - } - - if (cb < HR_SCALE * HR_SCALE) { - rec[2][i][j] = INT_MAX; - } else { - rec[2][i][j] = sumb / HR_SCALE / HR_SCALE; - } - - ds->r(i, j) = sumr / HR_SCALE / HR_SCALE; - ds->g(i, j) = sumg / HR_SCALE / HR_SCALE; - ds->b(i, j) = sumb / HR_SCALE / HR_SCALE; - } - } - - for (int i = 0; i < HR_SCALE; i++) { - delete [] reds[i]; - delete [] blues[i]; - } - - hlmultipliers (rec, max_3, dh, dw); - - if (hrmap[0] != NULL) { - freeJaggedArray (hrmap[0]); - freeJaggedArray (hrmap[1]); - freeJaggedArray (hrmap[2]); - } - - hrmap[0] = allocJaggedArray (dw, dh); - hrmap[1] = allocJaggedArray (dw, dh); - hrmap[2] = allocJaggedArray (dw, dh); - - for (int i = 0; i < dh; i++) - for (int j = 0; j < dw; j++) { - hrmap[0][i][j] = ds->r(i, j) > 0 ? (double)rec[0][i][j] / ds->r(i, j) : 1.0; - hrmap[1][i][j] = ds->g(i, j) > 0 ? (double)rec[1][i][j] / ds->g(i, j) : 1.0; - hrmap[2][i][j] = ds->b(i, j) > 0 ? (double)rec[2][i][j] / ds->b(i, j) : 1.0; - } - - delete ds; - - freeJaggedArray (rec[0]); - freeJaggedArray (rec[1]); - freeJaggedArray (rec[2]); -} - -} - diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 0c49a7e4c..bb9693f1a 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -46,8 +46,8 @@ public: ProfileContent (const ProfileContent& other); ProfileContent& operator= (const rtengine::ProfileContent& other); - ProfileContent (const Glib::ustring& fileName); - ProfileContent (cmsHPROFILE hProfile); + explicit ProfileContent (const Glib::ustring& fileName); + explicit ProfileContent (cmsHPROFILE hProfile); cmsHPROFILE toProfile () const; }; diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 5795ed32b..c8d58614c 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -6394,7 +6394,7 @@ void ImProcFunctions::EPDToneMapCIE(CieImage *ncie, float a_w, float c_, float w Qpro = maxQ; } - EdgePreservingDecomposition epd = EdgePreservingDecomposition(Wid, Hei); + EdgePreservingDecomposition epd(Wid, Hei); #pragma omp parallel for @@ -6498,7 +6498,7 @@ void ImProcFunctions::EPDToneMap(LabImage *lab, unsigned int Iterates, int skip) float *a = lab->a[0]; float *b = lab->b[0]; unsigned int i, N = lab->W * lab->H; - EdgePreservingDecomposition epd = EdgePreservingDecomposition(lab->W, lab->H); + EdgePreservingDecomposition epd(lab->W, lab->H); //Due to the taking of logarithms, L must be nonnegative. Further, scale to 0 to 1 using nominal range of L, 0 to 15 bit. float minL = FLT_MAX; diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h index 04b234cbd..3324d849b 100644 --- a/rtengine/improcfun.h +++ b/rtengine/improcfun.h @@ -321,7 +321,7 @@ public: void Median_Denoise( float **src, float **dst, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = NULL); void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve , const NoiseCurve & noiseCCurve , float &chaut, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &nresi, float &highresi); void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope); - void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &nresi, float &highresi, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); + void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false); void RGBtile_denoise (float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer ); //for DCT void RGBoutput_tile_row (float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top ); bool WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge); diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc index d79ec9b5b..312592b39 100644 --- a/rtengine/ipwavelet.cc +++ b/rtengine/ipwavelet.cc @@ -103,7 +103,6 @@ struct cont_params { int backm; float eddet; float eddetthr; - bool lips; float eddetthrHi; bool link; bool lip3; @@ -218,19 +217,12 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int cp.tmstrength = params->wavelet.tmrs; //cp.tonemap = params->wavelet.tmr; - cp.contena = true; cp.contena = params->wavelet.expcontrast; - cp.chromena = true; cp.chromena = params->wavelet.expchroma; - cp.edgeena = true; cp.edgeena = params->wavelet.expedge; - cp.resena = true; cp.resena = params->wavelet.expresid; - cp.finena = true; cp.finena = params->wavelet.expfinal; - cp.toningena = true; cp.toningena = params->wavelet.exptoning; - cp.noiseena = true; cp.noiseena = params->wavelet.expnoise; if(params->wavelet.Backmethod == "black") { @@ -491,7 +483,6 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int cp.lev3s = static_cast(params->wavelet.level3noise.value[0]); cp.lev3n = static_cast(params->wavelet.level3noise.value[1]); - cp.detectedge = false; cp.detectedge = params->wavelet.medianlev; //printf("low=%f mean=%f sd=%f max=%f\n",cp.edg_low,cp.edg_mean,cp.edg_sd,cp.edg_max); int minwin = min(imwidth, imheight); @@ -604,6 +595,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int //printf("levwav = %d\n",levwav); +#ifdef _OPENMP int numthreads = 1; int maxnumberofthreadsforwavelet = 0; @@ -641,7 +633,6 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int //printf("maxthre=%d\n",maxnumberofthreadsforwavelet); -#ifdef _OPENMP // Calculate number of tiles. If less than omp_get_max_threads(), then limit num_threads to number of tiles if( options.rgbDenoiseThreadLimit > 0) { @@ -675,10 +666,6 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int printf("Ip Wavelet uses %d main thread(s) and up to %d nested thread(s) for each main thread\n", numthreads, wavNestedLevels); } - -#endif - -#ifdef _OPENMP #pragma omp parallel num_threads(numthreads) #endif { @@ -881,7 +868,6 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int if(!Ldecomp->memoryAllocationFailed) { float madL[8][3]; - bool memoryAllocationFailed = false; #ifdef _RT_NESTED_OPENMP #pragma omp parallel for schedule(dynamic) collapse(2) num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif @@ -923,18 +909,16 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int vari[1] = 8.f * SQR((cp.lev1n / 125.0) * (1.0 + cp.lev1n / 25.0)); vari[2] = 8.f * SQR((cp.lev2n / 125.0) * (1.0 + cp.lev2n / 25.0)); vari[3] = 8.f * SQR((cp.lev3n / 125.0) * (1.0 + cp.lev3n / 25.0)); - int edge = 1; if((cp.lev0n > 0.1f || cp.lev1n > 0.1f || cp.lev2n > 0.1f || cp.lev3n > 0.1f) && cp.noiseena) { + int edge = 1; vari[0] = max(0.0001f, vari[0]); vari[1] = max(0.0001f, vari[1]); vari[2] = max(0.0001f, vari[2]); vari[3] = max(0.0001f, vari[3]); float* noisevarlum = NULL; // we need a dummy to pass it to WaveletDenoiseAllL - if(!WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge)) { // - memoryAllocationFailed = true; - } + WaveletDenoiseAllL(*Ldecomp, noisevarlum, madL, vari, edge); } ind = 1; @@ -988,7 +972,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int // printf("Levwava before: %d\n",levwava); if(cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels - while(levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f )) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || (cp.curv && cp.mulC[levwava - 1] == 0.f)))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) { + while(levwava > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwava - 1] == 0.f )) || (cp.CHmet != 2 && (levwava == 10 || (!cp.curv || cp.mulC[levwava - 1] == 0.f))))) && (!cp.opaRG || levwava == 10 || (cp.opaRG && cp.mulopaRG[levwava - 1] == 0.f)) && ((levwava == 10 || (cp.CHSLmet == 1 && cp.mulC[levwava - 1] == 0.f)))) { levwava--; } } @@ -1009,7 +993,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int //printf("Levwavb before: %d\n",levwavb); if(cp.chrores == 0.f && params->wavelet.CLmethod == "all" && !cp.cbena) { // no processing of residual ab => we probably can reduce the number of levels - while(levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f )) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavb - 1] == 0.f)))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) { + while(levwavb > 0 && !cp.diag && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavb - 1] == 0.f )) || (cp.CHmet != 2 && (levwavb == 10 || (!cp.curv || cp.mulC[levwavb - 1] == 0.f))))) && (!cp.opaBY || levwavb == 10 || (cp.opaBY && cp.mulopaBY[levwavb - 1] == 0.f)) && ((levwavb == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavb - 1] == 0.f)))) { levwavb--; } } @@ -1030,7 +1014,7 @@ SSEFUNCTION void ImProcFunctions::ip_wavelet(LabImage * lab, LabImage * dst, int // printf("Levwavab before: %d\n",levwavab); if(cp.chrores == 0.f && !hhutili && params->wavelet.CLmethod == "all") { // no processing of residual ab => we probably can reduce the number of levels - while(levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f )) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || (cp.curv && cp.mulC[levwavab - 1] == 0.f)))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) { + while(levwavab > 0 && (((cp.CHmet == 2 && (cp.chro == 0.f || cp.mul[levwavab - 1] == 0.f )) || (cp.CHmet != 2 && (levwavab == 10 || (!cp.curv || cp.mulC[levwavab - 1] == 0.f))))) && (!cp.opaRG || levwavab == 10 || (cp.opaRG && cp.mulopaRG[levwavab - 1] == 0.f)) && ((levwavab == 10 || (cp.CHSLmet == 1 && cp.mulC[levwavab - 1] == 0.f)))) { levwavab--; } } @@ -1406,14 +1390,11 @@ void ImProcFunctions::Evaluate2(wavelet_decomposition &WaveletCoeffs_L, void ImProcFunctions::Eval2 (float ** WavCoeffs_L, int level, const struct cont_params& cp, int W_L, int H_L, int skip_L, int ind, float *mean, float *meanN, float *sigma, float *sigmaN, float *MaxP, float *MaxN, float *madL) { - const float eps = 0.01f; - float ava[4], avb[4], avLP[4], avLN[4]; - float maxL[4], minL[4], maxa[4], maxb[4]; + float avLP[4], avLN[4]; + float maxL[4], minL[4]; float sigP[4], sigN[4]; - float AvL, AvN, SL, SN, maxLP, maxLN, MADL; - float madLlev[10]; - float thr = params->wavelet.thres; + float AvL, AvN, SL, SN, maxLP, maxLN; for (int dir = 1; dir < 4; dir++) { Aver(WavCoeffs_L[dir], W_L * H_L, avLP[dir], avLN[dir], maxL[dir], minL[dir]); @@ -1426,7 +1407,6 @@ void ImProcFunctions::Eval2 (float ** WavCoeffs_L, int level, const struct cont SN = 0.f; maxLP = 0.f; maxLN = 0.f; - MADL = 0.f; for (int dir = 1; dir < 4; dir++) { AvL += avLP[dir]; @@ -1435,7 +1415,6 @@ void ImProcFunctions::Eval2 (float ** WavCoeffs_L, int level, const struct cont SN += sigN[dir]; maxLP += maxL[dir]; maxLN += minL[dir]; - MADL += madL[dir]; } AvL /= 3; @@ -1444,13 +1423,6 @@ void ImProcFunctions::Eval2 (float ** WavCoeffs_L, int level, const struct cont SN /= 3; maxLP /= 3; maxLN /= 3; - MADL /= 3; - - if(level < 4) { - MADL = sqrt(MADL); - } else { - MADL = 0.f; - } mean[level] = AvL; meanN[level] = AvN; @@ -1648,7 +1620,7 @@ void ImProcFunctions::EPDToneMapResid(float * WavCoeffs_L0, unsigned int Iterat float sca = params->epd.scale; float gamm = params->wavelet.gamma; float rew = params->epd.reweightingIterates; - EdgePreservingDecomposition epd2 = EdgePreservingDecomposition(W_L, H_L); + EdgePreservingDecomposition epd2(W_L, H_L); cp.TMmeth = 2; //default after testing if(cp.TMmeth == 1) { @@ -1801,25 +1773,22 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * float maxkoeLi[12]; float *koeLibuffer = NULL; - bool lipschitz = true; - if(lipschitz == true) { - for(int y = 0; y < 12; y++) { - maxkoeLi[y] = 0.f; //9 - } - - koeLibuffer = new float[12 * H_L * W_L]; //12 - - for (int i = 0; i < 12; i++) { //9 - koeLi[i] = &koeLibuffer[i * W_L * H_L]; - } - - for(int j = 0; j < 12; j++) //9 - for (int i = 0; i < W_L * H_L; i++) { - koeLi[j][i] = 0.f; - } + for(int y = 0; y < 12; y++) { + maxkoeLi[y] = 0.f; //9 } + koeLibuffer = new float[12 * H_L * W_L]; //12 + + for (int i = 0; i < 12; i++) { //9 + koeLi[i] = &koeLibuffer[i * W_L * H_L]; + } + + for(int j = 0; j < 12; j++) //9 + for (int i = 0; i < W_L * H_L; i++) { + koeLi[j][i] = 0.f; + } + #ifdef _RT_NESTED_OPENMP #pragma omp parallel num_threads(wavNestedLevels) if(wavNestedLevels>1) #endif @@ -1923,7 +1892,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * // float eddlow=5.f + cp.edgampl/2.f;//settings->ed_low;//5 to 40 - if(cp.detectedge && lipschitz == true) { //enabled Lipschitz control...more memory..more time... + if(cp.detectedge) { //enabled Lipschitz control...more memory..more time... float *tmCBuffer = new float[H_L * W_L]; float *tmC[H_L]; @@ -2066,7 +2035,7 @@ void ImProcFunctions::WaveletcontAllL(LabImage * labco, float ** varhue, float * float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(lvl); - ContAllL (koeLi, maxkoeLi, lipschitz, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili); + ContAllL (koeLi, maxkoeLi, true, maxlvl, labco, varhue, varchrom, WavCoeffs_L, WavCoeffs_L0, lvl, dir, cp, Wlvl_L, Hlvl_L, skip, mean, meanN, sigma, sigmaN, MaxP, MaxN, wavCLVCcurve, waOpacityCurveW, ChCurve, Chutili); } @@ -2281,9 +2250,6 @@ void ImProcFunctions::WaveletcontAllAB(LabImage * labco, float ** varhue, float int Wlvl_ab = WaveletCoeffs_ab.level_W(lvl); int Hlvl_ab = WaveletCoeffs_ab.level_H(lvl); - - int skip_ab = WaveletCoeffs_ab.level_stride(lvl); - //printf("lev=%d skipL=%d skipab=%d\n",lvl, skip_L,skip_ab); float ** WavCoeffs_ab = WaveletCoeffs_ab.level_coeffs(lvl); ContAllAB (labco, maxlvl, varhue, varchrom, WavCoeffs_ab, WavCoeffs_ab0, lvl, dir, waOpacityCurveW, cp, Wlvl_ab, Hlvl_ab, useChannelA); } @@ -2622,7 +2588,6 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit scaleskip[sc] = scales[sc] / skip; } - float atten01234 = 0.80f; float t_r = settings->top_right; float t_l = settings->top_left; float b_r = settings->bot_right; @@ -2719,6 +2684,7 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit float value = ((float)cp.val) / 8.f; //strength if (scaleskip[1] < 1.f) { + float atten01234 = 0.80f; value *= (atten01234 * scaleskip[1]); //for zoom < 100% reduce strength...I choose level 1...but!! } @@ -2870,9 +2836,9 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit kinterm = 1.f; float kc = kmul * (wavCLVCcurve[absciss * 500.f] - 0.5f); float kcd = kmuld * (wavCLVCcurve[absciss * 500.f] - 0.5f); - float reduceeffect = 0.6f; if(kc >= 0.f) { + float reduceeffect = 0.6f; kinterm = 1.f + reduceeffect * kmul * (wavCLVCcurve[absciss * 500.f] - 0.5f); //about 1 to 3 general and big amplification for max (under 0) } else { kinterm = 1.f - (SQR(kcd)) / 10.f; @@ -3065,10 +3031,10 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit mea[8] = mean[level] + 2.5f * sigma[level]; //99% bool useChromAndHue = (skinprot != 0.f || cp.HSmet); - float modchro, kLlev; + float modchro; for (int i = 0; i < W_L * H_L; i++) { - kLlev = 1.f; + float kLlev = 1.f; if(cpMul < 0.f) { beta = 1.f; // disabled for negatives values "less contrast" @@ -3218,15 +3184,13 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit it = itmoins; } else if(level == med) { it = 7; - } else if(level > med) { + } else /*if(level > med)*/ { it = itplus; } for(int j = 0; j < it; j++) { //float bal = cp.balan;//-100 +100 float kba = 1.f; - float k1; - float k2; // if(dir <3) kba= 1.f + bal/600.f; // if(dir==3) kba = 1.f - bal/300.f; @@ -3234,8 +3198,8 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit int ii = i / W_L; int jj = i - ii * W_L; float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; - k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 - k2 = k1 * 2.f; + float k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 + float k2 = k1 * 2.f; if(dir < 3) { kba = 1.f + k1; @@ -3261,23 +3225,21 @@ void ImProcFunctions::ContAllL (float *koeLi[12], float *maxkoeLi, bool lipschit it = itmoins; } else if(level == med) { it = 7; - } else if(level > med) { + } else /*if(level > med)*/ { it = itplus; } for(int j = 0; j < it; j++) { float bal = cp.balan;//-100 +100 float kba = 1.f; - float k1; - float k2; // if(dir <3) kba= 1.f + bal/600.f; // if(dir==3) kba = 1.f - bal/300.f; for (int i = 0; i < W_L * H_L; i++) { int ii = i / W_L; int jj = i - ii * W_L; - k1 = 600.f; - k2 = 300.f; + float k1 = 600.f; + float k2 = 300.f; float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; float aa = 4970.f; float bb = -397000.f; @@ -3363,7 +3325,6 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, // if( (cp.curv || cp.CHSLmet==1) && cp.CHmet!=2 && level < 9 && cpMulC != 0.f) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip if( cp.CHmet != 2 && level < 9 && cpMulC != 0.f && cp.chromena) { // cpMulC == 0.f means all will be multiplied by 1.f, so we can skip - float modchro, modhue, kClev; const float skinprot = params->wavelet.skinprotect; const float skinprotneg = -skinprot; const float factorHard = (1.f - skinprotneg / 100.f); @@ -3373,15 +3334,13 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, int ii = i / W_ab; int jj = i - ii * W_ab; //WL and W_ab are identical - float LL = labco->L[ii * 2][jj * 2]; - float LL100 = LL / 327.68f; float scale = 1.f; - modchro = varchrom[ii * 2][jj * 2]; + float modchro = varchrom[ii * 2][jj * 2]; if(useSkinControl) { // hue chroma skin with initial lab datas - modhue = varhue[ii][jj]; - scale = 1.f; + float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; + float modhue = varhue[ii][jj]; if(skinprot > 0.f) { Color::SkinSatCbdl2 (LL100, modhue, modchro, skinprot, scale, true, cp.b_l, cp.t_l, cp.t_r, cp.b_r, 1); //1 for curve @@ -3397,7 +3356,7 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, beta = 0.02f; } - kClev = beta; + float kClev = beta; if(cp.CHmet == 1) { if(level < cp.chrom) { @@ -3479,15 +3438,13 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, it = itmoins; } else if(level == med) { it = 7; - } else if(level > med) { + } else /*if(level > med)*/ { it = itplus; } for(int j = 0; j < it; j++) { //float bal = cp.balan;//-100 +100 float kba = 1.f; - float k1; - float k2; // if(dir <3) kba= 1.f + bal/600.f; // if(dir==3) kba = 1.f - bal/300.f; @@ -3495,8 +3452,8 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, int ii = i / W_ab; int jj = i - ii * W_ab; float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; - k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 - k2 = k1 * 2.f; + float k1 = 0.3f * (waOpacityCurveW[6.f * LL100] - 0.5f); //k1 between 0 and 0.5 0.5==> 1/6=0.16 + float k2 = k1 * 2.f; if(dir < 3) { kba = 1.f + k1; @@ -3522,23 +3479,21 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, it = itmoins; } else if(level == med) { it = 7; - } else if(level > med) { + } else /*if(level > med)*/ { it = itplus; } for(int j = 0; j < it; j++) { float bal = cp.balan;//-100 +100 float kba = 1.f; - float k1; - float k2; // if(dir <3) kba= 1.f + bal/600.f; // if(dir==3) kba = 1.f - bal/300.f; for (int i = 0; i < W_ab * H_ab; i++) { int ii = i / W_ab; int jj = i - ii * W_ab; - k1 = 600.f; - k2 = 300.f; + float k1 = 600.f; + float k2 = 300.f; float LL100 = labco->L[ii * 2][jj * 2] / 327.68f; float aa = 4970.f; float bb = -397000.f; @@ -3607,10 +3562,8 @@ void ImProcFunctions::ContAllAB (LabImage * labco, int maxlvl, float ** varhue, if(choiceClevel < 3) { // not all levels visible, paint residual if(level == 0) { if(cp.backm != 2) { // nothing to change when residual is used as background - float backGroundChroma = (cp.backm == 1) ? 0.f : 0.f; //we can change first to colorized... - for (int i = 0; i < W_ab * H_ab; i++) { - WavCoeffs_ab0[i] = backGroundChroma; + WavCoeffs_ab0[i] = 0.f; } } } diff --git a/rtengine/jaggedarray.h b/rtengine/jaggedarray.h index 4d01747da..153ed2902 100644 --- a/rtengine/jaggedarray.h +++ b/rtengine/jaggedarray.h @@ -17,8 +17,9 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef JAGGEDARRAY_H -#define JAGGEDARRAY_H +#pragma once + +#include "noncopyable.h" namespace rtengine { @@ -50,7 +51,8 @@ inline void freeJaggedArray (T** const a) } template -class JaggedArray +class JaggedArray : + public NonCopyable { public: JaggedArray (const int W, const int H, const bool initZero = false) @@ -65,10 +67,6 @@ public: } } - JaggedArray (const JaggedArray&) = delete; - JaggedArray& operator= (const JaggedArray&) = delete; - -public: operator T** const () const { return a; @@ -85,5 +83,3 @@ template void freeJaggedArray (JaggedArray&); } // rtengine - -#endif // JAGGEDARRAY_H diff --git a/rtengine/klt/convolve.cc b/rtengine/klt/convolve.cc index b6041a7a6..7a2785cca 100644 --- a/rtengine/klt/convolve.cc +++ b/rtengine/klt/convolve.cc @@ -250,8 +250,8 @@ static void _convolveImageVert( static void _convolveSeparate( _KLT_FloatImage imgin, - ConvolutionKernel horiz_kernel, - ConvolutionKernel vert_kernel, + const ConvolutionKernel &horiz_kernel, + const ConvolutionKernel &vert_kernel, _KLT_FloatImage imgout) { /* Create temporary image */ diff --git a/rtengine/lcp.cc b/rtengine/lcp.cc index 1ed601301..0f45e1270 100644 --- a/rtengine/lcp.cc +++ b/rtengine/lcp.cc @@ -276,7 +276,7 @@ float LCPMapper::calcVignetteFac(int x, int y) const + 2.*aVig[0] * aVig[2] - 3.*param0Sqr * aVig[1]) * rsqr * rsqr)); } -LCPProfile::LCPProfile(Glib::ustring fname) +LCPProfile::LCPProfile(const Glib::ustring &fname) { const int BufferSize = 8192; char buf[BufferSize]; diff --git a/rtengine/lcp.h b/rtengine/lcp.h index fa60a6013..908bacf56 100644 --- a/rtengine/lcp.h +++ b/rtengine/lcp.h @@ -89,7 +89,7 @@ public: static const int MaxPersModelCount = 3000; LCPPersModel* aPersModel[MaxPersModelCount]; // Do NOT use std::list or something, it's buggy in GCC! - LCPProfile(Glib::ustring fname); + explicit LCPProfile(const Glib::ustring &fname); void calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const; // Interpolates between the persModels frames diff --git a/rtengine/median.h b/rtengine/median.h index b30a9354e..971452bc3 100644 --- a/rtengine/median.h +++ b/rtengine/median.h @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . * - * These median implementations from Floessie and Ingo Weyrich are inspired by this work: + * These median implementations from Flössie and Ingo Weyrich are inspired by this work: * * http://ndevilla.free.fr/median/median.pdf * http://pages.ripco.net/~jgamble/nw.html @@ -45,7 +45,7 @@ inline T median(std::array array) std::nth_element(array.begin(), middle, array.end()); return - N % 2 + (N % 2) ? *middle : ((*middle + *std::max_element(array.begin(), middle)) / static_cast(2)); } diff --git a/rtengine/noncopyable.h b/rtengine/noncopyable.h new file mode 100644 index 000000000..d34c42441 --- /dev/null +++ b/rtengine/noncopyable.h @@ -0,0 +1,34 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2016 Flössie + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#pragma once + +namespace rtengine +{ + +class NonCopyable +{ +public: + NonCopyable() = default; + + explicit NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator =(const NonCopyable&) = delete; +}; + +} diff --git a/rtengine/pipettebuffer.h b/rtengine/pipettebuffer.h index e6db8eb68..139438e1d 100644 --- a/rtengine/pipettebuffer.h +++ b/rtengine/pipettebuffer.h @@ -50,7 +50,7 @@ protected: void flush(); public: - PipetteBuffer(::EditDataProvider *dataProvider); + explicit PipetteBuffer(::EditDataProvider *dataProvider); ~PipetteBuffer(); /** @brief Getter to know if the pipette buffer is correctly filled */ diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 69cdd17c5..fe2b89535 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -753,13 +753,13 @@ void WaveletParams::setDefaults() hhcurve.push_back(FCT_Linear); Chcurve.clear (); Chcurve.push_back(FCT_Linear); - expcontrast = true; - expchroma = true; - expedge = true; - expresid = true; - expfinal = true; - exptoning = true; - expnoise = true; + expcontrast = false; + expchroma = false; + expedge = false; + expresid = false; + expfinal = false; + exptoning = false; + expnoise = false; for(int i = 0; i < 9; i ++) { c[i] = 0; diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 3f0331457..8750e58b0 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -19,11 +19,13 @@ #ifndef _PROCPARAMS_H_ #define _PROCPARAMS_H_ -#include #include #include #include + +#include #include + #include "LUT.h" #include "coord.h" @@ -1364,7 +1366,7 @@ class PartialProfile public: rtengine::procparams::ProcParams* pparams; ParamsEdited* pedited; - PartialProfile& operator=(PartialProfile& rhs) + PartialProfile& operator =(const PartialProfile& rhs) { pparams = rhs.pparams; pedited = rhs.pedited; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 86965a612..45e67cbac 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -20,8 +20,10 @@ #define __RAWIMAGE_H #include + #include "dcraw.h" #include "imageio.h" +#include "noncopyable.h" namespace rtengine { @@ -32,7 +34,8 @@ struct badPix { badPix( uint16_t xc, uint16_t yc ): x(xc), y(yc) {} }; -class PixelsMap +class PixelsMap : + public NonCopyable { int w; // line width in base_t units int h; // height @@ -48,6 +51,7 @@ public: pm = new base_t [h * w ]; memset(pm, 0, h * w * base_t_size ); } + ~PixelsMap() { delete [] pm; @@ -99,7 +103,7 @@ class RawImage: public DCraw { public: - RawImage( const Glib::ustring &name ); + explicit RawImage( const Glib::ustring &name ); ~RawImage(); int loadRaw (bool loadData = true, bool closeFile = true, ProgressListener *plistener = 0, double progressRange = 1.0); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 000e9ead0..2756ea7d7 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -4395,7 +4395,7 @@ void RawImageSource::HLRecovery_CIELab (float* rin, float* gin, float* bin, floa //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::hlRecovery (std::string method, float* red, float* green, float* blue, int width, float* hlmax ) +void RawImageSource::hlRecovery (const std::string &method, float* red, float* green, float* blue, int width, float* hlmax ) { if (method == "Luminance") { @@ -4403,8 +4403,6 @@ void RawImageSource::hlRecovery (std::string method, float* red, float* green, f } else if (method == "CIELab blending") { HLRecovery_CIELab (red, green, blue, red, green, blue, width, 65535.0, imatrices.xyz_cam, imatrices.cam_xyz); } - /*else if (method=="Color") - HLRecovery_ColorPropagation (red, green, blue, i, sx1, width, skip);*/ else if (method == "Blend") { // derived from Dcraw HLRecovery_blend(red, green, blue, width, 65535.0, hlmax); } diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index e682f0e79..60887d9cd 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -97,12 +97,10 @@ protected: void hphd_horizontal (float** hpmap, int row_from, int row_to); void hphd_green (float** hpmap); void processFalseColorCorrectionThread (Imagefloat* im, array2D &rbconv_Y, array2D &rbconv_I, array2D &rbconv_Q, array2D &rbout_I, array2D &rbout_Q, const int row_from, const int row_to); - void hlRecovery (std::string method, float* red, float* green, float* blue, int width, float* hlmax); + void hlRecovery (const std::string &method, float* red, float* green, float* blue, int width, float* hlmax); void transformRect (PreviewProps pp, int tran, int &sx1, int &sy1, int &width, int &height, int &fw); void transformPosition (int x, int y, int tran, int& tx, int& ty); - void updateHLRecoveryMap_ColorPropagation (); - void HLRecovery_ColorPropagation (float* red, float* green, float* blue, int i, int sx1, int width, int skip); unsigned FC(int row, int col) { return ri->FC(row, col); @@ -188,7 +186,7 @@ public: void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb); static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName) + static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName) { colorSpaceConversion_ (im, cmp, wb, pre_mul, embedded, camprofile, cam, camName); } diff --git a/rtengine/shmap.h b/rtengine/shmap.h index 97a394927..9bb496b54 100644 --- a/rtengine/shmap.h +++ b/rtengine/shmap.h @@ -21,11 +21,13 @@ #include "imagefloat.h" #include "image16.h" +#include "noncopyable.h" namespace rtengine { -class SHMap +class SHMap : + public NonCopyable { public: diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index a01597d96..e31103929 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -273,7 +273,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p float maxr = 0.f; float maxb = 0.f; float pondcorrec = 1.0f; - float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; + float chaut, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc; int Nb; chaut = 0.f; redaut = 0.f; @@ -282,7 +282,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p maxblueaut = 0.f; chromina = 0.f; sigma = 0.f; - ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, Nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); float multip = 1.f; float adjustr = 1.f; @@ -490,8 +490,8 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p imgsrc->convertColorSpace(provicalc, params.icm, currWB);//for denoise luminance curve int nb = 0; - float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, nresi = 0.f, highresi = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; - ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, nresi, highresi, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); + float chaut = 0.f, redaut = 0.f, blueaut = 0.f, maxredaut = 0.f, maxblueaut = 0.f, minredaut = 0.f, minblueaut = 0.f, chromina = 0.f, sigma = 0.f, lumema = 0.f, sigma_L = 0.f, redyel = 0.f, skinc = 0.f, nsknc = 0.f; + ipf.RGB_denoise_info(origCropPart, provicalc, imgsrc->isRAW(), gamcurve, gam, gamthresh, gamslope, params.dirpyrDenoise, imgsrc->getDirPyrDenoiseExpComp(), chaut, nb, redaut, blueaut, maxredaut, maxblueaut, minredaut, minblueaut, chromina, sigma, lumema, sigma_L, redyel, skinc, nsknc); Nb[hcr * 3 + wcr] = nb; ch_M[hcr * 3 + wcr] = chaut; max_r[hcr * 3 + wcr] = maxredaut; @@ -996,13 +996,12 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p } } - int kall = 2; bool wavcontlutili = false; CurveFactory::curveWavContL(wavcontlutili, params.wavelet.wavclCurve, wavclCurve,/* hist16C, dummy,*/ 1); - if((params.wavelet.enabled)) { - ipf.ip_wavelet(labView, labView, kall, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1); + if(params.wavelet.enabled) { + ipf.ip_wavelet(labView, labView, 2, WaveParams, wavCLVCurve, waOpacityCurveRG, waOpacityCurveBY, waOpacityCurveW, waOpacityCurveWL, wavclCurve, wavcontlutili, 1); } wavCLVCurve.Reset(); @@ -1053,25 +1052,19 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p float CAMMean = NAN; if (params.sharpening.enabled) { - float d; - double dd; - - int sk = 1; - if(settings->ciecamfloat) { - ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); + float d; + ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1); } else { + double dd; ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); } } else { - float d; - - double dd; - int sk = 1; - if(settings->ciecamfloat) { - ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, sk, 1); + float d; + ipf.ciecam_02float (cieView, float(adap), begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, d, 1, 1); } else { + double dd; ipf.ciecam_02 (cieView, adap, begh, endh, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1); } } diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index bd14c6514..41ab468cb 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -101,7 +101,7 @@ public: } char buffer[32]; - sprintf (buffer, "%.1fs %s", sec / 10., sec & 0x4000 ? ",Custom" : ""); + sprintf (buffer, "%.1fs %s", sec / 10., (sec & 0x4000) ? ",Custom" : ""); return buffer; } }; @@ -965,7 +965,7 @@ public: std::ostringstream candidates; for (r = choices.lower_bound(lensID); r != choices.upper_bound(lensID); r++) { - double a1, a2, f1, f2, lensAperture, dif; + double a1, a2, f1, f2, dif; if( !extractLensInfo( r->second , f1, f2, a1, a2) ) { continue; @@ -988,6 +988,7 @@ public: } if( maxApertureAtFocal > 0.1) { + double lensAperture; if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) { continue; } diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index 38f4ce1f0..a827eb1fe 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -147,10 +147,10 @@ public: { int a = t->toInt(); std::ostringstream str; - str << "MF = " << (a & 1 ? "Yes" : "No") << std::endl; - str << "D = " << (a & 2 ? "Yes" : "No") << std::endl; - str << "G = " << (a & 4 ? "Yes" : "No") << std::endl; - str << "VR = " << (a & 8 ? "Yes" : "No"); + str << "MF = " << ((a & 1) ? "Yes" : "No") << std::endl; + str << "D = " << ((a & 2) ? "Yes" : "No") << std::endl; + str << "G = " << ((a & 4) ? "Yes" : "No") << std::endl; + str << "VR = " << ((a & 8) ? "Yes" : "No"); return str.str(); } }; @@ -196,13 +196,13 @@ public: { int a = t->toInt(); std::ostringstream str; - str << "Continuous = " << (a & 1 ? "Yes" : "No") << std::endl; - str << "Delay = " << (a & 2 ? "Yes" : "No") << std::endl; - str << "PC Control = " << (a & 4 ? "Yes" : "No") << std::endl; - str << "White-Balance Bracketing = " << (a & 8 ? "Yes" : "No") << std::endl; - str << "Exposure Bracketing = " << (a & 16 ? "Yes" : "No") << std::endl; - str << "Auto ISO = " << (a & 32 ? "Yes" : "No") << std::endl; - str << "IR Control = " << (a & 64 ? "Yes" : "No"); + str << "Continuous = " << ((a & 1) ? "Yes" : "No") << std::endl; + str << "Delay = " << ((a & 2) ? "Yes" : "No") << std::endl; + str << "PC Control = " << ((a & 4) ? "Yes" : "No") << std::endl; + str << "White-Balance Bracketing = " << ((a & 8) ? "Yes" : "No") << std::endl; + str << "Exposure Bracketing = " << ((a & 16) ? "Yes" : "No") << std::endl; + str << "Auto ISO = " << ((a & 32) ? "Yes" : "No") << std::endl; + str << "IR Control = " << ((a & 64) ? "Yes" : "No"); return str.str(); } }; diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index f88e650ec..4d3cef90d 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -1911,12 +1911,12 @@ public: PAAFPointSelectedInterpreter() {} virtual std::string toString (Tag* t) { - const char *ps[] = {"Upper-left", "Top", "Upper-right", "Left", "Mid-left", "Center", "Mid-right", "Right", "Lower-left", "Bottom", "Lower-right"}; int c = t->toInt(0, SHORT); if( !c ) { return "Auto"; } else { + const char *ps[] = {"Upper-left", "Top", "Upper-right", "Left", "Mid-left", "Center", "Mid-right", "Right", "Lower-left", "Bottom", "Lower-right"}; for( int iBit = 0; iBit < 11; iBit++) if( c & (1 << iBit) ) { return ps[iBit]; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 91f52ce55..a13e9cae8 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -207,13 +207,11 @@ void TagDirectory::printAll (unsigned int level) const for (size_t i = 0; i < tags.size(); i++) { std::string name = tags[i]->nameToString (); - if (tags[i]->isDirectory()) + if (tags[i]->isDirectory()) { for (int j = 0; tags[i]->getDirectory(j); j++) { printf ("%s+-- DIRECTORY %s[%d]:\n", prefixStr, name.c_str(), j); tags[i]->getDirectory(j)->printAll (level + 1); } - else { - std::string value = tags[i]->valueToString (); } } } @@ -696,7 +694,7 @@ void TagDirectory::applyChange (std::string name, std::string value) } TagDirectoryTable::TagDirectoryTable () - : zeroOffset(0), valuesSize(0) + : values(nullptr), zeroOffset(0), valuesSize(0), defaultType(INVALID) { } @@ -1269,9 +1267,8 @@ Tag::~Tag () } // if there are directories behind the tag, delete them - int i = 0; - if (directory) { + int i = 0; while (directory[i]) { delete directory[i++]; } @@ -1600,11 +1597,10 @@ std::string Tag::nameToString (int i) std::string Tag::valueToString () { - char buffer[1024]; - if (attrib && attrib->interpreter) { return attrib->interpreter->toString (this); } else { + char buffer[1024]; toString (buffer); return buffer; } @@ -2831,7 +2827,6 @@ int ExifManager::createJPEGMarker (const TagDirectory* root, const rtengine::pro sset2 (42, buffer + offs, order); offs += 2; sset4 (8, buffer + offs, order); - offs += 4; TagDirectory* cl; @@ -2964,7 +2959,6 @@ int ExifManager::createTIFFHeader (const TagDirectory* root, const rtengine::pro sset2 (42, buffer + offs, order); offs += 2; sset4 (8, buffer + offs, order); - offs += 4; int endOffs = cl->write (8, buffer); diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 7777331e9..02d357a5d 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -28,7 +28,9 @@ #include #include #include + #include "../rtengine/procparams.h" +#include "../rtengine/noncopyable.h" class CacheImageData; @@ -178,7 +180,8 @@ public: }; // a class representing a single tag -class Tag +class Tag : + public rtengine::NonCopyable { protected: @@ -202,6 +205,7 @@ public: Tag (TagDirectory* parent, const TagAttrib* attr, unsigned char *data, TagType t); Tag (TagDirectory* parent, const TagAttrib* attr, int data, TagType t); // create a new tag from array (used Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used + ~Tag (); void initType (unsigned char *data, TagType type); void initInt (int data, TagType t, int count = 1); @@ -533,7 +537,7 @@ protected: double deltaMin = 1000.; for ( r = choices.lower_bound( lensID ); r != choices.upper_bound(lensID); ++r ) { - double lensAperture, dif; + double dif; if( !extractLensInfo( r->second , f1, f2, a1, a2) ) { continue; @@ -548,6 +552,7 @@ protected: } if( maxApertureAtFocal > 0.1) { + double lensAperture; if( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) { continue; } diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc index 7f4e1bb53..80db5018f 100644 --- a/rtexif/sonyminoltaattribs.cc +++ b/rtexif/sonyminoltaattribs.cc @@ -1966,7 +1966,7 @@ public: { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); - int a; + int a = 0; if (astype == BYTE) { a = t->getValue()[ofs]; @@ -1975,7 +1975,7 @@ public: } // Decode the value - if(a > 0.) { + if(a > 0) { return pow(2., 6. - (double(a) / 8.)); } else { return 0.; @@ -1984,7 +1984,7 @@ public: virtual int toInt (Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; + int a = 0; if (astype == INVALID || astype == AUTO) { astype = t->getType(); @@ -2026,7 +2026,7 @@ public: { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); - int a; + int a = 0; if (astype == BYTE) { a = t->getValue()[ofs]; @@ -2035,7 +2035,7 @@ public: } // Decode the value - if(a > 0.) { + if(a > 0) { return pow(2., (double(a) / 8. - 1.) / 2.); } else { return 0.; @@ -2044,7 +2044,7 @@ public: virtual int toInt (Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; + int a = 0; if (astype == INVALID || astype == AUTO) { astype = t->getType(); @@ -2085,7 +2085,7 @@ public: virtual int toInt (Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT - int a; + int a = 0; if (astype == INVALID || astype == AUTO) { astype = t->getType(); @@ -2235,7 +2235,7 @@ public: } virtual int toInt (Tag* t, int ofs, TagType astype) { - int a; + int a = 0; if (astype == INVALID || astype == AUTO) { astype = t->getType(); diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 1adc6ddd4..ad896041f 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -8,7 +8,7 @@ set (BASESOURCEFILES coarsepanel.cc cacorrection.cc chmixer.cc blackwhite.cc resize.cc icmpanel.cc crop.cc shadowshighlights.cc impulsedenoise.cc dirpyrdenoise.cc epd.cc - exifpanel.cc toolpanel.cc lensprofile.cc + exifpanel.cc toolpanel.cc lensprofile.cc lockablecolorpicker.cc sharpening.cc vibrance.cc rgbcurves.cc colortoning.cc whitebalance.cc vignetting.cc gradient.cc pcvignette.cc rotate.cc distortion.cc crophandler.cc dirbrowser.cc diff --git a/rtgui/adjuster.cc b/rtgui/adjuster.cc index f0e53fbbf..b481f4ebe 100644 --- a/rtgui/adjuster.cc +++ b/rtgui/adjuster.cc @@ -35,7 +35,6 @@ static double one2one(double val) Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, Gtk::Image *imgIcon1, Gtk::Image *imgIcon2, double2double_fun slider2value_, double2double_fun value2slider_) { - Gtk::HBox *hbox2 = NULL; label = NULL; adjusterListener = NULL; afterReset = false; @@ -107,6 +106,8 @@ Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep if (!imgIcon1 || !imgIcon2) { pack_start (*slider, true, true); } else { + Gtk::HBox *hbox2 = NULL; + // A second HBox is necessary hbox2 = Gtk::manage (new Gtk::HBox()); diff --git a/rtgui/batchqueue.h b/rtgui/batchqueue.h index 3bf3cb228..fad2b6a25 100644 --- a/rtgui/batchqueue.h +++ b/rtgui/batchqueue.h @@ -68,7 +68,7 @@ protected: void notifyListener (bool queueEmptied); public: - BatchQueue (FileCatalog* aFileCatalog); + explicit BatchQueue (FileCatalog* aFileCatalog); ~BatchQueue (); void addEntries (const std::vector& entries, bool head = false, bool save = true); diff --git a/rtgui/batchqueuebuttonset.h b/rtgui/batchqueuebuttonset.h index cb6ccda56..bef125bb6 100644 --- a/rtgui/batchqueuebuttonset.h +++ b/rtgui/batchqueuebuttonset.h @@ -33,7 +33,7 @@ public: static Cairo::RefPtr headIcon; static Cairo::RefPtr tailIcon; - BatchQueueButtonSet (BatchQueueEntry* myEntry); + explicit BatchQueueButtonSet (BatchQueueEntry* myEntry); }; #endif diff --git a/rtgui/batchqueuepanel.cc b/rtgui/batchqueuepanel.cc index 2c7f81729..e1def62ec 100644 --- a/rtgui/batchqueuepanel.cc +++ b/rtgui/batchqueuepanel.cc @@ -24,10 +24,6 @@ #include "soundman.h" #include "rtimage.h" -struct BQProcessLoaded { - BatchQueue* bq; -}; - int processLoadedBatchQueueUIThread (void* data) { diff --git a/rtgui/batchqueuepanel.h b/rtgui/batchqueuepanel.h index 997514bef..675745b8a 100644 --- a/rtgui/batchqueuepanel.h +++ b/rtgui/batchqueuepanel.h @@ -55,7 +55,7 @@ class BatchQueuePanel : public Gtk::VBox, public: - BatchQueuePanel (FileCatalog* aFileCatalog); + explicit BatchQueuePanel (FileCatalog* aFileCatalog); void setParent (RTWindow* p) { diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 0b3d65961..004a2c812 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -42,6 +42,10 @@ BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolP toolPanels.erase (ipi); } + if (toolBar) { + toolBar->setBatchMode (); + } + toolPanelNotebook->remove_page (*metadataPanel); metadataPanel = 0; toiM = 0; diff --git a/rtgui/batchtoolpanelcoord.h b/rtgui/batchtoolpanelcoord.h index e064452b2..0c12aa311 100644 --- a/rtgui/batchtoolpanelcoord.h +++ b/rtgui/batchtoolpanelcoord.h @@ -48,7 +48,7 @@ protected: public: - BatchToolPanelCoordinator (FilePanel* parent); + explicit BatchToolPanelCoordinator (FilePanel* parent); // FileSelectionChangeListener interface void selectionChanged (const std::vector& selected); diff --git a/rtgui/browserfilter.cc b/rtgui/browserfilter.cc index 6fa663aa3..3d43400ba 100644 --- a/rtgui/browserfilter.cc +++ b/rtgui/browserfilter.cc @@ -21,7 +21,8 @@ BrowserFilter::BrowserFilter () : exifFilterEnabled (false), showTrash (true), showNotTrash (true), - showOriginal (false) + showOriginal (false), + multiselect (false) { for (int i = 0; i < 6; i++) { showRanked[i] = true; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 75a6ab75a..220dcb2e8 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -24,7 +24,9 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), exifValid(false), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), thumbImgType(0) + timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), + redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { } diff --git a/rtgui/cachemanager.h b/rtgui/cachemanager.h index 4460204cc..99c732e88 100644 --- a/rtgui/cachemanager.h +++ b/rtgui/cachemanager.h @@ -24,11 +24,14 @@ #include +#include "../rtengine/noncopyable.h" + #include "threadutils.h" class Thumbnail; -class CacheManager +class CacheManager : + public rtengine::NonCopyable { private: using Entries = std::map; @@ -41,12 +44,7 @@ private: void applyCacheSizeLimitation () const; - CacheManager () = default; - CacheManager (const CacheManager&) = delete; - CacheManager& operator= (const CacheManager&) = delete; - public: - static CacheManager* getInstance (); void init (); @@ -69,7 +67,6 @@ public: const Glib::ustring& fname, const Glib::ustring& fext, const Glib::ustring& md5) const; - }; #define cacheMgr CacheManager::getInstance() diff --git a/rtgui/clipboard.cc b/rtgui/clipboard.cc index ad3ea6386..e7a5b7b2c 100644 --- a/rtgui/clipboard.cc +++ b/rtgui/clipboard.cc @@ -20,7 +20,7 @@ Clipboard clipboard; -Clipboard::Clipboard () : partProfile (false) {} +Clipboard::Clipboard () : partProfile (false), _hasIPTC(false), hasDiagonalCurveDataType(DCT_Empty), hasFlatCurveDataType(FCT_Empty) {} Clipboard::~Clipboard () { diff --git a/rtgui/coloredbar.h b/rtgui/coloredbar.h index 917085e3c..237cd8595 100644 --- a/rtgui/coloredbar.h +++ b/rtgui/coloredbar.h @@ -37,7 +37,7 @@ protected: std::vector bgGradient; public: - ColoredBar (eRTOrientation orient); + explicit ColoredBar (eRTOrientation orient); void expose(Glib::RefPtr destWindow); void expose(Cairo::RefPtr destSurface); diff --git a/rtgui/coordinateadjuster.cc b/rtgui/coordinateadjuster.cc index 61b5ae8b8..469013800 100644 --- a/rtgui/coordinateadjuster.cc +++ b/rtgui/coordinateadjuster.cc @@ -124,9 +124,8 @@ void CoordinateAdjuster::createWidgets(const std::vector &axis) set_spacing(3); - AxisAdjuster *currAdjuster = NULL; - for (unsigned int i = 0; i < count; ++i) { + AxisAdjuster *currAdjuster = NULL; const Axis *currAxis = &(axis.at(i)); axisAdjusters.at(i) = new AxisAdjuster(this, currAxis, i); currAdjuster = axisAdjusters.at(i); diff --git a/rtgui/createicon.cc b/rtgui/createicon.cc deleted file mode 100644 index 32884c182..000000000 --- a/rtgui/createicon.cc +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This file is part of RawTherapee. - * - * Copyright (c) 2004-2010 Gabor Horvath - * - * RawTherapee is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * RawTherapee is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with RawTherapee. If not, see . - */ -#include - -void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_size_t check; - - /* fread() returns 0 on error, so it is OK to store this in a png_size_t - * instead of an int, which is what fread() actually returns. - */ - check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_ptr->io_ptr); - - if (check != length) { - png_error(png_ptr, "Read Error"); - } -} - -void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) -{ - png_uint_32 check; - - check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)); - - if (check != length) { - png_error(png_ptr, "Write Error"); - } -} - -void png_flush(png_structp png_ptr) -{ - FILE *io_ptr; - io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); - - if (io_ptr != NULL) { - fflush(io_ptr); - } -} - - -unsigned char* loadPNG (char* fname, int& w, int& h) -{ - - FILE *file = fopen (fname, "rb"); - - unsigned char header[8]; - fread (header, 1, 8, file); - - png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); - png_infop info = png_create_info_struct (png); - png_infop end_info = png_create_info_struct (png); - - if (setjmp (png_jmpbuf(png))) { - png_destroy_read_struct (&png, &info, &end_info); - fclose (file); - return NULL; - } - - //set up png read - png_set_read_fn (png, file, png_read_data); - png_set_sig_bytes (png, 8); - - png_read_info(png, info); - - unsigned long width, height; - int bit_depth, color_type, interlace_type, compression_type, filter_method; - png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, - &compression_type, &filter_method); - - //converting to 32bpp format - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png); - } - - if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png); - } - - if (png_get_valid(png, info, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(png); - } - - if (interlace_type != PNG_INTERLACE_NONE) { - png_destroy_read_struct (&png, &info, &end_info); - fclose (file); - return NULL; - } - - if (color_type & PNG_COLOR_MASK_ALPHA) { - png_set_strip_alpha(png); - } - - //setting gamma - double gamma; - - if (png_get_gAMA(png, info, &gamma)) { - png_set_gamma(png, 2.0, gamma); - } else { - png_set_gamma(png, 2.0, 0.45455); - } - - int bps = 8; - - //updating png info struct - png_read_update_info(png, info); - png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, - &compression_type, &filter_method); - - if (color_type & PNG_COLOR_MASK_ALPHA) { - png_set_strip_alpha(png); - } - - png_read_update_info(png, info); - png_get_IHDR(png, info, &width, &height, &bit_depth, &color_type, &interlace_type, - &compression_type, &filter_method); - - - unsigned char* data = new unsigned char[width * height * 3]; - int rowlen = width * 3; - unsigned char *row = new unsigned char [rowlen]; - - for (unsigned int i = 0; i < height; i++) { - - png_read_row (png, (png_byte*)row, NULL); - memcpy (data + 3 * i * width, row, 3 * width); - } - - png_read_end (png, 0); - png_destroy_read_struct (&png, &info, &end_info); - - delete [] row; - fclose(file); - - w = width; - h = height; - return data; -} - -void savePNG (char* fname, unsigned char* data1, unsigned char* data2, int w, int h) -{ - - FILE* file = fopen(fname, "wb"); - - png_structp png = png_create_write_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); - png_infop info = png_create_info_struct(png); - - if (setjmp(png_jmpbuf(png))) { - png_destroy_write_struct (&png, &info); - fclose(file); - return; - } - - png_set_write_fn (png, file, png_write_data, png_flush); - png_set_compression_level(png, 6); - - int width = w; - int height = h; - int bps = 8; - - png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB_ALPHA, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE); - - - int rowlen = width * 4; - unsigned char *row = new unsigned char [rowlen]; - - png_write_info(png, info); - - for (unsigned int i = 0; i < height; i++) { - for (int j = 0; j < width; j++) { - int ofs = 3 * (width * i + j); - unsigned char alpha = data2[ofs] - data1[ofs]; - - if (i == 8 && j == 8) { - printf ("alpha=%d pix=%d\n", (int)alpha, (int)(data1[ofs + 0] / (1.0 - alpha / 255.0))); - } - - if (alpha < 255) { - row[4 * j + 0] = data1[ofs + 0] / (1.0 - alpha / 255.0); - row[4 * j + 1] = data1[ofs + 1] / (1.0 - alpha / 255.0); - row[4 * j + 2] = data1[ofs + 2] / (1.0 - alpha / 255.0); - } else { - - } - - row[4 * j + 3] = 255 - alpha; - } - - png_write_row (png, (png_byte*)row); - } - - png_write_end(png, info); - png_destroy_write_struct(&png, &info); - - delete [] row; - fclose (file); -} - -int main (int argc, char* argv[]) -{ - - int w, h; - unsigned char* data1 = loadPNG (argv[1], w, h); - unsigned char* data2 = loadPNG (argv[2], w, h); - savePNG (argv[3], data1, data2, w, h); - -} diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index a76f23717..d3c73bfdb 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -22,6 +22,7 @@ #include #include "guiutils.h" #include "cropwindow.h" +#include "imagearea.h" #include "../rtengine/dcrop.h" #include "../rtengine/refreshmap.h" #include "../rtengine/rt_math.h" @@ -32,6 +33,7 @@ CropHandler::CropHandler () : zoom(10), ww(0), wh(0), imx(-1), imy(-1), imw(0), imh(0), cax(-1), cay(-1), cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), cropimg(NULL), cropimgtrue(NULL), cropimg_width(0), cropimg_height(0), + cix(0), ciy(0), ciw(0), cih(0), cis(1), initial(false), isLowUpdatePriority(false), ipc(NULL), crop(NULL), displayHandler(NULL) { @@ -188,6 +190,15 @@ void CropHandler::setZoom (int z, int centerx, int centery) } } +float CropHandler::getZoomFactor () +{ + if (zoom >= 1000) { + return zoom / 1000; + } else { + return 1.f / (float)zoom; + } +} + void CropHandler::setWSize (int w, int h) { @@ -465,6 +476,95 @@ bool CropHandler::getEnabled () return enabled; } +void CropHandler::colorPick (const rtengine::Coord &pickerPos, float &r, float &g, float &b, float &rpreview, float &gpreview, float &bpreview, LockableColorPicker::Size size) +{ + + if (!cropPixbuf || !cropPixbuftrue) { + r = g = b = 0.f; + rpreview = gpreview = bpreview = 0.f; + return; + } + + int xSize = (int)size; + int ySize = (int)size; + int pixbufW = cropPixbuftrue->get_width(); + int pixbufH = cropPixbuftrue->get_height(); + rtengine::Coord topLeftPos(pickerPos.x - xSize/2, pickerPos.y - ySize/2); + + if (topLeftPos.x > pixbufW || topLeftPos.y > pixbufH || topLeftPos.x + xSize < 0 || topLeftPos.y + ySize < 0) { + return; + } + + // Store the position of the center of the picker + int radius = (int)size / 2; + + // X/Width clip + if (topLeftPos.x < 0) { + xSize += topLeftPos.x; + topLeftPos.x = 0; + } + if (topLeftPos.x + xSize > pixbufW) { + xSize = pixbufW - topLeftPos.x; + } + // Y/Height clip + if (topLeftPos.y < 0) { + ySize += topLeftPos.y; + topLeftPos.y = 0; + } + if (topLeftPos.y + ySize > pixbufH) { + ySize = pixbufH - topLeftPos.y; + } + + // Accumulating the data + std::uint32_t r2=0, g2=0, b2=0; + std::uint32_t count = 0; + const guint8* data = cropPixbuftrue->get_pixels(); + for (int j = topLeftPos.y ; j < topLeftPos.y + ySize ; ++j) { + const guint8* data2 = data + cropPixbuftrue->get_rowstride()*j; + for (int i = topLeftPos.x ; i < topLeftPos.x + xSize ; ++i) { + const guint8* data3 = data2 + i*3; + rtengine::Coord currPos(i, j); + rtengine::Coord delta = pickerPos - currPos; + rtengine::PolarCoord p(delta); + if (p.radius <= radius) { + r2 += *data3; + g2 += *(data3+1); + b2 += *(data3+2); + ++count; + } + } + } + + // Averaging + r = (float)r2 / (float)count / 255.f; + g = (float)g2 / (float)count / 255.f; + b = (float)b2 / (float)count / 255.f; + + // Accumulating the data + r2=0, g2=0, b2=0; + count = 0; + data = cropPixbuf->get_pixels(); + for (int j = topLeftPos.y ; j < topLeftPos.y + ySize ; ++j) { + const guint8* data2 = data + cropPixbuf->get_rowstride()*j; + for (int i = topLeftPos.x ; i < topLeftPos.x + xSize ; ++i) { + const guint8* data3 = data2 + i*3; + rtengine::Coord currPos(i, j); + rtengine::Coord delta = pickerPos - currPos; + rtengine::PolarCoord p(delta); + if (p.radius <= radius) { + r2 += *data3; + g2 += *(data3+1); + b2 += *(data3+2); + ++count; + } + } + } + // Averaging + rpreview = (float)r2 / (float)count / 255.f; + gpreview = (float)g2 / (float)count / 255.f; + bpreview = (float)b2 / (float)count / 255.f; +} + void CropHandler::getSize (int& w, int& h) { diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 6e479bb16..1350df27e 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -22,6 +22,7 @@ #include "../rtengine/rtengine.h" #include "threadutils.h" #include "edit.h" +#include "lockablecolorpicker.h" #include class CropDisplayHandler @@ -94,23 +95,26 @@ public: } void setEditSubscriber (EditSubscriber* newSubscriber); - void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow); - void setZoom (int z, int centerx = -1, int centery = -1); - double getFitZoom (); + void newImage (rtengine::StagedImageProcessor* ipc_, bool isDetailWindow); + void setZoom (int z, int centerx = -1, int centery = -1); + float getZoomFactor (); + double getFitZoom (); double getFitCropZoom(); - void setWSize (int w, int h); - void getWSize (int& w, int &h); + void setWSize (int w, int h); + void getWSize (int& w, int &h); void getAnchorPosition (int& x, int& y); void setAnchorPosition (int x, int y, bool update = true); - void moveAnchor (int deltaX, int deltaY, bool update = true); - void centerAnchor (bool update = true); - void getPosition (int& x, int& y); - void getSize (int& w, int& h); + void moveAnchor (int deltaX, int deltaY, bool update = true); + void centerAnchor (bool update = true); + void getPosition (int& x, int& y); + void getSize (int& w, int& h); void getFullImageSize (int& w, int& h); void setEnabled (bool e); bool getEnabled (); + void colorPick (const rtengine::Coord &pickerPos, float &r, float &g, float &b, float &rpreview, float &gpreview, float &bpreview, LockableColorPicker::Size size); + rtengine::DetailedCrop* getCrop() { return crop; diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index c4b555e8f..a4d7ded47 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -30,6 +30,7 @@ #include "cursormanager.h" #include "options.h" #include "imagearea.h" +#include "lockablecolorpicker.h" using namespace rtengine; @@ -65,13 +66,13 @@ ZoomStep zoomSteps[] = { #define MAXZOOMSTEPS 20 #define ZOOM11INDEX 13 -CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) +CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow) : ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false), - fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), cropLabel(Glib::ustring("100%")), + fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")), backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0), imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(NULL), - pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL), ipc(ipc_) + pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL) { Glib::RefPtr context = parent->get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); @@ -109,7 +110,14 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, minWidth = bsw + iw + 2 * sideBorderWidth; cropHandler.setDisplayHandler(this); - cropHandler.newImage (ipc_, isDetailWindow); + cropHandler.newImage (parent->getImProcCoordinator(), isDetailWindow); +} + +CropWindow::~CropWindow () +{ + for (auto colorPicker : colorPickers) { + delete colorPicker; + } } void CropWindow::enable() @@ -265,6 +273,34 @@ void CropWindow::flawnOver (bool isFlawnOver) this->isFlawnOver = isFlawnOver; } +void CropWindow::scroll (int state, GdkScrollDirection direction, int x, int y) +{ + if ((state & GDK_CONTROL_MASK) && onArea(ColorPicker, x, y)) { + // resizing a color picker + if (direction == GDK_SCROLL_UP) { + hoveredPicker->incSize(); + updateHoveredPicker(); + iarea->redraw (); + }else if (direction == GDK_SCROLL_DOWN) { + hoveredPicker->decSize(); + updateHoveredPicker(); + iarea->redraw (); + } + } else { + // not over a color picker, we zoom in/out + int newCenterX = x; + int newCenterY = y; + + screenCoordToImage(newCenterX, newCenterY, newCenterX, newCenterY); + + if (direction == GDK_SCROLL_UP && !isMaxZoom()) { + zoomIn (true, newCenterX, newCenterY); + } else if (!isMinZoom()) { + zoomOut (true, newCenterX, newCenterY); + } + } +} + void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { @@ -274,7 +310,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) iarea->grabFocus (this); if (button == 1) { - if (type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) { + if (type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && iarea->getToolMode () != TMColorPicker && (state == SNormal || state == SCropImgMove)) { if (fitZoomEnabled) { if (fitZoom) { state = SNormal; @@ -308,7 +344,35 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) press_y = height; } else { if (onArea (CropImage, x, y)) { // events inside of the image domain - if (onArea (CropTopLeft, x, y)) { + if (iarea->getToolMode () == TMColorPicker) { + if (hoveredPicker) { + if ((bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + hoveredPicker->decSize(); + updateHoveredPicker(); + needRedraw = true; + } else if (!(bstate & GDK_CONTROL_MASK) && (bstate & GDK_SHIFT_MASK)) { + hoveredPicker->rollDisplayedValues(); + needRedraw = true; + } else if (!(bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + // Color Picker drag starts + state = SDragPicker; + } + } else { + // Add a new Color Picker + rtengine::Coord imgPos; + screenCoordToImage(x, y, imgPos.x, imgPos.y); + LockableColorPicker *newPicker = new LockableColorPicker(this, &cropHandler.colorParams.output, &cropHandler.colorParams.working); + colorPickers.push_back(newPicker); + hoveredPicker = newPicker; + updateHoveredPicker(&imgPos); + state = SDragPicker; + press_x = x; + press_y = y; + action_x = 0; + action_y = 0; + needRedraw = true; + } + } else if (onArea (CropTopLeft, x, y)) { state = SResizeTL; press_x = x; action_x = cropHandler.cropParams.x; @@ -430,6 +494,18 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_x = 0; action_y = 0; } + } else if (iarea->getToolMode () == TMColorPicker && hoveredPicker) { + if ((bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + if (hoveredPicker->decSize()) { + updateHoveredPicker(); + needRedraw = true; + } + } else if (!(bstate & GDK_CONTROL_MASK) && (bstate & GDK_SHIFT_MASK)) { + hoveredPicker->rollDisplayedValues(); + } else if (!(bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + // Color Picker drag starts + state = SDragPicker; + } } } } @@ -473,6 +549,37 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) action_y = 0; } } + else if (iarea->getToolMode () == TMColorPicker && type == GDK_BUTTON_PRESS && state == SNormal) { + if (hoveredPicker) { + if((bstate & GDK_CONTROL_MASK) && (bstate & GDK_SHIFT_MASK)) { + // Deleting all pickers ! + for (auto colorPicker : colorPickers) { + delete colorPicker; + } + colorPickers.clear(); + hoveredPicker = nullptr; + state = SDeletePicker; + needRedraw = true; + } else if ((bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + if (hoveredPicker->incSize()) { + updateHoveredPicker(); + needRedraw = true; + } + } else if (!(bstate & GDK_CONTROL_MASK) && !(bstate & GDK_SHIFT_MASK)) { + // Deleting the hovered picker + for (std::vector::iterator i = colorPickers.begin(); i != colorPickers.end(); ++i) { + if (*i == hoveredPicker) { + colorPickers.erase(i); + delete hoveredPicker; + hoveredPicker = nullptr; + state = SDeletePicker; + needRedraw = true; + break; + } + } + } + } + } } if (needRedraw) { @@ -506,6 +613,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) } needRedraw = true; + } else if (state == SCropWinMove) { + if (iarea->showColorPickers () && !colorPickers.empty()) { + needRedraw = true; + } } else if (state == SCropImgMove) { cropHandler.update (); @@ -602,6 +713,10 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) } else { iarea->object = 0; } + } else if (state == SDeletePicker) { + needRedraw = true; + } else if (state == SNormal && iarea->getToolMode() == TMColorPicker && !hoveredPicker && button == 3) { + iarea->setToolHand (); } if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) { @@ -620,7 +735,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y) return; } - if (state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) { + if (state != SDeletePicker && state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) { iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f; needRedraw = iarea->object == 1; @@ -778,6 +893,26 @@ void CropWindow::pointerMoved (int bstate, int x, int y) action_x = new_action_x; action_y = new_action_y; iarea->redraw (); + } else if (state == SDragPicker) { + Coord imgPos; + action_x = x - press_x; + action_x = y - press_y; + screenCoordToImage (x, y, imgPos.x, imgPos.y); + if (imgPos.x < 0) { + imgPos.x = 0; + }else if (imgPos.x >= iarea->getImProcCoordinator()->getFullWidth()) { + imgPos.x = iarea->getImProcCoordinator()->getFullWidth()-1; + } + if (imgPos.y < 0) { + imgPos.y = 0; + }else if (imgPos.y >= iarea->getImProcCoordinator()->getFullHeight()) { + imgPos.y = iarea->getImProcCoordinator()->getFullHeight()-1; + } + updateHoveredPicker (&imgPos); + iarea->redraw (); + } else if (state == SNormal && iarea->getToolMode () == TMColorPicker && onArea(ColorPicker, x, y)) { + // TODO: we could set the hovered picker as Highlighted here + // Keep this if statement, the onArea will find out the hoveredPicker and will be used to update the cursor } else if (editSubscriber) { rtengine::Crop* crop = static_cast(cropHandler.getCrop()); @@ -931,6 +1066,16 @@ bool CropWindow::onArea (CursorArea a, int x, int y) case CropImage: return x >= xpos + imgX + imgAreaX && y >= ypos + imgY + imgAreaY && x < xpos + imgX + imgAreaX + imgW && y < ypos + imgY + imgAreaY + imgH; + case ColorPicker: + for (auto colorPicker : colorPickers) { + if (colorPicker->isOver(x, y)) { + hoveredPicker = colorPicker; + return true; + } + } + hoveredPicker = nullptr; + return false; + case CropBorder: return (x >= xpos + imgAreaX && y >= ypos + imgAreaY && x < xpos + imgAreaX + imgAreaW && y < ypos + imgAreaY + imgAreaH) && @@ -1048,6 +1193,8 @@ void CropWindow::updateCursor (int x, int y) cursorManager.setCursor (iarea->get_window(), CSMove); } else if (onArea (CropResize, x, y)) { cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal); + } else if (tm == TMColorPicker && hoveredPicker) { + cursorManager.setCursor (iarea->get_window(), CSMove); } else if (tm == TMHand && (onArea (CropTopLeft, x, y))) { cursorManager.setCursor (iarea->get_window(), CSResizeTopLeft); } else if (tm == TMHand && (onArea (CropTopRight, x, y))) { @@ -1083,6 +1230,8 @@ void CropWindow::updateCursor (int x, int y) cursorManager.setCursor (iarea->get_window(), CSCropSelect); } else if (tm == TMStraighten) { cursorManager.setCursor (iarea->get_window(), CSStraighten); + } else if (tm == TMColorPicker) { + cursorManager.setCursor (iarea->get_window(), CSAddColPicker); } } else { int objectID = -1; @@ -1121,6 +1270,8 @@ void CropWindow::updateCursor (int x, int y) cursorManager.setCursor (iarea->get_window(), CSResizeBottomRight); } else if (state == SCropWinResize) { cursorManager.setCursor (iarea->get_window(), CSResizeDiagonal); + } else if (state == SDragPicker) { + cursorManager.setCursor (iarea->get_window(), CSMove2D); } } @@ -1128,6 +1279,8 @@ void CropWindow::expose (Cairo::RefPtr cr) { MyMutex::MyLock lock(cropHandler.cimg); + bool isPreviewImg = false; + if (decorated) { drawDecoration (cr); } @@ -1640,6 +1793,8 @@ void CropWindow::expose (Cairo::RefPtr cr) } } + + isPreviewImg = true; } else { // cropHandler.cropPixbuf is null int cropX, cropY; @@ -1674,6 +1829,12 @@ void CropWindow::expose (Cairo::RefPtr cr) } } + if ((state == SNormal || state == SDragPicker) && isPreviewImg && iarea->showColorPickers()) { + for (auto colorPicker : colorPickers) { + colorPicker->draw(cr); + } + } + //t2.set (); // printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3)); } @@ -1888,10 +2049,10 @@ void CropWindow::buttonPressed (LWButton* button, int actionCode, void* actionDa } else if (button == bZoom100) { // zoom 100 zoom11 (); } else if (button == bClose) { // close - if(ipc->updateTryLock()) { + if(iarea->getImProcCoordinator()->updateTryLock()) { deleted = true; iarea->cropWindowClosed (this); - ipc->updateUnLock(); + iarea->getImProcCoordinator()->updateUnLock(); } } } @@ -1902,6 +2063,31 @@ void CropWindow::redrawNeeded (LWButton* button) iarea->redraw (); } +void CropWindow::updateHoveredPicker (rtengine::Coord *imgPos) +{ + + if (!hoveredPicker) { + return; + } + + rtengine::Coord cropPos; + float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; + if (imgPos) { + imageCoordToCropImage(imgPos->x, imgPos->y, cropPos.x, cropPos.y); + hoveredPicker->setPosition (*imgPos); + } else { + rtengine::Coord imgPos2; + hoveredPicker->getImagePosition(imgPos2); + imageCoordToCropImage(imgPos2.x, imgPos2.y, cropPos.x, cropPos.y); + } + LockableColorPicker::Validity validity = checkValidity (hoveredPicker, cropPos); + hoveredPicker->setValidity (validity); + if (validity == LockableColorPicker::Validity::INSIDE) { + cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize()); + hoveredPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); + } +} void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) { @@ -1924,6 +2110,43 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) iarea->redraw (); } +LockableColorPicker::Validity CropWindow::checkValidity (LockableColorPicker* picker, const rtengine::Coord &pos) +{ + + if (!cropHandler.cropPixbuftrue) { + return LockableColorPicker::Validity::OUTSIDE; + } + rtengine::Coord cropTopLeft, cropBottomRight, cropSize; + int skip; + cropHandler.getWindow(cropTopLeft.x, cropTopLeft.y, cropSize.x, cropSize.y, skip); + cropBottomRight = cropTopLeft + cropSize; + rtengine::Coord pickerPos, cropPickerPos; + picker->getImagePosition(pickerPos); + rtengine::Coord minPos(0, 0); + rtengine::Coord maxPos(cropHandler.cropPixbuftrue->get_width(), cropHandler.cropPixbuftrue->get_height()); + rtengine::Coord halfPickerSize((int)picker->getSize()/2, (int)picker->getSize()/2); + imageCoordToCropImage (pickerPos.x, pickerPos.y, cropPickerPos.x, cropPickerPos.y); + imageCoordToCropImage (cropTopLeft.x, cropTopLeft.y, minPos.x, minPos.y); + imageCoordToCropImage (cropBottomRight.x, cropBottomRight.y, maxPos.x, maxPos.y); + rtengine::Coord pickerMinPos = cropPickerPos - halfPickerSize; + rtengine::Coord pickerMaxPos = cropPickerPos + halfPickerSize; + if (pickerMaxPos.x < minPos.x || pickerMaxPos.y < minPos.y || pickerMinPos.x > maxPos.x || pickerMinPos.y > maxPos.y) { + return LockableColorPicker::Validity::OUTSIDE; + } else if (pickerMinPos >= minPos && pickerMaxPos < maxPos) { + return LockableColorPicker::Validity::INSIDE; + } else { + return LockableColorPicker::Validity::CROSSING; + } +} + +void CropWindow::deleteColorPickers () +{ + for (auto colorPicker : colorPickers) { + delete colorPicker; + } + colorPickers.clear(); +} + void CropWindow::screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy) { @@ -1945,8 +2168,8 @@ void CropWindow::screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) int cropX, cropY; cropHandler.getPosition (cropX, cropY); - imgx = cropX + (phyx - xpos - imgX) / zoomSteps[cropZoom].zoom; - imgy = cropY + (phyy - ypos - imgY) / zoomSteps[cropZoom].zoom; + imgx = cropX + (phyx - xpos - imgX - imgAreaX) / zoomSteps[cropZoom].zoom; + imgy = cropY + (phyy - ypos - imgY - imgAreaY) / zoomSteps[cropZoom].zoom; } void CropWindow::screenCoordToCropCanvas (int phyx, int phyy, int& prevx, int& prevy) @@ -1983,6 +2206,14 @@ void CropWindow::imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phy phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom + /*ypos + imgY +*/ crop->getUpperBorder(); } +void CropWindow::imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy) +{ + int cropX, cropY; + cropHandler.getPosition (cropX, cropY); + phyx = (imgx - cropX) * zoomSteps[cropZoom].zoom; + phyy = (imgy - cropY) * zoomSteps[cropZoom].zoom; +} + int CropWindow::scaleValueToImage (int value) { return int(double(value) / zoomSteps[cropZoom].zoom); @@ -2220,6 +2451,16 @@ void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, in void CropWindow::cropImageUpdated () { + for (auto colorPicker : colorPickers) { + Coord imgPos, cropPos; + colorPicker->getImagePosition(imgPos); + imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y); + float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; + colorPicker->setValidity (checkValidity (colorPicker, cropPos)); + cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, colorPicker->getSize()); + colorPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); + } iarea->redraw (); } @@ -2281,7 +2522,61 @@ void CropWindow::delCropWindowListener (CropWindowListener* l) } } -EditDataProvider* CropWindow::getImageArea() +ImageArea* CropWindow::getImageArea() { return iarea; } + +void CropWindow::setCropGUIListener (CropGUIListener* cgl) +{ + cropgl = cgl; +} + +void CropWindow::setPointerMotionListener (PointerMotionListener* pml) +{ + pmlistener = pml; + if (pml) { + pml->signal_cycle_rgb().connect( sigc::mem_fun(*this, &CropWindow::cycleRGB) ); + pml->signal_cycle_hsv().connect( sigc::mem_fun(*this, &CropWindow::cycleHSV) ); + } +} + +PointerMotionListener* CropWindow::getPointerMotionListener () +{ + return pmlistener; +} + +void CropWindow::setPointerMotionHListener (PointerMotionListener* pml) +{ + pmhlistener = pml; +} + +// crop window listeners +void CropWindow::addCropWindowListener (CropWindowListener* l) +{ + listeners.push_back (l); +} + +void CropWindow::cycleRGB () +{ + bool redraw = false; + for (auto colorPicker : colorPickers) { + redraw |= colorPicker->cycleRGB (); + } + + if (redraw) { + iarea->redraw (); + } +} + +void CropWindow::cycleHSV () +{ + bool redraw = false; + for (auto colorPicker : colorPickers) { + redraw |= colorPicker->cycleHSV (); + } + + if (redraw) { + iarea->redraw (); + } +} diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index d9f738f66..eec1b812a 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -59,6 +59,10 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed bool fitZoom; bool isLowUpdatePriority; + // color pickers + std::vector colorPickers; + LockableColorPicker* hoveredPicker; + // decoration LWButton *bZoomIn, *bZoomOut, *bZoom100, /**bZoomFit,*/ *bClose; LWButtonSet buttonSet; @@ -90,7 +94,6 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed std::list listeners; CropWindow* observedCropWin; // Pointer to the currently active detail CropWindow - rtengine::StagedImageProcessor* ipc; bool onArea (CursorArea a, int x, int y); void updateCursor (int x, int y); @@ -100,13 +103,19 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed void drawUnscaledSpotRectangle (Cairo::RefPtr cr, int rectSize); void drawObservedFrame (Cairo::RefPtr cr, int rw = 0, int rh = 0); void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1); + void updateHoveredPicker (rtengine::Coord *imgPos = nullptr); + void cycleRGB (); + void cycleHSV (); + + LockableColorPicker::Validity checkValidity (LockableColorPicker* picker, const rtengine::Coord &pos); // Used by the mainCropWindow only void getObservedFrameArea (int& x, int& y, int& w, int& h, int rw = 0, int rh = 0); public: CropHandler cropHandler; - CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow); + CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow); + ~CropWindow (); void setDecorated (bool decorated) { @@ -120,6 +129,7 @@ public: { observedCropWin = cw; } + void deleteColorPickers (); void screenCoordToCropBuffer (int phyx, int phyy, int& cropx, int& cropy); void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy); @@ -127,6 +137,7 @@ public: void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy); void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy); + void imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy); int scaleValueToImage (int value); float scaleValueToImage (float value); double scaleValueToImage (double value); @@ -157,6 +168,7 @@ public: bool isInside (int x, int y); + void scroll (int state, GdkScrollDirection direction, int x, int y); void buttonPress (int button, int num, int state, int x, int y); void buttonRelease (int button, int num, int state, int x, int y); void pointerMoved (int bstate, int x, int y); @@ -179,24 +191,13 @@ public: void setCropAnchorPosition (int& w, int& h); // listeners - void setCropGUIListener (CropGUIListener* cgl) - { - cropgl = cgl; - } - void setPointerMotionListener (PointerMotionListener* pml) - { - pmlistener = pml; - } - void setPointerMotionHListener (PointerMotionListener* pml) - { - pmhlistener = pml; - } + void setCropGUIListener (CropGUIListener* cgl); + void setPointerMotionListener (PointerMotionListener* pml); + PointerMotionListener* getPointerMotionListener (); + void setPointerMotionHListener (PointerMotionListener* pml); // crop window listeners - void addCropWindowListener (CropWindowListener* l) - { - listeners.push_back (l); - } + void addCropWindowListener (CropWindowListener* l); void delCropWindowListener (CropWindowListener* l); // crophandlerlistener interface @@ -208,7 +209,7 @@ public: void remoteMove (int deltaX, int deltaY); void remoteMoveReady (); - EditDataProvider* getImageArea(); + ImageArea* getImageArea(); }; #endif diff --git a/rtgui/cursormanager.cc b/rtgui/cursormanager.cc index e011fd969..78e2513a5 100644 --- a/rtgui/cursormanager.cc +++ b/rtgui/cursormanager.cc @@ -44,6 +44,7 @@ void CursorManager::init (Glib::RefPtr mainWin) Glib::RefPtr hand = RTImage::createFromFile ("cross.png"); Glib::RefPtr close_hand = RTImage::createFromFile ("closedhand.png"); Glib::RefPtr wbpick = RTImage::createFromFile ("gtk-color-picker-small.png"); + Glib::RefPtr cpick = RTImage::createFromFile ("gtk-color-picker-add.png"); Glib::RefPtr empty = RTImage::createFromFile ("empty.png"); Glib::RefPtr move2D = RTImage::createFromFile ("move-2D.png"); Glib::RefPtr move1DH = RTImage::createFromFile ("move-1D-h.png"); @@ -52,7 +53,8 @@ void CursorManager::init (Glib::RefPtr mainWin) cHand = hand ? new Gdk::Cursor (cAdd->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2); cClosedHand = close_hand ? new Gdk::Cursor (cAdd->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2); - cWB = wbpick ? new Gdk::Cursor (cAdd->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW); + cWB = wbpick ? new Gdk::Cursor (cAdd->get_display(), wbpick, 3, 15) : new Gdk::Cursor (Gdk::ARROW); + cAddPicker = cpick ? new Gdk::Cursor (cAdd->get_display(), cpick, 3, 18) : new Gdk::Cursor (Gdk::ARROW); cHidden = empty ? new Gdk::Cursor (cAdd->get_display(), empty, 12, 12) : new Gdk::Cursor (Gdk::FLEUR); cMove2D = move2D ? new Gdk::Cursor (cAdd->get_display(), move2D, 11, 11) : new Gdk::Cursor (Gdk::FLEUR); cMove1DH = move1DH ? new Gdk::Cursor (cAdd->get_display(), move1DH, 11, 11) : new Gdk::Cursor (Gdk::FLEUR); @@ -100,6 +102,8 @@ void CursorManager::setCursor (Glib::RefPtr window, CursorShape sha window->set_cursor (*cMoveRotate); } else if (shape == CSSpotWB) { window->set_cursor (*cWB); + } else if (shape == CSAddColPicker) { + window->set_cursor (*cAddPicker); } else if (shape == CSCropSelect) { window->set_cursor (*cHand); } else if (shape == CSMoveLeft) { diff --git a/rtgui/cursormanager.h b/rtgui/cursormanager.h index b51fb1e38..f256415c1 100644 --- a/rtgui/cursormanager.h +++ b/rtgui/cursormanager.h @@ -26,7 +26,7 @@ enum CursorShape { CSMoveRight, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSResizeTopLeft, CSResizeTopRight, CSResizeBottomLeft, CSResizeBottomRight, CSMove2D, CSMove1DH, CSMove1DV, CSMoveRotate, - CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSWait, CSEmpty + CSSpotWB, CSAddColPicker, CSCropSelect, CSStraighten, CSPlus, CSWait, CSEmpty }; class CursorManager @@ -51,6 +51,7 @@ protected: Gdk::Cursor* cHand; Gdk::Cursor* cClosedHand; Gdk::Cursor* cWB; + Gdk::Cursor* cAddPicker; Gdk::Cursor* cHidden; Gdk::Cursor* cMove2D; Gdk::Cursor* cMove1DH; diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc index adf950ab0..46c89edb8 100644 --- a/rtgui/curveeditorgroup.cc +++ b/rtgui/curveeditorgroup.cc @@ -113,10 +113,9 @@ CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabe */ void CurveEditorGroup::newLine() { - Gtk::HBox* headerBox; if (curveEditors.size() > numberOfPackedCurve) { - headerBox = Gtk::manage (new Gtk::HBox ()); + Gtk::HBox* headerBox = Gtk::manage (new Gtk::HBox ()); if (!numberOfPackedCurve) { headerBox->pack_start(*curveGroupLabel, Gtk::PACK_SHRINK, 2); @@ -381,7 +380,7 @@ void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) } } -CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), lastFilename("") +CurveEditorSubGroup::CurveEditorSubGroup(Glib::ustring& curveDir) : curveDir(curveDir), lastFilename(""), valLinear(0), valUnchanged(0), parent(nullptr), curveBBoxPos(0) { leftBar = NULL; bottomBar = NULL; diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h index 09cbb8167..f4ca3e8ed 100644 --- a/rtgui/curveeditorgroup.h +++ b/rtgui/curveeditorgroup.h @@ -154,7 +154,7 @@ protected: * This variable will be updated with actions in the * dialogs. */ - CurveEditorSubGroup(Glib::ustring& curveDir); + explicit CurveEditorSubGroup(Glib::ustring& curveDir); Glib::ustring outputFile (); Glib::ustring inputFile (); diff --git a/rtgui/diagonalcurveeditorsubgroup.cc b/rtgui/diagonalcurveeditorsubgroup.cc index 657186a12..a806a710d 100644 --- a/rtgui/diagonalcurveeditorsubgroup.cc +++ b/rtgui/diagonalcurveeditorsubgroup.cc @@ -1117,12 +1117,10 @@ bool DiagonalCurveEditorSubGroup::curveReset(CurveEditor *ce) case (DCT_NURBS) : // = Control cage NURBSCurve->reset (dce->NURBSResetCurve, dce->getIdentityValue()); return true; - break; case (DCT_Spline) : // = Custom customCurve->reset (dce->customResetCurve, dce->getIdentityValue()); return true; - break; case (DCT_Parametric) : { DiagonalCurveEditor* dCurve = static_cast(parent->displayedCurve); @@ -1137,12 +1135,10 @@ bool DiagonalCurveEditorSubGroup::curveReset(CurveEditor *ce) shcSelector->reset(); paramCurve->reset (dce->paramResetCurve, dce->getIdentityValue()); return true; - break; } default: return false; - break; } return true; diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index 6f25f0f47..9eaf38587 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -59,7 +59,7 @@ std::vector listSubDirs (const Glib::RefPtr& dir, bool } catch (const Glib::Exception& exception) { if (options.rtSettings.verbose) { - std::cerr << "Failed to list subdirectories of \"" << dir->get_basename() << "\": " << exception.what () << std::endl; + std::cerr << "Failed to list subdirectories of \"" << dir->get_parse_name() << "\": " << exception.what () << std::endl; } } diff --git a/rtgui/edit.h b/rtgui/edit.h index c49c45408..e28a6acec 100644 --- a/rtgui/edit.h +++ b/rtgui/edit.h @@ -208,10 +208,12 @@ public: virtual void screenCoordToImage (int phyx, int phyy, int& imgx, int& imgy) = 0; /// Convert the image coords to the widget's DrawingArea (i.e. preview area) coords virtual void imageCoordToScreen (int imgx, int imgy, int& phyx, int& phyy) = 0; - /// Convert the image coords to the crop's canvas coords + /// Convert the image coords to the crop's canvas coords (full image + padding) virtual void imageCoordToCropCanvas (int imgx, int imgy, int& phyx, int& phyy) = 0; - /// Convert the image coords to the edit buffer coords + /// Convert the image coords to the edit buffer coords (includes borders) virtual void imageCoordToCropBuffer (int imgx, int imgy, int& phyx, int& phyy) = 0; + /// Convert the image coords to the displayed image coords (no borders here) + virtual void imageCoordToCropImage (int imgx, int imgy, int& phyx, int& phyy) = 0; /// Convert a size value from the preview's scale to the image's scale virtual int scaleValueToImage (int value) = 0; /// Convert a size value from the preview's scale to the image's scale @@ -463,7 +465,7 @@ protected: } action; /// object mode only, ignored in Pipette mode public: - EditSubscriber (EditType editType); + explicit EditSubscriber (EditType editType); virtual ~EditSubscriber () {} void setEditProvider(EditDataProvider *provider); diff --git a/rtgui/editenums.h b/rtgui/editenums.h index 557912222..264576789 100644 --- a/rtgui/editenums.h +++ b/rtgui/editenums.h @@ -21,9 +21,9 @@ enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR, SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, - SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3 + SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3, SDragPicker, SDeletePicker }; -enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft, +enum CursorArea {CropWinButtons, CropToolBar, CropImage, ColorPicker, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft, CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved }; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index f8af941c8..2015586d8 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -223,7 +223,7 @@ private: } public: - ColorManagementToolbar (rtengine::StagedImageProcessor* const& ipc) : + explicit ColorManagementToolbar (rtengine::StagedImageProcessor* const& ipc) : intentBox (Glib::ustring (), true), processor (ipc) { @@ -392,6 +392,7 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iareapanel = new ImageAreaPanel (); tpc->setEditProvider(iareapanel->imageArea); + tpc->getToolBar()->setLockablePickerToolListener(iareapanel->imageArea); Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ()); toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1); diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index dbf99d58d..921cc9c64 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -138,7 +138,7 @@ protected: public: - EditorPanel (FilePanel* filePanel = NULL); + explicit EditorPanel (FilePanel* filePanel = NULL); virtual ~EditorPanel (); void open (Thumbnail* tmb, rtengine::InitialImage* isrc); diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc index 605e915af..3115d9c1f 100644 --- a/rtgui/editwindow.cc +++ b/rtgui/editwindow.cc @@ -37,7 +37,7 @@ EditWindow* EditWindow::getInstance(RTWindow* p) { EditWindow editWnd; - EditWindowInstance(RTWindow* p) : editWnd(p) + explicit EditWindowInstance(RTWindow* p) : editWnd(p) { // Determine the other display and maximize the window on that const Glib::RefPtr< Gdk::Window >& wnd = p->get_window(); diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h index fa47de489..9315b0eb9 100644 --- a/rtgui/editwindow.h +++ b/rtgui/editwindow.h @@ -42,7 +42,7 @@ public: // Should only be created once, auto-creates window on correct display static EditWindow* getInstance(RTWindow* p); - EditWindow (RTWindow* p); + explicit EditWindow (RTWindow* p); void addEditorPanel (EditorPanel* ep, const std::string &name); void remEditorPanel (EditorPanel* ep); diff --git a/rtgui/extprog.cc b/rtgui/extprog.cc index 06f99826d..cf2b6ba9c 100644 --- a/rtgui/extprog.cc +++ b/rtgui/extprog.cc @@ -102,7 +102,7 @@ void ExtProgStore::init () #endif } - +#ifdef WIN32 bool ExtProgStore::searchProgram (const Glib::ustring& name, const Glib::ustring& exePath, const Glib::ustring& exePath86, @@ -111,7 +111,6 @@ bool ExtProgStore::searchProgram (const Glib::ustring& name, bool allowQueueProcess) { -#ifdef WIN32 // get_user_special_dir crashes on some Windows configurations. static Glib::ustring progFilesDir, progFilesDirx86; @@ -196,10 +195,10 @@ bool ExtProgStore::searchProgram (const Glib::ustring& name, return true; } -#endif return false; } +#endif bool ExtProgStore::spawnCommandAsync (const Glib::ustring& cmd) { diff --git a/rtgui/extprog.h b/rtgui/extprog.h index fe7375ce7..154a825e1 100644 --- a/rtgui/extprog.h +++ b/rtgui/extprog.h @@ -44,13 +44,14 @@ class ExtProgStore MyMutex mtx; // covers actions std::vector actions; +#ifdef WIN32 bool searchProgram (const Glib::ustring& name, const Glib::ustring& exePath, const Glib::ustring& exePath86, int maxVer, bool allowRaw, bool allowQueueProcess); - +#endif public: static ExtProgStore* getInstance(); diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 68825c696..e3066e4dc 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -487,13 +487,13 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) untrash->set_sensitive (false); for (size_t i = 0; i < selected.size(); i++) - if ((static_cast(selected[i]))->thumbnail->getStage() == 1) { + if ((static_cast(selected[i]))->thumbnail->getStage()) { untrash->set_sensitive (true); break; } for (size_t i = 0; i < selected.size(); i++) - if ((static_cast(selected[i]))->thumbnail->getStage() == 0) { + if (!(static_cast(selected[i]))->thumbnail->getStage()) { trash->set_sensitive (true); break; } @@ -512,7 +512,6 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) submenuDF->attach (*Gtk::manage(autoDF = new Gtk::MenuItem (M("FILEBROWSER_AUTODARKFRAME"))), 0, 1, p, p + 1); p++; submenuDF->attach (*Gtk::manage(thisIsDF = new Gtk::MenuItem (M("FILEBROWSER_MOVETODARKFDIR"))), 0, 1, p, p + 1); - p++; selectDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selectDF)); autoDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoDF)); thisIsDF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), thisIsDF )); @@ -527,7 +526,6 @@ void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) submenuFF->attach (*Gtk::manage(autoFF = new Gtk::MenuItem (M("FILEBROWSER_AUTOFLATFIELD"))), 0, 1, p, p + 1); p++; submenuFF->attach (*Gtk::manage(thisIsFF = new Gtk::MenuItem (M("FILEBROWSER_MOVETOFLATFIELDDIR"))), 0, 1, p, p + 1); - p++; selectFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selectFF)); autoFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), autoFF)); thisIsFF->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), thisIsFF )); @@ -612,7 +610,7 @@ void FileBrowser::addEntry_ (FileBrowserEntry* entry) entry->addButtonSet (new FileThumbnailButtonSet (entry)); entry->getThumbButtonSet()->setRank (entry->thumbnail->getRank()); entry->getThumbButtonSet()->setColorLabel (entry->thumbnail->getColorLabel()); - entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage() == 1); + entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()); entry->getThumbButtonSet()->setButtonListener (this); entry->resize (getThumbnailHeight()); @@ -1134,8 +1132,9 @@ bool FileBrowser::keyPressed (GdkEventKey* event) bool ctrl = event->state & GDK_CONTROL_MASK; bool shift = event->state & GDK_SHIFT_MASK; bool alt = event->state & GDK_MOD1_MASK; +#ifdef __WIN32__ bool altgr = event->state & GDK_MOD2_MASK; - +#endif if ((event->keyval == GDK_C || event->keyval == GDK_c || event->keyval == GDK_Insert) && ctrl) { copyProfile (); return true; @@ -1474,8 +1473,8 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry ((entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[0]) && !filter.showRecentlySaved[1]) || ((!entry->thumbnail->isRecentlySaved() && filter.showRecentlySaved[1]) && !filter.showRecentlySaved[0]) || - (entry->thumbnail->getStage() == 1 && !filter.showTrash) || - (entry->thumbnail->getStage() == 0 && !filter.showNotTrash)) { + (entry->thumbnail->getStage() && !filter.showTrash) || + (!entry->thumbnail->getStage() && !filter.showNotTrash)) { return false; } @@ -1568,11 +1567,11 @@ void FileBrowser::toTrashRequested (std::vector tbe) // no need to notify listeners as item goes to trash, likely to be deleted - if (tbe[i]->thumbnail->getStage() == 1) { + if (tbe[i]->thumbnail->getStage()) { continue; } - tbe[i]->thumbnail->setStage (1); + tbe[i]->thumbnail->setStage (true); if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank()); @@ -1592,11 +1591,11 @@ void FileBrowser::fromTrashRequested (std::vector tbe) for (size_t i = 0; i < tbe.size(); i++) { // if thumbnail was marked inTrash=true then param file must be there, no need to run customprofilebuilder - if (tbe[i]->thumbnail->getStage() == 0) { + if (!tbe[i]->thumbnail->getStage()) { continue; } - tbe[i]->thumbnail->setStage (0); + tbe[i]->thumbnail->setStage (false); if (tbe[i]->getThumbButtonSet()) { tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank()); @@ -1715,7 +1714,7 @@ void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionD FileBrowserEntry* entry = static_cast(actionData); tbe.push_back (entry); - if (entry->thumbnail->getStage() == 0) { + if (!entry->thumbnail->getStage()) { toTrashRequested (tbe); } else { fromTrashRequested (tbe); diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index ad11e079d..21660d330 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -989,9 +989,6 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m fc.set_filename(tbe[0]->filename); //!!! TODO prevent dialog closing on "enter" key press - bool filecopymovecomplete; - int i_copyindex; - if( fc.run() == Gtk::RESPONSE_OK ) { Glib::ustring dest_Dir = fc.get_current_folder(); @@ -1020,8 +1017,8 @@ void FileCatalog::copyMoveRequested (std::vector tbe, bool m /* comparison of src_Dir and dest_Dir is done per image for compatibility with possible future use of Collections as source where each file's source path may be different.*/ - filecopymovecomplete = false; - i_copyindex = 1; + bool filecopymovecomplete = false; + int i_copyindex = 1; while(!filecopymovecomplete) { // check for filename conflicts at destination - prevent overwriting (actually RT will crash on overwriting attempt) @@ -1225,8 +1222,6 @@ void FileCatalog::setExportPanel (ExportPanel* expanel) void FileCatalog::renameRequested (std::vector tbe) { - bool success; - RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel()); for (size_t i = 0; i < tbe.size(); i++) { @@ -1236,7 +1231,7 @@ void FileCatalog::renameRequested (std::vector tbe) Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename); Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename); - success = false; + bool success = false; do { if (renameDlg->run () == Gtk::RESPONSE_OK) { diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index b7ea1802f..eb23e65a6 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -43,7 +43,7 @@ class DirEntry public: Glib::ustring fullName; - DirEntry (const Glib::ustring& n) : fullName (n) {} + explicit DirEntry (const Glib::ustring& n) : fullName (n) {} bool operator< (DirEntry& other) { diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index fd53db555..429c8f430 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -52,7 +52,6 @@ FilePanel::FilePanel () : parent(NULL) dirpaned->pack1 (*placespaned, false, true); tpc = new BatchToolPanelCoordinator (this); - tpc->removeWbTool(); fileCatalog = Gtk::manage ( new FileCatalog (tpc->coarse, tpc->getToolBar(), this) ); ribbonPane = Gtk::manage ( new Gtk::Paned() ); ribbonPane->add(*fileCatalog); diff --git a/rtgui/filethumbnailbuttonset.h b/rtgui/filethumbnailbuttonset.h index b152c3853..a83bacf7b 100644 --- a/rtgui/filethumbnailbuttonset.h +++ b/rtgui/filethumbnailbuttonset.h @@ -44,7 +44,7 @@ public: static Cairo::RefPtr colorLabelIcon_4; static Cairo::RefPtr colorLabelIcon_5; - FileThumbnailButtonSet (FileBrowserEntry* myEntry); + explicit FileThumbnailButtonSet (FileBrowserEntry* myEntry); void setRank (int stars); void setColorLabel (int colorlabel); void setInTrash (bool inTrash); diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index c984a03f1..e52c83e65 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -1080,11 +1080,35 @@ void TextOrIcon::switchTo(TOITypes type) BackBuffer::BackBuffer() : x(0), y(0), w(0), h(0), offset(0, 0), dirty(true) {} +void BackBuffer::setDestPosition(int x, int y) +{ + // values will be clamped when used... + this->x = x; + this->y = y; +} + void BackBuffer::setSrcOffset(int x, int y) { // values will be clamped when used... - offset.x = x; - offset.y = y; + offset.set(x, y); +} + +void BackBuffer::setSrcOffset(const rtengine::Coord &newOffset) +{ + // values will be clamped when used... + offset = newOffset; +} + +void BackBuffer::getSrcOffset(int &x, int &y) +{ + // values will be clamped when used... + offset.get(x, y); +} + +void BackBuffer::getSrcOffset(rtengine::Coord &offset) +{ + // values will be clamped when used... + offset = this->offset; } // Note: newW & newH must be > 0 @@ -1092,12 +1116,16 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, in { assert(newW && newH); - bool newSize = w != newW || h != newH; + bool newSize = (newW > 0 && w != newW) || (newH > 0 && h != newH); x = newX; y = newY; - w = newW; - h = newH; + if (newH > 0) { + w = newW; + } + if (newH > 0) { + h = newH; + } // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? if (updateBackBufferSize && newSize && window) { @@ -1113,14 +1141,18 @@ bool BackBuffer::setDrawRectangle(Glib::RefPtr window, int newX, in // Note: newW & newH must be > 0 bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize) { - assert(!newW && !newH); + assert(newW && newH); - bool newSize = w != newW || h != newH; + bool newSize = (newW > 0 && w != newW) || (newH > 0 && h != newH); x = newX; y = newY; - w = newW; - h = newH; + if (newH > 0) { + w = newW; + } + if (newH > 0) { + h = newH; + } // WARNING: we're assuming that the surface type won't change during all the execution time of RT. I guess it may be wrong when the user change the gfx card display settings!? if (updateBackBufferSize && newSize) { @@ -1136,7 +1168,7 @@ bool BackBuffer::setDrawRectangle(Cairo::Format format, int newX, int newY, int /* * Copy the backbuffer to a Gdk::Window */ -void BackBuffer::copySurface(Glib::RefPtr window, GdkRectangle *rectangle) +void BackBuffer::copySurface(Glib::RefPtr &window, GdkRectangle *rectangle) { if (surface && window) { // TODO: look out if window can be different on each call, and if not, store a reference to the window @@ -1190,7 +1222,7 @@ void BackBuffer::copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle /* * Copy the BackBuffer to another Cairo::Surface */ -void BackBuffer::copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle) +void BackBuffer::copySurface(Cairo::RefPtr &destSurface, GdkRectangle *rectangle) { if (surface && destSurface) { // compute the source offset @@ -1212,3 +1244,23 @@ void BackBuffer::copySurface(Cairo::RefPtr destSurface, Gdk } } +void BackBuffer::copySurface(Cairo::RefPtr &context, GdkRectangle *rectangle) +{ + if (surface && context) { + // compute the source offset + int offsetX = rtengine::LIM(offset.x, 0, surface->get_width()); + int offsetY = rtengine::LIM(offset.y, 0, surface->get_height()); + + // now copy the off-screen Surface to the destination Surface + context->set_source(surface, x - offsetX, y - offsetY); + context->set_line_width(0.); + + if (rectangle) { + context->rectangle(rectangle->x, rectangle->y, rectangle->width, rectangle->height); + } else { + context->rectangle(x, y, w, h); + } + + context->fill(); + } +} diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index f91bb0245..1b9c298ca 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -21,6 +21,7 @@ #include #include "../rtengine/rtengine.h" +#include "../rtengine/coord.h" #include #include @@ -79,7 +80,7 @@ public: class ConnectionBlocker { public: - ConnectionBlocker (sigc::connection& connection) : connection (connection) + explicit ConnectionBlocker (sigc::connection& connection) : connection (connection) { wasBlocked = connection.block(); } @@ -101,7 +102,7 @@ private: Gtk::Container *pC; public: - ExpanderBox( Gtk::Container *p); + explicit ExpanderBox( Gtk::Container *p); ~ExpanderBox( ) { delete pC; @@ -382,33 +383,6 @@ public: } }; -/** - * @brief Handle point coordinates - */ -template -class Point -{ -public: - T x, y; - Point() - { - x = T(0); - y = T(0); - } - - Point(T coordX, T coordY) - { - x = coordX; - y = coordY; - } - - void setCoords(T coordX, T coordY) - { - x = coordX; - y = coordY; - } -}; - /** * @brief Handle backbuffers as automatically as possible */ @@ -417,7 +391,7 @@ class BackBuffer protected: int x, y, w, h; // Rectangle where the colored bar has to be drawn - Point offset; // Offset of the source region to draw, relative to the top left corner + rtengine::Coord offset; // Offset of the source region to draw, relative to the top left corner Cairo::RefPtr surface; bool dirty; // mean that the Surface has to be (re)allocated @@ -426,13 +400,19 @@ public: // set the destination drawing rectangle; return true if the dimensions are different // Note: newW & newH must be > 0 - bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW, int newH, bool updateBackBufferSize = true); - bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW, int newH, bool updateBackBufferSize = true); + bool setDrawRectangle(Glib::RefPtr window, int newX, int newY, int newW=-1, int newH=-1, bool updateBackBufferSize = true); + bool setDrawRectangle(Cairo::Format format, int newX, int newY, int newW=-1, int newH=-1, bool updateBackBufferSize = true); + // set the destination drawing location, do not modify other parameters like size and offset. Use setDrawRectangle to set all parameters at the same time + void setDestPosition(int x, int y); void setSrcOffset(int x, int y); + void setSrcOffset(const rtengine::Coord &newOffset); + void getSrcOffset(int &x, int &y); + void getSrcOffset(rtengine::Coord &offset); - void copySurface(Glib::RefPtr window, GdkRectangle *rectangle = NULL); + void copySurface(Glib::RefPtr &window, GdkRectangle *rectangle = NULL); void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle = NULL); - void copySurface(Cairo::RefPtr destSurface, GdkRectangle *rectangle = NULL); + void copySurface(Cairo::RefPtr &destSurface, GdkRectangle *rectangle = NULL); + void copySurface(Cairo::RefPtr &context, GdkRectangle *rectangle = NULL); void setDirty(bool isDirty) { diff --git a/rtgui/histogrampanel.cc b/rtgui/histogrampanel.cc index 4c6d4f4c0..f6fdda596 100644 --- a/rtgui/histogrampanel.cc +++ b/rtgui/histogrampanel.cc @@ -353,7 +353,8 @@ void HistogramPanel::toggle_button_full () // // HistogramRGBArea HistogramRGBArea::HistogramRGBArea () ://needChroma unactive by default - frozen(false), valid(false), needRed(true), needGreen(true), needBlue(true), needLuma(true), rawMode(false), showMode(options.histogramBar), barDisplayed(options.histogramBar), needChroma(false) + val(0), r(0), g(0), b(0), frozen(false), valid(false), needRed(true), needGreen(true), needBlue(true), needLuma(true), rawMode(false), + showMode(options.histogramBar), barDisplayed(options.histogramBar), needChroma(false), parent(nullptr) { harih = new HistogramRGBAreaIdleHelper; diff --git a/rtgui/histogrampanel.h b/rtgui/histogrampanel.h index 16a0747e3..60cb1a444 100644 --- a/rtgui/histogrampanel.h +++ b/rtgui/histogrampanel.h @@ -144,7 +144,7 @@ protected: public: - HistogramArea(FullModeListener *fml = NULL); + explicit HistogramArea(FullModeListener *fml = NULL); ~HistogramArea(); void renderHistogram (); diff --git a/rtgui/history.h b/rtgui/history.h index 760444b5f..23a7c30ae 100644 --- a/rtgui/history.h +++ b/rtgui/history.h @@ -95,7 +95,7 @@ protected: public: - History (bool bookmarkSupport = true); + explicit History (bool bookmarkSupport = true); void setProfileChangeListener (ProfileChangeListener* tpc_) { diff --git a/rtgui/ilabel.cc b/rtgui/ilabel.cc index 591564305..2c7edfd80 100644 --- a/rtgui/ilabel.cc +++ b/rtgui/ilabel.cc @@ -18,7 +18,7 @@ */ #include "ilabel.h" -ILabel::ILabel (Glib::ustring lab) : label(lab) {} +ILabel::ILabel (const Glib::ustring &lab) : label(lab) {} void ILabel::on_realize() { diff --git a/rtgui/ilabel.h b/rtgui/ilabel.h index aef5eb2ed..82064bd23 100644 --- a/rtgui/ilabel.h +++ b/rtgui/ilabel.h @@ -27,7 +27,7 @@ class ILabel : public Gtk::DrawingArea Glib::ustring label; public: - ILabel (Glib::ustring lab); + explicit ILabel (const Glib::ustring &lab); bool on_expose_event(GdkEventExpose* event); void on_realize(); void on_style_changed (const Glib::RefPtr& style); diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 0b757d8ec..125968b8e 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -88,7 +88,7 @@ void ImageArea::on_resized (Gtk::Allocation& req) { if (ipc && get_width() > 1) { // sometimes on_resize is called in some init state, causing wrong sizes if (!mainCropWindow) { - mainCropWindow = new CropWindow (this, ipc, false, false); + mainCropWindow = new CropWindow (this, false, false); mainCropWindow->setDecorated (false); mainCropWindow->setFitZoomEnabled (true); mainCropWindow->addCropWindowListener (this); @@ -106,7 +106,12 @@ void ImageArea::on_resized (Gtk::Allocation& req) } } -void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) +rtengine::StagedImageProcessor* ImageArea::getImProcCoordinator() const +{ + return ipc; +} + +void ImageArea::setImProcCoordinator(rtengine::StagedImageProcessor* ipc_) { if( !ipc_ ) { focusGrabber = NULL; @@ -117,6 +122,7 @@ void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) cropWins.clear(); + mainCropWindow->deleteColorPickers (); mainCropWindow->setObservedCropWin (NULL); } @@ -178,7 +184,6 @@ CropWindow* ImageArea::getCropWindow (int x, int y) return cw; } - void ImageArea::redraw () { // dirty prevents multiple updates queued up @@ -188,6 +193,11 @@ void ImageArea::redraw () } } +void ImageArea::switchPickerVisibility (bool isVisible) +{ + redraw(); +} + bool ImageArea::on_expose_event(GdkEventExpose* event) { dirty = false; @@ -269,18 +279,8 @@ bool ImageArea::on_scroll_event (GdkEventScroll* event) { CropWindow* cw = getCropWindow (event->x, event->y); - if (cw) { - int newCenterX = (int)event->x; - int newCenterY = (int)event->y; - - cw->screenCoordToImage(newCenterX, newCenterY, newCenterX, newCenterY); - - if (event->direction == GDK_SCROLL_UP && !cw->isMaxZoom()) { - cw->zoomIn (true, newCenterX, newCenterY); - } else if (!cw->isMinZoom()) { - cw->zoomOut (true, newCenterX, newCenterY); - } + cw->scroll (event->state, event->direction, event->x, event->y); } return true; @@ -403,7 +403,7 @@ void ImageArea::addCropWindow () return; // if called but no image is loaded, it would crash } - CropWindow* cw = new CropWindow (this, ipc, true, true); + CropWindow* cw = new CropWindow (this, true, true); cw->zoom11(); cw->setCropGUIListener (cropgl); cw->setPointerMotionListener (pmlistener); @@ -690,6 +690,16 @@ ToolMode ImageArea::getToolMode () } } +bool ImageArea::showColorPickers () +{ + + if (listener && listener->getToolBar()) { + return listener->getToolBar()->showColorPickers (); + } else { + return false; + } +} + void ImageArea::setToolHand () { diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index bd2c19093..dcdc4f3ec 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -33,7 +33,7 @@ #include "edit.h" class ImageAreaPanel; -class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider +class ImageArea : public Gtk::DrawingArea, public CropWindowListener, public EditDataProvider, public LockablePickerToolListener { friend class ZoomPanel; @@ -70,10 +70,11 @@ public: PreviewModePanel* previewModePanel; ImageArea* iLinkedImageArea; // used to set a reference to the Before image area, which is set when before/after view is enabled - ImageArea (ImageAreaPanel* p); + explicit ImageArea (ImageAreaPanel* p); ~ImageArea (); - void setImProcCoordinator (rtengine::StagedImageProcessor* ipc_); + rtengine::StagedImageProcessor* getImProcCoordinator() const; + void setImProcCoordinator(rtengine::StagedImageProcessor* ipc_); void setPreviewModePanel(PreviewModePanel* previewModePanel_) { previewModePanel = previewModePanel_; @@ -122,6 +123,7 @@ public: void cropWindowSelected (CropWindow* cw); void cropWindowClosed (CropWindow* cw); ToolMode getToolMode (); + bool showColorPickers (); void setToolHand (); void straightenReady (double rotDeg); void spotWBSelected (int x, int y); @@ -143,6 +145,9 @@ public: void cropZoomChanged (CropWindow* cw); void initialImageArrived (CropWindow* cw) ; + // LockablePickerToolListener interface + void switchPickerVisibility (bool isVisible); + CropWindow* getMainCropWindow () { return mainCropWindow; diff --git a/rtgui/imageareatoollistener.h b/rtgui/imageareatoollistener.h index 3f1238810..edb93f030 100644 --- a/rtgui/imageareatoollistener.h +++ b/rtgui/imageareatoollistener.h @@ -27,6 +27,7 @@ class ImageAreaToolListener { public: + virtual ~ImageAreaToolListener() {} virtual void spotWBselected (int x, int y, Thumbnail* thm = NULL) {} virtual int getSpotWBRectSize () { @@ -38,7 +39,6 @@ public: { return NULL; } - virtual void removeWbTool() = 0; virtual CropGUIListener* startCropEditing (Thumbnail* thm = NULL) { return NULL; diff --git a/rtgui/indclippedpanel.h b/rtgui/indclippedpanel.h index 199a9f620..3a6bc5296 100644 --- a/rtgui/indclippedpanel.h +++ b/rtgui/indclippedpanel.h @@ -30,7 +30,7 @@ protected: ImageArea* imageArea; public: - IndicateClippedPanel (ImageArea* ia); + explicit IndicateClippedPanel (ImageArea* ia); void buttonToggled (); diff --git a/rtgui/inspector.h b/rtgui/inspector.h index ce2da9aeb..4d275abd5 100644 --- a/rtgui/inspector.h +++ b/rtgui/inspector.h @@ -34,7 +34,7 @@ public: int currTransform; // coarse rotation from RT, not from shot orientation bool fromRaw; - InspectorBuffer(const Glib::ustring &imgagePath); + explicit InspectorBuffer(const Glib::ustring &imgagePath); //~InspectorBuffer(); }; diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc new file mode 100644 index 000000000..abfb94344 --- /dev/null +++ b/rtgui/lockablecolorpicker.cc @@ -0,0 +1,383 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#include "lockablecolorpicker.h" +#include "options.h" +#include "../rtengine/color.h" +#include "../rtengine/rt_math.h" +#include "imagearea.h" +#include "multilangmgr.h" +#include "navigator.h" + +extern Options options; + +LockableColorPicker::LockableColorPicker (CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile) +: cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(0, 0), size(Size::S15), + outputProfile(oProfile), workingProfile(wProfile), validity(Validity::OUTSIDE), + r(0.f), g(0.f), b(0.f), rpreview(0.f), gpreview(0.f), bpreview(0.f), hue(0.f), sat(0.f), val(0.f), L(0.f), a(0.f), bb(0.f) +{} + +void LockableColorPicker::updateBackBuffer () +{ + int newW, newH; + + // -------------------- setting some key constants --------------------- + constexpr float circlePadding = 3.f; // keep this value odd + constexpr double opacity = 0.62; + // --------------------------------------------------------------------- + + if (validity == Validity::INSIDE) { + Gtk::DrawingArea *iArea = cropWindow->getImageArea(); + + Glib::RefPtr pangoContext = iArea->get_pango_context (); + Pango::FontDescription fontd(options.colorPickerFont); + fontd.set_weight(Pango::WEIGHT_NORMAL); + pangoContext->set_font_description (fontd); + + Glib::RefPtr layout[3][2]; + Glib::ustring s1, s2, s3; + PointerMotionListener* navigator = cropWindow->getPointerMotionListener (); + + switch (displayedValues) { + case ColorPickerType::RGB: + navigator->getRGBText ((int)(r*255.f), (int)(g*255.f), (int)(b*255.f), s1, s2, s3); + layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_R")); + layout[0][1] = iArea->create_pango_layout(s1); + layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_G")); + layout[1][1] = iArea->create_pango_layout(s2); + layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_B")); + layout[2][1] = iArea->create_pango_layout(s3); + break; + case ColorPickerType::HSV: + navigator->getHSVText (hue, sat, val, s1, s2, s3); + layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_H")); + layout[0][1] = iArea->create_pango_layout(s1); + layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_S")); + layout[1][1] = iArea->create_pango_layout(s2); + layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_V")); + layout[2][1] = iArea->create_pango_layout(s3); + break; + case ColorPickerType::LAB: + default: + navigator->getLABText (L, a, bb, s1, s2, s3); + layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_L")); + layout[0][1] = iArea->create_pango_layout(s1); + layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_A")); + layout[1][1] = iArea->create_pango_layout(s2); + layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_B")); + layout[2][1] = iArea->create_pango_layout(s3); + } + + int w00, w01, w10, w11, w20, w21, h00, h01, h10, h11, h20, h21; + layout[0][0]->get_pixel_size(w00, h00); + layout[1][0]->get_pixel_size(w10, h10); + layout[2][0]->get_pixel_size(w20, h20); + layout[0][1]->get_pixel_size(w01, h01); + layout[1][1]->get_pixel_size(w11, h11); + layout[2][1]->get_pixel_size(w21, h21); + int maxWCol0 = rtengine::max(w00, w10, w20); + int maxWCol1 = rtengine::max(w01, w11, w21); + int maxHRow0 = rtengine::max(h00, h01); + int maxHRow1 = rtengine::max(h10, h11); + int maxHRow2 = rtengine::max(h20, h21); + + // -------------------- setting some key constants --------------------- + constexpr int textPadding = 3; + const int textWidth = maxWCol0 + maxWCol1 + textPadding; + const int textHeight = maxHRow0 + maxHRow1 + maxHRow2 + 2*textPadding; + // --------------------------------------------------------------------- + + newW = rtengine::max((int)size + 2 * circlePadding, textWidth + 2 * textPadding); + newH = (int)size + 2 * circlePadding + textHeight + 2 * textPadding; + + setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, newW, newH, true); + + Cairo::RefPtr bbcr = BackBuffer::getContext(); + + // cleaning the back buffer + bbcr->set_source_rgba (0., 0., 0., 0.); + bbcr->set_operator (Cairo::OPERATOR_CLEAR); + bbcr->paint (); + bbcr->set_operator (Cairo::OPERATOR_OVER); + + bbcr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); + bbcr->set_line_width (0.); + + float center = (float)size / 2.f + circlePadding; + + // black background of the whole color picker + bbcr->set_line_width (0.); + bbcr->set_source_rgba (0., 0., 0., opacity); + bbcr->arc_negative (center, center, center, 0., (double)M_PI); + bbcr->line_to (0, 2. * center + textHeight); + bbcr->arc_negative (2. * textPadding, 2. * center + textHeight, 2. * textPadding, (double)M_PI, (double)M_PI / 2.); + bbcr->line_to (textWidth, 2. * center + textHeight + 2. * textPadding); + bbcr->arc_negative (textWidth, 2. * center + textHeight, 2. * textPadding, (double)M_PI / 2., 0.); + bbcr->line_to (textWidth + 2. * textPadding, 2. * center + 2. * textPadding); + bbcr->arc_negative (textWidth, 2. * center + 2. * textPadding, 2. * textPadding, 0., (double)M_PI * 1.5); + bbcr->line_to (2. * center, 2. * center); + bbcr->close_path(); + bbcr->set_line_join (Cairo::LINE_JOIN_BEVEL); + bbcr->set_line_cap (Cairo::LINE_CAP_SQUARE); + bbcr->fill (); + + // light grey circle around the color mark + bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)M_PI); + bbcr->set_source_rgb (0.75, 0.75, 0.75); + bbcr->set_line_width (circlePadding - 2.); + bbcr->stroke (); + + // spot disc with picked color + bbcr->arc (center, center, center - circlePadding, 0., 2. * (double)M_PI); + bbcr->set_source_rgb (rpreview, gpreview, bpreview); // <- set the picker color here + bbcr->set_line_width (0.); + bbcr->fill(); + + // adding the font + bbcr->set_line_width (0.); + bbcr->set_line_join (Cairo::LINE_JOIN_ROUND); + bbcr->set_line_cap (Cairo::LINE_CAP_ROUND); + bbcr->set_source_rgb (1., 1., 1.); + double txtOffsetX = textPadding; + double txtOffsetY = (double)size + 2. * circlePadding + textPadding; + switch (iArea->get_direction()) { + case Gtk::TEXT_DIR_RTL: + bbcr->move_to (txtOffsetX , txtOffsetY); + layout[0][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY); + layout[0][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + + bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + textPadding); + layout[1][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY + maxHRow0 + textPadding); + layout[1][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + + bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding); + layout[2][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol1 + textPadding, txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding); + layout[2][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + break; + default: + bbcr->move_to (txtOffsetX , txtOffsetY); + layout[0][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY); + layout[0][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + + bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + textPadding); + layout[1][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY + maxHRow0 + textPadding); + layout[1][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + + bbcr->move_to (txtOffsetX , txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding); + layout[2][0]->add_to_cairo_context (bbcr); + bbcr->fill (); + bbcr->move_to (txtOffsetX + maxWCol0 + textPadding, txtOffsetY + maxHRow0 + maxHRow1 + 2*textPadding); + layout[2][1]->add_to_cairo_context (bbcr); + bbcr->fill (); + } + + anchorOffset.set (center, center); + + setDirty (false); + } else if (validity == Validity::CROSSING) { + newH = newW = (int)size + 2 * circlePadding; + + setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, newW, newH, true); + + Cairo::RefPtr bbcr = BackBuffer::getContext(); + + // cleaning the back buffer + bbcr->set_source_rgba (0., 0., 0., 0.); + bbcr->set_operator (Cairo::OPERATOR_CLEAR); + bbcr->paint (); + bbcr->set_operator (Cairo::OPERATOR_OVER); + + bbcr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL); + + float center = (float)size / 2.f + circlePadding; + + // light grey circle around the color mark + bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)M_PI); + bbcr->set_source_rgba (0., 0., 0., opacity); + bbcr->set_line_width(circlePadding); + bbcr->stroke_preserve(); + bbcr->set_source_rgb (0.75, 0.75, 0.75); + bbcr->set_line_width (circlePadding - 2.); + bbcr->stroke (); + + anchorOffset.set (center, center); + + setDirty (false); + } + +} + +void LockableColorPicker::draw (Cairo::RefPtr &cr) +{ + if (validity == Validity::OUTSIDE) { + return; + } + + if (isDirty()) { + updateBackBuffer(); + } + int px, py; + cropWindow->imageCoordToScreen(position.x, position.y, px, py); + setDestPosition(px - anchorOffset.x, py - anchorOffset.y); + + copySurface(cr); +} + +void LockableColorPicker::setPosition (const rtengine::Coord &newPos) +{ + // we're not checking bounds here, this will be done at rendering time + position = newPos; +} + +void LockableColorPicker::setRGB (const float R, const float G, const float B, const float previewR, const float previewG, const float previewB) +{ + if (r==R && g==G && b==B) { + return; + } + + r = R; + g = G; + b = B; + + rpreview = previewR; + gpreview = previewG; + bpreview = previewB; + + rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, hue, sat, val); + rtengine::Color::rgb2lab (*outputProfile, *workingProfile, r * 65535.f, g * 65535.f, b * 65535.f, L, a, bb, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? + + if (validity != Validity::OUTSIDE) { + setDirty(true); + } +} + +void LockableColorPicker::getImagePosition (rtengine::Coord &imgPos) +{ + imgPos = position; +} + +void LockableColorPicker::getScreenPosition (rtengine::Coord &screenPos) +{ + if (cropWindow) { + cropWindow->imageCoordToScreen(position.x, position.y, screenPos.x, screenPos.y); + } +} + +bool LockableColorPicker::isOver (int x, int y) +{ + if (!cropWindow) { + return false; + } + rtengine::Coord pickerScreenPos; + cropWindow->imageCoordToScreen(position.x, position.y, pickerScreenPos.x, pickerScreenPos.y); + + rtengine::Coord mousePos(x, y); + rtengine::Coord wh(getWidth(), getHeight()); + rtengine::Coord tl(pickerScreenPos - anchorOffset); + rtengine::Coord br(tl + wh); + return mousePos >= tl && mousePos <= br; +} + +void LockableColorPicker::setValidity (Validity validity) +{ + if (this->validity != validity) { + setDirty(true); + } + this->validity = validity; +} + +void LockableColorPicker::setSize (Size newSize) +{ + if (size != newSize) + { + size = newSize; + setDirty(true); + } +} + +LockableColorPicker::Size LockableColorPicker::getSize () +{ + return size; +} + +void LockableColorPicker::rollDisplayedValues () +{ + if (displayedValues < ColorPickerType::LAB) { + displayedValues = (ColorPickerType)(rtengine::toUnderlying(displayedValues) + 1); + } else { + displayedValues = ColorPickerType::RGB; + } + setDirty(true); + +} + +bool LockableColorPicker::incSize () +{ + if (size < Size::S30) { + size = (Size)(rtengine::toUnderlying(size) + 5); + setDirty(true); + return true; + } + return false; +} + +bool LockableColorPicker::decSize () +{ + if (size > Size::S5) { + size = (Size)(rtengine::toUnderlying(size) - 5); + setDirty(true); + return true; + } + return false; +} + +// return true if the picker has to be redrawn +bool LockableColorPicker::cycleRGB () +{ + if (displayedValues == ColorPickerType::RGB) { + setDirty (true); + return true; + } + return false; +} + +// return true if the picker has to be redrawn +bool LockableColorPicker::cycleHSV () +{ + if (displayedValues == ColorPickerType::HSV) { + setDirty (true); + return true; + } + return false; +} diff --git a/rtgui/lockablecolorpicker.h b/rtgui/lockablecolorpicker.h new file mode 100644 index 000000000..308f5d6d5 --- /dev/null +++ b/rtgui/lockablecolorpicker.h @@ -0,0 +1,97 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2004-2010 Gabor Horvath + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ + +#ifndef __COLORPICKER__ +#define __COLORPICKER__ + + +#include "../rtengine/coord.h" +#include "guiutils.h" +#include "edit.h" + +class CropWindow; + +class LockablePickerToolListener { +public: + virtual ~LockablePickerToolListener () {} + + /// Callback on Color Picker's visibility switch + virtual void switchPickerVisibility (bool isVisible) {} +}; + +class LockableColorPicker : BackBuffer +{ +public: + enum class Size { + S5=5, + S10=10, + S15=15, + S20=20, + S25=25, + S30=30 + }; + enum class Validity { + INSIDE, + CROSSING, + OUTSIDE + }; +private: + enum class ColorPickerType { + RGB, + HSV, + LAB + }; + CropWindow* cropWindow; // the color picker is displayed in a single cropWindow, the one that the user has clicked in + ColorPickerType displayedValues; + rtengine::Coord position; // Coordinate in image space + rtengine::Coord anchorOffset; + Size size; + Glib::ustring *outputProfile; + Glib::ustring *workingProfile; + Validity validity; + float r, g, b; // red green blue in [0;1] range + float rpreview, gpreview, bpreview; + float hue, sat, val; // hue saturation value in [0;1] range + float L, a, bb; // L*a*b value in [0;1] range + + void updateBackBuffer (); + +public: + + LockableColorPicker (CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile); + + void draw (Cairo::RefPtr &cr); + + // Used to update the RGB color, the HSV values will be updated accordingly + void setPosition (const rtengine::Coord &newPos); + void setRGB (const float R, const float G, const float B, const float previewR, const float previewG, const float previewB); + void getImagePosition (rtengine::Coord &imgPos); + void getScreenPosition (rtengine::Coord &screenPos); + Size getSize (); + bool isOver (int x, int y); + void setValidity (Validity isValid); + void setSize (Size newSize); + void rollDisplayedValues (); + bool incSize (); + bool decSize (); + bool cycleRGB (); + bool cycleHSV (); +}; + +#endif diff --git a/rtgui/lwbutton.cc b/rtgui/lwbutton.cc index 52b7fd7e8..f7914eedb 100644 --- a/rtgui/lwbutton.cc +++ b/rtgui/lwbutton.cc @@ -20,7 +20,7 @@ #include "guiutils.h" LWButton::LWButton (Cairo::RefPtr i, int aCode, void* aData, Alignment ha, Alignment va, Glib::ustring tooltip) - : halign(ha), valign(va), icon(i), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) + : xpos(0), ypos(0), halign(ha), valign(va), icon(i), bgr(0.0), bgg(0.0), bgb(0.0), fgr(0.0), fgg(0.0), fgb(0.0), state(Normal), listener(NULL), actionCode(aCode), actionData(aData), toolTip(tooltip) { if (i) { diff --git a/rtgui/lwbuttonset.cc b/rtgui/lwbuttonset.cc index bfa4684af..c801cc33b 100644 --- a/rtgui/lwbuttonset.cc +++ b/rtgui/lwbuttonset.cc @@ -18,7 +18,7 @@ */ #include "lwbuttonset.h" -LWButtonSet::LWButtonSet () : aw(0), ah(0) +LWButtonSet::LWButtonSet () : aw(0), ah(0), ax(0), ay(0) { } diff --git a/rtgui/mydiagonalcurve.cc b/rtgui/mydiagonalcurve.cc index fd57633fb..969b197a2 100644 --- a/rtgui/mydiagonalcurve.cc +++ b/rtgui/mydiagonalcurve.cc @@ -165,11 +165,11 @@ void MyDiagonalCurve::get_LUT (LUTf &lut) // calculate remaining points std::vector curveDescr = getPoints (); rtengine::DiagonalCurve rtcurve(curveDescr, lut.getUpperBound() * 1.2); - double t; + double maxVal = double(lut.getUpperBound()); for (int i = 0; i < size; i++) { - t = double(i) / maxVal; + double t = double(i) / maxVal; lut[i] = rtcurve.getVal (t); } @@ -1167,7 +1167,6 @@ void MyDiagonalCurve::pipetteButton1Released(EditDataProvider *provider) snapToElmt = -100; if (curve.type != DCT_Parametric) { - std::vector::iterator itx, ity; buttonPressed = false; /* get the pointer position */ getCursorPosition(Gdk::EventType(Gdk::BUTTON_RELEASE), false, graphY, 0, Gdk::ModifierType(0)); diff --git a/rtgui/myflatcurve.cc b/rtgui/myflatcurve.cc index 4127d1ae8..4ccc8b5bb 100644 --- a/rtgui/myflatcurve.cc +++ b/rtgui/myflatcurve.cc @@ -86,11 +86,10 @@ void MyFlatCurve::get_LUT (LUTf &lut) std::vector curveDescr = getPoints (); rtengine::FlatCurve rtcurve(curveDescr, periodic, lut.getUpperBound() * 1.2 > 5000 ? 5000 : lut.getUpperBound() * 1.2); - double t; double maxVal = double(lut.getUpperBound()); for (int i = 0; i < size; i++) { - t = double(i) / maxVal; + double t = double(i) / maxVal; lut[i] = rtcurve.getVal (t); } @@ -815,13 +814,13 @@ bool MyFlatCurve::handleEvents (GdkEvent* event) case Gdk::BUTTON_RELEASE: if (edited_point == -1) { //curve.type!=FCT_Parametric) { if (buttonPressed && event->button.button == 1) { - int src, dst; buttonPressed = false; remove_modal_grab (); // Removing any deleted point if we were previously modifying the point position if (editedHandle & (FCT_EditedHandle_CPoint | FCT_EditedHandle_CPointX | FCT_EditedHandle_CPointY)) { /* delete inactive points: */ + int src, dst; itx = curve.x.begin(); ity = curve.y.begin(); itlt = curve.leftTangent.begin(); diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 049b4ec7e..2c724ee4c 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -215,6 +215,55 @@ void Navigator::setInvalid (int fullWidth, int fullHeight) LAB_L->set_text (M("NAVIGATOR_NA")); } +void Navigator::getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB) +{ + switch (currentRGBUnit) { + case (Options::NavigatorUnit::R0_1): + sR = Glib::ustring::format(std::fixed, std::setprecision(4), r / 255.f); + sG = Glib::ustring::format(std::fixed, std::setprecision(4), g / 255.f); + sB = Glib::ustring::format(std::fixed, std::setprecision(4), b / 255.f); + break; + case (Options::NavigatorUnit::R0_255): + sR = Glib::ustring::format(std::fixed, std::setprecision(0), r); + sG = Glib::ustring::format(std::fixed, std::setprecision(0), g); + sB = Glib::ustring::format(std::fixed, std::setprecision(0), b); + break; + case (Options::NavigatorUnit::PERCENT): + default: + sR = Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.f / 255.f) + Glib::ustring("%"); + sG = Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.f / 255.f) + Glib::ustring("%"); + sB = Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.f / 255.f) + Glib::ustring("%"); + } +} + +void Navigator::getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV) +{ + switch (currentHSVUnit) { + case (Options::NavigatorUnit::R0_1): + sH = Glib::ustring::format(std::fixed, std::setprecision(4), h); + sS = Glib::ustring::format(std::fixed, std::setprecision(4), s); + sV = Glib::ustring::format(std::fixed, std::setprecision(4), v); + break; + case (Options::NavigatorUnit::R0_255): + sH = Glib::ustring::format(std::fixed, std::setprecision(0), h * 255); + sS = Glib::ustring::format(std::fixed, std::setprecision(0), s * 255); + sV = Glib::ustring::format(std::fixed, std::setprecision(0), v * 255); + break; + case (Options::NavigatorUnit::PERCENT): + default: + sH = Glib::ustring::format(std::fixed, std::setprecision(1), h * 360.f) + Glib::ustring("\xc2\xb0"); + sS = Glib::ustring::format(std::fixed, std::setprecision(1), s * 100.f) + Glib::ustring("%"); + sV = Glib::ustring::format(std::fixed, std::setprecision(1), v * 100.f) + Glib::ustring("%"); + } +} + +void Navigator::getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB) +{ + sL = Glib::ustring::format(std::fixed, std::setprecision(1), l); + sA = Glib::ustring::format(std::fixed, std::setprecision(1), a); + sB = Glib::ustring::format(std::fixed, std::setprecision(1), b); +} + // if !validPos then x/y contain the full image size void Navigator::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) { @@ -222,54 +271,28 @@ void Navigator::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustrin if (!validPos) { setInvalid (x, y); } else { + Glib::ustring s1, s2, s3; + float h, s, v; + float LAB_a, LAB_b, LAB_l; + position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); - switch (currentRGBUnit) { - case (Options::NavigatorUnit::R0_1): - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), r / 255.f)); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), g / 255.f)); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), b / 255.f)); - break; - case (Options::NavigatorUnit::R0_255): - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), r)); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), g)); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), b)); - break; - case (Options::NavigatorUnit::PERCENT): - default: - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.f / 255.f) + Glib::ustring("%")); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.f / 255.f) + Glib::ustring("%")); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.f / 255.f) + Glib::ustring("%")); - break; - } + getRGBText (r, g, b, s1, s2, s3); + R->set_text (s1); + G->set_text (s2); + B->set_text (s3); - float h, s, v; Color::rgb2hsv (r * 0xffff / 0xff, g * 0xffff / 0xff, b * 0xffff / 0xff, h, s, v); - switch (currentHSVUnit) { - case (Options::NavigatorUnit::R0_1): - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), h)); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), s)); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), v)); - break; - case (Options::NavigatorUnit::R0_255): - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), h * 255)); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), s * 255)); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), v * 255)); - break; - case (Options::NavigatorUnit::PERCENT): - default: - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), h * 360.f) + Glib::ustring("\xc2\xb0")); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), s * 100.f) + Glib::ustring("%")); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), v * 100.f) + Glib::ustring("%")); - break; - } + getHSVText (h, s, v, s1, s2, s3); + H->set_text (s1); + S->set_text (s2); + V->set_text (s3); - float LAB_a, LAB_b, LAB_l; - //rgb2lab (r, g, b, LAB_l, LAB_a, LAB_b); - rgb2lab (profile, profileW, r, g, b, LAB_l, LAB_a, LAB_b); // TODO: Really sure this function works? - LAB_A->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_a)); - LAB_B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_b)); - LAB_L->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_l)); + Color::rgb2lab (profile, profileW, r * 0xffff / 0xff, g * 0xffff / 0xff, b * 0xffff / 0xff, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? + getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3); + LAB_L->set_text (s1); + LAB_A->set_text (s2); + LAB_B->set_text (s3); } } @@ -299,6 +322,7 @@ void Navigator::cycleUnitsRGB (GdkEventButton *event) { B->set_text ("[%]"); break; } + sig_cycle_rgb.emit(); } void Navigator::cycleUnitsHSV (GdkEventButton *event) { @@ -327,151 +351,5 @@ void Navigator::cycleUnitsHSV (GdkEventButton *event) { V->set_text ("[%]"); break; } -} - -void Navigator::rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b) -{ - double xyz_rgb[3][3]; - const double ep = 216.0 / 24389.0; - const double ka = 24389.0 / 27.0; - - double var_R = r / 255.0; - double var_G = g / 255.0; - double var_B = b / 255.0; - - Glib::ustring profileCalc; - profileCalc = "sRGB"; //default - - if(options.rtSettings.HistogramWorking) { - profileCalc = profileW; //display working - } - - else {// if you want display = output space - if (profile == "RT_sRGB" || profile == "RT_sRGB_gBT709" || profile == "RT_sRGB_g10") { - profileCalc = "sRGB"; - } - - if (profile == "ProPhoto" || profile == "RT_Large_gBT709" || profile == "RT_Large_g10" || profile == "RT_Large_gsRGB") { - profileCalc = "ProPhoto"; - } - - if (profile == "AdobeRGB1998" || profile == "RT_Medium_gsRGB") { - profileCalc = "Adobe RGB"; - } - - if (profile == "WideGamutRGB") { - profileCalc = "WideGamut"; - } - } - - if(options.rtSettings.HistogramWorking) {//display working - if (profileW == "sRGB") { //apply sRGB inverse gamma - - if ( var_R > 0.04045 ) { - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_R = var_R / 12.92; - } - - if ( var_G > 0.04045 ) { - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_G = var_G / 12.92; - } - - if ( var_B > 0.04045 ) { - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_B = var_B / 12.92; - } - } else if (profileW == "ProPhoto") { // apply inverse gamma 1.8 - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } else { // apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } else { //display outout profile - - if (profile == "RT_sRGB" || profile == "RT_Large_gsRGB" || profile == "RT_Medium_gsRGB") { //apply sRGB inverse gamma - if ( var_R > 0.04045 ) { - var_R = pow ( ( ( var_R + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_R = var_R / 12.92; - } - - if ( var_G > 0.04045 ) { - var_G = pow ( ( ( var_G + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_G = var_G / 12.92; - } - - if ( var_B > 0.04045 ) { - var_B = pow ( ( ( var_B + 0.055 ) / 1.055 ), rtengine::Color::sRGBGammaCurve); - } else { - var_B = var_B / 12.92; - } - } - - else if (profile == "RT_sRGB_gBT709" || profile == "RT_Large_gBT709") { // - if ( var_R > 0.0795 ) { - var_R = pow ( ( ( var_R + 0.0954 ) / 1.0954 ), 2.2); - } else { - var_R = var_R / 4.5; - } - - if ( var_G > 0.0795 ) { - var_G = pow ( ( ( var_G + 0.0954 ) / 1.0954 ), 2.2); - } else { - var_G = var_G / 4.5; - } - - if ( var_B > 0.0795 ) { - var_B = pow ( ( ( var_B + 0.0954 ) / 1.0954 ), 2.2); - } else { - var_B = var_B / 4.5; - } - - } else if (profile == "ProPhoto") { // apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.8); - var_G = pow ( var_G, 1.8); - var_B = pow ( var_B, 1.8); - } else if (profile == "RT_sRGB_g10" || profile == "RT_Large_g10") { // apply inverse gamma 1.8 - - var_R = pow ( var_R, 1.); - var_G = pow ( var_G, 1.); - var_B = pow ( var_B, 1.); - } - - else {// apply inverse gamma 2.2 - var_R = pow ( var_R, 2.2); - var_G = pow ( var_G, 2.2); - var_B = pow ( var_B, 2.2); - } - } - - // TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileW); - - TMatrix wprof = rtengine::ICCStore::getInstance()->workingSpaceMatrix (profileCalc); - - for (int m = 0; m < 3; m++) - for (int n = 0; n < 3; n++) { - xyz_rgb[m][n] = wprof[m][n]; - } - - double varxx, varyy, varzz; - double var_X = ( xyz_rgb[0][0] * var_R + xyz_rgb[0][1] * var_G + xyz_rgb[0][2] * var_B ) / Color::D50x; - double var_Y = ( xyz_rgb[1][0] * var_R + xyz_rgb[1][1] * var_G + xyz_rgb[1][2] * var_B ) ; - double var_Z = ( xyz_rgb[2][0] * var_R + xyz_rgb[2][1] * var_G + xyz_rgb[2][2] * var_B ) / Color::D50z; - - varxx = var_X > ep ? cbrt(var_X) : ( ka * var_X + 16.0) / 116.0 ; - varyy = var_Y > ep ? cbrt(var_Y) : ( ka * var_Y + 16.0) / 116.0 ; - varzz = var_Z > ep ? cbrt(var_Z) : ( ka * var_Z + 16.0) / 116.0 ; - LAB_l = ( 116 * varyy ) - 16; - LAB_a = 500 * ( varxx - varyy ); - LAB_b = 200 * ( varyy - varzz ); - + sig_cycle_hsv.emit(); } diff --git a/rtgui/navigator.h b/rtgui/navigator.h index e0b79d8dd..647df7a34 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.h @@ -46,8 +46,6 @@ protected: Gtk::Label *lH, *lS, *lV; Gtk::Label *lLAB_A, *lLAB_B, *lLAB_L; - void rgb2lab (Glib::ustring profile, Glib::ustring profileW, int r, int g, int b, float &LAB_l, float &LAB_a, float &LAB_b); - void setInvalid (int fullWidth = -1, int fullHeight = -1); public: @@ -59,6 +57,10 @@ public: // void pointerMoved (bool validPos, int x, int y, int r, int g, int b); void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b); + void getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB); + void getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV); + void getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB); + }; #endif diff --git a/rtgui/options.cc b/rtgui/options.cc index 774afde2e..c5711edfc 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -292,6 +292,7 @@ void Options::setDefaults () { font = "sans, 8"; + colorPickerFont = "sans, 8"; windowWidth = 1200; windowHeight = 680; windowX = 0; @@ -1248,6 +1249,10 @@ int Options::readFromFile (Glib::ustring fname) font = keyFile.get_string ("GUI", "Font"); } + if (keyFile.has_key ("GUI", "ColorPickerFont")) { + colorPickerFont = keyFile.get_string ("GUI", "ColorPickerFont"); + } + if (keyFile.has_key ("GUI", "WindowWidth")) { windowWidth = keyFile.get_integer ("GUI", "WindowWidth"); } @@ -1979,6 +1984,7 @@ int Options::saveToFile (Glib::ustring fname) keyFile.set_integer ("Profiles", "CustomProfileBuilderKeys", CPBKeys); keyFile.set_string ("GUI", "Font", font); + keyFile.set_string ("GUI", "ColorPickerFont", colorPickerFont); keyFile.set_integer ("GUI", "WindowWidth", windowWidth); keyFile.set_integer ("GUI", "WindowHeight", windowHeight); keyFile.set_integer ("GUI", "WindowX", windowX); @@ -2176,9 +2182,9 @@ bool Options::load () } else { #ifdef WIN32 WCHAR pathW[MAX_PATH] = {0}; - char pathA[MAX_PATH]; if (SHGetSpecialFolderPathW(NULL, pathW, CSIDL_LOCAL_APPDATA, false)) { + char pathA[MAX_PATH]; WideCharToMultiByte(CP_UTF8, 0, pathW, -1, pathA, MAX_PATH, 0, 0); rtdir = Glib::build_filename(Glib::ustring(pathA), Glib::ustring(CACHEFOLDERNAME)); } diff --git a/rtgui/options.h b/rtgui/options.h index 46074f1a3..4f81a966a 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -120,6 +120,7 @@ public: bool editorFilmStripOpened; int historyPanelWidth; Glib::ustring font; + Glib::ustring colorPickerFont; int windowWidth; int windowHeight; int windowX; diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 5c35b20da..19d143398 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -784,7 +784,7 @@ public: bool exif; bool iptc; - ParamsEdited (bool value = false); + explicit ParamsEdited (bool value = false); void set (bool v); void initFrom (const std::vector& src); diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index d017b5409..78631b725 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -20,7 +20,7 @@ #include "multilangmgr.h" #include "paramsedited.h" -PartialPasteDlg::PartialPasteDlg (Glib::ustring title) +PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title) { set_modal (true); diff --git a/rtgui/partialpastedlg.h b/rtgui/partialpastedlg.h index 7376e1481..a054b042e 100644 --- a/rtgui/partialpastedlg.h +++ b/rtgui/partialpastedlg.h @@ -132,7 +132,7 @@ public: sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; public: - PartialPasteDlg (Glib::ustring title); + explicit PartialPasteDlg (const Glib::ustring &title); void applyPaste (rtengine::procparams::ProcParams* dstPP, ParamsEdited* dstPE, const rtengine::procparams::ProcParams* srcPP, const ParamsEdited* srcPE = NULL); diff --git a/rtgui/pointermotionlistener.h b/rtgui/pointermotionlistener.h index 46eb42476..09a9b3b4f 100644 --- a/rtgui/pointermotionlistener.h +++ b/rtgui/pointermotionlistener.h @@ -21,11 +21,26 @@ class PointerMotionListener { +protected: + sigc::signal sig_cycle_rgb; + sigc::signal sig_cycle_hsv; public: -// virtual void pointerMoved (bool validPos, int x, int y, int r, int g, int b) {} + virtual ~PointerMotionListener() {} virtual void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) {} virtual void toggleFreeze () {} + virtual void getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB) { sR = "--"; sG = "--"; sB = "--"; } + virtual void getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV) { sH = "--"; sS = "--"; sV = "--"; } + virtual void getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB) { sL = "--"; sA = "--"; sB = "--"; } + + sigc::signal signal_cycle_rgb() + { + return sig_cycle_rgb; + } + sigc::signal signal_cycle_hsv() + { + return sig_cycle_hsv; + } }; #endif diff --git a/rtgui/popuptogglebutton.h b/rtgui/popuptogglebutton.h index 930fae4f2..58a7ff82a 100644 --- a/rtgui/popuptogglebutton.h +++ b/rtgui/popuptogglebutton.h @@ -28,7 +28,7 @@ class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon { public: - PopUpToggleButton (const Glib::ustring& label = ""); + explicit PopUpToggleButton (const Glib::ustring& label = ""); void show (); void set_tooltip_text (const Glib::ustring &text); }; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 28f5e2096..b8e00fe27 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -609,9 +609,10 @@ Gtk::Widget* Preferences::getPerformancePanel () rgbDenoiseTreadLimitSB->set_digits (0); rgbDenoiseTreadLimitSB->set_increments (1, 5); rgbDenoiseTreadLimitSB->set_max_length(2); // Will this be sufficient? :) - int maxThreadNumber = 10; #ifdef _OPENMP - maxThreadNumber = omp_get_max_threads(); + int maxThreadNumber = omp_get_max_threads(); +#else + int maxThreadNumber = 10; #endif rgbDenoiseTreadLimitSB->set_range (0, maxThreadNumber); threadLimitHB->pack_start (*RGBDTLl, Gtk::PACK_SHRINK, 2); @@ -937,14 +938,21 @@ Gtk::Widget* Preferences::getGeneralPanel () hbtheme->pack_start (*fontbutton); vbftheme->pack_start(*hbtheme, Gtk::PACK_SHRINK, 0); + Gtk::Label* cpfontlab = Gtk::manage( new Gtk::Label (M("PREFERENCES_SELECTFONT_COLPICKER") + ":") ); + colorPickerFontButton = Gtk::manage( new Gtk::FontButton ()); + colorPickerFontButton->set_use_size(true); + colorPickerFontButton->set_font_name(options.colorPickerFont); + Gtk::HBox* hbcolorchooser = Gtk::manage( new Gtk::HBox () ); hbcolorchooser->set_spacing(4); hbcolorchooser->pack_start (*cutOverlayLabel, Gtk::PACK_SHRINK, 0); hbcolorchooser->pack_start (*butCropCol, Gtk::PACK_SHRINK, 0); - hbcolorchooser->pack_end (*butNavGuideCol, Gtk::PACK_SHRINK, 0); - hbcolorchooser->pack_end (*navGuideLabel, Gtk::PACK_SHRINK, 0); + hbcolorchooser->pack_start (*butNavGuideCol, Gtk::PACK_SHRINK, 0); + hbcolorchooser->pack_start (*navGuideLabel, Gtk::PACK_SHRINK, 0); + hbcolorchooser->pack_start (*cpfontlab, Gtk::PACK_EXPAND_WIDGET, 0); + hbcolorchooser->pack_start (*colorPickerFontButton, Gtk::PACK_SHRINK, 0); vbftheme->pack_start(*hbcolorchooser, Gtk::PACK_SHRINK, 0); @@ -1420,6 +1428,7 @@ void Preferences::storePreferences () moptions.navGuideBrush[3] = butNavGuideCol->get_alpha() / 65535.0; moptions.font = fontbutton->get_font_name(); + moptions.colorPickerFont = colorPickerFontButton->get_font_name(); #ifdef WIN32 moptions.gimpDir = gimpDir->get_filename (); moptions.psDir = psDir->get_filename (); @@ -1637,6 +1646,7 @@ void Preferences::fillPreferences () butNavGuideCol->set_alpha ( (unsigned short)(moptions.navGuideBrush[3] * 65535.0)); fontbutton->set_font_name(moptions.font); + colorPickerFontButton->set_font_name(moptions.colorPickerFont); showDateTime->set_active (moptions.fbShowDateTime); showBasicExif->set_active (moptions.fbShowBasicExif); showExpComp->set_active (moptions.fbShowExpComp); diff --git a/rtgui/preferences.h b/rtgui/preferences.h index 87af25941..a94601663 100644 --- a/rtgui/preferences.h +++ b/rtgui/preferences.h @@ -132,6 +132,7 @@ protected: Gtk::HBox* hbtheme; Gtk::CheckButton* chUseSystemTheme; Gtk::FontButton* fontbutton; + Gtk::FontButton* colorPickerFontButton; Gtk::ColorButton* butCropCol; Gtk::ColorButton* butNavGuideCol; @@ -230,7 +231,7 @@ protected: Gtk::Widget* getSoundPanel (); public: - Preferences (RTWindow *rtwindow); + explicit Preferences (RTWindow *rtwindow); ~Preferences (); void savePressed (); diff --git a/rtgui/previewloader.cc b/rtgui/previewloader.cc index 02082f7a7..c38fed49d 100644 --- a/rtgui/previewloader.cc +++ b/rtgui/previewloader.cc @@ -29,7 +29,8 @@ #define DEBUG(format,args...) //#define DEBUG(format,args...) printf("PreviewLoader::%s: " format "\n", __FUNCTION__, ## args) -class PreviewLoader::Impl +class PreviewLoader::Impl : + public rtengine::NonCopyable { public: struct Job { @@ -72,9 +73,10 @@ public: Impl(): nConcurrentThreads(0) { - int threadCount = 2; #ifdef _OPENMP - threadCount = omp_get_num_procs(); + int threadCount = omp_get_num_procs(); +#else + int threadCount = 2; #endif threadPool_ = new Glib::ThreadPool(threadCount, 0); diff --git a/rtgui/previewloader.h b/rtgui/previewloader.h index 762776ae7..d5207cd44 100644 --- a/rtgui/previewloader.h +++ b/rtgui/previewloader.h @@ -21,11 +21,17 @@ #include #include + +#include "../rtengine/noncopyable.h" + #include "filebrowserentry.h" class PreviewLoaderListener { public: + virtual ~PreviewLoaderListener() + { + } /** * @brief a preview is ready @@ -33,18 +39,22 @@ public: * @param dir_id directory ID this is for * @param fd entry */ - virtual void previewReady (int dir_id, FileBrowserEntry* fd) {} + virtual void previewReady(int dir_id, FileBrowserEntry* fd) + { + } /** * @brief all previews have finished loading */ - virtual void previewsFinished (int dir_id_) {} + virtual void previewsFinished(int dir_id_) + { + } }; -class PreviewLoader +class PreviewLoader : + public rtengine::NonCopyable { public: - /** * @brief Singleton entry point. * diff --git a/rtgui/previewmodepanel.h b/rtgui/previewmodepanel.h index 10906c30f..d3bf3c8e4 100644 --- a/rtgui/previewmodepanel.h +++ b/rtgui/previewmodepanel.h @@ -47,7 +47,7 @@ protected: Gtk::Image* iBC2, *igBC2; public: - PreviewModePanel (ImageArea* ia); + explicit PreviewModePanel (ImageArea* ia); ~PreviewModePanel(); void toggleR (); diff --git a/rtgui/previewwindow.cc b/rtgui/previewwindow.cc index ea419427b..18c470e55 100644 --- a/rtgui/previewwindow.cc +++ b/rtgui/previewwindow.cc @@ -223,10 +223,10 @@ bool PreviewWindow::on_button_press_event (GdkEventButton* event) int x, y, w, h; getObservedFrameArea (x, y, w, h); if (x>imgX || y>imgY || w < imgW || h < imgH) { - bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; - bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; if (!isMoving) { + bool inside = event->x > x - 6 && event->x < x + w - 1 + 6 && event->y > y - 6 && event->y < y + h - 1 + 6; + bool moreInside = event->x > x + 6 && event->x < x + w - 1 - 6 && event->y > y + 6 && event->y < y + h - 1 - 6; isMoving = true; if (!inside || moreInside) { diff --git a/rtgui/profilepanel.h b/rtgui/profilepanel.h index 9bcc79196..f80438aac 100644 --- a/rtgui/profilepanel.h +++ b/rtgui/profilepanel.h @@ -69,7 +69,7 @@ protected: public: - ProfilePanel (bool readOnly = false); + explicit ProfilePanel (bool readOnly = false); virtual ~ProfilePanel (); void setProfileChangeListener (ProfileChangeListener* ppl) diff --git a/rtgui/profilestore.cc b/rtgui/profilestore.cc index acbbfba63..4f4f2c187 100644 --- a/rtgui/profilestore.cc +++ b/rtgui/profilestore.cc @@ -164,10 +164,10 @@ bool ProfileStore::parseDir (Glib::ustring& realPath, Glib::ustring& virtualPath { bool fileFound = false; - unsigned int folder = 0; // folder's own Id // reload the available profiles from the profile dir if (!realPath.empty() && Glib::file_test(realPath, Glib::FILE_TEST_EXISTS) && Glib::file_test (realPath, Glib::FILE_TEST_IS_DIR)) { + unsigned int folder = 0; // folder's own Id // add this entry to the folder list folders.push_back(virtualPath); @@ -488,7 +488,7 @@ void ProfileStore::dumpFolderList() printf("Folder list:\n------------\n"); for (unsigned int i = 0; i < folders.size(); i++) { - printf(" #%3d - %s\n", i, folders.at(i).c_str()); + printf(" #%3ud - %s\n", i, folders.at(i).c_str()); } printf("\n"); diff --git a/rtgui/profilestore.h b/rtgui/profilestore.h index 2928a01ef..05a0a3797 100644 --- a/rtgui/profilestore.h +++ b/rtgui/profilestore.h @@ -21,11 +21,14 @@ #include #include +#include + #include "../rtengine/rtengine.h" +#include "../rtengine/noncopyable.h" + #include "threadutils.h" #include "paramsedited.h" #include "guiutils.h" -#include /** @brief This will implement callback functions for the ProfileStore @@ -108,7 +111,7 @@ public: * * @param entry Pointer to the ProfileStoreEntry object, be it a directory or a file */ - ProfileStoreLabel(const ProfileStoreEntry *entry); + explicit ProfileStoreLabel(const ProfileStoreEntry *entry); ProfileStoreLabel (const ProfileStoreLabel &other); }; @@ -118,7 +121,8 @@ public: * This store can be queried by the GUI to display a Tree of the profiles available * in the user's and system's profile directory and subdirectories. */ -class ProfileStore +class ProfileStore : + public rtengine::NonCopyable { typedef enum { @@ -177,6 +181,7 @@ public: ProfileStore(); ~ProfileStore(); + bool init (); void parseProfiles (); int findFolderId(const Glib::ustring &path); diff --git a/rtgui/progressconnector.h b/rtgui/progressconnector.h index ffa4bee67..fe824a6a1 100644 --- a/rtgui/progressconnector.h +++ b/rtgui/progressconnector.h @@ -32,7 +32,7 @@ class PLDBridge : public rtengine::ProgressListener rtengine::ProgressListener* pl; public: - PLDBridge ( rtengine::ProgressListener* pb) + explicit PLDBridge ( rtengine::ProgressListener* pb) : pl(pb) {} // ProgressListener interface @@ -90,7 +90,7 @@ class ProgressConnector public: - ProgressConnector (): workThread( 0 ) { } + ProgressConnector (): retval( 0 ), workThread( 0 ) { } void startFunc (const sigc::slot0& startHandler, const sigc::slot0& endHandler ) { diff --git a/rtgui/renamedlg.cc b/rtgui/renamedlg.cc index a33011f09..16bfaff00 100644 --- a/rtgui/renamedlg.cc +++ b/rtgui/renamedlg.cc @@ -88,159 +88,159 @@ Glib::ustring RenameDialog::getNewName () return newName->get_text (); } -void RenameDialog::fillTemplateList () -{ +//void RenameDialog::fillTemplateList () +//{ +// +// templateModel->clear (); +// +// for (size_t i = 0; i < options.renameTemplates.size(); i++) { +// Gtk::TreeModel::iterator iter = templateModel->append (); +// iter->set_value (templateColumns.tmplName, options.renameTemplates[i]); +// iter->set_value (templateColumns.rowSeparator, false); +// } +// +// // append separator and the manage... item +// Gtk::TreeModel::iterator iter = templateModel->append (); +// iter->set_value (templateColumns.tmplName, Glib::ustring("")); +// iter->set_value (templateColumns.rowSeparator, true); +// iter = templateModel->append (); +// iter->set_value (templateColumns.tmplName, Glib::ustring(M("FILEBROWSER_ADDDELTEMPLATE"))); +// iter->set_value (templateColumns.rowSeparator, false); +//} - templateModel->clear (); +//bool RenameDialog::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) +//{ +// +// return iter->get_value (templateColumns.rowSeparator); +//} - for (size_t i = 0; i < options.renameTemplates.size(); i++) { - Gtk::TreeModel::iterator iter = templateModel->append (); - iter->set_value (templateColumns.tmplName, options.renameTemplates[i]); - iter->set_value (templateColumns.rowSeparator, false); - } +//void RenameDialog::useTemplToggled () +//{ +// +// templates->set_sensitive (useTmpl->get_active ()); +// +// if (useTmpl->get_active () && isTemplSelected ()) { +// all->set_sensitive (true); +// newName->set_text (applyTemplate (oldName->get_text(), imageData, getActiveTemplate())); +// } else { +// all->set_sensitive (false); +// } +// +// newName->select_region (0, newName->get_text().size()); +//} - // append separator and the manage... item - Gtk::TreeModel::iterator iter = templateModel->append (); - iter->set_value (templateColumns.tmplName, Glib::ustring("")); - iter->set_value (templateColumns.rowSeparator, true); - iter = templateModel->append (); - iter->set_value (templateColumns.tmplName, Glib::ustring(M("FILEBROWSER_ADDDELTEMPLATE"))); - iter->set_value (templateColumns.rowSeparator, false); -} +//bool RenameDialog::isTemplSelected () +//{ +// +// Gtk::TreeModel::iterator iter = templates->get_active(); +// return iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE"); +//} -bool RenameDialog::rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter) -{ +//Glib::ustring RenameDialog::getActiveTemplate () +//{ +// +// Gtk::TreeModel::iterator iter = templates->get_active(); +// +// if (iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE")) { +// return iter->get_value (templateColumns.tmplName); +// } else { +// return ""; +// } +//} - return iter->get_value (templateColumns.rowSeparator); -} +//void RenameDialog::tmplSelectionChanged () +//{ +// +// Gtk::TreeModel::iterator iter = templates->get_active(); +// +// if (iter && iter->get_value (templateColumns.tmplName) == M("FILEBROWSER_ADDDELTEMPLATE")) { +// RenameTemplateEditor* rte = new RenameTemplateEditor (p); +// +// if (rte->run() == Gtk::RESPONSE_OK) { +// fillTemplateList (); +// } +// +// delete rte; +// // show add/del template dialog +// } else { +// useTemplToggled (); +// } +//} -void RenameDialog::useTemplToggled () -{ +//RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) +// : Gtk::Dialog ("Edit rename templates", *parent, true, true) +//{ +// +// list = Gtk::manage (new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); +// list->set_headers_visible (false); +// get_vbox ()->pack_start (*list); +// +// Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); +// templ = Gtk::manage (new Gtk::Entry ()); +// Gtk::Button* add = Gtk::manage (new Gtk::Button ()); +// Gtk::Button* del = Gtk::manage (new Gtk::Button ()); +// add->add (*Gtk::manage (new RTImage ("list-add-small.png"))); +// del->add (*Gtk::manage (new RTImage ("list-remove-red-small.png"))); +// hb->pack_start (*templ); +// hb->pack_start (*add, Gtk::PACK_SHRINK, 2); +// hb->pack_start (*del, Gtk::PACK_SHRINK, 2); +// +// get_vbox ()->pack_start (*hb, Gtk::PACK_SHRINK, 4); +// +// add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); +// +// refreshTemplateList (); +// +// add->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::addPressed) ); +// del->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::delPressed) ); +// +// show_all_children (); +// +// set_size_request (-1, 250); +//} +// +//void RenameTemplateEditor::refreshTemplateList () +//{ +// +// list->clear_items (); +// +// for (size_t i = 0; i < options.renameTemplates.size(); i++) { +// list->append_text (options.renameTemplates[i]); +// } +//} +// +//void RenameTemplateEditor::addPressed () +//{ +// +// if (templ->get_text() != "") { +// options.renameTemplates.push_back (templ->get_text ()); +// refreshTemplateList (); +// templ->set_text(""); +// } +//} +// +//void RenameTemplateEditor::delPressed () +//{ +// +// std::vector sel = list->get_selected (); +// +// for (size_t i = 0; i < sel.size(); i++) { +// Glib::ustring toDel = list->get_text (sel[i]); +// std::vector::iterator f = std::find (options.renameTemplates.begin(), options.renameTemplates.end(), toDel); +// +// if (f != options.renameTemplates.end()) { +// options.renameTemplates.erase (f); +// } +// } +// +// refreshTemplateList (); +//} - templates->set_sensitive (useTmpl->get_active ()); - - if (useTmpl->get_active () && isTemplSelected ()) { - all->set_sensitive (true); - newName->set_text (applyTemplate (oldName->get_text(), imageData, getActiveTemplate())); - } else { - all->set_sensitive (false); - } - - newName->select_region (0, newName->get_text().size()); -} - -bool RenameDialog::isTemplSelected () -{ - - Gtk::TreeModel::iterator iter = templates->get_active(); - return iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE"); -} - -Glib::ustring RenameDialog::getActiveTemplate () -{ - - Gtk::TreeModel::iterator iter = templates->get_active(); - - if (iter && iter->get_value (templateColumns.tmplName) != M("FILEBROWSER_ADDDELTEMPLATE")) { - return iter->get_value (templateColumns.tmplName); - } else { - return ""; - } -} - -void RenameDialog::tmplSelectionChanged () -{ - - Gtk::TreeModel::iterator iter = templates->get_active(); - - if (iter && iter->get_value (templateColumns.tmplName) == M("FILEBROWSER_ADDDELTEMPLATE")) { - RenameTemplateEditor* rte = new RenameTemplateEditor (p); - - if (rte->run() == Gtk::RESPONSE_OK) { - fillTemplateList (); - } - - delete rte; - // show add/del template dialog - } else { - useTemplToggled (); - } -} - -RenameTemplateEditor::RenameTemplateEditor (Gtk::Window* parent) - : Gtk::Dialog ("Edit rename templates", *parent, true, true) -{ - - list = Gtk::manage (new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE)); - list->set_headers_visible (false); - get_vbox ()->pack_start (*list); - - Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); - templ = Gtk::manage (new Gtk::Entry ()); - Gtk::Button* add = Gtk::manage (new Gtk::Button ()); - Gtk::Button* del = Gtk::manage (new Gtk::Button ()); - add->add (*Gtk::manage (new RTImage ("list-add-small.png"))); - del->add (*Gtk::manage (new RTImage ("list-remove-red-small.png"))); - hb->pack_start (*templ); - hb->pack_start (*add, Gtk::PACK_SHRINK, 2); - hb->pack_start (*del, Gtk::PACK_SHRINK, 2); - - get_vbox ()->pack_start (*hb, Gtk::PACK_SHRINK, 4); - - add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); - - refreshTemplateList (); - - add->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::addPressed) ); - del->signal_pressed().connect( sigc::mem_fun(*this, &RenameTemplateEditor::delPressed) ); - - show_all_children (); - - set_size_request (-1, 250); -} - -void RenameTemplateEditor::refreshTemplateList () -{ - - list->clear_items (); - - for (size_t i = 0; i < options.renameTemplates.size(); i++) { - list->append_text (options.renameTemplates[i]); - } -} - -void RenameTemplateEditor::addPressed () -{ - - if (templ->get_text() != "") { - options.renameTemplates.push_back (templ->get_text ()); - refreshTemplateList (); - templ->set_text(""); - } -} - -void RenameTemplateEditor::delPressed () -{ - - std::vector sel = list->get_selected (); - - for (size_t i = 0; i < sel.size(); i++) { - Glib::ustring toDel = list->get_text (sel[i]); - std::vector::iterator f = std::find (options.renameTemplates.begin(), options.renameTemplates.end(), toDel); - - if (f != options.renameTemplates.end()) { - options.renameTemplates.erase (f); - } - } - - refreshTemplateList (); -} - -Glib::ustring RenameDialog::applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ) -{ - - return Glib::ustring ("szeva"); - -} +//Glib::ustring RenameDialog::applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ) +//{ +// +// return Glib::ustring ("szeva"); +// +//} diff --git a/rtgui/renamedlg.h b/rtgui/renamedlg.h index a5dec4efa..94972d575 100644 --- a/rtgui/renamedlg.h +++ b/rtgui/renamedlg.h @@ -30,62 +30,62 @@ class RenameDialog : public Gtk::Dialog protected: - class TemplateColumns : public Gtk::TreeModel::ColumnRecord - { - public: - Gtk::TreeModelColumn tmplName; - Gtk::TreeModelColumn rowSeparator; - TemplateColumns() - { - add(tmplName); - add(rowSeparator); - } - }; - TemplateColumns templateColumns; - Glib::RefPtr templateModel; +// class TemplateColumns : public Gtk::TreeModel::ColumnRecord +// { +// public: +// Gtk::TreeModelColumn tmplName; +// Gtk::TreeModelColumn rowSeparator; +// TemplateColumns() +// { +// add(tmplName); +// add(rowSeparator); +// } +// }; +// TemplateColumns templateColumns; +// Glib::RefPtr templateModel; Gtk::Window* p; Gtk::Label* oldName; Gtk::Entry* newName; - Gtk::CheckButton* useTmpl; - MyComboBox* templates; - Gtk::Button* all; +// Gtk::CheckButton* useTmpl; +// MyComboBox* templates; +// Gtk::Button* all; const CacheImageData* imageData; - void fillTemplateList (); +// void fillTemplateList (); public: - RenameDialog (Gtk::Window* parent); + explicit RenameDialog (Gtk::Window* parent); void initName (const Glib::ustring& iname, const CacheImageData* cid); Glib::ustring getNewName (); - bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); - void tmplSelectionChanged (); - void useTemplToggled (); +// bool rowSeparatorFunc (const Glib::RefPtr& model, const Gtk::TreeModel::iterator& iter); +// void tmplSelectionChanged (); +// void useTemplToggled (); - bool isTemplSelected (); - Glib::ustring getActiveTemplate (); +// bool isTemplSelected (); +// Glib::ustring getActiveTemplate (); - static Glib::ustring applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ); +// static Glib::ustring applyTemplate (const Glib::ustring& oName, const CacheImageData* cid, const Glib::ustring& templ); }; -class RenameTemplateEditor : public Gtk::Dialog -{ - -protected: - Gtk::ListViewText* list; - Gtk::Entry* templ; - - void refreshTemplateList (); -public: - RenameTemplateEditor (Gtk::Window* parent); - - Glib::ustring getSelectedTemplate (); - - void addPressed (); - void delPressed (); -}; +//class RenameTemplateEditor : public Gtk::Dialog +//{ +// +//protected: +// Gtk::ListViewText* list; +// Gtk::Entry* templ; +// +// void refreshTemplateList (); +//public: +// explicit RenameTemplateEditor (Gtk::Window* parent); +// +// Glib::ustring getSelectedTemplate (); +// +// void addPressed (); +// void delPressed (); +//}; #endif diff --git a/rtgui/retinex.cc b/rtgui/retinex.cc index fead40b88..d44cef912 100644 --- a/rtgui/retinex.cc +++ b/rtgui/retinex.cc @@ -1121,7 +1121,7 @@ void Retinex::gammaretinexChanged() if(gammaretinex->get_active_row_number() == 4) { gam->show(); slope->show(); - } else if(gammaretinex->get_active_row_number() != 4) { + } else /*if(gammaretinex->get_active_row_number() != 4)*/ { gam->hide(); slope->hide(); } diff --git a/rtgui/saveasdlg.cc b/rtgui/saveasdlg.cc index c9490f585..2afd1eb58 100644 --- a/rtgui/saveasdlg.cc +++ b/rtgui/saveasdlg.cc @@ -22,7 +22,7 @@ #include "rtimage.h" extern Options options; -SaveAsDialog::SaveAsDialog (Glib::ustring initialDir) +SaveAsDialog::SaveAsDialog (const Glib::ustring &initialDir) { set_title(M("GENERAL_SAVE")); diff --git a/rtgui/saveasdlg.h b/rtgui/saveasdlg.h index 4727b574c..4810b46d9 100644 --- a/rtgui/saveasdlg.h +++ b/rtgui/saveasdlg.h @@ -45,7 +45,7 @@ protected: void putToQueueClicked (); public: - SaveAsDialog (Glib::ustring initialDir); + explicit SaveAsDialog (const Glib::ustring &initialDir); Glib::ustring getFileName (); Glib::ustring getDirectory (); diff --git a/rtgui/shcselector.cc b/rtgui/shcselector.cc index 461eb118f..9cb41e1a5 100644 --- a/rtgui/shcselector.cc +++ b/rtgui/shcselector.cc @@ -21,7 +21,7 @@ #include "multilangmgr.h" #include "mycurve.h" -SHCSelector::SHCSelector() : ColoredBar(RTO_Left2Right), movingPosition(-1), cl(NULL) +SHCSelector::SHCSelector() : ColoredBar(RTO_Left2Right), movingPosition(-1), tmpX(0.0), tmpPos(0.0), wslider(0.0), cl(NULL) { positions[0] = defaults[0] = 0.25; diff --git a/rtgui/splash.h b/rtgui/splash.h index 5e3d5e1b4..9fe6d8220 100644 --- a/rtgui/splash.h +++ b/rtgui/splash.h @@ -46,7 +46,7 @@ private: public: Splash (Gtk::Window& parent, int maxtime); - Splash (Gtk::Window& parent); + explicit Splash (Gtk::Window& parent); bool hasReleaseNotes() { diff --git a/rtgui/threadutils.h b/rtgui/threadutils.h index 03203db82..1215d53a1 100644 --- a/rtgui/threadutils.h +++ b/rtgui/threadutils.h @@ -27,6 +27,8 @@ #include +#include "../rtengine/noncopyable.h" + #if STRICT_MUTEX && NDEBUG using MyMutexBase = Glib::Threads::Mutex; #else @@ -41,15 +43,13 @@ using MyMutexBase = Glib::Threads::RecMutex; * It will behave like Glib::Threads::RecMutex (STRICT_MUTEX=0) or Glib::Threads::Mutex (STRICT_MUTEX=1). * Debug builds with strict mutexes, will emit a message and crash immediately upon recursive locking. */ -class MyMutex : private MyMutexBase +class MyMutex : + public rtengine::NonCopyable, + private MyMutexBase { public: class MyLock; - MyMutex () = default; - MyMutex (const MyMutex&) = delete; - MyMutex& operator= (const MyMutex&) = delete; - void lock (); bool trylock (); void unlock (); @@ -62,7 +62,8 @@ private: #endif }; -class MyMutex::MyLock +class MyMutex::MyLock : + public rtengine::NonCopyable { public: explicit MyLock (MyMutex& mutex); @@ -71,9 +72,6 @@ public: ~MyLock (); - MyLock (const MyLock&) = delete; - MyLock& operator= (const MyLock&) = delete; - void acquire (); bool try_acquire (); void release (); @@ -86,13 +84,10 @@ private: /** * @brief Custom implementation to replace Glib::Threads::RWLock */ -class MyRWMutex +class MyRWMutex : + public rtengine::NonCopyable { public: - MyRWMutex () = default; - MyRWMutex (const MyRWMutex&) = delete; - MyRWMutex& operator= (const MyRWMutex&) = delete; - friend class MyReaderLock; friend class MyWriterLock; @@ -113,14 +108,12 @@ private: /** * @brief Custom implementation to replace Glib::Threads::RWLock::ReaderLock */ -class MyReaderLock +class MyReaderLock : + public rtengine::NonCopyable { public: ~MyReaderLock (); - MyReaderLock (const MyReaderLock&) = delete; - MyReaderLock& operator= (const MyReaderLock&) = delete; - #if !TRACE_MYRWMUTEX explicit MyReaderLock (MyRWMutex& mutex); @@ -141,14 +134,12 @@ private: /** * @brief Custom implementation to replace Glib::Threads::RWLock::WriterLock */ -class MyWriterLock +class MyWriterLock : + public rtengine::NonCopyable { public: ~MyWriterLock (); - MyWriterLock (const MyWriterLock&) = delete; - MyWriterLock& operator= (const MyWriterLock&) = delete; - #if !TRACE_MYRWMUTEX explicit MyWriterLock (MyRWMutex& mutex); diff --git a/rtgui/thumbbrowserbase.cc b/rtgui/thumbbrowserbase.cc index ea2bb00dd..2d022f9f7 100644 --- a/rtgui/thumbbrowserbase.cc +++ b/rtgui/thumbbrowserbase.cc @@ -559,7 +559,6 @@ void ThumbBrowserBase::arrangeFiles () int ct = 0; int currx = 0; - int curry = 0; while (ct < N) { // find widest item in the column @@ -571,7 +570,7 @@ void ThumbBrowserBase::arrangeFiles () } // arrange items in the column - curry = 0; + int curry = 0; for (int i = 0; ct < N && i < numOfRows; i++, ct++) { while (ct < N && fd[ct]->filtered) { @@ -641,12 +640,11 @@ void ThumbBrowserBase::arrangeFiles () // arrange files int ct = 0; - int currx = 0; int curry = 0; while (ct < N) { // arrange items in the row - currx = 0; + int currx = 0; for (int i = 0; ct < N && i < numOfCols; i++, ct++) { while (ct < N && fd[ct]->filtered) { diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index b924655c5..3783c5164 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -119,7 +119,6 @@ void ThumbBrowserEntryBase::updateBackBuffer () getTextSizes (infow, infoh); int iofs_x = 4, iofs_y = 4; - int igap = 2; int istartx = prex; int istarty = prey; @@ -141,6 +140,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () istarty += iofs_y; if (!bbIcons.empty()) { + int igap = 2; int iwidth = 0; int iheight = 0; @@ -251,7 +251,6 @@ void ThumbBrowserEntryBase::updateBackBuffer () fn->set_width (textw * Pango::SCALE); fn->set_ellipsize (Pango::ELLIPSIZE_MIDDLE); backBuffer->draw_layout (gc_, textposx_ex, textposy + tpos, fn); - tpos += exlabh; } } } diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index 1b7f0691a..59b2c022f 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.h @@ -107,7 +107,7 @@ public: bool updatepriority; eWithFilename withFilename; - ThumbBrowserEntryBase (const Glib::ustring& fname); + explicit ThumbBrowserEntryBase (const Glib::ustring& fname); virtual ~ThumbBrowserEntryBase (); void setParent (ThumbBrowserBase* l) diff --git a/rtgui/thumbimageupdater.cc b/rtgui/thumbimageupdater.cc index 29160236e..39711a5ae 100644 --- a/rtgui/thumbimageupdater.cc +++ b/rtgui/thumbimageupdater.cc @@ -30,8 +30,8 @@ #define DEBUG(format,args...) //#define DEBUG(format,args...) printf("ThumbImageUpdate::%s: " format "\n", __FUNCTION__, ## args) -class - ThumbImageUpdater::Impl +class ThumbImageUpdater::Impl : + public rtengine::NonCopyable { public: diff --git a/rtgui/thumbimageupdater.h b/rtgui/thumbimageupdater.h index ea9cff6d7..3b34c9456 100644 --- a/rtgui/thumbimageupdater.h +++ b/rtgui/thumbimageupdater.h @@ -20,14 +20,19 @@ #define _THUMBIMAGEUPDATER_ #include -#include "../rtengine/rtengine.h" -#include "thumbbrowserentrybase.h" #include +#include "../rtengine/rtengine.h" +#include "../rtengine/noncopyable.h" + +#include "thumbbrowserentrybase.h" + class ThumbImageUpdateListener { - public: + virtual ~ThumbImageUpdateListener() + { + } /** * @brief Called when thumbnail image is update @@ -38,14 +43,15 @@ public: * * @note no locks are held when called back */ - virtual void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {} + virtual void updateImage(rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) + { + } }; -class ThumbImageUpdater +class ThumbImageUpdater : + public rtengine::NonCopyable { - public: - /** * @brief Singleton entry point. * diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index b9d23e46d..62d48b2ec 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -63,8 +63,8 @@ Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, CacheImageDa Thumbnail::Thumbnail (CacheManager* cm, const Glib::ustring& fname, const std::string& md5) : fname(fname), cachemgr(cm), ref(1), enqueueNumber(0), tpp(NULL), pparamsValid(false), - needsReProcessing(true), imageLoading(false), lastImg(NULL), - initial_(true) + pparamsSet(false), needsReProcessing(true), imageLoading(false), lastImg(NULL), + lastW(0), lastH(0), lastScale(0.0), initial_(true) { diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index ca2f898ec..97dd20b5a 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -187,7 +187,7 @@ public: { return pparams.inTrash; } - void setStage (int stage) + void setStage (bool stage) { if (pparams.inTrash != stage) { pparams.inTrash = stage; diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index 7a7222299..86604863e 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -1,3 +1,4 @@ + /* * This file is part of RawTherapee. * @@ -20,7 +21,7 @@ #include "multilangmgr.h" #include "guiutils.h" -ToolBar::ToolBar () : listener (NULL) +ToolBar::ToolBar () : showColPickers(true), listener (NULL) { editingMode = false; @@ -47,6 +48,19 @@ ToolBar::ToolBar () : listener (NULL) pack_start (*wbTool); + showcolpickersimg = Gtk::manage (new RTImage ("colorPickers-show.png")); + showcolpickersimg->reference(); + hidecolpickersimg = Gtk::manage (new RTImage ("colorPickers-hide.png")); + hidecolpickersimg->reference(); + + colPickerTool = Gtk::manage (new Gtk::ToggleButton ()); + colPickerTool->add (*showcolpickersimg); + showcolpickersimg->show (); + colPickerTool->set_relief(Gtk::RELIEF_NONE); + colPickerTool->show (); + + pack_start (*colPickerTool); + cropTool = Gtk::manage (new Gtk::ToggleButton ()); Gtk::Image* cropimg = Gtk::manage (new RTImage ("crop.png")); cropTool->add (*cropimg); @@ -71,11 +85,13 @@ ToolBar::ToolBar () : listener (NULL) handConn = handTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::hand_pressed)); wbConn = wbTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::wb_pressed)); + cpConn = colPickerTool->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &ToolBar::colPicker_pressed)); cropConn = cropTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::crop_pressed)); straConn = straTool->signal_toggled().connect( sigc::mem_fun(*this, &ToolBar::stra_pressed)); handTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_HAND")); wbTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_WB")); + colPickerTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_COLORPICKER")); cropTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_CROP")); straTool->set_tooltip_markup (M("TOOLBAR_TOOLTIP_STRAIGHTEN")); } @@ -84,6 +100,8 @@ ToolBar::~ToolBar () { handimg->unreference(); editinghandimg->unreference(); + showcolpickersimg->unreference(); + hidecolpickersimg->unreference(); } // @@ -92,14 +110,18 @@ ToolBar::~ToolBar () void ToolBar::setTool (ToolMode tool) { - handConn.block (true); - cropConn.block (true); + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; if (wbTool) { - wbConn.block (true); + wbWasBlocked = wbConn.block (true); + } + if (colPickerTool) { + cpWasBlocked = cpConn.block (true); } - straConn.block (true); + bool straWasBlocked = straConn.block (true); bool stopEdit = tool == TMHand && handTool->get_active() && editingMode; @@ -111,6 +133,9 @@ void ToolBar::setTool (ToolMode tool) cropTool->set_active (false); straTool->set_active (false); + if (colPickerTool) { + colPickerTool->set_active (false); + } if (tool == TMHand) { handTool->set_active (true); @@ -123,18 +148,25 @@ void ToolBar::setTool (ToolMode tool) cropTool->set_active (true); } else if (tool == TMStraighten) { straTool->set_active (true); + } else if (tool == TMColorPicker) { + if (colPickerTool) { + colPickerTool->set_active (true); + } } current = tool; - handConn.block (false); - cropConn.block (false); + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); if (wbTool) { - wbConn.block (false); + if (!wbWasBlocked) wbConn.block (false); + } + if (colPickerTool) { + if (!cpWasBlocked) cpConn.block (false); } - straConn.block (false); + if (!straWasBlocked) straConn.block (false); if (stopEdit) { stopEditMode(); @@ -148,7 +180,44 @@ void ToolBar::setTool (ToolMode tool) void ToolBar::startEditMode() { if (!editingMode) { - handTool->set_active(true); // will call hand_pressed, with editingMode=false + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; + if (colPickerTool) { + cpWasBlocked = cpConn.block (true); + } + + if (wbTool) { + wbWasBlocked = wbConn.block (true); + } + + bool straWasBlocked = straConn.block (true); + + if (current != TMHand) { + if (colPickerTool) { + colPickerTool->set_active(false); + } + if (wbTool) { + wbTool->set_active (false); + } + + cropTool->set_active (false); + straTool->set_active (false); + current = TMHand; + } + handTool->set_active (true); + + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (colPickerTool) { + if (!cpWasBlocked) cpConn.block (false); + } + if (wbTool) { + if (!wbWasBlocked) wbConn.block (false); + } + + if (!straWasBlocked) straConn.block (false); + editingMode = true; handTool->set_image(*editinghandimg); } @@ -165,13 +234,6 @@ void ToolBar::stopEditMode() { if (editingMode) { editingMode = false; - /* WARNING: Should we toggle the Hand button on? - * This method can be called while another tool is active, e.g. if the user toggle off - * the Subscriber's Edit button. For now, we keep that other tool active. If one want to - * switch to the Hand tool, uncommenting the following line should suffice (not tested). - * - * handTool->set_active(true); - */ handTool->set_image(*handimg); } } @@ -179,16 +241,29 @@ void ToolBar::stopEditMode() void ToolBar::hand_pressed () { - handConn.block (true); - cropConn.block (true); - - if (wbTool) { - wbConn.block (true); + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; + if (colPickerTool) { + cpWasBlocked = cpConn.block (true); } - straConn.block (true); + if (wbTool) { + wbWasBlocked = wbConn.block (true); + } + bool straWasBlocked = straConn.block (true); + + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff (); + } + } if (current != TMHand) { + if (colPickerTool) { + colPickerTool->set_active(false); + } if (wbTool) { wbTool->set_active (false); } @@ -196,25 +271,19 @@ void ToolBar::hand_pressed () cropTool->set_active (false); straTool->set_active (false); current = TMHand; - } else { - if (editingMode) { - stopEditMode(); - } - - if (listener) { - listener->editModeSwitchedOff (); - } } handTool->set_active (true); - handConn.block (false); - cropConn.block (false); - + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (colPickerTool) { + if (!cpWasBlocked) cpConn.block (false); + } if (wbTool) { - wbConn.block (false); + if (!wbWasBlocked) wbConn.block (false); } - straConn.block (false); + if (!straWasBlocked) straConn.block (false); if (listener) { listener->toolSelected (TMHand); @@ -224,19 +293,31 @@ void ToolBar::hand_pressed () void ToolBar::wb_pressed () { - handConn.block (true); - cropConn.block (true); - + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; + if (colPickerTool) { + cpWasBlocked = cpConn.block (true); + } if (wbTool) { - wbConn.block (true); + wbWasBlocked = wbConn.block (true); } - straConn.block (true); + bool straWasBlocked = straConn.block (true); if (current != TMSpotWB) { + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff (); + } + } handTool->set_active (false); cropTool->set_active (false); straTool->set_active (false); + if (colPickerTool) { + colPickerTool->set_active(false); + } current = TMSpotWB; } @@ -244,35 +325,139 @@ void ToolBar::wb_pressed () wbTool->set_active (true); } - handConn.block (false); - cropConn.block (false); - + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (colPickerTool) { + if (!cpWasBlocked) cpConn.block (false); + } if (wbTool) { - wbConn.block (false); + if (!wbWasBlocked) wbConn.block (false); } - straConn.block (false); + if (!straWasBlocked) straConn.block (false); if (listener) { listener->toolSelected (TMSpotWB); } } +void ToolBar::colPicker_pressed (GdkEventButton* event) +{ + + if (event->button == 1) { + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true; + bool cpWasBlocked = cpConn.block (true); + if (wbTool) { + wbWasBlocked = wbConn.block (true); + } + + bool straWasBlocked = straConn.block (true); + + cropTool->set_active (false); + if (wbTool) { + wbTool->set_active (false); + } + straTool->set_active (false); + + if (current != TMColorPicker) { + // Disabling all other tools, enabling the Picker tool and entering the "visible pickers" mode + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff (); + } + } + handTool->set_active (false); + showColorPickers(true); + current = TMColorPicker; + if (pickerListener) { + pickerListener->switchPickerVisibility (showColPickers); + } + } else { + // Disabling the picker tool, enabling the Hand tool and keeping the "visible pickers" mode + handTool->set_active (true); + //colPickerTool->set_active (false); Done by the standard event handler + current = TMHand; + } + + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (!cpWasBlocked) cpConn.block (false); + if (!wbWasBlocked) wbConn.block (false); + if (!straWasBlocked) straConn.block (false); + + if (listener) { + listener->toolSelected (current); + } + } else if (event->button == 3) { + if (current == TMColorPicker) { + // Disabling the Picker tool and entering into the "invisible pickers" mode + bool cpWasBlocked = cpConn.block (true); + bool handWasBlocked = handConn.block (true); + handTool->set_active (true); + colPickerTool->set_active (false); + current = TMHand; + showColorPickers(false); + if (!cpWasBlocked) cpConn.block (false); + if (!handWasBlocked) handConn.block (false); + } else { + // The Picker tool is already disabled, entering into the "invisible pickers" mode + switchColorPickersVisibility(); + } + if (pickerListener) { + pickerListener->switchPickerVisibility (showColPickers); + } + } +} + +bool ToolBar::showColorPickers(bool showCP) +{ + if (showColPickers != showCP) { + // Inverting the state + colPickerTool->set_image(showCP ? *showcolpickersimg : *hidecolpickersimg); + showColPickers = showCP; + return true; + } + + return false; +} + +void ToolBar::switchColorPickersVisibility() +{ + // Inverting the state + showColPickers = !showColPickers; + colPickerTool->set_image(showColPickers ? *showcolpickersimg : *hidecolpickersimg); +} + void ToolBar::crop_pressed () { - handConn.block (true); - cropConn.block (true); - - if (wbTool) { - wbConn.block (true); + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; + if (colPickerTool) { + cpWasBlocked = cpConn.block(true); } - straConn.block (true); + if (wbTool) { + wbWasBlocked = wbConn.block (true); + } + + bool straWasBlocked = straConn.block (true); if (current != TMCropSelect) { + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff (); + } + } handTool->set_active (false); - + if (colPickerTool) { + colPickerTool->set_active(false); + } if (wbTool) { wbTool->set_active (false); } @@ -282,10 +467,12 @@ void ToolBar::crop_pressed () } cropTool->set_active (true); - handConn.block (false); - cropConn.block (false); - wbConn.block (false); - straConn.block (false); + cropTool->grab_focus (); + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (!cpWasBlocked) cpConn.block(false); + if (!wbWasBlocked) wbConn.block (false); + if (!straWasBlocked) straConn.block (false); if (listener) { listener->toolSelected (TMCropSelect); @@ -295,18 +482,30 @@ void ToolBar::crop_pressed () void ToolBar::stra_pressed () { - handConn.block (true); - cropConn.block (true); - - if (wbTool) { - wbConn.block (true); + bool handWasBlocked = handConn.block (true); + bool cropWasBlocked = cropConn.block (true); + bool wbWasBlocked = true, cpWasBlocked = true; + if (colPickerTool) { + cpWasBlocked = cpConn.block (true); } - straConn.block (true); + if (wbTool) { + wbWasBlocked = wbConn.block (true); + } + + bool straWasBlocked = straConn.block (true); if (current != TMStraighten) { + if (editingMode) { + stopEditMode(); + if (listener) { + listener->editModeSwitchedOff (); + } + } handTool->set_active (false); - + if (colPickerTool) { + colPickerTool->set_active(false); + } if (wbTool) { wbTool->set_active (false); } @@ -316,14 +515,15 @@ void ToolBar::stra_pressed () } straTool->set_active (true); - handConn.block (false); - cropConn.block (false); + if (!handWasBlocked) handConn.block (false); + if (!cropWasBlocked) cropConn.block (false); + if (!cpWasBlocked) cpConn.block (false); if (wbTool) { - wbConn.block (false); + if (!wbWasBlocked) wbConn.block (false); } - straConn.block (false); + if (!straWasBlocked) straConn.block (false); if (listener) { listener->toolSelected (TMStraighten); @@ -371,12 +571,17 @@ bool ToolBar::handleShortcutKey (GdkEventKey* event) return false; } -void ToolBar::removeWbTool() +void ToolBar::setBatchMode() { if (wbTool) { wbConn.disconnect(); removeIfThere(this, wbTool, false); - wbTool = NULL; + wbTool = nullptr; + } + if (colPickerTool) { + cpConn.disconnect(); + removeIfThere(this, colPickerTool, false); + colPickerTool = nullptr; } } diff --git a/rtgui/toolbar.h b/rtgui/toolbar.h index e00520721..c5bc68696 100644 --- a/rtgui/toolbar.h +++ b/rtgui/toolbar.h @@ -22,6 +22,7 @@ #include #include "toolenum.h" #include "rtimage.h" +#include "lockablecolorpicker.h" class ToolBarListener { @@ -40,17 +41,31 @@ class ToolBar : public Gtk::HBox private: RTImage* handimg; RTImage* editinghandimg; + RTImage* showcolpickersimg; + RTImage* hidecolpickersimg; + bool showColPickers; + + void hand_pressed (); + void wb_pressed (); + void colPicker_pressed (GdkEventButton* event); + void crop_pressed (); + void stra_pressed (); + bool showColorPickers(bool showCP); + void switchColorPickersVisibility(); protected: Gtk::ToggleButton* handTool; Gtk::ToggleButton* wbTool; + Gtk::ToggleButton* colPickerTool; Gtk::ToggleButton* cropTool; Gtk::ToggleButton* straTool; ToolBarListener* listener; + LockablePickerToolListener* pickerListener; ToolMode current; bool editingMode; // true if the cursor is being used to remotely edit tool's values sigc::connection handConn; sigc::connection wbConn; + sigc::connection cpConn; sigc::connection cropConn; sigc::connection straConn; @@ -64,21 +79,25 @@ public: return current; } + bool showColorPickers() { + return showColPickers; + } + void setToolBarListener (ToolBarListener* tpl) { listener = tpl; } + void setLockablePickerToolListener (LockablePickerToolListener* lptl) + { + pickerListener = lptl; + } + void startEditMode(); void stopEditMode(); - void hand_pressed (); - void wb_pressed (); - void crop_pressed (); - void stra_pressed (); - bool handleShortcutKey (GdkEventKey* event); - void removeWbTool(); + void setBatchMode(); }; #endif diff --git a/rtgui/toolenum.h b/rtgui/toolenum.h index f06fda376..06212682a 100644 --- a/rtgui/toolenum.h +++ b/rtgui/toolenum.h @@ -19,6 +19,6 @@ #ifndef _TOOLENUM_ #define _TOOLENUM_ -enum ToolMode {TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3}; +enum ToolMode {TMHand = 0, TMSpotWB = 1, TMCropSelect = 2, TMStraighten = 3, TMColorPicker = 4}; #endif diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 46285ce3e..14774df48 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -294,12 +294,6 @@ public: { return toolBar; } - void removeWbTool() - { - if (toolBar) { - toolBar->removeWbTool(); - } - } int getSpotWBRectSize (); CropGUIListener* startCropEditing (Thumbnail* thm = NULL) { diff --git a/rtgui/whitebalance.cc b/rtgui/whitebalance.cc index f77ce74e7..3c4b61fe3 100644 --- a/rtgui/whitebalance.cc +++ b/rtgui/whitebalance.cc @@ -104,14 +104,13 @@ static double wbTemp2Slider(double temp) const double slope = (double)(CENTERTEMP - MINTEMP) / (MAXTEMP - CENTERTEMP); const double y = (temp - CENTERTEMP) / (MAXTEMP - CENTERTEMP); double x = pow(y, 0.25); // rough guess of x, will be a little lower - double y1; double k = 0.1; bool add = true; // the y=f(x) function is a mess to invert, therefore we have this trial-refinement loop instead. // from tests, worst case is about 20 iterations, ie no problem for (;;) { - y1 = x * slope + (1.0 - slope) * pow(x, 4.0); + double y1 = x * slope + (1.0 - slope) * pow(x, 4.0); if (5000 * fabs(y1 - y) < 0.1) { break; diff --git a/rtgui/zoompanel.h b/rtgui/zoompanel.h index aa4d9177f..bcfbc2b34 100644 --- a/rtgui/zoompanel.h +++ b/rtgui/zoompanel.h @@ -38,7 +38,7 @@ protected: public: - ZoomPanel (ImageArea* iarea); + explicit ZoomPanel (ImageArea* iarea); void zoomInClicked (); void zoomOutClicked (); diff --git a/tools/source_icons/scalable/colorPickers-hide.file b/tools/source_icons/scalable/colorPickers-hide.file new file mode 100644 index 000000000..728529716 --- /dev/null +++ b/tools/source_icons/scalable/colorPickers-hide.file @@ -0,0 +1 @@ +colorPickers-hide.png,w22,actions diff --git a/tools/source_icons/scalable/colorPickers-hide.svg b/tools/source_icons/scalable/colorPickers-hide.svg new file mode 100644 index 000000000..fe0c7bf14 --- /dev/null +++ b/tools/source_icons/scalable/colorPickers-hide.svg @@ -0,0 +1,4301 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/colorPickers-show.file b/tools/source_icons/scalable/colorPickers-show.file new file mode 100644 index 000000000..96db803fc --- /dev/null +++ b/tools/source_icons/scalable/colorPickers-show.file @@ -0,0 +1 @@ +colorPickers-show.png,w22,actions diff --git a/tools/source_icons/scalable/colorPickers-show.svg b/tools/source_icons/scalable/colorPickers-show.svg new file mode 100644 index 000000000..d03472020 --- /dev/null +++ b/tools/source_icons/scalable/colorPickers-show.svg @@ -0,0 +1,4372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/gtk-color-picker-add.file b/tools/source_icons/scalable/gtk-color-picker-add.file new file mode 100644 index 000000000..f51e051bd --- /dev/null +++ b/tools/source_icons/scalable/gtk-color-picker-add.file @@ -0,0 +1 @@ +gtk-color-picker-add.png,w22,actions diff --git a/tools/source_icons/scalable/gtk-color-picker-add.svg b/tools/source_icons/scalable/gtk-color-picker-add.svg new file mode 100644 index 000000000..a12197ffe --- /dev/null +++ b/tools/source_icons/scalable/gtk-color-picker-add.svg @@ -0,0 +1,4839 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/win/InnoSetup/WindowsInnoSetup.iss.in b/tools/win/InnoSetup/WindowsInnoSetup.iss.in index 5c4a2a239..1ba02590d 100644 --- a/tools/win/InnoSetup/WindowsInnoSetup.iss.in +++ b/tools/win/InnoSetup/WindowsInnoSetup.iss.in @@ -54,7 +54,7 @@ AllowNoIcons=yes LicenseFile={#MyBuildBasePath}\LICENSE.txt OutputDir={#MyBuildBasePath}\..\ OutputBaseFilename={#MyAppName}_{#MySystemName}_{#MyBitDepth}_{#MyAppFullVersion} -SetupIconFile={#MySourceBasePath}\rtgui\RT.ico +SetupIconFile={#MySourceBasePath}\rtdata\icons\RT.ico WizardImageFile={#MySourceBasePath}\tools\win\InnoSetup\installerStrip.bmp WizardImageBackColor=$2A2A2A Compression=lzma