Merge branch 'master' into softproofing

This commit is contained in:
Hombre 2016-10-16 01:45:52 +02:00
commit 50165dab20
159 changed files with 15819 additions and 2723 deletions

41
.travis.yml Normal file
View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

View File

@ -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 <b>Shift</b> 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: <b>c</b>\nDéplacez le recadrage en utilisant Shift + Glisser
TOOLBAR_TOOLTIP_HAND;Outil de navigation\nRaccourci: <b>h</b>
TOOLBAR_TOOLTIP_STRAIGHTEN;Sélection de la ligne d'horizon\nRaccourci: <b>s</b>\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.

View File

@ -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 <b>Shift</b> 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;<b>Crop</b> selection.\nShortcut: <b>c</b>\nMove the crop area using <b>Shift-mouse drag</b>
TOOLBAR_TOOLTIP_HAND;Hand tool.\nShortcut: <b>h</b>
TOOLBAR_TOOLTIP_STRAIGHTEN;<b>Straighten</b> / <b>fine rotation</b>.\nShortcut: <b>s</b>\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.

View File

@ -1,264 +0,0 @@
#include "EdgePreserveLab.h"
#include "boxblur.h"
#include <cstdlib>
#ifdef _OPENMP
#include <omp.h>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <cmath>
#include <stdio.h>
#include <string.h>
#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;
};

View File

@ -67,13 +67,16 @@ ben_s or nonbasketless. Enjoy!
#include <cstdio>
#include <cstdlib>
#include <cstring>
#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);

View File

@ -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<float> *Lin;
array2D<float> *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;

View File

@ -61,13 +61,16 @@
#include <cstring>
#include <cstdint>
#include <cassert>
#ifndef NDEBUG
#include <glibmm.h>
#include <fstream>
#endif
#include "opthelper.h"
#include <assert.h>
#include "rt_math.h"
#include "noncopyable.h"
// Bit representations of flags
enum {
@ -85,7 +88,8 @@ using LUTd = LUT<double>;
using LUTuc = LUT<uint8_t>;
template<typename T>
class LUT
class LUT :
public rtengine::NonCopyable
{
protected:
// list of variables ordered to improve cache speed

View File

@ -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;

View File

@ -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;
}

View File

@ -66,8 +66,11 @@
#include <cstring>
#include <cstdio>
#include "noncopyable.h"
template<typename T>
class array2D
class array2D :
public rtengine::NonCopyable
{
private:

View File

@ -1,7 +1,7 @@
/*
* This file is part of RawTherapee.
*
* Copyright (C) 2016 Floessie <floessie.mail@gmail.com>
* Copyright (C) 2016 Flössie <floessie.mail@gmail.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -20,11 +20,13 @@
#define _CIEIMAGE_H_
#include "image16.h"
#include "noncopyable.h"
namespace rtengine
{
class CieImage
class CieImage :
public NonCopyable
{
private:
bool fromImage;

View File

@ -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<HaldCLUT> getClut(const Glib::ustring& filename);
void clearCache();

View File

@ -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)
{

View File

@ -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]

View File

@ -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
*/

View File

@ -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);

View File

@ -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;

View File

@ -22,15 +22,17 @@
#define CPLX_WAVELET_DEC_H_INCLUDED
#include <cstddef>
#include <math.h>
#include <cmath>
#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:

View File

@ -26,11 +26,12 @@
#include <glibmm.h>
#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<double, 3>;
using Matrix = std::array<Triple, 3>;
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;

View File

@ -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;

View File

@ -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 <http://www.gnu.org/licenses/>.
*
* (C) 2010 Emil Martinec <ejmartin@uchicago.edu>
*
*/
#include <cstddef>
#include <cmath>
#include "curves.h"
#include "labimage.h"
#include "improcfun.h"
#include "rawimagesource.h"
#include "rt_math.h"
#ifdef _OPENMP
#include <omp.h>
#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<int> (w + 128, h + 128);
buffer[1] = allocArray<int> (w + 128, h + 128);
buffer[2] = allocArray<int> (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<int>(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
}

View File

@ -1,150 +0,0 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "rtengine.h"
#include <iostream>
//#include <giomm.h>
#include <helpers.h>
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 <infile> <paramfile> <outfile>" << 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);
}

View File

@ -1,441 +0,0 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <climits>
#include <cstdio>
#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]<max[c2]*3/4)
{
continue;
}
ratio[1] += (double)rec[co][i + x][j + y] / rec[c2][i + x][j + y];
count[1] ++;
}
}
// compute new pixel values from the surrounding color ratios
if ((phase == 1 && count[0] > 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<int> (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<char>(needhr);
}
needhr = allocJaggedArray<char> (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<float> (hrmap[0]);
freeJaggedArray<float> (hrmap[1]);
freeJaggedArray<float> (hrmap[2]);
}
hrmap[0] = allocJaggedArray<float> (dw, dh);
hrmap[1] = allocJaggedArray<float> (dw, dh);
hrmap[2] = allocJaggedArray<float> (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<int> (rec[0]);
freeJaggedArray<int> (rec[1]);
freeJaggedArray<int> (rec[2]);
}
}

View File

@ -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;
};

