Bilinear demosaic from dcraw + omp support. Faster then light! Great for previews.

This commit is contained in:
Andrey Skvortsov
2010-09-11 23:05:36 -07:00
parent 5bf5ce84b8
commit 7a3942aaab
4 changed files with 121 additions and 6 deletions

View File

@@ -906,6 +906,8 @@ int RawImageSource::load (Glib::ustring fname) {
vng4_demosaic ();
else if (settings->demosaicMethod=="ahd")
ahd_demosaic ();
else if (settings->demosaicMethod=="bilinear")
bilinear_demosaic();
//else if (settings->demosaicMethod=="ppg")
// ppg_demosaic ();
else if (settings->demosaicMethod=="amaze")
@@ -2339,13 +2341,14 @@ void RawImageSource::ppg_demosaic()
free (image);
}
void RawImageSource::border_interpolate(int border, ushort (*image)[4])
void RawImageSource::border_interpolate(int border, ushort (*image)[4], int start, int end)
{
unsigned row, col, y, x, f, c, sum[8];
int width=W, height=H;
int colors = 3;
for (row=0; row < height; row++)
if (end == 0 )end = H;
for (row=start; row < end; row++)
for (col=0; col < width; col++) {
if (col==border && row >= border && row < height-border)
col = width-border;
@@ -2363,6 +2366,110 @@ void RawImageSource::border_interpolate(int border, ushort (*image)[4])
}
}
void RawImageSource::bilinear_interpolate_block(ushort (*image)[4], int start, int end)
{
ushort (*pix);
int i, *ip, sum[4];
int width=W;
int colors = 3;
for (int row = start; row < end; row++)
for (int col=1; col < width-1; col++) {
pix = image[row*width+col];
ip = blcode[row & 15][col & 15];
memset (sum, 0, sizeof sum);
for (i=8; i--; ip+=3)
sum[ip[2]] += pix[ip[0]] << ip[1];
for (i=colors; --i; ip+=2)
pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
}
for (int i=start; i<end; i++) {
red[i] = new unsigned short[W];
green[i] = new unsigned short[W];
blue[i] = new unsigned short[W];
for (int j=0; j<W; j++){
red[i][j] = image[i*W+j][0];
green[i][j] = image[i*W+j][1];
blue[i][j] = image[i*W+j][2];
}
}
}
void RawImageSource::bilinear_demosaic()
{
int width=W, height=H;
int *ip, sum[4];
int c, x, y, row, col, shift, color;
int colors = 3;
ushort (*image)[4], *pix;
image = (ushort (*)[4]) calloc (H*W, sizeof *image);
for (int ii=0; ii<H; ii++)
for (int jj=0; jj<W; jj++)
image[ii*W+jj][fc(ii,jj)] = ri->data[ii][jj];
//if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
if (plistener) {
plistener->setProgressStr ("Demosaicing...");
plistener->setProgress (0.0);
}
for (row=0; row < 16; row++)
for (col=0; col < 16; col++) {
ip = blcode[row][col];
memset (sum, 0, sizeof sum);
for (y=-1; y <= 1; y++)
for (x=-1; x <= 1; x++) {
shift = (y==0) + (x==0);
if (shift == 2) continue;
color = fc(row+y,col+x);
*ip++ = (width*y + x)*4 + color;
*ip++ = shift;
*ip++ = color;
sum[color] += 1 << shift;
}
FORCC
if (c != fc(row,col)) {
*ip++ = c;
*ip++ = 256 / sum[c];
}
}
red = new unsigned short*[H];
green = new unsigned short*[H];
blue = new unsigned short*[H];
#ifdef _OPENMP
#pragma omp parallel
{
int tid = omp_get_thread_num();
int nthreads = omp_get_num_threads();
int blk = W/nthreads;
int start = 0;
if (tid == 0) start = 1;
if (tid<nthreads-1)
{
border_interpolate(1, image, tid*blk, (tid+1)*blk);
bilinear_interpolate_block(image, start+tid*blk, (tid+1)*blk);
}
else
{
border_interpolate(1, image, tid*blk, height);
bilinear_interpolate_block(image, tid*blk, height-1);
}
}
#else
border_interpolate(1, image);
bilinear_interpolate_block(image, 1, height-1);
#endif
if(plistener) plistener->setProgress (1.0);
free (image);
}
/*
Adaptive Homogeneity-Directed interpolation is based on
the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.

View File

@@ -65,6 +65,7 @@ class RawImageSource : public ImageSource {
char** needhr; // for color propagation
int max[3];
double defGain;
int blcode[16][16][32];
bool full;
Glib::ustring oldmethod;
cmsHPROFILE camProfile;
@@ -154,7 +155,9 @@ class RawImageSource : public ImageSource {
void amaze_demosaic_RT ();//Emil's code for AMaZE
void dcb_demosaic(int iterations, int dcb_enhance);
void ahd_demosaic();
void border_interpolate(int border, ushort (*image)[4]);
void bilinear_demosaic();
void bilinear_interpolate_block(ushort (*image)[4], int start, int end);
void border_interpolate(int border, ushort (*image)[4], int start = 0, int end = 0);
void dcb_initTileLimits(int &colMin, int &rowMin, int &colMax, int &rowMax, int x0, int y0, int border);
void fill_raw( ushort (*cache )[4], int x0, int y0, ushort** rawData);
void fill_border( ushort (*cache )[4], int border, int x0, int y0);

View File

@@ -25,7 +25,7 @@ namespace rtengine {
class Settings {
public:
bool dualThreadEnabled; ///< If true, the image processing operations with utilize two processor cores (if possible)
std::string demosaicMethod; ///< The algorithm used for demosaicing. Can be "eahd", "hphd" or "vng4".
std::string demosaicMethod; ///< The algorithm used for demosaicing. Can be "eahd", "hphd", "ahd", "vng4", "amaze", "bilinear".
int colorCorrectionSteps; ///< The number of color correction steps applied right after the demosaicing
Glib::ustring iccDirectory; ///< The directory containing the possible output icc profiles
int colorimetricIntent; ///< Colorimetric intent used at color space conversions

View File

@@ -267,6 +267,7 @@ Gtk::Widget* Preferences::getProcParamsPanel () {
dmethod->append_text ("AMaZE");//Emil's code for AMaZE
dmethod->append_text ("DCB");
dmethod->append_text ("AHD");
dmethod->append_text ("Bilinear");
Gtk::Label* cclab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FALSECOLOR")+":"));
ccSteps = Gtk::manage (new Gtk::SpinButton ());
ccSteps->set_digits (0);
@@ -748,6 +749,8 @@ void Preferences::storePreferences () {
moptions.rtSettings.demosaicMethod = "dcb";
else if (dmethod->get_active_row_number()==5)
moptions.rtSettings.demosaicMethod = "ahd";
else if (dmethod->get_active_row_number()==6)
moptions.rtSettings.demosaicMethod = "bilinear";
moptions.rtSettings.dcb_iterations=(int)dcbIterations->get_value();
moptions.rtSettings.dcb_enhance=dcbEnhance->get_active();
moptions.rtSettings.ca_autocorrect=caAutoCorrect->get_active();//Emil's CA correction
@@ -848,6 +851,8 @@ void Preferences::fillPreferences () {
dmethod->set_active (4);
else if (moptions.rtSettings.demosaicMethod=="ahd")
dmethod->set_active (5);
else if (moptions.rtSettings.demosaicMethod=="bilinear")
dmethod->set_active (6);
dcbEnhance->set_active(moptions.rtSettings.dcb_enhance);
dcbIterations->set_value(moptions.rtSettings.dcb_iterations);
dcbEnhance->set_sensitive(moptions.rtSettings.demosaicMethod=="dcb");