Optimization for dark frames and hot/dead pixel detection/interpolation, Issue 2486

This commit is contained in:
Ingo 2014-09-10 14:55:58 +02:00
parent 7d16d8e422
commit 13a49eb7b3
20 changed files with 343 additions and 154 deletions

View File

@ -8,6 +8,7 @@ Developement contributors, in last name alphabetical order:
Martin Burri
Javier Celaya
Jacques Desmis
Pavlov Dmitry
Oliver Duis
Maciek Dworak
Michael Ezra
@ -36,6 +37,7 @@ Other contributors (profiles, ideas, mockups, testing, forum activity, translati
Thorsten Bartolomäus
Patrik Brunner
Fernando Carello
Pat David
Reine Edvardsson
André Gauthier
Sébastien Guyader

View File

@ -623,7 +623,8 @@ PARTIALPASTE_METAICMGROUP;Gruppe Metadaten / ICM
PARTIALPASTE_PCVIGNETTE;Vignettierungsfilter
PARTIALPASTE_PERSPECTIVE;Perspektive
PARTIALPASTE_PREPROCESS_GREENEQUIL;Vorverarbeitung: Grün-Ausgleich
PARTIALPASTE_PREPROCESS_HOTDEADPIXFILT;Vorverarbeitung: Hot/Dead-Pixel-Filter anwenden
PARTIALPASTE_PREPROCESS_HOTPIXFILT;Vorverarbeitung: Hot-Pixel-Filter
PARTIALPASTE_PREPROCESS_DEADPIXFILT;Vorverarbeitung: Dead-Pixel-Filter
PARTIALPASTE_PREPROCESS_LINEDENOISE;Vorverarbeitung: Zeilenrauschfilter
PARTIALPASTE_RAWCACORR_AUTO;Chromatische Aberration: Automatische Korrektur
PARTIALPASTE_RAWCACORR_CABLUE;Chromatische Aberration: Blau
@ -633,7 +634,7 @@ PARTIALPASTE_RAWEXPOS_LINEAR;RAW-Weiß/Schwarz-Punkt: Linearer Korrekturfaktor
PARTIALPASTE_RAWEXPOS_PRESER;RAW-Weiß/Schwarz-Punkt: Lichter bewahren (EV)
PARTIALPASTE_RAWGROUP;Gruppe RAW
PARTIALPASTE_RAW_ALLENHANCE;Farbinterpolation: Artifakt-/Rauschminderung
PARTIALPASTE_RAW_DCBENHANCE;Farbinterpolation: DCB-Verfeinerungsschritt durchführen
PARTIALPASTE_RAW_DCBENHANCE;Farbinterpolation: DCB-Verfeinerungsschritt
PARTIALPASTE_RAW_DCBITERATIONS;Farbinterpolation: Anzahl der DCB-Iterationen
PARTIALPASTE_RAW_DMETHOD;Farbinterpolation: Methode
PARTIALPASTE_RAW_FALSECOLOR;Farbinterpolation: Falschfarbenunterdrückung Stufen
@ -1206,7 +1207,8 @@ TP_PERSPECTIVE_HORIZONTAL;Horizontal
TP_PERSPECTIVE_LABEL;Perspektive
TP_PERSPECTIVE_VERTICAL;Vertikal
TP_PREPROCESS_GREENEQUIL;Grün-Ausgleich
TP_PREPROCESS_HOTDEADPIXFILT;Hot/Dead-Pixel-Filter anwenden
TP_PREPROCESS_HOTPIXFILT;Hot-Pixel-Filter
TP_PREPROCESS_DEADPIXFILT;Dead-Pixel-Filter
TP_PREPROCESS_HOTDEADPIXTHRESH;Hot/Dead-Pixel-Erkennung\nSchwellenwert
TP_PREPROCESS_LABEL;Vorverarbeitung
TP_PREPROCESS_LINEDENOISE;Zeilenrauschfilter
@ -1223,7 +1225,7 @@ TP_RAWEXPOS_LINEAR;Weißpunkt: Linearer\nKorrekturfaktor
TP_RAWEXPOS_PRESER;Weißpunkt: Lichter\nbewahrende Korrektur (EV)
TP_RAWEXPOS_TWOGREEN;Grün-Werte automatisch angleichen
TP_RAW_ALLENHANCE;Artifakt-/Rauschminderung nach\nFarbinterpolation durchführen
TP_RAW_DCBENHANCE;DCB-Verfeinerungsschritt durchführen
TP_RAW_DCBENHANCE;DCB-Verfeinerungsschritt
TP_RAW_DCBITERATIONS;Anzahl der DCB-Iterationen
TP_RAW_DMETHOD;Methode
TP_RAW_FALSECOLOR;Falschfarbenunterdrückung\nStufen

View File

@ -690,7 +690,8 @@ PARTIALPASTE_METAICMGROUP;Réglages des Métadonnées/ICM
PARTIALPASTE_PCVIGNETTE;Filtre Vignettage
PARTIALPASTE_PERSPECTIVE;Perspective
PARTIALPASTE_PREPROCESS_GREENEQUIL;Équilibrage du vert
PARTIALPASTE_PREPROCESS_HOTDEADPIXFILT;Filtrage des pixels chauds/morts
PARTIALPASTE_PREPROCESS_HOTPIXFILT;Filtrage des pixels chauds
PARTIALPASTE_PREPROCESS_DEADPIXFILT;Filtrage des pixels morts
PARTIALPASTE_PREPROCESS_LINEDENOISE;Filtre de bruit de ligne
PARTIALPASTE_RAWCACORR_AUTO;Corr. auto. de l'aberr. chromatique
PARTIALPASTE_RAWCACORR_CABLUE;Aberr. chromatique bleu
@ -1360,8 +1361,10 @@ TP_PERSPECTIVE_VERTICAL;Verticale
TP_PFCURVE_CURVEEDITOR_CH;Teinte
TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Contrôle la force du défrangeage en fonction de la couleur. En haut = action maxi, en bas = pas d'action sur la couleur.
TP_PREPROCESS_GREENEQUIL;Équilibrage du vert
TP_PREPROCESS_HOTDEADPIXFILT;Filtrer les pixels chauds/morts
TP_PREPROCESS_HOTDEADPIXFILT_TOOLTIP;Essaie de supprimer les pixels chauds/morts
TP_PREPROCESS_HOTPIXFILT;Filtrer les pixels chauds
TP_PREPROCESS_DEADPIXFILT;Filtrer les pixels morts
TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Essaie de supprimer les pixels chauds
TP_PREPROCESS_DEADPIXFILT_TOOLTIP;Essaie de supprimer les pixels morts
TP_PREPROCESS_LABEL;Traitement pre-dématriçage
TP_PREPROCESS_LINEDENOISE;Filtre de bruit de ligne
TP_PREPROCESS_NO_FOUND;Aucun trouvé

View File

@ -319,7 +319,7 @@ HISTORY_MSG_95;Lab - Chromaticity
HISTORY_MSG_96;'a' Curve
HISTORY_MSG_97;'b' Curve
HISTORY_MSG_98;Demosaicing Method
HISTORY_MSG_99;Hot/Dead pixel filter
HISTORY_MSG_99;Hot pixel filter
HISTORY_MSG_100;Saturation
HISTORY_MSG_101;HSV - Hue
HISTORY_MSG_102;HSV - Saturation
@ -517,6 +517,7 @@ HISTORY_MSG_294;Film Simulation - Strength
HISTORY_MSG_295;Film Simulation - Film
HISTORY_MSG_296;NR - Modulate luminance
HISTORY_MSG_297;NR - Quality
HISTORY_MSG_298;Dead pixel filter
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: <b>Alt-s</b>
HISTORY_SNAPSHOTS;Snapshots
@ -686,7 +687,8 @@ PARTIALPASTE_METAICMGROUP;Metadata/Color Management Settings
PARTIALPASTE_PCVIGNETTE;Vignette filter
PARTIALPASTE_PERSPECTIVE;Perspective
PARTIALPASTE_PREPROCESS_GREENEQUIL;Green equilibration
PARTIALPASTE_PREPROCESS_HOTDEADPIXFILT;Apply hot/dead pixel filter
PARTIALPASTE_PREPROCESS_HOTPIXFILT;Apply hot pixel filter
PARTIALPASTE_PREPROCESS_DEADPIXFILT;Apply dead pixel filter
PARTIALPASTE_PREPROCESS_LINEDENOISE;Line noise filter
PARTIALPASTE_RAWCACORR_AUTO;CA auto-correction
PARTIALPASTE_RAWCACORR_CABLUE;CA blue
@ -1376,8 +1378,10 @@ TP_PERSPECTIVE_VERTICAL;Vertical
TP_PFCURVE_CURVEEDITOR_CH;Hue
TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Controls defringe strength by color.\nHigher = more,\nLower = less.
TP_PREPROCESS_GREENEQUIL;Green Equilibration
TP_PREPROCESS_HOTDEADPIXFILT;Hot/Dead pixel filter
TP_PREPROCESS_HOTDEADPIXFILT_TOOLTIP;Tries to suppress hot and dead pixels.
TP_PREPROCESS_HOTPIXFILT;Hot pixel filter
TP_PREPROCESS_HOTPIXFILT_TOOLTIP;Tries to suppress hot pixels.
TP_PREPROCESS_DEADPIXFILT;Dead pixel filter
TP_PREPROCESS_DEADPIXFILT_TOOLTIP;Tries to suppress dead pixels.
TP_PREPROCESS_LABEL;Preprocessing
TP_PREPROCESS_LINEDENOISE;Line Noise Filter
TP_PREPROCESS_NO_FOUND;None found

View File

@ -95,7 +95,7 @@ RawImage* dfInfo::getRawImage()
return ri;
}
std::list<badPix>& dfInfo::getHotPixels()
std::vector<badPix>& dfInfo::getHotPixels()
{
if( !ri ){
updateRawImage();
@ -172,26 +172,36 @@ void dfInfo::updateRawImage()
void dfInfo::updateBadPixelList( RawImage *df )
{
const int threshold=10;
const float threshold=10.f/8.f;
if( ri->getSensorType()!=ST_NONE ){
std::vector<badPix> badPixelsTemp;
#pragma omp parallel
{
std::vector<badPix> badPixelsThread;
#pragma omp for nowait
for( int row=2; row<df->get_height()-2; row++)
for( int col=2; col < df->get_width()-2; col++){
int m = (df->data[row-2][col-2] + df->data[row-2][col] + df->data[row-2][col+2]+
float m = (df->data[row-2][col-2] + df->data[row-2][col] + df->data[row-2][col+2]+
df->data[row][col-2] + df->data[row][col+2]+
df->data[row+2][col-2] + df->data[row+2][col] + df->data[row+2][col+2])/8;
if( df->data[row][col]/threshold > m )
badPixels.push_back( badPix(col,row) );
df->data[row+2][col-2] + df->data[row+2][col] + df->data[row+2][col+2]);
if( df->data[row][col] > m*threshold )
badPixelsThread.push_back( badPix(col,row) );
}
#pragma omp critical
badPixelsTemp.insert(badPixelsTemp.end(),badPixelsThread.begin(),badPixelsThread.end());
}
badPixels.insert(badPixels.end(),badPixelsTemp.begin(),badPixelsTemp.end());
}else{
for( int row=1; row<df->get_height()-1; row++)
for( int col=1; col < df->get_width()-1; col++){
int m[3];
float m[3];
for( int c=0; c<3;c++){
m[c] = (df->data[row-1][3*(col-1)+c] + df->data[row-1][3*col+c] + df->data[row-1][3*(col+1)+c]+
df->data[row] [3*(col-1)+c] + df->data[row] [3*col+c]+
df->data[row+1][3*(col-1)+c] + df->data[row+1][3*col+c] + df->data[row+1][3*(col+1)+c])/8;
df->data[row+1][3*(col-1)+c] + df->data[row+1][3*col+c] + df->data[row+1][3*(col+1)+c]);
}
if( df->data[row][3*col]/threshold > m[0] || df->data[row][3*col+1]/threshold > m[1] || df->data[row][3*col+2]/threshold > m[2])
if( df->data[row][3*col] > m[0]*threshold || df->data[row][3*col+1] > m[1]*threshold || df->data[row][3*col+2] > m[2]*threshold)
badPixels.push_back( badPix(col,row) );
}
}
@ -367,7 +377,7 @@ RawImage* DFManager::searchDarkFrame( const Glib::ustring filename )
return df->getRawImage();
return 0;
}
std::list<badPix> *DFManager::getHotPixels ( const Glib::ustring filename )
std::vector<badPix> *DFManager::getHotPixels ( const Glib::ustring filename )
{
for ( dfList_t::iterator iter = dfList.begin(); iter != dfList.end();iter++ ){
if( iter->second.pathname.compare( filename )==0 )
@ -375,7 +385,7 @@ std::list<badPix> *DFManager::getHotPixels ( const Glib::ustring filename )
}
return 0;
}
std::list<badPix> *DFManager::getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
std::vector<badPix> *DFManager::getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t )
{
dfInfo *df = find( mak, mod, iso, shut, t );
if( df ){
@ -408,13 +418,21 @@ int DFManager::scanBadPixelsFile( Glib::ustring filename )
dirpos1= dirpos2;
std::string makmodel(filename,dirpos1+1,lastdot-(dirpos1+1) );
std::list<badPix> bp;
std::vector<badPix> bp;
char line[256];
while( fgets(line,sizeof(line),file ) ){
if(fgets(line,sizeof(line),file )) {
int x,y;
if( sscanf(line,"%d %d",&x,&y) == 2 )
bp.push_back( badPix(x,y) );
}
int offset = 0;
int numparms = sscanf(line,"%d %d",&x,&y);
if( numparms == 1 ) // only one number in first line means, that this is the offset.
offset = x;
else if(numparms == 2)
bp.push_back( badPix(x+offset,y+offset) );
while( fgets(line,sizeof(line),file ) ){
if( sscanf(line,"%d %d",&x,&y) == 2 )
bp.push_back( badPix(x+offset,y+offset) );
}
}
int numPixels = bp.size();
if( numPixels >0 )
bpList[ makmodel ] = bp;
@ -422,21 +440,42 @@ int DFManager::scanBadPixelsFile( Glib::ustring filename )
return numPixels;
}
std::list<badPix> *DFManager::getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial)
std::vector<badPix> *DFManager::getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial)
{
std::ostringstream s;
s << mak << " " <<mod;
if( !serial.empty())
s << " " << serial;
bpList_t::iterator iter = bpList.find( s.str() );
if( iter != bpList.end() ){
bpList_t::iterator iter;
bool found = false;
if( !serial.empty() ) {
// search with sreial number first
std::ostringstream s;
s << mak << " " << mod << " " << serial;
iter = bpList.find( s.str() );
if( iter != bpList.end() )
found = true;
if( settings->verbose )
printf("Found:%s.badpixels in list\n",s.str().c_str());
if(found)
printf("%s.badpixels found\n",s.str().c_str());
else
printf("%s.badpixels not found\n",s.str().c_str());
}
if(!found) {
// search without serial number
std::ostringstream s;
s << mak << " " <<mod;
iter = bpList.find( s.str() );
if( iter != bpList.end() )
found = true;
if( settings->verbose )
if(found)
printf("%s.badpixels found\n",s.str().c_str());
else
printf("%s.badpixels not found\n",s.str().c_str());
}
if(!found) {
return 0;
} else {
return &(iter->second);
}
if( settings->verbose )
printf("%s.badpixels not found\n",s.str().c_str());
return 0;
}
// Global variable

View File

@ -55,11 +55,11 @@ public:
std::string key(){ return key( maker,model,iso,shutter); }
RawImage *getRawImage();
std::list<badPix> &getHotPixels();
std::vector<badPix> &getHotPixels();
protected:
RawImage *ri; ///< Dark Frame raw data
std::list<badPix> badPixels; ///< Extracted hot pixels
std::vector<badPix> badPixels; ///< Extracted hot pixels
void updateBadPixelList( RawImage *df );
void updateRawImage();
@ -73,13 +73,13 @@ public:
void getStat( int &totFiles, int &totTemplate);
RawImage *searchDarkFrame( const std::string &mak, const std::string &mod, int iso, double shut, time_t t );
RawImage *searchDarkFrame( const Glib::ustring filename );
std::list<badPix> *getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t );
std::list<badPix> *getHotPixels ( const Glib::ustring filename );
std::list<badPix> *getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial);
std::vector<badPix> *getHotPixels ( const std::string &mak, const std::string &mod, int iso, double shut, time_t t );
std::vector<badPix> *getHotPixels ( const Glib::ustring filename );
std::vector<badPix> *getBadPixels ( const std::string &mak, const std::string &mod, const std::string &serial);
protected:
typedef std::multimap<std::string,dfInfo> dfList_t;
typedef std::map<std::string, std::list<badPix> > bpList_t;
typedef std::map<std::string, std::vector<badPix> > bpList_t;
dfList_t dfList;
bpList_t bpList;
bool initialized;