View File

@ -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;

View File

@ -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);

View File

@ -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<float>(params->wavelet.level3noise.value[0]);
cp.lev3n = static_cast<float>(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;
}
}
}

View File

@ -17,8 +17,9 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#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 T>
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<class T>
void freeJaggedArray (JaggedArray<T>&);
} // rtengine
#endif // JAGGEDARRAY_H

View File

@ -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 */

View File

@ -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];

View File

@ -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

View File

@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* 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<T, N> array)
std::nth_element(array.begin(), middle, array.end());
return
N % 2
(N % 2)
? *middle
: ((*middle + *std::max_element(array.begin(), middle)) / static_cast<T>(2));
}

34
rtengine/noncopyable.h Normal file
View File

@ -0,0 +1,34 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2016 Flössie <floessie.mail@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace rtengine
{
class NonCopyable
{
public:
NonCopyable() = default;
explicit NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator =(const NonCopyable&) = delete;
};
}

View File

@ -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 */

View File

@ -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;

View File

@ -19,11 +19,13 @@
#ifndef _PROCPARAMS_H_
#define _PROCPARAMS_H_
#include <glibmm.h>
#include <vector>
#include <cstdio>
#include <cmath>
#include <glibmm.h>
#include <lcms2.h>
#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;

View File

@ -20,8 +20,10 @@
#define __RAWIMAGE_H
#include <ctime>
#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);

View File

@ -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);
}

View File

@ -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<float> &rbconv_Y, array2D<float> &rbconv_I, array2D<float> &rbconv_Q, array2D<float> &rbout_I, array2D<float> &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);
}

View File

@ -21,11 +21,13 @@
#include "imagefloat.h"
#include "image16.h"
#include "noncopyable.h"
namespace rtengine
{
class SHMap
class SHMap :
public NonCopyable
{
public:

View File

@ -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, &params, 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, &params, 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, &params, 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, &params, 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, &params, 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, &params, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, 1, true, dd, 1, 1);
}
}

View File

@ -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;
}

View File

@ -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();
}
};

View File

@ -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];

View File

@ -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);

View File

@ -28,7 +28,9 @@
#include <cstdlib>
#include <cmath>
#include <glibmm.h>
#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;
}

View File

@ -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();

View File

@ -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

View File

@ -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());

View File

@ -68,7 +68,7 @@ protected:
void notifyListener (bool queueEmptied);
public:
BatchQueue (FileCatalog* aFileCatalog);
explicit BatchQueue (FileCatalog* aFileCatalog);
~BatchQueue ();
void addEntries (const std::vector<BatchQueueEntry*>& entries, bool head = false, bool save = true);

View File

@ -33,7 +33,7 @@ public:
static Cairo::RefPtr<Cairo::ImageSurface> headIcon;
static Cairo::RefPtr<Cairo::ImageSurface> tailIcon;
BatchQueueButtonSet (BatchQueueEntry* myEntry);
explicit BatchQueueButtonSet (BatchQueueEntry* myEntry);
};
#endif

View File

