synced with master (merged master into retinex)

This commit is contained in:
Beep6581 2015-10-17 12:27:26 +02:00
commit 349c6d33a6
20 changed files with 874 additions and 649 deletions

View File

@ -37,7 +37,6 @@ namespace rtengine
SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh) SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw, int winh)
{ {
#define HCLIP(x) x //is this still necessary??? #define HCLIP(x) x //is this still necessary???
//min(clip_pt,x) //min(clip_pt,x)
@ -1615,10 +1614,10 @@ SSEFUNCTION void RawImageSource::amaze_demosaic_RT(int winx, int winy, int winw,
if(plistener) { if(plistener) {
progresscounter++; progresscounter++;
if(progresscounter % 4 == 0) { if(progresscounter % 16 == 0) {
#pragma omp critical #pragma omp critical
{ {
progress += (double)4 * ((TS - 32) * (TS - 32)) / (height * width); progress += (double)16 * ((TS - 32) * (TS - 32)) / (height * width);
if (progress > 1.0) if (progress > 1.0)
{ {

View File

@ -23,7 +23,7 @@
* Usage: * Usage:
* *
* array2D<type> name (X-size,Y-size); * array2D<type> name (X-size,Y-size);
* array2D<type> name (X-size,Y-size type ** data); * array2D<type> name (X-size,Y-size,type ** data);
* *
* creates an array which is valid within the normal C/C++ scope "{ ... }" * creates an array which is valid within the normal C/C++ scope "{ ... }"
* *
@ -75,7 +75,7 @@ private:
T ** ptr; T ** ptr;
T * data; T * data;
bool lock; // useful lock to ensure data is not changed anymore. bool lock; // useful lock to ensure data is not changed anymore.
void ar_realloc(int w, int h) void ar_realloc(int w, int h, int offset = 0)
{ {
if ((ptr) && ((h > y) || (4 * h < y))) { if ((ptr) && ((h > y) || (4 * h < y))) {
delete[] ptr; delete[] ptr;
@ -92,14 +92,14 @@ private:
} }
if (data == NULL) { if (data == NULL) {
data = new T[h * w]; data = new T[h * w + offset];
} }
x = w; x = w;
y = h; y = h;
for (int i = 0; i < h; i++) { for (int i = 0; i < h; i++) {
ptr[i] = data + w * i; ptr[i] = data + offset + w * i;
} }
owner = 1; owner = 1;
@ -184,6 +184,19 @@ public:
} }
} }
void free()
{
if ((owner) && (data)) {
delete[] data;
data = NULL;
}
if (ptr) {
delete [] ptr;
ptr = NULL;
}
}
// use with indices // use with indices
T * operator[](int index) T * operator[](int index)
{ {
@ -207,7 +220,7 @@ public:
// useful within init of parent object // useful within init of parent object
// or use as resize of 2D array // or use as resize of 2D array
void operator()(int w, int h, unsigned int flgs = 0) void operator()(int w, int h, unsigned int flgs = 0, int offset = 0)
{ {
flags = flgs; flags = flgs;
@ -223,10 +236,10 @@ public:
lock = flags & ARRAY2D_LOCK_DATA; lock = flags & ARRAY2D_LOCK_DATA;
ar_realloc(w, h); ar_realloc(w, h, offset);
if (flags & ARRAY2D_CLEAR_DATA) { if (flags & ARRAY2D_CLEAR_DATA) {
memset(data, 0, w * h * sizeof(T)); memset(data + offset, 0, w * h * sizeof(T));
} }
} }
@ -298,10 +311,10 @@ private:
array2D<T> list[num]; array2D<T> list[num];
public: public:
multi_array2D(int x, int y, int flags = 0) multi_array2D(int x, int y, int flags = 0, int offset = 0)
{ {
for (size_t i = 0; i < num; i++) { for (size_t i = 0; i < num; i++) {
list[i](x, y, flags); list[i](x, y, flags, (i + 1) * offset);
} }
} }
@ -312,11 +325,7 @@ public:
array2D<T> & operator[](int index) array2D<T> & operator[](int index)
{ {
if (static_cast<size_t>(index) >= num) { assert(static_cast<size_t>(index) < num);
printf("index %0u is out of range[0..%0lu]", index, num - 1);
raise( SIGSEGV);
}
return list[index]; return list[index];
} }
}; };

View File

@ -814,7 +814,7 @@ const DCPProfile::HSBModify* DCPProfile::MakeHueSatMap(ColorTemp &wb, int prefer
return aDeltas; return aDeltas;
} }
DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile) DCPProfile::DCPProfile(Glib::ustring fname)
{ {
const int TIFFFloatSize = 4; const int TIFFFloatSize = 4;
const int TagColorMatrix1 = 50721, TagColorMatrix2 = 50722, TagProfileHueSatMapDims = 50937; const int TagColorMatrix1 = 50721, TagColorMatrix2 = 50722, TagProfileHueSatMapDims = 50937;
@ -989,7 +989,7 @@ DCPProfile::DCPProfile(Glib::ustring fname, bool isRTProfile)
// Read tone curve points, if any, but disable to RTs own profiles // Read tone curve points, if any, but disable to RTs own profiles
tag = tagDir->getTag(TagProfileToneCurve); tag = tagDir->getTag(TagProfileToneCurve);
if (tag != NULL && !isRTProfile) { if (tag != NULL) {
std::vector<double> cPoints; std::vector<double> cPoints;
cPoints.push_back(double(DCT_Spline)); // The first value is the curve type cPoints.push_back(double(DCT_Spline)); // The first value is the curve type
@ -1760,7 +1760,7 @@ void DCPStore::init (Glib::ustring rtProfileDir)
} }
} }
DCPProfile* DCPStore::getProfile (Glib::ustring filename, bool isRTProfile) DCPProfile* DCPStore::getProfile (Glib::ustring filename)
{ {
MyMutex::MyLock lock(mtx); MyMutex::MyLock lock(mtx);
@ -1771,7 +1771,7 @@ DCPProfile* DCPStore::getProfile (Glib::ustring filename, bool isRTProfile)
} }
// Add profile // Add profile
profileCache[filename] = new DCPProfile(filename, isRTProfile); profileCache[filename] = new DCPProfile(filename);
return profileCache[filename]; return profileCache[filename];
} }
@ -1783,7 +1783,7 @@ DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName)
// Warning: do NOT use map.find(), since it does not seem to work reliably here // Warning: do NOT use map.find(), since it does not seem to work reliably here
for (std::map<Glib::ustring, Glib::ustring>::iterator i = fileStdProfiles.begin(); i != fileStdProfiles.end(); i++) for (std::map<Glib::ustring, Glib::ustring>::iterator i = fileStdProfiles.begin(); i != fileStdProfiles.end(); i++)
if (name2 == (*i).first) { if (name2 == (*i).first) {
return getProfile((*i).second, true); return getProfile((*i).second);
} }
return NULL; return NULL;

View File

@ -76,7 +76,7 @@ class DCPProfile
void HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const; void HSDApply(const HSDTableInfo &ti, const HSBModify *tableBase, float &h, float &s, float &v) const;
public: public:
DCPProfile(Glib::ustring fname, bool isRTProfile); DCPProfile(Glib::ustring fname);
~DCPProfile(); ~DCPProfile();
bool getHasToneCurve() bool getHasToneCurve()
@ -122,7 +122,7 @@ public:
bool isValidDCPFileName(Glib::ustring filename) const; bool isValidDCPFileName(Glib::ustring filename) const;
DCPProfile* getProfile(Glib::ustring filename, bool isRTProfile = false); DCPProfile* getProfile(Glib::ustring filename);
DCPProfile* getStdProfile(Glib::ustring camShortName); DCPProfile* getStdProfile(Glib::ustring camShortName);
static DCPStore* getInstance(); static DCPStore* getInstance();

View File

@ -136,10 +136,10 @@ const float d65_white[3] = { 0.950456, 1, 1.088754 };
#define SQR(x) rtengine::SQR(x) #define SQR(x) rtengine::SQR(x)
#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) #define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
#define MIN(a,b) rtengine::min(a,static_cast<typeof(a)>(b)) #define MIN(a,b) rtengine::min(a,static_cast<__typeof__(a)>(b))
#define MAX(a,b) rtengine::max(a,static_cast<typeof(a)>(b)) #define MAX(a,b) rtengine::max(a,static_cast<__typeof__(a)>(b))
#define LIM(x,min,max) rtengine::LIM(x,static_cast<typeof(x)>(min),static_cast<typeof(x)>(max)) #define LIM(x,min,max) rtengine::LIM(x,static_cast<__typeof__(x)>(min),static_cast<__typeof__(x)>(max))
#define ULIM(x,y,z) rtengine::ULIM(x,static_cast<typeof(x)>(y),static_cast<typeof(x)>(z)) #define ULIM(x,y,z) rtengine::ULIM(x,static_cast<__typeof__(x)>(y),static_cast<__typeof__(x)>(z))
#define CLIP(x) rtengine::CLIP(x) #define CLIP(x) rtengine::CLIP(x)
#define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; }

View File

@ -1,5 +1,5 @@
--- dcraw.c 2015-08-15 15:35:27 +0000 --- dcraw.c 2015-09-21 10:08:04 +0000
+++ dcraw.cc 2015-08-16 13:46:33 +0000 +++ dcraw.cc 2015-10-14 14:29:55 +0000
@@ -1,3 +1,15 @@ @@ -1,3 +1,15 @@
+/*RT*/#include <glib.h> +/*RT*/#include <glib.h>
+/*RT*/#include <glib/gstdio.h> +/*RT*/#include <glib/gstdio.h>
@ -148,10 +148,10 @@
-#define LIM(x,min,max) MAX(min,MIN(x,max)) -#define LIM(x,min,max) MAX(min,MIN(x,max))
-#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) -#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
-#define CLIP(x) LIM(x,0,65535) -#define CLIP(x) LIM(x,0,65535)
+#define MIN(a,b) rtengine::min(a,static_cast<typeof(a)>(b)) +#define MIN(a,b) rtengine::min(a,static_cast<__typeof__(a)>(b))
+#define MAX(a,b) rtengine::max(a,static_cast<typeof(a)>(b)) +#define MAX(a,b) rtengine::max(a,static_cast<__typeof__(a)>(b))
+#define LIM(x,min,max) rtengine::LIM(x,static_cast<typeof(x)>(min),static_cast<typeof(x)>(max)) +#define LIM(x,min,max) rtengine::LIM(x,static_cast<__typeof__(x)>(min),static_cast<__typeof__(x)>(max))
+#define ULIM(x,y,z) rtengine::ULIM(x,static_cast<typeof(x)>(y),static_cast<typeof(x)>(z)) +#define ULIM(x,y,z) rtengine::ULIM(x,static_cast<__typeof__(x)>(y),static_cast<__typeof__(x)>(z))
+#define CLIP(x) rtengine::CLIP(x) +#define CLIP(x) rtengine::CLIP(x)
#define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } #define SWAP(a,b) { a=a+b; b=a-b; a=a-b; }

View File

@ -72,7 +72,11 @@ DiagonalCurve::DiagonalCurve (const std::vector<double>& p, int poly_pn)
if(x[0] == 0.f && x[1] == 0.f) if(x[0] == 0.f && x[1] == 0.f)
// Avoid crash when first two points are at x = 0 (git Issue 2888) // Avoid crash when first two points are at x = 0 (git Issue 2888)
x[1] = 0.5f; x[1] = 0.01f;
if(x[0] == 1.f && x[1] == 1.f)
// Avoid crash when first two points are at x = 1 (100 in gui) (git Issue 2923)
x[0] = 0.99f;
if (!identity) { if (!identity) {
if (kind == DCT_Spline && N > 2) { if (kind == DCT_Spline && N > 2) {

File diff suppressed because it is too large Load Diff

View File

@ -226,13 +226,11 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
} }
imgsrc->demosaic( rp);//enabled demosaic imgsrc->demosaic( rp);//enabled demosaic
// if a demosaic happened we should also call getimage later, so we need to set the M_INIT flag
todo |= M_INIT;
if (highDetailNeeded) { if (highDetailNeeded) {
highDetailRawComputed = true; highDetailRawComputed = true;
if (params.toneCurve.hrenabled && params.toneCurve.method == "Color") {
todo |= M_INIT;
}
} else { } else {
highDetailRawComputed = false; highDetailRawComputed = false;
} }

View File

@ -887,8 +887,8 @@ void ColorManagementParams::setDefaults()
{ {
input = "(cameraICC)"; input = "(cameraICC)";
blendCMSMatrix = false; blendCMSMatrix = false;
toneCurve = true; toneCurve = false;
applyLookTable = true; applyLookTable = false;
applyBaselineExposureOffset = true; applyBaselineExposureOffset = true;
applyHueSatMap = true; applyHueSatMap = true;
dcpIlluminant = 0; dcpIlluminant = 0;

View File

@ -31,7 +31,6 @@
#include "curves.h" #include "curves.h"
#include "dfmanager.h" #include "dfmanager.h"
#include "ffmanager.h" #include "ffmanager.h"
#include "slicer.h"
#include "../rtgui/options.h" #include "../rtgui/options.h"
#include "dcp.h" #include "dcp.h"
#include "rt_math.h" #include "rt_math.h"
@ -554,7 +553,9 @@ int RawImageSource::interpolateBadPixelsBayer( PixelsMap &bitmapBads )
{ {
static const float eps = 1.f; static const float eps = 1.f;
int counter = 0; int counter = 0;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) #pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
#endif
for( int row = 2; row < H - 2; row++ ) { for( int row = 2; row < H - 2; row++ ) {
for(int col = 2; col < W - 2; col++ ) { for(int col = 2; col < W - 2; col++ ) {
@ -669,7 +670,9 @@ int RawImageSource::interpolateBadPixelsNColours( PixelsMap &bitmapBads, const i
{ {
static const float eps = 1.f; static const float eps = 1.f;
int counter = 0; int counter = 0;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) #pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
#endif
for( int row = 2; row < H - 2; row++ ) { for( int row = 2; row < H - 2; row++ ) {
for(int col = 2; col < W - 2; col++ ) { for(int col = 2; col < W - 2; col++ ) {
@ -721,7 +724,7 @@ int RawImageSource::interpolateBadPixelsNColours( PixelsMap &bitmapBads, const i
} }
} }
if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% if (LIKELY(norm[0] > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
for(int c = 0; c < colours; c++) { for(int c = 0; c < colours; c++) {
rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps rawData[row][col * colours + c] = wtdsum[c] / (2.f * norm[c]); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
} }
@ -763,13 +766,15 @@ int RawImageSource::interpolateBadPixelsNColours( PixelsMap &bitmapBads, const i
return counter; // Number of interpolated pixels. return counter; // Number of interpolated pixels.
} }
/* interpolateBadPixelsXtrans: correct raw pixels looking at the bitmap /* interpolateBadPixelsXtrans: correct raw pixels looking at the bitmap
* takes into consideration if there are multiple bad pixels in the neighborhood * takes into consideration if there are multiple bad pixels in the neighbourhood
*/ */
int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads ) int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
{ {
static const float eps = 1.f; static const float eps = 1.f;
int counter = 0; int counter = 0;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16) #pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
#endif
for( int row = 2; row < H - 2; row++ ) { for( int row = 2; row < H - 2; row++ ) {
for(int col = 2; col < W - 2; col++ ) { for(int col = 2; col < W - 2; col++ ) {
@ -791,10 +796,10 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
if(pixelColor == 1) { if(pixelColor == 1) {
// green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels // green channel. A green pixel can either be a solitary green pixel or a member of a 2x2 square of green pixels
if(ri->XTRANSFC(row, col - 1) == ri->XTRANSFC(row, col + 1)) { if(ri->XTRANSFC(row, col - 1) == ri->XTRANSFC(row, col + 1)) {
// If left and right neighbour have same color, then this is a solitary green pixel // If left and right neighbour have same colour, then this is a solitary green pixel
// For these the following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. // For these the following pixels will be used for interpolation. Pixel to be interpolated is in centre and marked with a P.
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
// 0 means, the pixel has a different color and will not be used // 0 means, the pixel has a different colour and will not be used
// 0 1 0 2 0 // 0 1 0 2 0
// 3 5 0 6 4 // 3 5 0 6 4
// 0 0 P 0 0 // 0 0 P 0 0
@ -833,12 +838,14 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
// this is a member of a 2x2 square of green pixels // this is a member of a 2x2 square of green pixels
// For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example. // For these the following pixels will be used for interpolation. Pixel to be interpolated is at position P in the example.
// Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad // Pairs of pixels used in this step are numbered. A pair will be used if none of the pixels of the pair is marked bad
// 0 means, the pixel has a different color and will not be used // 0 means, the pixel has a different colour and will not be used
// 1 0 0 3 // 1 0 0 3
// 0 P 2 0 // 0 P 2 0
// 0 2 1 0 // 0 2 1 0
// 3 0 0 0 // 3 0 0 0
int offset1 = ri->XTRANSFC(row - 1, col - 1) == ri->XTRANSFC(row + 1, col + 1) ? 1 : -1; // pixels marked 1 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f
// pixels marked 1 in above example. Distance to P is sqrt(2) => weighting is 0.70710678f
int offset1 = ri->XTRANSFC(row - 1, col - 1) == ri->XTRANSFC(row + 1, col + 1) ? 1 : -1;
if( !(bitmapBads.get(col - offset1, row - 1) || bitmapBads.get(col + offset1, row + 1))) { if( !(bitmapBads.get(col - offset1, row - 1) || bitmapBads.get(col + offset1, row + 1))) {
float dirwt = 0.70710678f / ( fabsf( rawData[row - 1][col - offset1] - rawData[row + 1][col + offset1]) + eps); float dirwt = 0.70710678f / ( fabsf( rawData[row - 1][col - offset1] - rawData[row + 1][col + offset1]) + eps);
@ -846,6 +853,7 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
norm += dirwt; norm += dirwt;
} }
// pixels marked 2 in above example. Distance to P is 1 => weighting is 1.f
int offsety = (ri->XTRANSFC(row - 1, col) != 1 ? 1 : -1); int offsety = (ri->XTRANSFC(row - 1, col) != 1 ? 1 : -1);
int offsetx = offset1 * offsety; int offsetx = offset1 * offsety;
@ -869,9 +877,9 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
} }
} else { } else {
// red and blue channel. // red and blue channel.
// Each red or blue pixel has exactly one neigbour of same color in distance 2 and four neighbours of same color which can be reached by a move of a knight in chess. // Each red or blue pixel has exactly one neighbour of same colour in distance 2 and four neighbours of same colour which can be reached by a move of a knight in chess.
// For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V) // For the distance 2 pixel (marked with an X) we generate a virtual counterpart (marked with a V)
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center and marked with a P. // For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in centre and marked with a P.
// Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad // Pairs of pixels used in this step are numbered except for distance 2 pixels which are marked X and V. A pair will be used if none of the pixels of the pair is marked bad
// 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric // 0 1 0 0 0 0 0 X 0 0 remaining cases are symmetric
// 0 0 0 0 2 1 0 0 0 2 // 0 0 0 0 2 1 0 0 0 2
@ -879,12 +887,12 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
// 0 0 0 0 1 0 0 0 0 0 // 0 0 0 0 1 0 0 0 0 0
// 0 2 0 0 0 0 2 V 1 0 // 0 2 0 0 0 0 2 V 1 0
// Find two knight moves landing on a pixel of same color as the pixel to be interpolated. // Find two knight moves landing on a pixel of same colour as the pixel to be interpolated.
// If we look at first and last row of 5x5 square, we will find exactly two knight pixels. // If we look at first and last row of 5x5 square, we will find exactly two knight pixels.
// Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the center pixel // Additionally we know that the column of this pixel has 1 or -1 horizontal distance to the centre pixel
// When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel. // When we find a knight pixel, we get its counterpart, which has distance (+-3,+-3), where the signs of distance depend on the corner of the found knight pixel.
// These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f // These pixels are marked 1 or 2 in above examples. Distance to P is sqrt(5) => weighting is 0.44721359f
// The following loop simply scans the four possible places. To keep things simple, it doesn't stop after finding two knight pixels, because it will not find more than two // The following loop simply scans the four possible places. To keep things simple, it does not stop after finding two knight pixels, because it will not find more than two
for(int d1 = -2, offsety = 3; d1 <= 2; d1 += 4, offsety -= 6) { for(int d1 = -2, offsety = 3; d1 <= 2; d1 += 4, offsety -= 6) {
for(int d2 = -1, offsetx = 3; d2 < 1; d2 += 2, offsetx -= 6) { for(int d2 = -1, offsetx = 3; d2 < 1; d2 += 2, offsetx -= 6) {
if(ri->XTRANSFC(row + d1, col + d2) == pixelColor) { if(ri->XTRANSFC(row + d1, col + d2) == pixelColor) {
@ -930,10 +938,8 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
norm += dirwt; norm += dirwt;
} }
if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelyhood of this case is about 99.999% if (LIKELY(norm > 0.f)) { // This means, we found at least one pair of valid pixels in the steps above, likelihood of this case is about 99.999%
rawData[row][col] = wtdsum / (2.f * norm); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps rawData[row][col] = wtdsum / (2.f * norm); //gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
//#pragma omp critical
// printf("%s Pixel at (col/row) : (%4d/%4d) : Original : %f, interpolated: %f\n",pixelColor == 0 ? "Red " : pixelColor==1 ? "Green" : "Blue ", col-7,row-7,oldval, rawData[row][col]);
counter++; counter++;
} }
} }
@ -944,95 +950,122 @@ int RawImageSource::interpolateBadPixelsXtrans( PixelsMap &bitmapBads )
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* Search for hot or dead pixels in the image and update the map /* Search for hot or dead pixels in the image and update the map
* For each pixel compare its value to the average of similar color surrounding * For each pixel compare its value to the average of similar colour surrounding
* (Taken from Emil Martinec idea) * (Taken from Emil Martinec idea)
* (Optimized by Ingo Weyrich 2013) * (Optimized by Ingo Weyrich 2013 and 2015)
*/ */
int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels ) SSEFUNCTION int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels )
{ {
float varthresh = (20.0 * (thresh / 100.0) + 1.0 ); float varthresh = (20.0 * (thresh / 100.0) + 1.0 ) / 24.f;
// counter for dead or hot pixels
int counter = 0;
// allocate temporary buffer // allocate temporary buffer
float (*cfablur); float (*cfablur);
cfablur = (float (*)) malloc (H * W * sizeof * cfablur); cfablur = (float (*)) malloc (H * W * sizeof * cfablur);
// counter for dead or hot pixels
int counter = 0;
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
#pragma omp for #ifdef _OPENMP
#pragma omp for schedule(dynamic,16) nowait
#endif
for (int i = 0; i < H; i++) { for (int i = 2; i < H - 2; i++) {
int iprev, inext, jprev, jnext; float p[9], temp; // we need this for med3x3 macro
float p[9], temp;
if (i < 2) { for (int j = 2; j < W - 2; j++) {
iprev = i + 2; med3x3(rawData[i - 2][j - 2], rawData[i - 2][j], rawData[i - 2][j + 2],
} else { rawData[i][j - 2], rawData[i][j], rawData[i][j + 2],
iprev = i - 2; rawData[i + 2][j - 2], rawData[i + 2][j], rawData[i + 2][j + 2], temp);
}
if (i > H - 3) {
inext = i - 2;
} else {
inext = i + 2;
}
for (int j = 0; j < W; j++) {
if (j < 2) {
jprev = j + 2;
} else {
jprev = j - 2;
}
if (j > W - 3) {
jnext = j - 2;
} else {
jnext = j + 2;
}
med3x3(rawData[iprev][jprev], rawData[iprev][j], rawData[iprev][jnext],
rawData[i][jprev], rawData[i][j], rawData[i][jnext],
rawData[inext][jprev], rawData[inext][j], rawData[inext][jnext], temp);
cfablur[i * W + j] = rawData[i][j] - temp; cfablur[i * W + j] = rawData[i][j] - temp;
} }
} }
// process borders. Former version calculated the median using mirrored border which does not make sense because the original pixel loses weight
// Setting the difference between pixel and median for border pixels to zero should do the job not worse then former version
#ifdef _OPENMP
#pragma omp single
#endif
{
for(int i = 0; i < 2; i++) {
for(int j = 0; j < W; j++) {
cfablur[i * W + j] = 0.f;
}
}
for(int i = 2; i < H - 2; i++) {
for(int j = 0; j < 2; j++) {
cfablur[i * W + j] = 0.f;
}
for(int j = W - 2; j < W; j++) {
cfablur[i * W + j] = 0.f;
}
}
for(int i = H - 2; i < H; i++) {
for(int j = 0; j < W; j++) {
cfablur[i * W + j] = 0.f;
}
}
}
#ifdef _OPENMP
#pragma omp barrier // barrier because of nowait clause above
#pragma omp for reduction(+:counter) schedule(dynamic,16) #pragma omp for reduction(+:counter) schedule(dynamic,16)
#endif
//cfa pixel heat/death evaluation //cfa pixel heat/death evaluation
for (int rr = 0; rr < H; rr++) { for (int rr = 2; rr < H - 2; rr++) {
int top = max(0, rr - 2); int rrmWpcc = rr * W + 2;
int bottom = min(H - 1, rr + 2);
int rrmWpcc = rr * W;
for (int cc = 0; cc < W; cc++, rrmWpcc++) { for (int cc = 2; cc < W - 2; cc++, rrmWpcc++) {
//evaluate pixel for heat/death //evaluate pixel for heat/death
float pixdev = cfablur[rrmWpcc]; float pixdev = cfablur[rrmWpcc];
if((!findDeadPixels) && pixdev <= 0) { if(pixdev == 0.f) {
continue; continue;
} }
if((!findHotPixels) && pixdev >= 0) { if((!findDeadPixels) && pixdev < 0) {
continue;
}
if((!findHotPixels) && pixdev > 0) {
continue; continue;
} }
pixdev = fabsf(pixdev); pixdev = fabsf(pixdev);
float hfnbrave = -pixdev; float hfnbrave = -pixdev;
int left = max(0, cc - 2);
int right = min(W - 1, cc + 2);
for (int mm = top; mm <= bottom; mm++) { #ifdef __SSE2__
int mmmWpnn = mm * W + left; // sum up 5*4 = 20 values using SSE
vfloat sum = vabsf(LVFU(cfablur[(rr - 2) * W + cc - 2])) + vabsf(LVFU(cfablur[(rr - 1) * W + cc - 2]));
sum += vabsf(LVFU(cfablur[(rr) * W + cc - 2]));
sum += vabsf(LVFU(cfablur[(rr + 1) * W + cc - 2]));
sum += vabsf(LVFU(cfablur[(rr + 2) * W + cc - 2]));
// horizontally add the values and add the result to hfnbrave
hfnbrave += vhadd(sum);
for (int nn = left; nn <= right; nn++, mmmWpnn++) { // add remaining 5 values of last column
hfnbrave += fabsf(cfablur[mmmWpnn]); for (int mm = rr - 2; mm <= rr + 2; mm++) {
hfnbrave += fabsf(cfablur[mm * W + cc + 2]);
}
#else
for (int mm = rr - 2; mm <= rr + 2; mm++) {
for (int nn = cc - 2; nn <= cc + 2; nn++) {
hfnbrave += fabsf(cfablur[mm * W + nn]);
} }
} }
if (pixdev * ((bottom - top + 1) * (right - left + 1) - 1) > varthresh * hfnbrave) { #endif
if (pixdev > varthresh * hfnbrave) {
// mark the pixel as "bad" // mark the pixel as "bad"
bpMap.set(cc, rr); bpMap.set(cc, rr);
counter++; counter++;
@ -1543,7 +1576,10 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
int totBP = 0; // Hold count of bad pixels to correct int totBP = 0; // Hold count of bad pixels to correct
if(ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) if(ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica)
#ifdef _OPENMP
#pragma omp parallel for reduction(+:totBP) #pragma omp parallel for reduction(+:totBP)
#endif
for(int i = 0; i < H; i++) for(int i = 0; i < H; i++)
for(int j = 0; j < W; j++) { for(int j = 0; j < W; j++) {
if(ri->data[i][j] == 0.f) { if(ri->data[i][j] == 0.f) {
@ -1618,7 +1654,9 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
if (pLCPProf && idata->getFocalLen() > 0.f) { if (pLCPProf && idata->getFocalLen() > 0.f) {
LCPMapper map(pLCPProf, idata->getFocalLen(), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1); LCPMapper map(pLCPProf, idata->getFocalLen(), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1);
#ifdef _OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif
for (int y = 0; y < H; y++) { for (int y = 0; y < H; y++) {
for (int x = 0; x < W; x++) { for (int x = 0; x < W; x++) {
@ -1652,7 +1690,9 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
int ng1 = 0, ng2 = 0, i = 0; int ng1 = 0, ng2 = 0, i = 0;
double avgg1 = 0., avgg2 = 0.; double avgg1 = 0., avgg2 = 0.;
#ifdef _OPENMP
#pragma omp parallel for default(shared) private(i) reduction(+: ng1, ng2, avgg1, avgg2) #pragma omp parallel for default(shared) private(i) reduction(+: ng1, ng2, avgg1, avgg2)
#endif
for (i = border; i < H - border; i++) for (i = border; i < H - border; i++)
for (int j = border; j < W - border; j++) for (int j = border; j < W - border; j++)
@ -1669,7 +1709,9 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
double corrg1 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg1 / ng1); double corrg1 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg1 / ng1);
double corrg2 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg2 / ng2); double corrg2 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg2 / ng2);
#ifdef _OPENMP
#pragma omp parallel for default(shared) #pragma omp parallel for default(shared)
#endif
for (int i = border; i < H - border; i++) for (int i = border; i < H - border; i++)
for (int j = border; j < W - border; j++) for (int j = border; j < W - border; j++)
@ -2461,10 +2503,14 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
float maxval = 0.f; float maxval = 0.f;
int c = FC(m, n); int c = FC(m, n);
int c4 = ( c == 1 && !(m & 1) ) ? 3 : c; int c4 = ( c == 1 && !(m & 1) ) ? 3 : c;
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float maxvalthr = 0.f; float maxvalthr = 0.f;
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int row = 0; row < H - m; row += 2) { for (int row = 0; row < H - m; row += 2) {
for (int col = 0; col < W - n; col += 2) { for (int col = 0; col < W - n; col += 2) {
@ -2476,7 +2522,9 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
if(maxvalthr > maxval) { if(maxvalthr > maxval) {
@ -2506,11 +2554,15 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
for (int m = 0; m < 2; m++) for (int m = 0; m < 2; m++)
for (int n = 0; n < 2; n++) { for (int n = 0; n < 2; n++) {
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
int c = FC(m, n); int c = FC(m, n);
int c4 = ( c == 1 && !(m & 1) ) ? 3 : c; int c4 = ( c == 1 && !(m & 1) ) ? 3 : c;
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int row = 0; row < H - m; row += 2) for (int row = 0; row < H - m; row += 2)
{ {
@ -2546,10 +2598,14 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
int clipControlGui = 0; int clipControlGui = 0;
float maxval = 0.f; float maxval = 0.f;
// xtrans files have only one black level actually, so we can simplify the code a bit // xtrans files have only one black level actually, so we can simplify the code a bit
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float maxvalthr = 0.f; float maxvalthr = 0.f;
#ifdef _OPENMP
#pragma omp for schedule(dynamic,16) nowait #pragma omp for schedule(dynamic,16) nowait
#endif
for (int row = 0; row < H; row++) { for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) { for (int col = 0; col < W; col++) {
@ -2561,7 +2617,9 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
if(maxvalthr > maxval) { if(maxvalthr > maxval) {
maxval = maxvalthr; maxval = maxvalthr;
@ -2583,7 +2641,9 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
refcolor[c] *= limitFactor; refcolor[c] *= limitFactor;
} }
#ifdef _OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif
for (int row = 0; row < H; row++) { for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) { for (int col = 0; col < W; col++) {
@ -2606,7 +2666,9 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
if(ri->getSensorType() == ST_BAYER) { if(ri->getSensorType() == ST_BAYER) {
for (int m = 0; m < 2; m++) for (int m = 0; m < 2; m++)
for (int n = 0; n < 2; n++) { for (int n = 0; n < 2; n++) {
#ifdef _OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif
for (int row = 0; row < H - m; row += 2) { for (int row = 0; row < H - m; row += 2) {
int c = FC(row, 0); int c = FC(row, 0);
@ -2620,7 +2682,9 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
} }
} }
} else if(ri->getSensorType() == ST_FUJI_XTRANS) { } else if(ri->getSensorType() == ST_FUJI_XTRANS) {
#ifdef _OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif
for (int row = 0; row < H; row++) { for (int row = 0; row < H; row++) {
for (int col = 0; col < W; col++) { for (int col = 0; col < W; col++) {
@ -2729,9 +2793,13 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur
cfatmp = (float (*)) calloc (H * W, sizeof * cfatmp); cfatmp = (float (*)) calloc (H * W, sizeof * cfatmp);
// const float hotdeadthresh = 0.5; // const float hotdeadthresh = 0.5;
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int i = 0; i < H; i++) { for (int i = 0; i < H; i++) {
int iprev, inext, jprev, jnext; int iprev, inext, jprev, jnext;
@ -2780,7 +2848,9 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur
//box blur cfa image; box size = BS //box blur cfa image; box size = BS
//horizontal blur //horizontal blur
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int row = 0; row < H; row++) { for (int row = 0; row < H; row++) {
int len = boxW / 2 + 1; int len = boxW / 2 + 1;
@ -2819,7 +2889,9 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur
__m128 onev = _mm_set1_ps( 1.0f ); __m128 onev = _mm_set1_ps( 1.0f );
__m128 temp1v, temp2v, lenv, lenp1v, lenm1v; __m128 temp1v, temp2v, lenv, lenp1v, lenm1v;
int row; int row;
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int col = 0; col < W - 3; col += 4) { for (int col = 0; col < W - 3; col += 4) {
lenv = leninitv; lenv = leninitv;
@ -2908,7 +2980,9 @@ SSEFUNCTION void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur
} }
#else #else
#ifdef _OPENMP
#pragma omp for #pragma omp for
#endif
for (int col = 0; col < W; col++) { for (int col = 0; col < W; col++) {
int len = boxH / 2 + 1; int len = boxH / 2 + 1;
@ -2990,12 +3064,15 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
// scale image colors // scale image colors
if( ri->getSensorType() == ST_BAYER) { if( ri->getSensorType() == ST_BAYER) {
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float tmpchmax[3]; float tmpchmax[3];
tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f;
#ifdef _OPENMP
#pragma omp for nowait #pragma omp for nowait
#endif
for (int row = winy; row < winy + winh; row ++) for (int row = winy; row < winy + winh; row ++)
{ {
@ -3010,7 +3087,9 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
chmax[0] = max(tmpchmax[0], chmax[0]); chmax[0] = max(tmpchmax[0], chmax[0]);
chmax[1] = max(tmpchmax[1], chmax[1]); chmax[1] = max(tmpchmax[1], chmax[1]);
@ -3018,11 +3097,14 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
} else if ( ri->get_colors() == 1 ) { } else if ( ri->get_colors() == 1 ) {
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float tmpchmax = 0.0f; float tmpchmax = 0.0f;
#ifdef _OPENMP
#pragma omp for nowait #pragma omp for nowait
#endif
for (int row = winy; row < winy + winh; row ++) for (int row = winy; row < winy + winh; row ++)
{ {
@ -3035,18 +3117,23 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
chmax[0] = chmax[1] = chmax[2] = chmax[3] = max(tmpchmax, chmax[0]); chmax[0] = chmax[1] = chmax[2] = chmax[3] = max(tmpchmax, chmax[0]);
} }
} }
} else if(ri->getSensorType() == ST_FUJI_XTRANS) { } else if(ri->getSensorType() == ST_FUJI_XTRANS) {
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float tmpchmax[3]; float tmpchmax[3];
tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f;
#ifdef _OPENMP
#pragma omp for nowait #pragma omp for nowait
#endif
for (int row = winy; row < winy + winh; row ++) for (int row = winy; row < winy + winh; row ++)
{ {
@ -3061,7 +3148,9 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
chmax[0] = max(tmpchmax[0], chmax[0]); chmax[0] = max(tmpchmax[0], chmax[0]);
chmax[1] = max(tmpchmax[1], chmax[1]); chmax[1] = max(tmpchmax[1], chmax[1]);
@ -3069,12 +3158,15 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
} else { } else {
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
float tmpchmax[3]; float tmpchmax[3];
tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f; tmpchmax[0] = tmpchmax[1] = tmpchmax[2] = 0.0f;
#ifdef _OPENMP
#pragma omp for nowait #pragma omp for nowait
#endif
for (int row = winy; row < winy + winh; row ++) for (int row = winy; row < winy + winh; row ++)
{ {
@ -3089,7 +3181,9 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
chmax[0] = max(tmpchmax[0], chmax[0]); chmax[0] = max(tmpchmax[0], chmax[0]);
chmax[1] = max(tmpchmax[1], chmax[1]); chmax[1] = max(tmpchmax[1], chmax[1]);
@ -3402,8 +3496,9 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam
mat[i][j] += work[i][k] * camMatrix[k][j]; // rgb_xyz * imatrices.xyz_cam mat[i][j] += work[i][k] * camMatrix[k][j]; // rgb_xyz * imatrices.xyz_cam
} }
#ifdef _OPENMP
#pragma omp parallel for #pragma omp parallel for
#endif
for (int i = 0; i < im->height; i++) for (int i = 0; i < im->height; i++)
for (int j = 0; j < im->width; j++) { for (int j = 0; j < im->width; j++) {
@ -3726,91 +3821,6 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, ColorManagementParam
// printf ("ICM TIME: %d usec\n", t3.etime(t1)); // printf ("ICM TIME: %d usec\n", t3.etime(t1));
} }
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Converts raw image including ICC input profile to working space - 16bit int version
/*void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName) {
cmsHPROFILE in;
DCPProfile *dcpProf;
if (!findInputProfile(cmp.input, embedded, camName, &dcpProf, in)) return;
if (dcpProf!=NULL) {
dcpProf->Apply(im, (DCPLightType)cmp.preferredProfile, cmp.working, cmp.toneCurve);
} else {
if (in==NULL) {
// Take camprofile from DCRAW
// in this case we avoid using the slllllooooooowwww lcms
TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
mat[i][j] += work[i][k] * camMatrix[k][j]; // rgb_xyz * imatrices.xyz_cam
#pragma omp parallel for
for (int i=0; i<im->height; i++)
for (int j=0; j<im->width; j++) {
float newr = mat[0][0]*im->r(i,j) + mat[0][1]*im->g(i,j) + mat[0][2]*im->b(i,j);
float newg = mat[1][0]*im->r(i,j) + mat[1][1]*im->g(i,j) + mat[1][2]*im->b(i,j);
float newb = mat[2][0]*im->r(i,j) + mat[2][1]*im->g(i,j) + mat[2][2]*im->b(i,j);
im->r(i,j) = CLIP((int)newr);
im->g(i,j) = CLIP((int)newg);
im->b(i,j) = CLIP((int)newb);
}
} else {
// Gamma preprocessing
float gammaFac, lineFac, lineSum;
getProfilePreprocParams(in, gammaFac, lineFac, lineSum);
if (gammaFac>0) {
#pragma omp parallel for
for ( int h = 0; h < im->height; ++h )
for ( int w = 0; w < im->width; ++w ) {
im->r(h,w)= (int) (pow ((double)(im->r(h,w) / 65535.0), (double)gammaFac) * 65535.0);
im->g(h,w)= (int) (pow ((double)(im->g(h,w) / 65535.0), (double)gammaFac) * 65535.0);
im->b(h,w)= (int) (pow ((double)(im->b(h,w) / 65535.0), (double)gammaFac) * 65535.0);
}
}
cmsHPROFILE out = iccStore->workingSpace (cmp.working);
//out = iccStore->workingSpaceGamma (wProfile);
lcmsMutex->lock ();
cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16, out, TYPE_RGB_16, settings->colorimetricIntent,
cmsFLAGS_NOCACHE); // NOCACHE is important for thread safety
lcmsMutex->unlock ();
if (hTransform) {
im->ExecCMSTransform(hTransform);
// There might be Nikon postprocessings
if (lineSum>0) {
#pragma omp parallel for
for ( int h = 0; h < im->height; ++h )
for ( int w = 0; w < im->width; ++w ) {
im->r(h,w) *= im->r(h,w) * lineFac / 65535.0 + lineSum;
im->g(h,w) *= im->g(h,w) * lineFac / 65535.0 + lineSum;
im->b(h,w) *= im->b(h,w) * lineFac / 65535.0 + lineSum;
}
}
}
else {
lcmsMutex->lock ();
hTransform = cmsCreateTransform (camprofile, TYPE_RGB_16, out, TYPE_RGB_16,
settings->colorimetricIntent, cmsFLAGS_NOCACHE);
lcmsMutex->unlock ();
im->ExecCMSTransform(hTransform);
}
cmsDeleteTransform(hTransform);
}
}
//t3.set ();
//printf ("ICM TIME: %d\n", t3.etime(t1));
}*/
// Determine RAW input and output profiles. Returns TRUE on success // Determine RAW input and output profiles. Returns TRUE on success
bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in) bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in)
@ -4109,11 +4119,15 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr)
histogram(65536 >> histcompr); histogram(65536 >> histcompr);
histogram.clear(); histogram.clear();
#ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif
{ {
LUTu tmphistogram(65536 >> histcompr); LUTu tmphistogram(65536 >> histcompr);
tmphistogram.clear(); tmphistogram.clear();
#ifdef _OPENMP
#pragma omp for nowait #pragma omp for nowait
#endif
for (int i = border; i < H - border; i++) { for (int i = border; i < H - border; i++) {
int start, end; int start, end;
@ -4152,7 +4166,9 @@ void RawImageSource::getAutoExpHistogram (LUTu & histogram, int& histcompr)
} }
} }
#ifdef _OPENMP
#pragma omp critical #pragma omp critical
#endif
{ {
for(int i = 0; i < (65536 >> histcompr); i++) { for(int i = 0; i < (65536 >> histcompr); i++) {
histogram[i] += tmphistogram[i]; histogram[i] += tmphistogram[i];

View File

@ -228,8 +228,8 @@ public:
} }
static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]); static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]);
void boxblur2(float** src, float** dst, int H, int W, int box ); void boxblur2(float** src, float** dst, float** temp, int H, int W, int box );
void boxblur_resamp(float **src, float **dst, int H, int W, int box, int samp ); void boxblur_resamp(float **src, float **dst, float** temp, int H, int W, int box, int samp );
void MSR(float** luminance, float **originalLuminance, float **exLuminance, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax); void MSR(float** luminance, float **originalLuminance, float **exLuminance, int width, int height, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
// void MSR(LabImage* lab, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve); // void MSR(LabImage* lab, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve);

View File

@ -1322,5 +1322,11 @@ static inline void vswap( vmask condition, vfloat &a, vfloat &b) {
b = temp; b = temp;
} }
static inline float vhadd( vfloat a )
{
a += _mm_movehl_ps(a, a);
return _mm_cvtss_f32(_mm_add_ss(a, _mm_shuffle_ps(a, a, 1)));
}
#endif // __SSE2__ #endif // __SSE2__
#endif // SLEEFSSEAVX #endif // SLEEFSSEAVX

View File

@ -92,7 +92,6 @@ public:
void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) void convertColorSpace(Imagefloat* image, ColorManagementParams cmp, ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h)
static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat);
//static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded);
static inline double intpow (double a, int b) static inline double intpow (double a, int b)
{ {

View File

@ -17,7 +17,7 @@
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "adjuster.h" #include "adjuster.h"
#include <sigc++/class_slot.h> #include <sigc++/slot.h>
#include <cmath> #include <cmath>
#include "multilangmgr.h" #include "multilangmgr.h"
#include "../rtengine/rtengine.h" #include "../rtengine/rtengine.h"

View File

@ -30,7 +30,7 @@ using namespace rtengine::procparams;
extern Options options; extern Options options;
ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(NULL), icmplistener(NULL), lastRefFilename("") ICMPanel::ICMPanel () : FoldableToolPanel(this, "icm", M("TP_ICM_LABEL")), iunchanged(NULL), icmplistener(NULL), lastRefFilename(""), camName("")
{ {
isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = lastBlendCMSMatrix = lastgamfree = false; isBatchMode = lastToneCurve = lastApplyLookTable = lastApplyBaselineExposureOffset = lastApplyHueSatMap = lastBlendCMSMatrix = lastgamfree = false;
@ -348,8 +348,13 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name)
dcpIll->set_sensitive (false); dcpIll->set_sensitive (false);
dcpFrame->set_sensitive(false); dcpFrame->set_sensitive(false);
if (ifromfile->get_active() && dcpStore->isValidDCPFileName(dcp_name)) { DCPProfile* dcp = NULL;
DCPProfile* dcp = dcpStore->getProfile(dcp_name, false);
if(dcp_name == "(cameraICC)") {
dcp = dcpStore->getStdProfile(camName);
} else if (ifromfile->get_active() && dcpStore->isValidDCPFileName(dcp_name)) {
dcp = dcpStore->getProfile(dcp_name);
}
if (dcp) { if (dcp) {
dcpFrame->set_sensitive(true); dcpFrame->set_sensitive(true);
@ -416,7 +421,6 @@ void ICMPanel::updateDCP (int dcpIlluminant, Glib::ustring dcp_name)
} }
} }
} }
}
if (!dcpIllLabel->get_sensitive() && dcpIll->get_active_row_number() != 0) { if (!dcpIllLabel->get_sensitive() && dcpIll->get_active_row_number() != 0) {
if (dcpTemperatures[0] != 0 || dcpTemperatures[1] != 0) { if (dcpTemperatures[0] != 0 || dcpTemperatures[1] != 0) {
@ -467,7 +471,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
} else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) { } else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state() != Gtk::STATE_INSENSITIVE) {
icameraICC->set_active (true); icameraICC->set_active (true);
ckbBlendCMSMatrix->set_sensitive (true); ckbBlendCMSMatrix->set_sensitive (true);
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)");
} else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() != Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) { } else if ((pp->icm.input == "(cameraICC)") && icamera->get_state() != Gtk::STATE_INSENSITIVE && icameraICC->get_state() == Gtk::STATE_INSENSITIVE) {
// this is the case when (cameraICC) is instructed by packaged profiles, but ICC file is not found // this is the case when (cameraICC) is instructed by packaged profiles, but ICC file is not found
// therefore falling back UI to explicitly reflect the (camera) option // therefore falling back UI to explicitly reflect the (camera) option
@ -478,7 +482,7 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
// If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded). // If neither (camera) nor (cameraICC) are available, as is the case when loading a non-raw, activate (embedded).
iembedded->set_active (true); iembedded->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); ckbBlendCMSMatrix->set_sensitive (false);
updateDCP(pp->icm.dcpIlluminant, ""); updateDCP(pp->icm.dcpIlluminant, "(cameraICC)");
} else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) { } else if ((pp->icm.input == "(camera)" || pp->icm.input == "") && icamera->get_state() != Gtk::STATE_INSENSITIVE) {
icamera->set_active (true); icamera->set_active (true);
ckbBlendCMSMatrix->set_sensitive (false); ckbBlendCMSMatrix->set_sensitive (false);
@ -603,8 +607,13 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited)
pp->icm.freegamma = freegamma->get_active(); pp->icm.freegamma = freegamma->get_active();
DCPProfile* dcp = NULL;
if (ifromfile->get_active() && pp->icm.input.substr(0, 5) == "file:" && dcpStore->isValidDCPFileName(pp->icm.input.substr(5))) { if (ifromfile->get_active() && pp->icm.input.substr(0, 5) == "file:" && dcpStore->isValidDCPFileName(pp->icm.input.substr(5))) {
DCPProfile* dcp = dcpStore->getProfile(pp->icm.input.substr(5), false); dcp = dcpStore->getProfile(pp->icm.input.substr(5));
} else if(icameraICC->get_active()) {
dcp = dcpStore->getStdProfile(camName);
}
if (dcp) { if (dcp) {
if (dcp->getHasToneCurve()) { if (dcp->getHasToneCurve()) {
@ -623,7 +632,6 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited)
pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active (); pp->icm.applyHueSatMap = ckbApplyHueSatMap->get_active ();
} }
} }
}
pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active (); pp->icm.blendCMSMatrix = ckbBlendCMSMatrix->get_active ();
pp->icm.gampos = (double) gampos->getValue(); pp->icm.gampos = (double) gampos->getValue();
@ -880,6 +888,7 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta)
icamera->set_active (raw); icamera->set_active (raw);
iembedded->set_active (!raw); iembedded->set_active (!raw);
icamera->set_sensitive (raw); icamera->set_sensitive (raw);
camName = pMeta->getCamera();
icameraICC->set_sensitive (raw && (iccStore->getStdProfile(pMeta->getCamera()) != NULL || dcpStore->getStdProfile(pMeta->getCamera()) != NULL)); icameraICC->set_sensitive (raw && (iccStore->getStdProfile(pMeta->getCamera()) != NULL || dcpStore->getStdProfile(pMeta->getCamera()) != NULL));
iembedded->set_sensitive (!raw); iembedded->set_sensitive (!raw);

View File

@ -93,6 +93,7 @@ private:
double dcpTemperatures[2]; double dcpTemperatures[2];
bool enableLastICCWorkDirChange; bool enableLastICCWorkDirChange;
Glib::ustring lastRefFilename; Glib::ustring lastRefFilename;
Glib::ustring camName;
void updateDCP(int dcpIlluminant, Glib::ustring dcp_name); void updateDCP(int dcpIlluminant, Glib::ustring dcp_name);
public: public:
ICMPanel (); ICMPanel ();

View File

@ -16,7 +16,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <sigc++/class_slot.h> #include <sigc++/slot.h>
#include "preferences.h" #include "preferences.h"
#include "multilangmgr.h" #include "multilangmgr.h"
#include "splash.h" #include "splash.h"

View File

@ -17,7 +17,7 @@
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "thresholdadjuster.h" #include "thresholdadjuster.h"
#include <sigc++/class_slot.h> #include <sigc++/slot.h>
#include <cmath> #include <cmath>
#include "multilangmgr.h" #include "multilangmgr.h"
#include "../rtengine/rtengine.h" #include "../rtengine/rtengine.h"

View File

@ -18,7 +18,7 @@
*/ */
#include "tonecurve.h" #include "tonecurve.h"
#include "adjuster.h" #include "adjuster.h"
#include <sigc++/class_slot.h> #include <sigc++/slot.h>
#include <iomanip> #include <iomanip>
#include "ppversion.h" #include "ppversion.h"
#include "edit.h" #include "edit.h"