View File

@ -155,7 +155,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
rp.bayersensor.ccSteps = 0;
rp.xtranssensor.ccSteps = 0;
rp.hotdeadpix_filt = false;
rp.deadPixelFilter = rp.hotPixelFilter = false;
}
progress ("Applying white balance, color correction & sRGB conversion...",100*readyphase/numofphases);

View File

@ -120,7 +120,7 @@ enum ProcEvent {
EvLaCurve=95,
EvLbCurve=96,
EvDemosaicMethod=97,
EvPreProcessHotDeadPixel=98,
EvPreProcessHotPixel=98,
EvSaturation=99,
EvHSVEqualizerH=100,
EvHSVEqualizerS=101,
@ -322,6 +322,7 @@ enum ProcEvent {
EvFilmSimulationFilename=294,
EvDPDNLCurve=295,
EvDPDNsmet=296,
EvPreProcessDeadPixel=297,
NUMOFEVENTS
};

View File

@ -835,7 +835,8 @@ void ProcParams::setDefaults () {
raw.cared = 0;
raw.cablue = 0;
raw.ca_autocorrect = false;
raw.hotdeadpix_filt = false;
raw.hotPixelFilter = false;
raw.deadPixelFilter = false;
raw.hotdeadpix_thresh = 40;
exif.clear ();
iptc.clear ();
@ -1494,7 +1495,8 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, bool fnameAbsol
if (!pedited || pedited->raw.caCorrection) keyFile.set_boolean ("RAW", "CA", raw.ca_autocorrect );
if (!pedited || pedited->raw.caRed) keyFile.set_double ("RAW", "CARed", raw.cared );
if (!pedited || pedited->raw.caBlue) keyFile.set_double ("RAW", "CABlue", raw.cablue );
if (!pedited || pedited->raw.hotDeadPixelFilter) keyFile.set_boolean ("RAW", "HotDeadPixels", raw.hotdeadpix_filt );
if (!pedited || pedited->raw.hotPixelFilter) keyFile.set_boolean ("RAW", "HotPixelFilter", raw.hotPixelFilter );
if (!pedited || pedited->raw.deadPixelFilter) keyFile.set_boolean ("RAW", "DeadPixelFilter", raw.deadPixelFilter );
if (!pedited || pedited->raw.hotDeadPixelThresh) keyFile.set_integer ("RAW", "HotDeadPixelThresh", raw.hotdeadpix_thresh );
if (!pedited || pedited->raw.bayersensor.method) keyFile.set_string ("RAW Bayer", "Method", raw.bayersensor.method );
@ -2201,7 +2203,11 @@ if (keyFile.has_group ("RAW")) {
if (keyFile.has_key ("RAW", "CA")) { raw.ca_autocorrect = keyFile.get_boolean ("RAW", "CA" ); if (pedited) pedited->raw.caCorrection = true; }
if (keyFile.has_key ("RAW", "CARed")) { raw.cared = keyFile.get_double ("RAW", "CARed" ); if (pedited) pedited->raw.caRed = true; }
if (keyFile.has_key ("RAW", "CABlue")) { raw.cablue = keyFile.get_double ("RAW", "CABlue" ); if (pedited) pedited->raw.caBlue = true; }
if (keyFile.has_key ("RAW", "HotDeadPixels")) { raw.hotdeadpix_filt = keyFile.get_boolean ("RAW", "HotDeadPixels" ); if (pedited) pedited->raw.hotDeadPixelFilter = true; }
// for compatibility to elder pp3 versions
if (keyFile.has_key ("RAW", "HotDeadPixels")) { raw.deadPixelFilter = raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotDeadPixels" ); if (pedited) pedited->raw.hotPixelFilter = pedited->raw.deadPixelFilter = true; }
if (keyFile.has_key ("RAW", "HotPixelFilter")) { raw.hotPixelFilter = keyFile.get_boolean ("RAW", "HotPixelFilter" ); if (pedited) pedited->raw.hotPixelFilter = true; }
if (keyFile.has_key ("RAW", "DeadPixelFilter")) { raw.deadPixelFilter = keyFile.get_boolean ("RAW", "DeadPixelFilter" ); if (pedited) pedited->raw.deadPixelFilter = true; }
if (keyFile.has_key ("RAW", "HotDeadPixelThresh")) { raw.hotdeadpix_thresh = keyFile.get_integer ("RAW", "HotDeadPixelThresh" ); if (pedited) pedited->raw.hotDeadPixelThresh = true; }
if (keyFile.has_key ("RAW", "PreExposure")) { raw.expos =keyFile.get_double("RAW", "PreExposure"); if (pedited) pedited->raw.exPos = true; }
if (keyFile.has_key ("RAW", "PrePreserv")) { raw.preser =keyFile.get_double("RAW", "PrePreserv"); if (pedited) pedited->raw.exPreser = true; }
@ -2570,7 +2576,8 @@ bool ProcParams::operator== (const ProcParams& other) {
&& raw.ca_autocorrect == other.raw.ca_autocorrect
&& raw.cared == other.raw.cared
&& raw.cablue == other.raw.cablue
&& raw.hotdeadpix_filt == other.raw.hotdeadpix_filt
&& raw.hotPixelFilter == other.raw.hotPixelFilter
&& raw.deadPixelFilter == other.raw.deadPixelFilter
&& raw.hotdeadpix_thresh == other.raw.hotdeadpix_thresh
&& icm.input == other.icm.input
&& icm.toneCurve == other.icm.toneCurve

View File

@ -947,7 +947,8 @@ class RAWParams {
double expos;
double preser;
bool hotdeadpix_filt;
bool hotPixelFilter;
bool deadPixelFilter;
int hotdeadpix_thresh;
};

View File

@ -20,7 +20,6 @@
#define __RAWIMAGE_H
#include <ctime>
#include <glibmm.h>
#include "dcraw.h"
#include "imageio.h"
@ -28,9 +27,9 @@ namespace rtengine {
struct badPix
{
int x;
int y;
badPix( int xc, int yc ):x(xc),y(yc){}
uint16_t x;
uint16_t y;
badPix( uint16_t xc, uint16_t yc ):x(xc),y(yc){}
};
class PixelsMap{
@ -66,12 +65,12 @@ public:
}
// set pixels from a list
int set( std::list<badPix> &bp)
int set( std::vector<badPix> &bp)
{
int totSet=0;
for(std::list<badPix>::iterator iter = bp.begin(); iter != bp.end(); iter++,totSet++)
for(std::vector<badPix>::iterator iter = bp.begin(); iter != bp.end(); ++iter)
set( iter->x,iter->y);
return totSet;
return bp.size();
}
void clear(){
@ -156,6 +155,8 @@ public:
int get_thumbBPS(){ return thumb_load_raw ? 16 : 8; }
bool get_thumbSwap() const;
unsigned get_thumbLength(){ return thumb_length;}
bool zeroIsBad() {return zero_is_bad == 1 ? true : false;}
public:
// dcraw functions
void scale_colors(){ if(isXtrans()) clearXtransCblack( ); DCraw::scale_colors(); }

View File

@ -456,13 +456,14 @@ void RawImageSource::convertColorSpace(Imagefloat* image, ColorManagementParams
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/* cfaCleanFromMap: correct raw pixels looking at the bitmap
/* interpolateBadPixels: correct raw pixels looking at the bitmap
* takes into consideration if there are multiple bad pixels in the neighborhood
*/
int RawImageSource::cfaCleanFromMap( PixelsMap &bitmapBads )
int RawImageSource::interpolateBadPixels( PixelsMap &bitmapBads )
{
float eps=1.0;
static const float eps=1.f;
int counter=0;
#pragma omp parallel for reduction(+:counter) schedule(dynamic,16)
for( int row = 2; row < H-2; row++ ){
for(int col = 2; col <W-2; col++ ){
int sk = bitmapBads.skipIfZero(col,row); //optimization for a stripe all zero
@ -470,32 +471,90 @@ int RawImageSource::cfaCleanFromMap( PixelsMap &bitmapBads )
col +=sk-1; //-1 is because of col++ in cycle
continue;
}
if( ! bitmapBads.get(col,row ) )
if(!bitmapBads.get(col,row))
continue;
double wtdsum=0,norm=0,sum=0,tot=0;
for( int dy=-2;dy<=2;dy+=2){
for( int dx=-2;dx<=2;dx+=2){
if (dy==0 && dx==0) continue;
if( bitmapBads.get(col+dx,row+dy) ) continue;
sum += rawData[row+dy][col+dx];
tot++;
if (bitmapBads.get(col-dx,row-dy)) continue;
float wtdsum=0.f,norm=0.f;
double dirwt = 1/( fabs( rawData[row+dy][col+dx]- rawData[row-dy][col-dx])+eps);
wtdsum += dirwt* rawData[row+dy][col+dx];
// diagonal interpolation
if(FC(row,col)==1) {
// green channel. We can use closer pixels than for red or blue channel. Distance to center pixel is sqrt(2) => weighting is 0.70710678
// For green channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
// 0 0 0 0 0
// 0 1 0 1 0
// 0 0 0 0 0
// 0 1 0 1 0
// 0 0 0 0 0
for( int dx=-1;dx<=1;dx+=2){
if( bitmapBads.get(col+dx,row-1) || bitmapBads.get(col-dx,row+1))
continue;
float dirwt = 0.70710678f/( fabsf( rawData[row-1][col+dx]- rawData[row+1][col-dx])+eps);
wtdsum += dirwt * (rawData[row-1][col+dx] + rawData[row+1][col-dx]);
norm += dirwt;
}
} else {
// red and blue channel. Distance to center pixel is sqrt(8) => weighting is 0.35355339
// For red and blue channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
// 1 0 0 0 1
// 0 0 0 0 0
// 0 0 0 0 0
// 0 0 0 0 0
// 1 0 0 0 1
for( int dx=-2;dx<=2;dx+=4){
if( bitmapBads.get(col+dx,row-2) || bitmapBads.get(col-dx,row+2))
continue;
float dirwt = 0.35355339f/( fabsf( rawData[row-2][col+dx]- rawData[row+2][col-dx])+eps);
wtdsum += dirwt * (rawData[row-2][col+dx] + rawData[row+2][col-dx]);
norm += dirwt;
}
}
if (norm > 0.0){
rawData[row][col]= wtdsum / norm;//gradient weighted average
// channel independent. Distance to center pixel is 2 => weighting is 0.5
// Additionally for all channel following pixels will be used for interpolation. Pixel to be interpolated is in center.
// 1 means that pixel is used in this step, if itself and his counterpart are not marked bad
// 0 0 1 0 0
// 0 0 0 0 0
// 1 0 0 0 1
// 0 0 0 0 0
// 0 0 1 0 0
// horizontal interpolation
if(!(bitmapBads.get(col-2,row) || bitmapBads.get(col+2,row))) {
float dirwt = 0.5f/( fabsf( rawData[row][col-2]- rawData[row][col+2])+eps);
wtdsum += dirwt * (rawData[row][col-2] + rawData[row][col+2]);
norm += dirwt;
}
// vertical interpolation
if(!(bitmapBads.get(col,row-2) || bitmapBads.get(col,row+2))) {
float dirwt = 0.5f/( fabsf( rawData[row-2][col]- rawData[row+2][col])+eps);
wtdsum += dirwt * (rawData[row-2][col] + rawData[row+2][col]);
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%
rawData[row][col]= wtdsum / (2.f * norm);//gradient weighted average, Factor of 2.f is an optimization to avoid multiplications in former steps
counter++;
} else {
if (tot > 0.1) rawData[row][col] = sum/tot;//backup plan -- simple average
} else { //backup plan -- simple average. Same method for all channels. We could improve this, but it's really unlikely that this case happens
int tot = 0;
float sum = 0;
for( int dy=-2;dy<=2;dy+=2){
for( int dx=-2;dx<=2;dx+=2){
if(bitmapBads.get(col+dx,row+dy))
continue;
sum += rawData[row+dy][col+dx];
tot++;
}
}
if (tot > 0) {
rawData[row][col] = sum/tot;
counter ++;
}
}
}
}
return counter;
return counter; // Number of interpolated pixels.
}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -505,8 +564,10 @@ int RawImageSource::cfaCleanFromMap( PixelsMap &bitmapBads )
* (Taken from Emil Martinec idea)
* (Optimized by Ingo Weyrich 2013)
*/
int RawImageSource::findHotDeadPixel( PixelsMap &bpMap, float thresh)
int RawImageSource::findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels )
{
float varthresh = (20.0*(thresh/100.0) + 1.0 );
// counter for dead or hot pixels
int counter=0;
@ -528,7 +589,7 @@ int RawImageSource::findHotDeadPixel( PixelsMap &bpMap, float thresh)
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] = fabs(rawData[i][j]-temp);
cfablur[i*W+j] = rawData[i][j]-temp;
}
}
#pragma omp for reduction(+:counter) schedule (dynamic,16)
@ -540,16 +601,21 @@ int RawImageSource::findHotDeadPixel( PixelsMap &bpMap, float thresh)
for (int cc=0; cc < W; cc++,rrmWpcc++) {
//evaluate pixel for heat/death
float pixdev = cfablur[rrmWpcc];
if((!findDeadPixels) && pixdev <= 0)
continue;
if((!findHotPixels) && pixdev >= 0)
continue;
pixdev = fabsf(pixdev);
float hfnbrave = -pixdev;
int left=max(0,cc-2);
int right=min(W-1,cc+2);
for (int mm=top; mm<=bottom; mm++) {
int mmmWpnn = mm*W+left;
for (int nn=left; nn<=right; nn++,mmmWpnn++) {
hfnbrave += cfablur[mmmWpnn];
hfnbrave += fabsf(cfablur[mmmWpnn]);
}
}
if (pixdev * ((bottom-top+1)*(right-left+1)-1) > thresh*hfnbrave) {
if (pixdev * ((bottom-top+1)*(right-left+1)-1) > varthresh*hfnbrave) {
// mark the pixel as "bad"
bpMap.set(cc,rr);
counter++;
@ -1015,7 +1081,23 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
if( rid && settings->verbose){
printf( "Subtracting Darkframe:%s\n",rid->get_filename().c_str());
}
//copyOriginalPixels(ri, rid);
PixelsMap bitmapBads(W,H);
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)
#pragma omp parallel for reduction(+:totBP)
for(int i=0;i<H;i++)
for(int j=0;j<W;j++) {
if(ri->data[i][j] == 0.f) {
bitmapBads.set(j,i);
totBP++;
}
}
if( settings->verbose) {
printf( "%d pixels with value zero marked as bad pixels\n",totBP);
}
}
//FLATFIELD start
Glib::ustring newFF = raw.ff_file;
@ -1027,20 +1109,18 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
rif = ffm.searchFlatField( idata->getMake(), idata->getModel(),idata->getLens(),idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
}
bool hasFlatField = (rif!=NULL);
if( hasFlatField && settings->verbose) {
printf( "Flat Field Correction:%s\n",rif->get_filename().c_str());
}
copyOriginalPixels(raw, ri, rid, rif);
//FLATFIELD end
PixelsMap bitmapBads(W,H);
int totBP=0; // Hold count of bad pixels to correct
// Always correct camera badpixels
std::list<badPix> *bp = dfm.getBadPixels( ri->get_maker(), ri->get_model(), std::string("") );
// Always correct camera badpixels from .badpixels file
std::vector<badPix> *bp = dfm.getBadPixels( ri->get_maker(), ri->get_model(), idata->getSerialNumber() );
if( bp ){
totBP+=bitmapBads.set( *bp );
if( settings->verbose ){
@ -1061,6 +1141,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
}
}
scaleColors( 0,0, W, H, raw);//+ + raw parameters for black level(raw.blackxx)
// Correct vignetting of lens profile
@ -1081,20 +1162,17 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
defGain = 0.0;//log(initialGain) / log(2.0);
if ( raw.hotdeadpix_filt>0 ) {
if ( raw.hotPixelFilter>0 || raw.deadPixelFilter>0) {
if (plistener) {
plistener->setProgressStr ("Hot/Dead Pixel Filter...");
plistener->setProgress (0.0);
}
float varthresh = (20.0*((float)raw.hotdeadpix_thresh/100.0) + 1.0 );
int nFound =findHotDeadPixel( bitmapBads, varthresh );
int nFound = findHotDeadPixels( bitmapBads, raw.hotdeadpix_thresh, raw.hotPixelFilter, raw.deadPixelFilter );
totBP += nFound;
if( settings->verbose && nFound>0){
printf( "Correcting %d hot/dead pixels found inside image\n",nFound );
}
}
if( totBP )
cfaCleanFromMap( bitmapBads );
// check if it is an olympus E camera, if yes, compute G channel pre-compensation factors
if ( ri->getSensorType()==ST_BAYER && (raw.bayersensor.greenthresh || (((idata->getMake().size()>=7 && idata->getMake().substr(0,7)=="OLYMPUS" && idata->getModel()[0]=='E') || (idata->getMake().size()>=9 && idata->getMake().substr(0,9)=="Panasonic")) && raw.bayersensor.method != RAWParams::BayerSensor::methodstring[ RAWParams::BayerSensor::vng4])) ) {
@ -1137,6 +1215,10 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
}
if( totBP )
interpolateBadPixels( bitmapBads );
if ( ri->getSensorType()==ST_BAYER && raw.bayersensor.linenoise >0 ) {
if (plistener) {
plistener->setProgressStr ("Line Denoise...");

View File

@ -217,8 +217,8 @@ class RawImageSource : public ImageSource {
void ddct8x8s(int isgn, float a[8][8]);
void processRawWhitepoint (float expos, float preser); // exposure before interpolation
int cfaCleanFromMap( PixelsMap &bitmapBads );
int findHotDeadPixel( PixelsMap &bpMap, float thresh);
int interpolateBadPixels( PixelsMap &bitmapBads );
int findHotDeadPixels( PixelsMap &bpMap, float thresh, bool findHotPixels, bool findDeadPixels );
void cfa_linedn (float linenoiselevel);//Emil's line denoise
void cfa_tile_denoise (fftwf_complex * fcfablox, int vblk, int hblk, int numblox_H, int numblox_W, float noisevar, float * rolloff );

View File

@ -118,7 +118,7 @@ LUMINANCECURVE, // EvLSaturation,
LUMINANCECURVE, // EvLaCurve,
LUMINANCECURVE, // EvLbCurve,
DEMOSAIC, // EvDemosaicMethod
DARKFRAME, // EvPreProcessHotDeadPixel
DARKFRAME, // EvPreProcessHotPixel
RGBCURVE, // EvSaturation,
RGBCURVE, // EvHSVEqualizerH,
RGBCURVE, // EvHSVEqualizerS,
@ -318,8 +318,8 @@ RGBCURVE, //EvFilmSimulationEnabled
RGBCURVE, //EvFilmSimulationStrength
RGBCURVE, //EvFilmSimulationFilename
ALLNORAW, // EvDPDNLCurve
ALLNORAW // EvDPDNsmet
ALLNORAW, // EvDPDNsmet
DARKFRAME // EvPreProcessDeadPixel
};

View File

@ -317,7 +317,8 @@ void ParamsEdited::set (bool v) {
raw.caCorrection = v;
raw.caBlue = v;
raw.caRed = v;
raw.hotDeadPixelFilter = v;
raw.hotPixelFilter = v;
raw.deadPixelFilter = v;
raw.hotDeadPixelThresh = v;
raw.darkFrame = v;
raw.dfAuto = v;
@ -649,7 +650,8 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
raw.caCorrection = raw.caCorrection && p.raw.ca_autocorrect == other.raw.ca_autocorrect;
raw.caRed = raw.caRed && p.raw.cared == other.raw.cared;
raw.caBlue = raw.caBlue && p.raw.cablue == other.raw.cablue;
raw.hotDeadPixelFilter = raw.hotDeadPixelFilter && p.raw.hotdeadpix_filt == other.raw.hotdeadpix_filt;
raw.hotPixelFilter = raw.hotPixelFilter && p.raw.hotPixelFilter == other.raw.hotPixelFilter;
raw.deadPixelFilter = raw.deadPixelFilter && p.raw.deadPixelFilter == other.raw.deadPixelFilter;
raw.hotDeadPixelThresh = raw.hotDeadPixelThresh && p.raw.hotdeadpix_thresh == other.raw.hotdeadpix_thresh;
raw.darkFrame = raw.darkFrame && p.raw.dark_frame == other.raw.dark_frame;
raw.dfAuto = raw.dfAuto && p.raw.df_autoselect == other.raw.df_autoselect;
@ -989,7 +991,8 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
if (raw.exPos) toEdit.raw.expos = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_LINEAR] ? toEdit.raw.expos + mods.raw.expos : mods.raw.expos;
if (raw.exPreser) toEdit.raw.preser = dontforceSet && options.baBehav[ADDSET_RAWEXPOS_PRESER] ? toEdit.raw.preser + mods.raw.preser : mods.raw.preser;
if (raw.hotDeadPixelFilter) toEdit.raw.hotdeadpix_filt = mods.raw.hotdeadpix_filt;
if (raw.hotPixelFilter) toEdit.raw.hotPixelFilter = mods.raw.hotPixelFilter;
if (raw.deadPixelFilter) toEdit.raw.deadPixelFilter = mods.raw.deadPixelFilter;
if (raw.hotDeadPixelThresh) toEdit.raw.hotdeadpix_thresh = mods.raw.hotdeadpix_thresh;
if (raw.darkFrame) toEdit.raw.dark_frame = mods.raw.dark_frame;
if (raw.dfAuto) toEdit.raw.df_autoselect = mods.raw.df_autoselect;
@ -1042,7 +1045,7 @@ bool RAWParamsEdited::XTransSensor::isUnchanged() const {
}
bool RAWParamsEdited::isUnchanged() const {
return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotDeadPixelFilter && hotDeadPixelThresh && darkFrame
return bayersensor.isUnchanged() && xtranssensor.isUnchanged() && caCorrection && caRed && caBlue && hotPixelFilter && deadPixelFilter && hotDeadPixelThresh && darkFrame
&& dfAuto && ff_file && ff_AutoSelect && ff_BlurRadius && ff_BlurType && exPos && exPreser && ff_AutoClipControl && ff_clipControl;
}

View File

@ -536,7 +536,8 @@ class RAWParamsEdited {
bool caCorrection;
bool caRed;
bool caBlue;
bool hotDeadPixelFilter;
bool hotPixelFilter;
bool deadPixelFilter;
bool hotDeadPixelThresh;
bool darkFrame;
bool dfAuto;

View File

@ -97,7 +97,8 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
raw_ca_autocorrect = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_AUTO")));
raw_cared = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_CARED")));
raw_cablue = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAWCACORR_CABLUE")));
raw_hotdeadpix_filt = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_HOTDEADPIXFILT")));
raw_hotpix_filt = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_HOTPIXFILT")));
raw_deadpix_filt = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_DEADPIXFILT")));
raw_linenoise = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_LINEDENOISE")));
raw_greenthresh = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PREPROCESS_GREENEQUIL")));
raw_method = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RAW_DMETHOD")));
@ -190,7 +191,8 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0);
vboxes[6]->pack_start (*raw_linenoise, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_greenthresh, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_hotdeadpix_filt, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_hotpix_filt, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_deadpix_filt, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*Gtk::manage (new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 0);
vboxes[6]->pack_start (*raw_expos, Gtk::PACK_SHRINK, 2);
vboxes[6]->pack_start (*raw_preser, Gtk::PACK_SHRINK, 2);
@ -307,7 +309,8 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
raw_ca_autocorrectConn = raw_ca_autocorrect->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_caredConn = raw_cared->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_cablueConn = raw_cablue->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_hotdeadpix_filtConn = raw_hotdeadpix_filt->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_hotpix_filtConn = raw_hotpix_filt->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_deadpix_filtConn = raw_deadpix_filt->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_linenoiseConn = raw_linenoise->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
raw_greenthreshConn = raw_greenthresh->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
df_fileConn = df_file->signal_toggled().connect (sigc::bind (sigc::mem_fun(*raw, &Gtk::CheckButton::set_inconsistent), true));
@ -378,7 +381,8 @@ void PartialPasteDlg::rawToggled () {
raw_ca_autocorrectConn.block (true);
raw_caredConn.block (true);
raw_cablueConn.block (true);
raw_hotdeadpix_filtConn.block (true);
raw_hotpix_filtConn.block (true);
raw_deadpix_filtConn.block (true);
raw_linenoiseConn.block (true);
raw_greenthreshConn.block (true);
df_fileConn.block (true);
@ -403,7 +407,8 @@ void PartialPasteDlg::rawToggled () {
raw_ca_autocorrect->set_active (raw->get_active ());
raw_cared->set_active (raw->get_active ());
raw_cablue->set_active (raw->get_active ());
raw_hotdeadpix_filt->set_active (raw->get_active ());
raw_hotpix_filt->set_active (raw->get_active ());
raw_deadpix_filt->set_active (raw->get_active ());
raw_linenoise->set_active (raw->get_active ());
raw_greenthresh->set_active (raw->get_active ());
df_file->set_active (raw->get_active ());
@ -426,7 +431,8 @@ void PartialPasteDlg::rawToggled () {
raw_ca_autocorrectConn.block (false);
raw_caredConn.block (false);
raw_cablueConn.block (false);
raw_hotdeadpix_filtConn.block (false);
raw_hotpix_filtConn.block (false);
raw_deadpix_filtConn.block (false);
raw_linenoiseConn.block (false);
raw_greenthreshConn.block (false);
df_fileConn.block (false);
@ -688,7 +694,9 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
if (!raw_ca_autocorrect->get_active ()) filterPE.raw.caCorrection = falsePE.raw.caCorrection;
if (!raw_cared->get_active ()) filterPE.raw.caRed = falsePE.raw.caRed;
if (!raw_cablue->get_active ()) filterPE.raw.caBlue = falsePE.raw.caBlue;
if (!raw_hotdeadpix_filt->get_active ()) { filterPE.raw.hotDeadPixelFilter = falsePE.raw.hotDeadPixelFilter;
if (!raw_hotpix_filt->get_active ()) { filterPE.raw.hotPixelFilter = falsePE.raw.hotPixelFilter;
filterPE.raw.hotDeadPixelThresh = falsePE.raw.hotDeadPixelThresh; }
if (!raw_deadpix_filt->get_active ()) { filterPE.raw.deadPixelFilter = falsePE.raw.deadPixelFilter;
filterPE.raw.hotDeadPixelThresh = falsePE.raw.hotDeadPixelThresh; }
if (!df_file->get_active ()) filterPE.raw.darkFrame = falsePE.raw.darkFrame;
if (!df_AutoSelect->get_active ()) filterPE.raw.dfAuto = falsePE.raw.dfAuto;

View File

@ -94,7 +94,8 @@ class PartialPasteDlg : public Gtk::Dialog {
Gtk::CheckButton* raw_ca_autocorrect;
Gtk::CheckButton* raw_cared;
Gtk::CheckButton* raw_cablue;
Gtk::CheckButton* raw_hotdeadpix_filt;
Gtk::CheckButton* raw_hotpix_filt;
Gtk::CheckButton* raw_deadpix_filt;
Gtk::CheckButton* raw_linenoise;
Gtk::CheckButton* raw_greenthresh;
Gtk::CheckButton* raw_method;
@ -121,7 +122,7 @@ class PartialPasteDlg : public Gtk::Dialog {
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn;
sigc::connection exifchConn, iptcConn, icmConn, gamcsconn;
sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn;
sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotdeadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn
sigc::connection raw_caredConn, raw_cablueConn, raw_ca_autocorrectConn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_dcb_enhanceConn, raw_exposConn, raw_preserConn, raw_blackConn; //,raw_all_enhanceConn
public:
PartialPasteDlg (Glib::ustring title);

View File

@ -26,54 +26,86 @@ using namespace rtengine::procparams;
PreProcess::PreProcess () : FoldableToolPanel(this)
{
hotDeadPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_HOTDEADPIXFILT"))));
hotDeadPixel->set_tooltip_markup (M("TP_PREPROCESS_HOTDEADPIXFILT_TOOLTIP"));
pack_start( *hotDeadPixel, Gtk::PACK_SHRINK, 4);
Gtk::HBox* hotdeadPixel = Gtk::manage( new Gtk::HBox () );
hotdeadPixel->set_spacing(4);
hotPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_HOTPIXFILT"))));
deadPixel = Gtk::manage(new Gtk::CheckButton((M("TP_PREPROCESS_DEADPIXFILT"))));
hdpixelconn = hotDeadPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::hotDeadPixelChanged), true);
hotPixel->set_tooltip_markup (M("TP_PREPROCESS_HOTPIXFILT_TOOLTIP"));
deadPixel->set_tooltip_markup (M("TP_PREPROCESS_DEADPIXFILT_TOOLTIP"));
hotdeadPixel->pack_start( *hotPixel, Gtk::PACK_SHRINK);
hotdeadPixel->pack_start( *deadPixel, Gtk::PACK_SHRINK, 0);
pack_start(*hotdeadPixel, Gtk::PACK_SHRINK, 0);
// hotdeadPixel->show();
hpixelconn = hotPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::hotPixelChanged), true);
dpixelconn = deadPixel->signal_toggled().connect ( sigc::mem_fun(*this, &PreProcess::deadPixelChanged), true);
}
void PreProcess::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited)
{
disableListener ();
hdpixelconn.block (true);
hpixelconn.block (true);
dpixelconn.block (true);
if(pedited ){
hotDeadPixel->set_inconsistent (!pedited->raw.hotDeadPixelFilter);
hotPixel->set_inconsistent (!pedited->raw.hotPixelFilter);
deadPixel->set_inconsistent (!pedited->raw.deadPixelFilter);
}
lastHot = pp->raw.hotdeadpix_filt;
lastHot = pp->raw.hotPixelFilter;
lastDead = pp->raw.deadPixelFilter;
hotPixel->set_active (pp->raw.hotPixelFilter);
deadPixel->set_active (pp->raw.deadPixelFilter);
hotDeadPixel->set_active (pp->raw.hotdeadpix_filt);
hdpixelconn.block (false);
hpixelconn.block (false);
dpixelconn.block (false);
enableListener ();
}
void PreProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
{
pp->raw.hotdeadpix_filt = hotDeadPixel->get_active();
pp->raw.hotPixelFilter = hotPixel->get_active();
pp->raw.deadPixelFilter = deadPixel->get_active();
if (pedited) {
pedited->raw.hotDeadPixelFilter = !hotDeadPixel->get_inconsistent();
pedited->raw.hotPixelFilter = !hotPixel->get_inconsistent();
pedited->raw.deadPixelFilter = !deadPixel->get_inconsistent();
}
}
void PreProcess::hotDeadPixelChanged ()
void PreProcess::hotPixelChanged ()
{
if (batchMode) {
if (hotDeadPixel->get_inconsistent()) {
hotDeadPixel->set_inconsistent (false);
hdpixelconn.block (true);
hotDeadPixel->set_active (false);
hdpixelconn.block (false);
if (hotPixel->get_inconsistent()) {
hotPixel->set_inconsistent (false);
hpixelconn.block (true);
hotPixel->set_active (false);
hpixelconn.block (false);
}
else if (lastHot)
hotDeadPixel->set_inconsistent (true);
hotPixel->set_inconsistent (true);
lastHot = hotDeadPixel->get_active ();
lastHot = hotPixel->get_active ();
}
if (listener)
listener->panelChanged (EvPreProcessHotDeadPixel, hotDeadPixel->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED"));
listener->panelChanged (EvPreProcessHotPixel, hotPixel->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED"));
}
void PreProcess::deadPixelChanged ()
{
if (batchMode) {
if (deadPixel->get_inconsistent()) {
deadPixel->set_inconsistent (false);
dpixelconn.block (true);
deadPixel->set_active (false);
dpixelconn.block (false);
}
else if (lastDead)
deadPixel->set_inconsistent (true);
lastDead = deadPixel->get_active ();
}
if (listener)
listener->panelChanged (EvPreProcessDeadPixel, deadPixel->get_active()?M("GENERAL_ENABLED"):M("GENERAL_DISABLED"));
}

View File

@ -27,10 +27,11 @@
class PreProcess : public ToolParamBlock, /*public AdjusterListener,*/ public FoldableToolPanel {
protected:
Gtk::CheckButton* hotDeadPixel;
bool lastHot;
sigc::connection hdpixelconn;
Gtk::CheckButton* hotPixel;
Gtk::CheckButton* deadPixel;
bool lastHot,lastDead;
sigc::connection hpixelconn;
sigc::connection dpixelconn;
public:
@ -41,7 +42,8 @@ class PreProcess : public ToolParamBlock, /*public AdjusterListener,*/ public Fo
//void setBatchMode (bool batchMode);
//void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
void hotDeadPixelChanged();
void hotPixelChanged();
void deadPixelChanged();
//void adjusterChanged (Adjuster* a, double newval);
//void setAdjusterBehavior (bool linedenoiseadd, bool greenequiladd);