@ -24,10 +24,6 @@
#include "soundman.h"
#include "rtimage.h"
struct BQProcessLoaded {
BatchQueue* bq;
};
int processLoadedBatchQueueUIThread (void* data)
{

View File

@ -55,7 +55,7 @@ class BatchQueuePanel : public Gtk::VBox,
public:
BatchQueuePanel (FileCatalog* aFileCatalog);
explicit BatchQueuePanel (FileCatalog* aFileCatalog);
void setParent (RTWindow* p)
{

View File

@ -42,6 +42,10 @@ BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolP
toolPanels.erase (ipi);
}
if (toolBar) {
toolBar->setBatchMode ();
}
toolPanelNotebook->remove_page (*metadataPanel);
metadataPanel = 0;
toiM = 0;

View File

@ -48,7 +48,7 @@ protected:
public:
BatchToolPanelCoordinator (FilePanel* parent);
explicit BatchToolPanelCoordinator (FilePanel* parent);
// FileSelectionChangeListener interface
void selectionChanged (const std::vector<Thumbnail*>& selected);

View File

@ -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;

View File

@ -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)
{
}

View File

@ -24,11 +24,14 @@
#include <glibmm/ustring.h>
#include "../rtengine/noncopyable.h"
#include "threadutils.h"
class Thumbnail;
class CacheManager
class CacheManager :
public rtengine::NonCopyable
{
private:
using Entries = std::map<std::string, Thumbnail*>;
@ -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()

View File

@ -20,7 +20,7 @@
Clipboard clipboard;
Clipboard::Clipboard () : partProfile (false) {}
Clipboard::Clipboard () : partProfile (false), _hasIPTC(false), hasDiagonalCurveDataType(DCT_Empty), hasFlatCurveDataType(FCT_Empty) {}
Clipboard::~Clipboard ()
{

View File

@ -37,7 +37,7 @@ protected:
std::vector<GradientMilestone> bgGradient;
public:
ColoredBar (eRTOrientation orient);
explicit ColoredBar (eRTOrientation orient);
void expose(Glib::RefPtr<Gdk::Window> destWindow);
void expose(Cairo::RefPtr<Cairo::ImageSurface> destSurface);

View File

@ -124,9 +124,8 @@ void CoordinateAdjuster::createWidgets(const std::vector<Axis> &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);

View File

@ -1,223 +0,0 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <png.h>
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);
}

View File

@ -22,6 +22,7 @@
#include <cstring>
#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)
{

View File

@ -22,6 +22,7 @@
#include "../rtengine/rtengine.h"
#include "threadutils.h"
#include "edit.h"
#include "lockablecolorpicker.h"
#include <gtkmm.h>
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;

View File

@ -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<Pango::Context> 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<LockableColorPicker*>::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<rtengine::Crop*>(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<Cairo::Context> cr)
{
MyMutex::MyLock lock(cropHandler.cimg);
bool isPreviewImg = false;
if (decorated) {
drawDecoration (cr);
}
@ -1640,6 +1793,8 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr)
}
}
isPreviewImg = true;
} else {
// cropHandler.cropPixbuf is null
int cropX, cropY;
@ -1674,6 +1829,12 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> 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<Cairo::Context> 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 ();
}
}

View File

@ -59,6 +59,10 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed
bool fitZoom;
bool isLowUpdatePriority;
// color pickers
std::vector<LockableColorPicker*> 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<CropWindowListener*> 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<Cairo::Context> cr, int rectSize);
void drawObservedFrame (Cairo::RefPtr<Cairo::Context> 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

View File

@ -44,6 +44,7 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin)
Glib::RefPtr<Gdk::Pixbuf> hand = RTImage::createFromFile ("cross.png");
Glib::RefPtr<Gdk::Pixbuf> close_hand = RTImage::createFromFile ("closedhand.png");
Glib::RefPtr<Gdk::Pixbuf> wbpick = RTImage::createFromFile ("gtk-color-picker-small.png");
Glib::RefPtr<Gdk::Pixbuf> cpick = RTImage::createFromFile ("gtk-color-picker-add.png");
Glib::RefPtr<Gdk::Pixbuf> empty = RTImage::createFromFile ("empty.png");
Glib::RefPtr<Gdk::Pixbuf> move2D = RTImage::createFromFile ("move-2D.png");
Glib::RefPtr<Gdk::Pixbuf> move1DH = RTImage::createFromFile ("move-1D-h.png");
@ -52,7 +53,8 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> 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<Gdk::Window> 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) {

View File

@ -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;

View File

@ -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;

View File

@ -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 ();

View File

@ -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<DiagonalCurveEditor*>(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;

View File

@ -59,7 +59,7 @@ std::vector<Glib::ustring> listSubDirs (const Glib::RefPtr<Gio::File>& 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;
}
}

View File

@ -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);

View File

@ -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
};

View File

@ -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);

View File

