Add flat field correction for monochrome raw files

This commit is contained in:
heckflosse 2018-03-09 14:51:28 +01:00
parent 9e05e18c8f
commit 84f46eaab6
9 changed files with 61 additions and 25 deletions

View File

@ -138,7 +138,7 @@ void ffInfo::updateRawImage()
int H = ri->get_height(); int H = ri->get_height();
int W = ri->get_width(); int W = ri->get_width();
ri->compress_image(0); ri->compress_image(0);
int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS) ? 1 : 3); int rSize = W * ((ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) ? 1 : 3);
acc_t **acc = new acc_t*[H]; acc_t **acc = new acc_t*[H];
for( int row = 0; row < H; row++) { for( int row = 0; row < H; row++) {
@ -160,7 +160,7 @@ void ffInfo::updateRawImage()
temp->compress_image(0); //\ TODO would be better working on original, because is temporary temp->compress_image(0); //\ TODO would be better working on original, because is temporary
nFiles++; nFiles++;
if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS ) { if( ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1 ) {
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++) {
acc[row][col] += temp->data[row][col]; acc[row][col] += temp->data[row][col];

View File

@ -87,6 +87,7 @@ public:
// use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat*
virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hlp, const RAWParams &raw) = 0; virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hlp, const RAWParams &raw) = 0;
virtual eSensorType getSensorType () const = 0; virtual eSensorType getSensorType () const = 0;
virtual bool isMono () const = 0;
// true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource // true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource
virtual bool isWBProviderReady () = 0; virtual bool isWBProviderReady () = 0;

View File

@ -215,7 +215,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
// If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST // If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST
if (imageTypeListener) { if (imageTypeListener) {
imageTypeListener->imageTypeChanged (imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS); imageTypeListener->imageTypeChanged (imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono());
} }
if ( (todo & M_RAW) if ( (todo & M_RAW)

View File

@ -2815,7 +2815,7 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
cfaboxblur(riFlatFile, cfablur, BS, BS); cfaboxblur(riFlatFile, cfablur, BS, BS);
} }
if(ri->getSensorType() == ST_BAYER) { if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
float refcolor[2][2]; float refcolor[2][2];
//find centre average values by channel //find centre average values by channel
@ -2823,8 +2823,8 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
for (int n = 0; n < 2; n++) { for (int n = 0; n < 2; n++) {
int row = 2 * (H >> 2) + m; int row = 2 * (H >> 2) + m;
int col = 2 * (W >> 2) + n; int col = 2 * (W >> 2) + n;
int c = FC(row, col); int c = ri->get_colors() != 1 ? FC(row, col) : 0;
int c4 = ( c == 1 && !(row & 1) ) ? 3 : c; 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]); refcolor[m][n] = max(0.0f, cfablur[row * W + col] - black[c4]);
} }
@ -2836,8 +2836,8 @@ 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++) {
float maxval = 0.f; float maxval = 0.f;
int c = FC(m, n); int c = ri->get_colors() != 1 ? FC(m, n) : 0;
int c4 = ( c == 1 && !(m & 1) ) ? 3 : c; int c4 = ri->get_colors() != 1 ? (( c == 1 && !(m & 1) ) ? 3 : c) : 0;
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel #pragma omp parallel
#endif #endif
@ -2886,13 +2886,20 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
refcolor[m][n] *= limitFactor; refcolor[m][n] *= limitFactor;
} }
unsigned int c[2][2] {};
unsigned int c[2][2] = {{FC(0, 0), FC(0, 1)}, {FC(1, 0), FC(1, 1)}}; unsigned int c4[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][0] = ( c[0][0] == 1) ? 3 : c[0][0];
c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1]; c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1];
c4[1][0] = c[1][0]; c4[1][0] = c[1][0];
c4[1][1] = c[1][1]; c4[1][1] = c[1][1];
}
#ifdef __SSE2__ #ifdef __SSE2__
vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]), vfloat refcolorv[2] = {_mm_set_ps(refcolor[0][1], refcolor[0][0], refcolor[0][1], refcolor[0][0]),
@ -3016,13 +3023,20 @@ void RawImageSource::processFlatField(const RAWParams &raw, RawImage *riFlatFile
cfaboxblur(riFlatFile, cfablur1, 0, 2 * BS); //now do horizontal blur cfaboxblur(riFlatFile, cfablur1, 0, 2 * BS); //now do horizontal blur
cfaboxblur(riFlatFile, cfablur2, 2 * BS, 0); //now do vertical blur cfaboxblur(riFlatFile, cfablur2, 2 * BS, 0); //now do vertical blur
if(ri->getSensorType() == ST_BAYER) { if(ri->getSensorType() == ST_BAYER || ri->get_colors() == 1) {
unsigned int c[2][2] = {{FC(0, 0), FC(0, 1)}, {FC(1, 0), FC(1, 1)}}; unsigned int c[2][2] {};
unsigned int c4[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][0] = ( c[0][0] == 1) ? 3 : c[0][0];
c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1]; c4[0][1] = ( c[0][1] == 1) ? 3 : c[0][1];
c4[1][0] = c[1][0]; c4[1][0] = c[1][0];
c4[1][1] = c[1][1]; c4[1][1] = c[1][1];
}
#ifdef __SSE2__ #ifdef __SSE2__
vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]), vfloat blackv[2] = {_mm_set_ps(black[c4[0][1]], black[c4[0][0]], black[c4[0][1]], black[c4[0][0]]),
@ -3140,6 +3154,9 @@ void RawImageSource::copyOriginalPixels(const RAWParams &raw, RawImage *src, Raw
} }
} }
} }
if (riFlatFile && W == riFlatFile->get_width() && H == riFlatFile->get_height()) {
processFlatField(raw, riFlatFile, black);
} // flatfield
} else { } else {
// No bayer pattern // No bayer pattern
// TODO: Is there a flat field correction possible? // TODO: Is there a flat field correction possible?

View File

@ -145,6 +145,10 @@ public:
{ {
return ri != nullptr ? ri->getSensorType() : ST_NONE; return ri != nullptr ? ri->getSensorType() : ST_NONE;
} }
bool isMono () const
{
return ri->get_colors() == 1;
}
ColorTemp getWB () const ColorTemp getWB () const
{ {
return camera_wb; return camera_wb;

View File

@ -359,7 +359,7 @@ class ImageTypeListener
{ {
public : public :
virtual ~ImageTypeListener() = default; virtual ~ImageTypeListener() = default;
virtual void imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans) = 0; virtual void imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans, bool is_Mono = false) = 0;
}; };
class WaveletListener class WaveletListener

View File

@ -52,6 +52,7 @@ public:
ColorTemp getSpotWB (std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, int tran, double equal); ColorTemp getSpotWB (std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, int tran, double equal);
eSensorType getSensorType() const {return ST_NONE;} eSensorType getSensorType() const {return ST_NONE;}
bool isMono() const {return false;}
bool isWBProviderReady () bool isWBProviderReady ()
{ {

View File

@ -261,7 +261,7 @@ ToolPanelCoordinator::~ToolPanelCoordinator ()
delete toolBar; delete toolBar;
} }
void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans) void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans, bool isMono)
{ {
if (isRaw) { if (isRaw) {
if (isBayer) { if (isBayer) {
@ -292,7 +292,20 @@ void ToolPanelCoordinator::imageTypeChanged (bool isRaw, bool isBayer, bool isXt
}; };
idle_register.add(func, this); idle_register.add(func, this);
} }
else { else if (isMono) {
const auto func = [](gpointer data) -> gboolean {
ToolPanelCoordinator* const self = static_cast<ToolPanelCoordinator*>(data);
self->rawPanelSW->set_sensitive (true);
self->sensorbayer->FoldableToolPanel::hide();
self->sensorxtrans->FoldableToolPanel::hide();
self->preprocess->FoldableToolPanel::hide();
self->flatfield->FoldableToolPanel::show();
return FALSE;
};
idle_register.add(func, this);
} else {
const auto func = [](gpointer data) -> gboolean { const auto func = [](gpointer data) -> gboolean {
ToolPanelCoordinator* const self = static_cast<ToolPanelCoordinator*>(data); ToolPanelCoordinator* const self = static_cast<ToolPanelCoordinator*>(data);

View File

@ -218,7 +218,7 @@ public:
// toolpanellistener interface // toolpanellistener interface
void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr); void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr);
void imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans); void imageTypeChanged (bool isRaw, bool isBayer, bool isXtrans, bool isMono = false);
// profilechangelistener interface // profilechangelistener interface
void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = nullptr); void profileChange (const rtengine::procparams::PartialProfile* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited = nullptr);
void setDefaults (rtengine::procparams::ProcParams* defparams); void setDefaults (rtengine::procparams::ProcParams* defparams);