merge with dev
This commit is contained in:
commit
91b80b23d2
@ -1983,7 +1983,7 @@ TP_FLATFIELD_BT_HORIZONTAL;Horizontal
|
|||||||
TP_FLATFIELD_BT_VERTHORIZ;Vertical + Horizontal
|
TP_FLATFIELD_BT_VERTHORIZ;Vertical + Horizontal
|
||||||
TP_FLATFIELD_BT_VERTICAL;Vertical
|
TP_FLATFIELD_BT_VERTICAL;Vertical
|
||||||
TP_FLATFIELD_CLIPCONTROL;Clip control
|
TP_FLATFIELD_CLIPCONTROL;Clip control
|
||||||
TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast.
|
TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, value 0 is used.
|
||||||
TP_FLATFIELD_LABEL;Flat-Field
|
TP_FLATFIELD_LABEL;Flat-Field
|
||||||
TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1.
|
TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1.
|
||||||
TP_GRADIENT_CENTER;Center
|
TP_GRADIENT_CENTER;Center
|
||||||
|
@ -114,6 +114,7 @@ set(RTENGINESOURCEFILES
|
|||||||
processingjob.cc
|
processingjob.cc
|
||||||
procparams.cc
|
procparams.cc
|
||||||
profilestore.cc
|
profilestore.cc
|
||||||
|
rawflatfield.cc
|
||||||
rawimage.cc
|
rawimage.cc
|
||||||
rawimagesource.cc
|
rawimagesource.cc
|
||||||
rcd_demosaic.cc
|
rcd_demosaic.cc
|
||||||
|
536
rtengine/rawflatfield.cc
Normal file
536
rtengine/rawflatfield.cc
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RawTherapee.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2019 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include "rawimagesource.h"
|
||||||
|
#include "procparams.h"
|
||||||
|
//#define BENCHMARK
|
||||||
|
//#include "StopWatch.h"
|
||||||
|
#include "opthelper.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void cfaboxblur(const float* const * riFlatFile, float* cfablur, int boxH, int boxW, int H, int W)
|
||||||
|
{
|
||||||
|
if (boxW < 0 || boxH < 0 || (boxW == 0 && boxH == 0)) { // nothing to blur or negative values
|
||||||
|
memcpy(cfablur, riFlatFile[0], W * H * sizeof(float));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<float []> tmpBuffer;
|
||||||
|
float *cfatmp = cfablur;
|
||||||
|
|
||||||
|
|
||||||
|
if (boxH > 0 && boxW > 0) {
|
||||||
|
// we need a temporary buffer if we have to blur both directions
|
||||||
|
tmpBuffer.reset(new float [H * W]);
|
||||||
|
cfatmp = tmpBuffer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if boxW == 0 we can skip the horizontal blur and process the vertical blur from riFlatFile to cfablur without using a temporary buffer
|
||||||
|
const float* srcVertical = boxW == 0 ? riFlatFile[0] : cfatmp;
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
if (boxW > 0) {
|
||||||
|
//box blur cfa image; box size = BS
|
||||||
|
//horizontal blur
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
int len = boxW / 2 + 1;
|
||||||
|
cfatmp[row * W] = riFlatFile[row][0] / len;
|
||||||
|
cfatmp[row * W + 1] = riFlatFile[row][1] / len;
|
||||||
|
|
||||||
|
for (int j = 2; j <= boxW; j += 2) {
|
||||||
|
cfatmp[row * W] += riFlatFile[row][j] / len;
|
||||||
|
cfatmp[row * W + 1] += riFlatFile[row][j + 1] / len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int col = 2; col <= boxW; col += 2) {
|
||||||
|
cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len + riFlatFile[row][boxW + col]) / (len + 1);
|
||||||
|
cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len + riFlatFile[row][boxW + col + 1]) / (len + 1);
|
||||||
|
len ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float rlen = 1.f / len;
|
||||||
|
for (int col = boxW + 2; col < W - boxW; col++) {
|
||||||
|
cfatmp[row * W + col] = cfatmp[row * W + col - 2] + (riFlatFile[row][boxW + col] - cfatmp[row * W + col - boxW - 2]) * rlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int col = W - boxW; col < W; col += 2) {
|
||||||
|
cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len - cfatmp[row * W + col - boxW - 2]) / (len - 1);
|
||||||
|
|
||||||
|
if (col + 1 < W) {
|
||||||
|
cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len - cfatmp[row * W + col - boxW - 1]) / (len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
len --;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (boxH > 0) {
|
||||||
|
//vertical blur
|
||||||
|
#ifdef __SSE2__
|
||||||
|
const vfloat leninitv = F2V(boxH / 2 + 1);
|
||||||
|
const vfloat onev = F2V(1.f);
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for nowait
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int col = 0; col < W - 7; col += 8) {
|
||||||
|
vfloat lenv = leninitv;
|
||||||
|
vfloat temp1v = LVFU(srcVertical[col]) / lenv;
|
||||||
|
vfloat temp2v = LVFU(srcVertical[W + col]) / lenv;
|
||||||
|
vfloat temp3v = LVFU(srcVertical[col + 4]) / lenv;
|
||||||
|
vfloat temp4v = LVFU(srcVertical[W + col + 4]) / lenv;
|
||||||
|
|
||||||
|
for (int i = 2; i < boxH + 2; i += 2) {
|
||||||
|
temp1v += LVFU(srcVertical[i * W + col]) / lenv;
|
||||||
|
temp2v += LVFU(srcVertical[(i + 1) * W + col]) / lenv;
|
||||||
|
temp3v += LVFU(srcVertical[i * W + col + 4]) / lenv;
|
||||||
|
temp4v += LVFU(srcVertical[(i + 1) * W + col + 4]) / lenv;
|
||||||
|
}
|
||||||
|
|
||||||
|
STVFU(cfablur[col], temp1v);
|
||||||
|
STVFU(cfablur[W + col], temp2v);
|
||||||
|
STVFU(cfablur[col + 4], temp3v);
|
||||||
|
STVFU(cfablur[W + col + 4], temp4v);
|
||||||
|
|
||||||
|
int row;
|
||||||
|
for (row = 2; row < boxH + 2; row += 2) {
|
||||||
|
const vfloat lenp1v = lenv + onev;
|
||||||
|
temp1v = (temp1v * lenv + LVFU(srcVertical[(row + boxH) * W + col])) / lenp1v;
|
||||||
|
temp2v = (temp2v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col])) / lenp1v;
|
||||||
|
temp3v = (temp3v * lenv + LVFU(srcVertical[(row + boxH) * W + col + 4])) / lenp1v;
|
||||||
|
temp4v = (temp4v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col + 4])) / lenp1v;
|
||||||
|
STVFU(cfablur[row * W + col], temp1v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col], temp2v);
|
||||||
|
STVFU(cfablur[row * W + col + 4], temp3v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col + 4], temp4v);
|
||||||
|
lenv = lenp1v;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; row < H - boxH - 1; row += 2) {
|
||||||
|
temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv;
|
||||||
|
temp2v = temp2v + (LVFU(srcVertical[(row + 1 + boxH) * W + col]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col])) / lenv;
|
||||||
|
temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv;
|
||||||
|
temp4v = temp4v + (LVFU(srcVertical[(row + 1 + boxH) * W + col + 4]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col + 4])) / lenv;
|
||||||
|
STVFU(cfablur[row * W + col], temp1v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col], temp2v);
|
||||||
|
STVFU(cfablur[row * W + col + 4], temp3v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col + 4], temp4v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row < H - boxH) {
|
||||||
|
temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv;
|
||||||
|
temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv;
|
||||||
|
STVFU(cfablur[row * W + col], temp1v);
|
||||||
|
STVFU(cfablur[row * W + col + 4], temp3v);
|
||||||
|
vfloat swapv = temp1v;
|
||||||
|
temp1v = temp2v;
|
||||||
|
temp2v = swapv;
|
||||||
|
swapv = temp3v;
|
||||||
|
temp3v = temp4v;
|
||||||
|
temp4v = swapv;
|
||||||
|
++row;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; row < H - 1; row += 2) {
|
||||||
|
const vfloat lenm1v = lenv - onev;
|
||||||
|
temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v;
|
||||||
|
temp2v = (temp2v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col])) / lenm1v;
|
||||||
|
temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v;
|
||||||
|
temp4v = (temp4v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col + 4])) / lenm1v;
|
||||||
|
STVFU(cfablur[row * W + col], temp1v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col], temp2v);
|
||||||
|
STVFU(cfablur[row * W + col + 4], temp3v);
|
||||||
|
STVFU(cfablur[(row + 1) * W + col + 4], temp4v);
|
||||||
|
lenv = lenm1v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row < H) {
|
||||||
|
vfloat lenm1v = lenv - onev;
|
||||||
|
temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v;
|
||||||
|
temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v;
|
||||||
|
STVFU(cfablur[row * W + col], temp1v);
|
||||||
|
STVFU(cfablur[row * W + col + 4], temp3v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp single
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int col = W - (W % 8); col < W; ++col) {
|
||||||
|
int len = boxH / 2 + 1;
|
||||||
|
cfablur[col] = srcVertical[col] / len;
|
||||||
|
cfablur[W + col] = srcVertical[W + col] / len;
|
||||||
|
|
||||||
|
for (int i = 2; i < boxH + 2; i += 2) {
|
||||||
|
cfablur[col] += srcVertical[i * W + col] / len;
|
||||||
|
cfablur[W + col] += srcVertical[(i + 1) * W + col] / len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = 2; row < boxH + 2; row += 2) {
|
||||||
|
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1);
|
||||||
|
cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = boxH + 2; row < H - boxH; ++row) {
|
||||||
|
cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = H - boxH; row < H; row += 2) {
|
||||||
|
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1);
|
||||||
|
|
||||||
|
if (row + 1 < H) {
|
||||||
|
cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1);
|
||||||
|
}
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int col = 0; col < W; ++col) {
|
||||||
|
int len = boxH / 2 + 1;
|
||||||
|
cfablur[col] = srcVertical[col] / len;
|
||||||
|
cfablur[W + col] = srcVertical[W + col] / len;
|
||||||
|
|
||||||
|
for (int i = 2; i < boxH + 2; i += 2) {
|
||||||
|
cfablur[col] += srcVertical[i * W + col] / len;
|
||||||
|
cfablur[W + col] += srcVertical[(i + 1) * W + col] / len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = 2; row < boxH + 2; row += 2) {
|
||||||
|
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1);
|
||||||
|
cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1);
|
||||||
|
++len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = boxH + 2; row < H - boxH; ++row) {
|
||||||
|
cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int row = H - boxH; row < H; row += 2) {
|
||||||
|
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1);
|
||||||
|
|
||||||
|
if (row + 1 < H) {
|
||||||
|
cfablur[(row + 1) * W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1);
|
||||||
|
}
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace rtengine
|
||||||
|
{
|
||||||
|
|
||||||
|
void RawImageSource::processFlatField(const RAWParams &raw, const RawImage *riFlatFile, const unsigned short black[4])
|
||||||
|
{
|
||||||
|
// BENCHFUN
|
||||||
|
const float fblack[4] = {static_cast<float>(black[0]), static_cast<float>(black[1]), static_cast<float>(black[2]), static_cast<float>(black[3])};
|
||||||
|
std::unique_ptr<float[]> cfablur(new float[H * W]);
|
||||||
|
|
||||||
|
const int BS = raw.ff_BlurRadius + (raw.ff_BlurRadius & 1);
|
||||||
|
|
||||||
|
if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::V)) {
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur.get(), 2 * BS, 0, H, W);
|
||||||
|
} else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::H)) {
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur.get(), 0, 2 * BS, H, W);
|
||||||
|
} else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) {
|
||||||
|
//slightly more complicated blur if trying to correct both vertical and horizontal anomalies
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur.get(), BS, BS, H, W); //first do area blur to correct vignette
|
||||||
|
} else { //(raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::area_ff))
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur.get(), BS, BS, H, W);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
|
||||||
|
float refcolor[2][2];
|
||||||
|
|
||||||
|
// find center values by channel
|
||||||
|
for (int m = 0; m < 2; ++m)
|
||||||
|
for (int n = 0; n < 2; ++n) {
|
||||||
|
const int row = 2 * (H >> 2) + m;
|
||||||
|
const int col = 2 * (W >> 2) + n;
|
||||||
|
const int c = ri->get_colors() != 1 ? FC(row, col) : 0;
|
||||||
|
const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(row & 1)) ? 3 : c) : 0;
|
||||||
|
refcolor[m][n] = std::max(0.0f, cfablur[row * W + col] - fblack[c4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float limitFactor = 1.f;
|
||||||
|
|
||||||
|
if (raw.ff_AutoClipControl) {
|
||||||
|
bool clippedBefore = false;
|
||||||
|
for (int m = 0; m < 2 && !clippedBefore; ++m) {
|
||||||
|
for (int n = 0; n < 2 && !clippedBefore; ++n) {
|
||||||
|
float maxval = 0.f;
|
||||||
|
const int c = ri->get_colors() != 1 ? FC(m, n) : 0;
|
||||||
|
const int c4 = ri->get_colors() != 1 ? ((c == 1 && !(m & 1)) ? 3 : c) : 0;
|
||||||
|
const float clipVal = ri->get_white(c4);
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for reduction(max:maxval) schedule(dynamic, 16)
|
||||||
|
#endif
|
||||||
|
for (int row = 0; row < H - m; row += 2) {
|
||||||
|
for (int col = 0; col < W - n && !clippedBefore; col += 2) {
|
||||||
|
const float rawVal = rawData[row + m][col + n];
|
||||||
|
if (rawVal >= clipVal) {
|
||||||
|
clippedBefore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const float tempval = (rawVal - fblack[c4]) * (refcolor[m][n] / std::max(1e-5f, cfablur[(row + m) * W + col + n] - fblack[c4]));
|
||||||
|
maxval = std::max(maxval, tempval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we have the max value for the channel
|
||||||
|
// if it clips, calculate factor to avoid clipping
|
||||||
|
if (maxval + fblack[c4] >= ri->get_white(c4)) {
|
||||||
|
if (!clippedBefore) {
|
||||||
|
limitFactor = std::min(limitFactor, ri->get_white(c4) / (maxval + fblack[c4]));
|
||||||
|
} else {
|
||||||
|
limitFactor = 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui
|
||||||
|
} else {
|
||||||
|
limitFactor = std::max((100 - raw.ff_clipControl) / 100.f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int m = 0; m < 2; ++m)
|
||||||
|
for (int n = 0; n < 2; ++n) {
|
||||||
|
refcolor[m][n] *= limitFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int c[2][2] {};
|
||||||
|
unsigned int c4[2][2] {};
|
||||||
|
if (ri->get_colors() != 1) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
for (int j = 0; j < 2; ++j) {
|
||||||
|
c[i][j] = FC(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c4[0][0] = (c[0][0] == 1) ? 3 : c[0][0];
|
||||||
|
c4[0][1] = (c[0][1] == 1) ? 3 : c[0][1];
|
||||||
|
c4[1][0] = c[1][0];
|
||||||
|
c4[1][1] = c[1][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied.
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
const vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]),
|
||||||
|
_mm_set_ps(refcolor[1][1], refcolor[1][0], refcolor[1][1], refcolor[1][0])
|
||||||
|
};
|
||||||
|
const vfloat blackv[2] = {_mm_set_ps(fblack[c4[0][1]], fblack[c4[0][0]], fblack[c4[0][1]], fblack[c4[0][0]]),
|
||||||
|
_mm_set_ps(fblack[c4[1][1]], fblack[c4[1][0]], fblack[c4[1][1]], fblack[c4[1][0]])
|
||||||
|
};
|
||||||
|
|
||||||
|
const vfloat onev = F2V(1.f);
|
||||||
|
const vfloat minValuev = F2V(minValue);
|
||||||
|
#endif
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for schedule(dynamic,16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
int col = 0;
|
||||||
|
#ifdef __SSE2__
|
||||||
|
const vfloat rowBlackv = blackv[row & 1];
|
||||||
|
const vfloat rowRefcolorv = refcolorv[row & 1];
|
||||||
|
|
||||||
|
for (; col < W - 3; col += 4) {
|
||||||
|
const vfloat blurv = LVFU(cfablur[row * W + col]) - rowBlackv;
|
||||||
|
vfloat vignettecorrv = rowRefcolorv / blurv;
|
||||||
|
vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv);
|
||||||
|
const vfloat valv = LVFU(rawData[row][col]) - rowBlackv;
|
||||||
|
STVFU(rawData[row][col], valv * vignettecorrv + rowBlackv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; col < W; ++col) {
|
||||||
|
const float blur = cfablur[row * W + col] - fblack[c4[row & 1][col & 1]];
|
||||||
|
const float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur;
|
||||||
|
rawData[row][col] = (rawData[row][col] - fblack[c4[row & 1][col & 1]]) * vignettecorr + fblack[c4[row & 1][col & 1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
||||||
|
float refcolor[3] = {0.f};
|
||||||
|
int cCount[3] = {0};
|
||||||
|
|
||||||
|
// find center average values by channel
|
||||||
|
for (int m = -3; m < 3; ++m)
|
||||||
|
for (int n = -3; n < 3; ++n) {
|
||||||
|
const int row = 2 * (H >> 2) + m;
|
||||||
|
const int col = 2 * (W >> 2) + n;
|
||||||
|
const int c = riFlatFile->XTRANSFC(row, col);
|
||||||
|
refcolor[c] += std::max(0.0f, cfablur[row * W + col] - fblack[c]);
|
||||||
|
cCount[c] ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int c = 0; c < 3; ++c) {
|
||||||
|
refcolor[c] = refcolor[c] / cCount[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
float limitFactor = 1.f;
|
||||||
|
|
||||||
|
if (raw.ff_AutoClipControl) {
|
||||||
|
// determine maximum calculated value to avoid clipping
|
||||||
|
bool clippedBefore = false;
|
||||||
|
const float clipVal = ri->get_white(0);
|
||||||
|
float maxval = 0.f;
|
||||||
|
// xtrans files have only one black level actually, so we can simplify the code a bit
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for reduction(max:maxval) schedule(dynamic,16)
|
||||||
|
#endif
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
for (int col = 0; col < W && !clippedBefore; ++col) {
|
||||||
|
const float rawVal = rawData[row][col];
|
||||||
|
if (rawVal >= clipVal) {
|
||||||
|
clippedBefore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const float tempval = (rawVal - fblack[0]) * (refcolor[ri->XTRANSFC(row, col)] / std::max(1e-5f, cfablur[(row) * W + col] - fblack[0]));
|
||||||
|
maxval = std::max(maxval, tempval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's only one white level for xtrans
|
||||||
|
if (!clippedBefore && maxval + fblack[0] > ri->get_white(0)) {
|
||||||
|
limitFactor = ri->get_white(0) / (maxval + fblack[0]);
|
||||||
|
flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
limitFactor = std::max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int c = 0; c < 3; ++c) {
|
||||||
|
refcolor[c] *= limitFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied.
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
for (int col = 0; col < W; ++col) {
|
||||||
|
const int c = ri->XTRANSFC(row, col);
|
||||||
|
const float blur = cfablur[(row) * W + col] - fblack[c];
|
||||||
|
const float vignettecorr = blur <= minValue ? 1.f : refcolor[c] / blur;
|
||||||
|
rawData[row][col] = (rawData[row][col] - fblack[c]) * vignettecorr + fblack[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) {
|
||||||
|
std::unique_ptr<float []> cfablur1(new float[H * W]);
|
||||||
|
std::unique_ptr<float []> cfablur2(new float[H * W]);
|
||||||
|
//slightly more complicated blur if trying to correct both vertical and horizontal anomalies
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur1.get(), 0, 2 * BS, H, W); //now do horizontal blur
|
||||||
|
cfaboxblur(riFlatFile->data, cfablur2.get(), 2 * BS, 0, H, W); //now do vertical blur
|
||||||
|
|
||||||
|
if (ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
|
||||||
|
unsigned int c[2][2] {};
|
||||||
|
unsigned int c4[2][2] {};
|
||||||
|
if (ri->get_colors() != 1) {
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
for (int j = 0; j < 2; ++j) {
|
||||||
|
c[i][j] = FC(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c4[0][0] = (c[0][0] == 1) ? 3 : c[0][0];
|
||||||
|
c4[0][1] = (c[0][1] == 1) ? 3 : c[0][1];
|
||||||
|
c4[1][0] = c[1][0];
|
||||||
|
c4[1][1] = c[1][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
const vfloat blackv[2] = {_mm_set_ps(fblack[c4[0][1]], fblack[c4[0][0]], fblack[c4[0][1]], fblack[c4[0][0]]),
|
||||||
|
_mm_set_ps(fblack[c4[1][1]], fblack[c4[1][0]], fblack[c4[1][1]], fblack[c4[1][0]])
|
||||||
|
};
|
||||||
|
|
||||||
|
const vfloat epsv = F2V(1e-5f);
|
||||||
|
#endif
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for schedule(dynamic,16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
int col = 0;
|
||||||
|
#ifdef __SSE2__
|
||||||
|
const vfloat rowBlackv = blackv[row & 1];
|
||||||
|
|
||||||
|
for (; col < W - 3; col += 4) {
|
||||||
|
const vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - rowBlackv, epsv)) /
|
||||||
|
(vmaxf(LVFU(cfablur1[row * W + col]) - rowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - rowBlackv, epsv));
|
||||||
|
const vfloat valv = LVFU(rawData[row][col]) - rowBlackv;
|
||||||
|
STVFU(rawData[row][col], valv * linecorrv + rowBlackv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; col < W; ++col) {
|
||||||
|
const float linecorr = SQR(std::max(1e-5f, cfablur[row * W + col] - fblack[c4[row & 1][col & 1]])) /
|
||||||
|
(std::max(1e-5f, cfablur1[row * W + col] - fblack[c4[row & 1][col & 1]]) * std::max(1e-5f, cfablur2[row * W + col] - fblack[c4[row & 1][col & 1]]));
|
||||||
|
rawData[row][col] = (rawData[row][col] - fblack[c4[row & 1][col & 1]]) * linecorr + fblack[c4[row & 1][col & 1]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int row = 0; row < H; ++row) {
|
||||||
|
for (int col = 0; col < W; ++col) {
|
||||||
|
const int c = ri->XTRANSFC(row, col);
|
||||||
|
const float hlinecorr = std::max(1e-5f, cfablur[(row) * W + col] - fblack[c]) / std::max(1e-5f, cfablur1[(row) * W + col] - fblack[c]);
|
||||||
|
const float vlinecorr = std::max(1e-5f, cfablur[(row) * W + col] - fblack[c]) / std::max(1e-5f, cfablur2[(row) * W + col] - fblack[c]);
|
||||||
|
rawData[row][col] = (rawData[row][col] - fblack[c]) * hlinecorr * vlinecorr + fblack[c];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* namespace */
|
@ -2397,311 +2397,6 @@ void RawImageSource::HLRecovery_Global(const ToneCurveParams &hrp)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4])
|
|
||||||
{
|
|
||||||
// BENCHFUN
|
|
||||||
float *cfablur = (float (*)) malloc(H * W * sizeof * cfablur);
|
|
||||||
int BS = raw.ff_BlurRadius;
|
|
||||||
BS += BS & 1;
|
|
||||||
|
|
||||||
//function call to cfabloxblur
|
|
||||||
if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::V)) {
|
|
||||||
cfaboxblur(riFlatFile, cfablur, 2 * BS, 0);
|
|
||||||
} else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::H)) {
|
|
||||||
cfaboxblur(riFlatFile, cfablur, 0, 2 * BS);
|
|
||||||
} else if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) {
|
|
||||||
//slightly more complicated blur if trying to correct both vertical and horizontal anomalies
|
|
||||||
cfaboxblur(riFlatFile, cfablur, BS, BS); //first do area blur to correct vignette
|
|
||||||
} else { //(raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::area_ff))
|
|
||||||
cfaboxblur(riFlatFile, cfablur, BS, BS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
|
|
||||||
float refcolor[2][2];
|
|
||||||
|
|
||||||
//find centre average values by channel
|
|
||||||
for (int m = 0; m < 2; m++)
|
|
||||||
for (int n = 0; n < 2; n++) {
|
|
||||||
int row = 2 * (H >> 2) + m;
|
|
||||||
int col = 2 * (W >> 2) + n;
|
|
||||||
int c = ri->get_colors() != 1 ? FC(row, col) : 0;
|
|
||||||
int c4 = ri->get_colors() != 1 ? (( c == 1 && !(row & 1) ) ? 3 : c) : 0;
|
|
||||||
refcolor[m][n] = max(0.0f, cfablur[row * W + col] - black[c4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
float limitFactor = 1.f;
|
|
||||||
|
|
||||||
if (raw.ff_AutoClipControl) {
|
|
||||||
for (int m = 0; m < 2; m++)
|
|
||||||
for (int n = 0; n < 2; n++) {
|
|
||||||
float maxval = 0.f;
|
|
||||||
int c = ri->get_colors() != 1 ? FC(m, n) : 0;
|
|
||||||
int c4 = ri->get_colors() != 1 ? (( c == 1 && !(m & 1) ) ? 3 : c) : 0;
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
float maxvalthr = 0.f;
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp for
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H - m; row += 2) {
|
|
||||||
for (int col = 0; col < W - n; col += 2) {
|
|
||||||
float tempval = (rawData[row + m][col + n] - black[c4]) * (refcolor[m][n] / max(1e-5f, cfablur[(row + m) * W + col + n] - black[c4]));
|
|
||||||
|
|
||||||
if (tempval > maxvalthr) {
|
|
||||||
maxvalthr = tempval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp critical
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
|
|
||||||
if (maxvalthr > maxval) {
|
|
||||||
maxval = maxvalthr;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we have the max value for the channel
|
|
||||||
// if it clips, calculate factor to avoid clipping
|
|
||||||
if (maxval + black[c4] >= ri->get_white(c4)) {
|
|
||||||
limitFactor = min(limitFactor, ri->get_white(c4) / (maxval + black[c4]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui
|
|
||||||
} else {
|
|
||||||
limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int m = 0; m < 2; m++)
|
|
||||||
for (int n = 0; n < 2; n++) {
|
|
||||||
refcolor[m][n] *= limitFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int c[2][2] {};
|
|
||||||
unsigned int c4[2][2] {};
|
|
||||||
if(ri->get_colors() != 1) {
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
for(int j = 0; j < 2; ++j) {
|
|
||||||
c[i][j] = FC(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c4[0][0] = ( c[0][0] == 1) ? 3 : c[0][0];
|
|
||||||
c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1];
|
|
||||||
c4[1][0] = c[1][0];
|
|
||||||
c4[1][1] = c[1][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied.
|
|
||||||
|
|
||||||
#ifdef __SSE2__
|
|
||||||
vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]),
|
|
||||||
_mm_set_ps(refcolor[1][1], refcolor[1][0], refcolor[1][1], refcolor[1][0])
|
|
||||||
};
|
|
||||||
vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]),
|
|
||||||
_mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]])
|
|
||||||
};
|
|
||||||
|
|
||||||
vfloat onev = F2V(1.f);
|
|
||||||
vfloat minValuev = F2V(minValue);
|
|
||||||
#endif
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel for schedule(dynamic,16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row ++) {
|
|
||||||
int col = 0;
|
|
||||||
#ifdef __SSE2__
|
|
||||||
vfloat rowBlackv = blackv[row & 1];
|
|
||||||
vfloat rowRefcolorv = refcolorv[row & 1];
|
|
||||||
|
|
||||||
for (; col < W - 3; col += 4) {
|
|
||||||
vfloat blurv = LVFU(cfablur[(row) * W + col]) - rowBlackv;
|
|
||||||
vfloat vignettecorrv = rowRefcolorv / blurv;
|
|
||||||
vignettecorrv = vself(vmaskf_le(blurv, minValuev), onev, vignettecorrv);
|
|
||||||
vfloat valv = LVFU(rawData[row][col]);
|
|
||||||
valv -= rowBlackv;
|
|
||||||
STVFU(rawData[row][col], valv * vignettecorrv + rowBlackv);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (; col < W; col ++) {
|
|
||||||
float blur = cfablur[(row) * W + col] - black[c4[row & 1][col & 1]];
|
|
||||||
float vignettecorr = blur <= minValue ? 1.f : refcolor[row & 1][col & 1] / blur;
|
|
||||||
rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * vignettecorr + black[c4[row & 1][col & 1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
|
||||||
float refcolor[3] = {0.f};
|
|
||||||
int cCount[3] = {0};
|
|
||||||
|
|
||||||
//find center ave values by channel
|
|
||||||
for (int m = -3; m < 3; m++)
|
|
||||||
for (int n = -3; n < 3; n++) {
|
|
||||||
int row = 2 * (H >> 2) + m;
|
|
||||||
int col = 2 * (W >> 2) + n;
|
|
||||||
int c = riFlatFile->XTRANSFC(row, col);
|
|
||||||
refcolor[c] += max(0.0f, cfablur[row * W + col] - black[c]);
|
|
||||||
cCount[c] ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int c = 0; c < 3; c++) {
|
|
||||||
refcolor[c] = refcolor[c] / cCount[c];
|
|
||||||
}
|
|
||||||
|
|
||||||
float limitFactor = 1.f;
|
|
||||||
|
|
||||||
if (raw.ff_AutoClipControl) {
|
|
||||||
// determine maximum calculated value to avoid clipping
|
|
||||||
float maxval = 0.f;
|
|
||||||
// xtrans files have only one black level actually, so we can simplify the code a bit
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
float maxvalthr = 0.f;
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp for schedule(dynamic,16) nowait
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row++) {
|
|
||||||
for (int col = 0; col < W; col++) {
|
|
||||||
float tempval = (rawData[row][col] - black[0]) * (refcolor[ri->XTRANSFC(row, col)] / max(1e-5f, cfablur[(row) * W + col] - black[0]));
|
|
||||||
|
|
||||||
if (tempval > maxvalthr) {
|
|
||||||
maxvalthr = tempval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp critical
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (maxvalthr > maxval) {
|
|
||||||
maxval = maxvalthr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// there's only one white level for xtrans
|
|
||||||
if (maxval + black[0] > ri->get_white(0)) {
|
|
||||||
limitFactor = ri->get_white(0) / (maxval + black[0]);
|
|
||||||
flatFieldAutoClipValue = (1.f - limitFactor) * 100.f; // this value can be used to set the clip control slider in gui
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
limitFactor = max((float)(100 - raw.ff_clipControl) / 100.f, 0.01f);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int c = 0; c < 3; c++) {
|
|
||||||
refcolor[c] *= limitFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr float minValue = 1.f; // if the pixel value in the flat field is less or equal this value, no correction will be applied.
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel for
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row++) {
|
|
||||||
for (int col = 0; col < W; col++) {
|
|
||||||
int c = ri->XTRANSFC(row, col);
|
|
||||||
float blur = cfablur[(row) * W + col] - black[c];
|
|
||||||
float vignettecorr = blur <= minValue ? 1.f : refcolor[c] / blur;
|
|
||||||
rawData[row][col] = (rawData[row][col] - black[c]) * vignettecorr + black[c];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (raw.ff_BlurType == RAWParams::getFlatFieldBlurTypeString(RAWParams::FlatFieldBlurType::VH)) {
|
|
||||||
float *cfablur1 = (float (*)) malloc(H * W * sizeof * cfablur1);
|
|
||||||
float *cfablur2 = (float (*)) malloc(H * W * sizeof * cfablur2);
|
|
||||||
//slightly more complicated blur if trying to correct both vertical and horizontal anomalies
|
|
||||||
cfaboxblur(riFlatFile, cfablur1, 0, 2 * BS); //now do horizontal blur
|
|
||||||
cfaboxblur(riFlatFile, cfablur2, 2 * BS, 0); //now do vertical blur
|
|
||||||
|
|
||||||
if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
|
|
||||||
unsigned int c[2][2] {};
|
|
||||||
unsigned int c4[2][2] {};
|
|
||||||
if(ri->get_colors() != 1) {
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
for(int j = 0; j < 2; ++j) {
|
|
||||||
c[i][j] = FC(i, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c4[0][0] = ( c[0][0] == 1) ? 3 : c[0][0];
|
|
||||||
c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1];
|
|
||||||
c4[1][0] = c[1][0];
|
|
||||||
c4[1][1] = c[1][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __SSE2__
|
|
||||||
vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]),
|
|
||||||
_mm_set_ps(black[c4[1][1]], black[c4[1][0]], black[c4[1][1]], black[c4[1][0]])
|
|
||||||
};
|
|
||||||
|
|
||||||
vfloat epsv = F2V(1e-5f);
|
|
||||||
#endif
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel for schedule(dynamic,16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row ++) {
|
|
||||||
int col = 0;
|
|
||||||
#ifdef __SSE2__
|
|
||||||
vfloat rowBlackv = blackv[row & 1];
|
|
||||||
|
|
||||||
for (; col < W - 3; col += 4) {
|
|
||||||
vfloat linecorrv = SQRV(vmaxf(LVFU(cfablur[row * W + col]) - rowBlackv, epsv)) /
|
|
||||||
(vmaxf(LVFU(cfablur1[row * W + col]) - rowBlackv, epsv) * vmaxf(LVFU(cfablur2[row * W + col]) - rowBlackv, epsv));
|
|
||||||
vfloat valv = LVFU(rawData[row][col]);
|
|
||||||
valv -= rowBlackv;
|
|
||||||
STVFU(rawData[row][col], valv * linecorrv + rowBlackv);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (; col < W; col ++) {
|
|
||||||
float linecorr = SQR(max(1e-5f, cfablur[row * W + col] - black[c4[row & 1][col & 1]])) /
|
|
||||||
(max(1e-5f, cfablur1[row * W + col] - black[c4[row & 1][col & 1]]) * max(1e-5f, cfablur2[row * W + col] - black[c4[row & 1][col & 1]])) ;
|
|
||||||
rawData[row][col] = (rawData[row][col] - black[c4[row & 1][col & 1]]) * linecorr + black[c4[row & 1][col & 1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel for
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row++) {
|
|
||||||
for (int col = 0; col < W; col++) {
|
|
||||||
int c = ri->XTRANSFC(row, col);
|
|
||||||
float hlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur1[(row) * W + col] - black[c]));
|
|
||||||
float vlinecorr = (max(1e-5f, cfablur[(row) * W + col] - black[c]) / max(1e-5f, cfablur2[(row) * W + col] - black[c]));
|
|
||||||
rawData[row][col] = ((rawData[row][col] - black[c]) * hlinecorr * vlinecorr + black[c]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
free(cfablur1);
|
|
||||||
free(cfablur2);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(cfablur);
|
|
||||||
}
|
|
||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
/* Copy original pixel data and
|
/* Copy original pixel data and
|
||||||
* subtract dark frame (if present) from current image and apply flat field correction (if present)
|
* subtract dark frame (if present) from current image and apply flat field correction (if present)
|
||||||
*/
|
*/
|
||||||
@ -2793,253 +2488,6 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawImageSource::cfaboxblur(RawImage *riFlatFile, float* cfablur, int boxH, int boxW)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (boxW < 0 || boxH < 0 || (boxW == 0 && boxH == 0)) { // nothing to blur or negative values
|
|
||||||
memcpy(cfablur, riFlatFile->data[0], W * H * sizeof(float));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
float *tmpBuffer = nullptr;
|
|
||||||
float *cfatmp = nullptr;
|
|
||||||
float *srcVertical = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
if (boxH > 0 && boxW > 0) {
|
|
||||||
// we need a temporary buffer if we have to blur both directions
|
|
||||||
tmpBuffer = (float (*)) calloc(H * W, sizeof * tmpBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boxH == 0) {
|
|
||||||
// if boxH == 0 we can skip the vertical blur and process the horizontal blur from riFlatFile to cfablur without using a temporary buffer
|
|
||||||
cfatmp = cfablur;
|
|
||||||
} else {
|
|
||||||
cfatmp = tmpBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boxW == 0) {
|
|
||||||
// if boxW == 0 we can skip the horizontal blur and process the vertical blur from riFlatFile to cfablur without using a temporary buffer
|
|
||||||
srcVertical = riFlatFile->data[0];
|
|
||||||
} else {
|
|
||||||
srcVertical = cfatmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp parallel
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
|
|
||||||
if (boxW > 0) {
|
|
||||||
//box blur cfa image; box size = BS
|
|
||||||
//horizontal blur
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp for
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int row = 0; row < H; row++) {
|
|
||||||
int len = boxW / 2 + 1;
|
|
||||||
cfatmp[row * W + 0] = riFlatFile->data[row][0] / len;
|
|
||||||
cfatmp[row * W + 1] = riFlatFile->data[row][1] / len;
|
|
||||||
|
|
||||||
for (int j = 2; j <= boxW; j += 2) {
|
|
||||||
cfatmp[row * W + 0] += riFlatFile->data[row][j] / len;
|
|
||||||
cfatmp[row * W + 1] += riFlatFile->data[row][j + 1] / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int col = 2; col <= boxW; col += 2) {
|
|
||||||
cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len + riFlatFile->data[row][boxW + col]) / (len + 1);
|
|
||||||
cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len + riFlatFile->data[row][boxW + col + 1]) / (len + 1);
|
|
||||||
len ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int col = boxW + 2; col < W - boxW; col++) {
|
|
||||||
cfatmp[row * W + col] = cfatmp[row * W + col - 2] + (riFlatFile->data[row][boxW + col] - cfatmp[row * W + col - boxW - 2]) / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int col = W - boxW; col < W; col += 2) {
|
|
||||||
cfatmp[row * W + col] = (cfatmp[row * W + col - 2] * len - cfatmp[row * W + col - boxW - 2]) / (len - 1);
|
|
||||||
|
|
||||||
if (col + 1 < W) {
|
|
||||||
cfatmp[row * W + col + 1] = (cfatmp[row * W + col - 1] * len - cfatmp[row * W + col - boxW - 1]) / (len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
len --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (boxH > 0) {
|
|
||||||
//vertical blur
|
|
||||||
#ifdef __SSE2__
|
|
||||||
vfloat leninitv = F2V(boxH / 2 + 1);
|
|
||||||
vfloat onev = F2V(1.0f);
|
|
||||||
vfloat temp1v, temp2v, temp3v, temp4v, lenv, lenp1v, lenm1v;
|
|
||||||
int row;
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp for nowait
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int col = 0; col < W - 7; col += 8) {
|
|
||||||
lenv = leninitv;
|
|
||||||
temp1v = LVFU(srcVertical[0 * W + col]) / lenv;
|
|
||||||
temp2v = LVFU(srcVertical[1 * W + col]) / lenv;
|
|
||||||
temp3v = LVFU(srcVertical[0 * W + col + 4]) / lenv;
|
|
||||||
temp4v = LVFU(srcVertical[1 * W + col + 4]) / lenv;
|
|
||||||
|
|
||||||
for (int i = 2; i < boxH + 2; i += 2) {
|
|
||||||
temp1v += LVFU(srcVertical[i * W + col]) / lenv;
|
|
||||||
temp2v += LVFU(srcVertical[(i + 1) * W + col]) / lenv;
|
|
||||||
temp3v += LVFU(srcVertical[i * W + col + 4]) / lenv;
|
|
||||||
temp4v += LVFU(srcVertical[(i + 1) * W + col + 4]) / lenv;
|
|
||||||
}
|
|
||||||
|
|
||||||
STVFU(cfablur[0 * W + col], temp1v);
|
|
||||||
STVFU(cfablur[1 * W + col], temp2v);
|
|
||||||
STVFU(cfablur[0 * W + col + 4], temp3v);
|
|
||||||
STVFU(cfablur[1 * W + col + 4], temp4v);
|
|
||||||
|
|
||||||
for (row = 2; row < boxH + 2; row += 2) {
|
|
||||||
lenp1v = lenv + onev;
|
|
||||||
temp1v = (temp1v * lenv + LVFU(srcVertical[(row + boxH) * W + col])) / lenp1v;
|
|
||||||
temp2v = (temp2v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col])) / lenp1v;
|
|
||||||
temp3v = (temp3v * lenv + LVFU(srcVertical[(row + boxH) * W + col + 4])) / lenp1v;
|
|
||||||
temp4v = (temp4v * lenv + LVFU(srcVertical[(row + boxH + 1) * W + col + 4])) / lenp1v;
|
|
||||||
STVFU(cfablur[row * W + col], temp1v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col], temp2v);
|
|
||||||
STVFU(cfablur[row * W + col + 4], temp3v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col + 4], temp4v);
|
|
||||||
lenv = lenp1v;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; row < H - boxH - 1; row += 2) {
|
|
||||||
temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv;
|
|
||||||
temp2v = temp2v + (LVFU(srcVertical[(row + 1 + boxH) * W + col]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col])) / lenv;
|
|
||||||
temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv;
|
|
||||||
temp4v = temp4v + (LVFU(srcVertical[(row + 1 + boxH) * W + col + 4]) - LVFU(srcVertical[(row + 1 - boxH - 2) * W + col + 4])) / lenv;
|
|
||||||
STVFU(cfablur[row * W + col], temp1v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col], temp2v);
|
|
||||||
STVFU(cfablur[row * W + col + 4], temp3v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col + 4], temp4v);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; row < H - boxH; row++) {
|
|
||||||
temp1v = temp1v + (LVFU(srcVertical[(row + boxH) * W + col]) - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenv;
|
|
||||||
temp3v = temp3v + (LVFU(srcVertical[(row + boxH) * W + col + 4]) - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenv;
|
|
||||||
STVFU(cfablur[row * W + col], temp1v);
|
|
||||||
STVFU(cfablur[row * W + col + 4], temp3v);
|
|
||||||
vfloat swapv = temp1v;
|
|
||||||
temp1v = temp2v;
|
|
||||||
temp2v = swapv;
|
|
||||||
swapv = temp3v;
|
|
||||||
temp3v = temp4v;
|
|
||||||
temp4v = swapv;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; row < H - 1; row += 2) {
|
|
||||||
lenm1v = lenv - onev;
|
|
||||||
temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v;
|
|
||||||
temp2v = (temp2v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col])) / lenm1v;
|
|
||||||
temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v;
|
|
||||||
temp4v = (temp4v * lenv - LVFU(srcVertical[(row - boxH - 1) * W + col + 4])) / lenm1v;
|
|
||||||
STVFU(cfablur[row * W + col], temp1v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col], temp2v);
|
|
||||||
STVFU(cfablur[row * W + col + 4], temp3v);
|
|
||||||
STVFU(cfablur[(row + 1)*W + col + 4], temp4v);
|
|
||||||
lenv = lenm1v;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; row < H; row++) {
|
|
||||||
lenm1v = lenv - onev;
|
|
||||||
temp1v = (temp1v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col])) / lenm1v;
|
|
||||||
temp3v = (temp3v * lenv - LVFU(srcVertical[(row - boxH - 2) * W + col + 4])) / lenm1v;
|
|
||||||
STVFU(cfablur[(row)*W + col], temp1v);
|
|
||||||
STVFU(cfablur[(row)*W + col + 4], temp3v);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp single
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int col = W - (W % 8); col < W; col++) {
|
|
||||||
int len = boxH / 2 + 1;
|
|
||||||
cfablur[0 * W + col] = srcVertical[0 * W + col] / len;
|
|
||||||
cfablur[1 * W + col] = srcVertical[1 * W + col] / len;
|
|
||||||
|
|
||||||
for (int i = 2; i < boxH + 2; i += 2) {
|
|
||||||
cfablur[0 * W + col] += srcVertical[i * W + col] / len;
|
|
||||||
cfablur[1 * W + col] += srcVertical[(i + 1) * W + col] / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = 2; row < boxH + 2; row += 2) {
|
|
||||||
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1);
|
|
||||||
cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1);
|
|
||||||
len ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = boxH + 2; row < H - boxH; row++) {
|
|
||||||
cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = H - boxH; row < H; row += 2) {
|
|
||||||
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1);
|
|
||||||
|
|
||||||
if (row + 1 < H) {
|
|
||||||
cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
len --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#pragma omp for
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int col = 0; col < W; col++) {
|
|
||||||
int len = boxH / 2 + 1;
|
|
||||||
cfablur[0 * W + col] = srcVertical[0 * W + col] / len;
|
|
||||||
cfablur[1 * W + col] = srcVertical[1 * W + col] / len;
|
|
||||||
|
|
||||||
for (int i = 2; i < boxH + 2; i += 2) {
|
|
||||||
cfablur[0 * W + col] += srcVertical[i * W + col] / len;
|
|
||||||
cfablur[1 * W + col] += srcVertical[(i + 1) * W + col] / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = 2; row < boxH + 2; row += 2) {
|
|
||||||
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len + srcVertical[(row + boxH) * W + col]) / (len + 1);
|
|
||||||
cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len + srcVertical[(row + boxH + 1) * W + col]) / (len + 1);
|
|
||||||
len ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = boxH + 2; row < H - boxH; row++) {
|
|
||||||
cfablur[row * W + col] = cfablur[(row - 2) * W + col] + (srcVertical[(row + boxH) * W + col] - srcVertical[(row - boxH - 2) * W + col]) / len;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int row = H - boxH; row < H; row += 2) {
|
|
||||||
cfablur[row * W + col] = (cfablur[(row - 2) * W + col] * len - srcVertical[(row - boxH - 2) * W + col]) / (len - 1);
|
|
||||||
|
|
||||||
if (row + 1 < H) {
|
|
||||||
cfablur[(row + 1)*W + col] = (cfablur[(row - 1) * W + col] * len - srcVertical[(row - boxH - 1) * W + col]) / (len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
len --;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmpBuffer) {
|
|
||||||
free(tmpBuffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Scale original pixels into the range 0 65535 using black offsets and multipliers
|
// Scale original pixels into the range 0 65535 using black offsets and multipliers
|
||||||
void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D<float> &rawData)
|
void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D<float> &rawData)
|
||||||
{
|
{
|
||||||
|
@ -138,9 +138,8 @@ public:
|
|||||||
return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified
|
return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified
|
||||||
}
|
}
|
||||||
|
|
||||||
void processFlatField(const RAWParams &raw, RawImage *riFlatFile, unsigned short black[4]);
|
void processFlatField(const RAWParams &raw, const RawImage *riFlatFile, const unsigned short black[4]);
|
||||||
void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData);
|
void copyOriginalPixels(const RAWParams &raw, RawImage *ri, RawImage *riDark, RawImage *riFlatFile, array2D<float> &rawData);
|
||||||
void cfaboxblur(RawImage *riFlatFile, float* cfablur, int boxH, int boxW);
|
|
||||||
void scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D<float> &rawData); // raw for cblack
|
void scaleColors(int winx, int winy, int winw, int winh, const RAWParams &raw, array2D<float> &rawData); // raw for cblack
|
||||||
|
|
||||||
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override;
|
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override;
|
||||||
|
@ -32,18 +32,17 @@ using namespace rtengine::procparams;
|
|||||||
FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_LABEL"))
|
FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_LABEL"))
|
||||||
{
|
{
|
||||||
hbff = Gtk::manage(new Gtk::HBox());
|
hbff = Gtk::manage(new Gtk::HBox());
|
||||||
hbff->set_spacing(2);
|
|
||||||
flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
|
flatFieldFile = Gtk::manage(new MyFileChooserButton(M("TP_FLATFIELD_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
|
||||||
bindCurrentFolder (*flatFieldFile, options.lastFlatfieldDir);
|
bindCurrentFolder (*flatFieldFile, options.lastFlatfieldDir);
|
||||||
ffLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE")));
|
ffLabel = Gtk::manage(new Gtk::Label(M("GENERAL_FILE")));
|
||||||
flatFieldFileReset = Gtk::manage(new Gtk::Button());
|
flatFieldFileReset = Gtk::manage(new Gtk::Button());
|
||||||
flatFieldFileReset->set_image (*Gtk::manage(new RTImage ("cancel-small.png")));
|
flatFieldFileReset->set_image (*Gtk::manage(new RTImage ("cancel-small.png")));
|
||||||
hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK, 0);
|
hbff->pack_start(*ffLabel, Gtk::PACK_SHRINK);
|
||||||
hbff->pack_start(*flatFieldFile);
|
hbff->pack_start(*flatFieldFile);
|
||||||
hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK, 0);
|
hbff->pack_start(*flatFieldFileReset, Gtk::PACK_SHRINK);
|
||||||
flatFieldAutoSelect = Gtk::manage(new Gtk::CheckButton((M("TP_FLATFIELD_AUTOSELECT"))));
|
flatFieldAutoSelect = Gtk::manage(new Gtk::CheckButton((M("TP_FLATFIELD_AUTOSELECT"))));
|
||||||
ffInfo = Gtk::manage(new Gtk::Label(""));
|
ffInfo = Gtk::manage(new Gtk::Label("-"));
|
||||||
ffInfo->set_alignment(0, 0); //left align
|
setExpandAlignProperties(ffInfo, true, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
|
||||||
flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"), 0, 200, 2, 32));
|
flatFieldBlurRadius = Gtk::manage(new Adjuster (M("TP_FLATFIELD_BLURRADIUS"), 0, 200, 2, 32));
|
||||||
flatFieldBlurRadius->setAdjusterListener (this);
|
flatFieldBlurRadius->setAdjusterListener (this);
|
||||||
|
|
||||||
@ -54,15 +53,14 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L
|
|||||||
flatFieldBlurRadius->show();
|
flatFieldBlurRadius->show();
|
||||||
|
|
||||||
Gtk::HBox* hbffbt = Gtk::manage (new Gtk::HBox ());
|
Gtk::HBox* hbffbt = Gtk::manage (new Gtk::HBox ());
|
||||||
hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") + ":")));
|
hbffbt->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_FLATFIELD_BLURTYPE") + ":")), Gtk::PACK_SHRINK);
|
||||||
hbffbt->set_spacing(4);
|
|
||||||
flatFieldBlurType = Gtk::manage (new MyComboBoxText ());
|
flatFieldBlurType = Gtk::manage (new MyComboBoxText ());
|
||||||
flatFieldBlurType->append(M("TP_FLATFIELD_BT_AREA"));
|
flatFieldBlurType->append(M("TP_FLATFIELD_BT_AREA"));
|
||||||
flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTICAL"));
|
flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTICAL"));
|
||||||
flatFieldBlurType->append(M("TP_FLATFIELD_BT_HORIZONTAL"));
|
flatFieldBlurType->append(M("TP_FLATFIELD_BT_HORIZONTAL"));
|
||||||
flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTHORIZ"));
|
flatFieldBlurType->append(M("TP_FLATFIELD_BT_VERTHORIZ"));
|
||||||
flatFieldBlurType->set_active(0);
|
flatFieldBlurType->set_active(0);
|
||||||
hbffbt->pack_end (*flatFieldBlurType);
|
hbffbt->pack_end (*flatFieldBlurType, Gtk::PACK_EXPAND_WIDGET);
|
||||||
|
|
||||||
flatFieldClipControl = Gtk::manage (new Adjuster(M("TP_FLATFIELD_CLIPCONTROL"), 0., 100., 1., 0.));
|
flatFieldClipControl = Gtk::manage (new Adjuster(M("TP_FLATFIELD_CLIPCONTROL"), 0., 100., 1., 0.));
|
||||||
flatFieldClipControl->setAdjusterListener(this);
|
flatFieldClipControl->setAdjusterListener(this);
|
||||||
@ -75,12 +73,12 @@ FlatField::FlatField () : FoldableToolPanel(this, "flatfield", M("TP_FLATFIELD_L
|
|||||||
flatFieldClipControl->show();
|
flatFieldClipControl->show();
|
||||||
flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP"));
|
flatFieldClipControl->set_tooltip_markup (M("TP_FLATFIELD_CLIPCONTROL_TOOLTIP"));
|
||||||
|
|
||||||
pack_start( *hbff, Gtk::PACK_SHRINK, 0);
|
pack_start( *hbff, Gtk::PACK_SHRINK);
|
||||||
pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK, 0);
|
pack_start( *flatFieldAutoSelect, Gtk::PACK_SHRINK);
|
||||||
pack_start( *ffInfo, Gtk::PACK_SHRINK, 0);
|
pack_start( *ffInfo, Gtk::PACK_SHRINK);
|
||||||
pack_start( *hbffbt, Gtk::PACK_SHRINK, 0);
|
pack_start( *hbffbt, Gtk::PACK_SHRINK);
|
||||||
pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK, 0);
|
pack_start( *flatFieldBlurRadius, Gtk::PACK_SHRINK);
|
||||||
pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK, 0);
|
pack_start( *flatFieldClipControl, Gtk::PACK_SHRINK);
|
||||||
|
|
||||||
flatFieldFileconn = flatFieldFile->signal_file_set().connect ( sigc::mem_fun(*this, &FlatField::flatFieldFileChanged)); //, true);
|
flatFieldFileconn = flatFieldFile->signal_file_set().connect ( sigc::mem_fun(*this, &FlatField::flatFieldFileChanged)); //, true);
|
||||||
flatFieldFileReset->signal_clicked().connect( sigc::mem_fun(*this, &FlatField::flatFieldFile_Reset), true );
|
flatFieldFileReset->signal_clicked().connect( sigc::mem_fun(*this, &FlatField::flatFieldFile_Reset), true );
|
||||||
@ -169,7 +167,7 @@ void FlatField::read(const rtengine::procparams::ProcParams* pp, const ParamsEdi
|
|||||||
ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND")));
|
ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ffInfo->set_text("");
|
ffInfo->set_text("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
ffChanged = false;
|
ffChanged = false;
|
||||||
@ -334,7 +332,7 @@ void FlatField::flatFieldFile_Reset()
|
|||||||
flatFieldFile->set_current_folder(options.lastFlatfieldDir);
|
flatFieldFile->set_current_folder(options.lastFlatfieldDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
ffInfo->set_text("");
|
ffInfo->set_text("-");
|
||||||
|
|
||||||
if (listener) {
|
if (listener) {
|
||||||
listener->panelChanged (EvFlatFieldFile, M("GENERAL_NONE") );
|
listener->panelChanged (EvFlatFieldFile, M("GENERAL_NONE") );
|
||||||
@ -384,7 +382,7 @@ void FlatField::flatFieldAutoSelectChanged()
|
|||||||
ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND")));
|
ffInfo->set_text(Glib::ustring(M("TP_PREPROCESS_NO_FOUND")));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ffInfo->set_text("");
|
ffInfo->set_text("-");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listener) {
|
if (listener) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user