@ -138,7 +138,7 @@ protected:
public:
EditorPanel (FilePanel* filePanel = NULL);
explicit EditorPanel (FilePanel* filePanel = NULL);
virtual ~EditorPanel ();
void open (Thumbnail* tmb, rtengine::InitialImage* isrc);

View File

@ -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();

View File

@ -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);

View File

@ -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)
{

View File

@ -44,13 +44,14 @@ class ExtProgStore
MyMutex mtx; // covers actions
std::vector<ExtProgAction> 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();

View File

@ -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<FileBrowserEntry*>(selected[i]))->thumbnail->getStage() == 1) {
if ((static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->getStage()) {
untrash->set_sensitive (true);
break;
}
for (size_t i = 0; i < selected.size(); i++)
if ((static_cast<FileBrowserEntry*>(selected[i]))->thumbnail->getStage() == 0) {
if (!(static_cast<FileBrowserEntry*>(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<FileBrowserEntry*> 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<FileBrowserEntry*> 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<FileBrowserEntry*>(actionData);
tbe.push_back (entry);
if (entry->thumbnail->getStage() == 0) {
if (!entry->thumbnail->getStage()) {
toTrashRequested (tbe);
} else {
fromTrashRequested (tbe);

View File

@ -989,9 +989,6 @@ void FileCatalog::copyMoveRequested (std::vector<FileBrowserEntry*> 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<FileBrowserEntry*> 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<FileBrowserEntry*> 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<FileBrowserEntry*> 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) {

View File

@ -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)
{

View File

@ -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);

View File

@ -44,7 +44,7 @@ public:
static Cairo::RefPtr<Cairo::ImageSurface> colorLabelIcon_4;
static Cairo::RefPtr<Cairo::ImageSurface> colorLabelIcon_5;
FileThumbnailButtonSet (FileBrowserEntry* myEntry);
explicit FileThumbnailButtonSet (FileBrowserEntry* myEntry);
void setRank (int stars);
void setColorLabel (int colorlabel);
void setInTrash (bool inTrash);

View File

@ -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<Gdk::Window> 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<Gdk::Window> 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<Gdk::Window> window, GdkRectangle *rectangle)
void BackBuffer::copySurface(Glib::RefPtr<Gdk::Window> &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<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle)
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> &destSurface, GdkRectangle *rectangle)
{
if (surface && destSurface) {
// compute the source offset
@ -1212,3 +1244,23 @@ void BackBuffer::copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, Gdk
}
}
void BackBuffer::copySurface(Cairo::RefPtr<Cairo::Context> &context, GdkRectangle *rectangle)
{
if (surface && context) {
// compute the source offset
int offsetX = rtengine::LIM<int>(offset.x, 0, surface->get_width());
int offsetY = rtengine::LIM<int>(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();
}
}

View File

@ -21,6 +21,7 @@
#include <gtkmm.h>
#include "../rtengine/rtengine.h"
#include "../rtengine/coord.h"
#include <sstream>
#include <iostream>
@ -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 T>
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<int> 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<Cairo::ImageSurface> 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<Gdk::Window> 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<Gdk::Window> 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<Gdk::Window> window, GdkRectangle *rectangle = NULL);
void copySurface(Glib::RefPtr<Gdk::Window> &window, GdkRectangle *rectangle = NULL);
void copySurface(BackBuffer *destBackBuffer, GdkRectangle *rectangle = NULL);
void copySurface(Cairo::RefPtr<Cairo::ImageSurface> destSurface, GdkRectangle *rectangle = NULL);
void copySurface(Cairo::RefPtr<Cairo::ImageSurface> &destSurface, GdkRectangle *rectangle = NULL);
void copySurface(Cairo::RefPtr<Cairo::Context> &context, GdkRectangle *rectangle = NULL);
void setDirty(bool isDirty)
{

View File

@ -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;

View File

@ -144,7 +144,7 @@ protected:
public:
HistogramArea(FullModeListener *fml = NULL);
explicit HistogramArea(FullModeListener *fml = NULL);
~HistogramArea();
void renderHistogram ();

View File

@ -95,7 +95,7 @@ protected:
public:
History (bool bookmarkSupport = true);
explicit History (bool bookmarkSupport = true);
void setProfileChangeListener (ProfileChangeListener* tpc_)
{

View File

@ -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()
{

Some files were not shown because too many files have changed in this diff Show More