diff --git a/rtengine/amaze_interpolate_RT.cc b/rtengine/amaze_interpolate_RT.cc new file mode 100644 index 000000000..4ee919d4d --- /dev/null +++ b/rtengine/amaze_interpolate_RT.cc @@ -0,0 +1,764 @@ +//////////////////////////////////////////////////////////////// +// +// AMaZE demosaic algorithm +// (Aliasing Minimization and Zipper Elimination) +// +// copyright (c) 2008-2010 Emil Martinec +// +// incorporating ideas of Luis Sanz Rodrigues and Paul Lee +// +// code dated: May 27, 2010 +// +// amaze_interpolate_RT.cc 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. +// +// This program 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 this program. If not, see . +// +//////////////////////////////////////////////////////////////// + + + +void RawImageSource::amaze_demosaic_RT() { + +#define SQR(x) ((x)*(x)) + //#define MIN(a,b) ((a) < (b) ? (a) : (b)) + //#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define LIM(x,min,max) MAX(min,MIN(x,max)) +#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) + //#define CLIP(x) LIM(x,0,65535) + + + int width=W, height=H; + red = new unsigned short*[H]; + for (int i=0; isetProgressStr ("AMaZE Demosaicing..."); + plistener->setProgress (0.0); + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + //determine GRBG coset + if (FC(0,0)==1) {//first pixel is G + if (FC(0,1)==0) {ey=0; ex=1;} else {ey=1; ex=0;} + } else {//first pixel is R or B + if (FC(0,0)==0) {ey=0; ex=0;} else {ey=1; ex=1;} + } + + // Main algorithm: Tile loop + //#pragma omp parallel for shared(ri->data,height,width,red,green,blue) private(top,left) schedule(dynamic) + //code is openmp ready; just have to pull local tile variable declarations inside the tile loop + for (top=-16; top < height; top += TS-32) + for (left=-16; left < width; left += TS-32) { + bottom = MIN( top+TS,height+16); + right = MIN(left+TS, width+16); + rr1 = bottom - top; + cc1 = right - left; + // rgb from input CFA data + // rgb values should be floating point number between 0 and 1 + // after white balance multipliers are applied + if (top<0) {rrmin=16;} else {rrmin=0;} + if (left<0) {ccmin=16;} else {ccmin=0;} + if (bottom>height) {rrmax=height-top;} else {rrmax=rr1;} + if (right>width) {ccmax=width-left;} else {ccmax=cc1;} + + for (rr=rrmin; rr < rrmax; rr++) + for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { + col = cc+left; + c = FC(rr,cc); + indx=row*width+col; + indx1=rr*TS+cc; + rgb[indx1][c] = (ri->data[row][col])/65535.0f; + cfa[indx1] = rgb[indx1][c]; + } + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //fill borders + if (rrmin>0) { + for (rr=0; rr<16; rr++) + for (cc=ccmin; ccdata[(height-rr-2)][left+cc])/65535.0f; + cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c]; + } + } + if (ccmin>0) { + for (rr=rrmin; rrdata[(top+rr)][(width-cc-2)])/65535.0f; + cfa[rr*TS+ccmax+cc] = rgb[rr*TS+ccmax+cc][c]; + } + } + + //also fill the image corners + if (rrmin>0 && ccmin>0) { + for (rr=0; rr<16; rr++) + for (cc=0; cc<16; cc++) { + c=FC(rr,cc); + rgb[(rr)*TS+cc][c] = (ri->data[32-rr][32-cc])/65535.0f; + cfa[(rr)*TS+cc] = rgb[(rr)*TS+cc][c]; + } + } + if (rrmaxdata[(height-rr-2)][(width-cc-2)])/65535.0f; + cfa[(rrmax+rr)*TS+ccmax+cc] = rgb[(rrmax+rr)*TS+ccmax+cc][c]; + } + } + if (rrmin>0 && ccmaxdata[(rr)][(width-cc-2)])/65535.0f; + cfa[(rr)*TS+ccmax+cc] = rgb[(rr)*TS+ccmax+cc][c]; + } + } + if (rrmax0) { + for (rr=0; rr<16; rr++) + for (cc=0; cc<16; cc++) { + c=FC(rr,cc); + rgb[(rrmax+rr)*TS+cc][c] = (ri->data[(height-rr-2)][cc])/65535.0f; + cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c]; + } + } + + //end of border fill + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + for (rr=1; rr < rr1-1; rr++) + for (cc=1, indx=(rr)*TS+cc; cc < cc1-1; cc++, indx++) { + + delh[indx] = fabs(cfa[indx+1]-cfa[indx-1]); + delv[indx] = fabs(cfa[indx+v1]-cfa[indx-v1]); + delhsq[indx] = SQR(delh[indx]); + delvsq[indx] = SQR(delv[indx]); + delp[indx] = fabs(cfa[indx+p1]-cfa[indx-p1]); + delm[indx] = fabs(cfa[indx+m1]-cfa[indx-m1]); + + } + + for (rr=2; rr < rr1-2; rr++) + for (cc=2,indx=(rr)*TS+cc; cc < cc1-2; cc++, indx++) { + + dirwts[indx][0] = eps+delv[indx+v1]+delv[indx-v1]+delv[indx];//+fabs(cfa[indx+v2]-cfa[indx-v2]); + //vert directional averaging weights + dirwts[indx][1] = eps+delh[indx+1]+delh[indx-1]+delh[indx];//+fabs(cfa[indx+2]-cfa[indx-2]); + //horizontal weights + + if (FC(rr,cc)&1) { + //for later use in diagonal interpolation + Dgrbp1[indx]=2*cfa[indx]-(cfa[indx-p1]+cfa[indx+p1]); + Dgrbm1[indx]=2*cfa[indx]-(cfa[indx-m1]+cfa[indx+m1]); + Dgrbpsq1[indx]=(SQR(cfa[indx]-cfa[indx-p1])+SQR(cfa[indx]-cfa[indx+p1])); + Dgrbmsq1[indx]=(SQR(cfa[indx]-cfa[indx-m1])+SQR(cfa[indx]-cfa[indx+m1])); + } + } + + //t2_init += clock()-t1_init; + // end of tile initialization + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //interpolate vertical and horizontal color differences + //t1_vcdhcd = clock(); + + for (rr=4; rr0 && fabs(0.5-diffwt)0) {nyquist[indx]=1;}//nyquist=1 for nyquist region + } + + for (rr=8; rr4) nyquist[indx]=1; + //or not + if (areawt<4) nyquist[indx]=0; + } + + //t2_nyqtest += clock() - t1_nyqtest; + // end of Nyquist test + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // in areas of Nyquist texture, do area interpolation + //t1_areainterp = clock(); + for (rr=8; rr (0.33*(2*Ginth+rbint[indx]))) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]); + if (rbint[indx]-2*Gintv > (0.33*(2*Gintv+rbint[indx]))) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); + + rgb[indx][1] = Ginth*(1-hvwt[indx]) + Gintv*hvwt[indx]; + } + //end of diagonal interpolation correction + //t2_diag += clock() - t1_diag; + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + //t1_chroma = clock(); + //fancy chrominance interpolation + //(ey,ex) is location of R site + for (rr=13-ey; rrsetProgress(fabs((float)top/height)); + } + + // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + // clean up + free(buffer); + + // done + +#undef TS + +} diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index af2c643f8..4f6c23d36 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -781,8 +781,10 @@ int RawImageSource::load (Glib::ustring fname) { vng4_demosaic (); else if (settings->demosaicMethod=="ahd") ahd_demosaic (); - else if (settings->demosaicMethod=="ppg") - ppg_demosaic (); + //else if (settings->demosaicMethod=="ppg") + // ppg_demosaic (); + else if (settings->demosaicMethod=="amaze") + amaze_demosaic_RT ();//Emil's code for AMaZE else if (settings->demosaicMethod=="dcb") dcb_demosaic(settings->dcb_iterations, settings->dcb_enhance? 1:0); else @@ -3124,6 +3126,11 @@ void RawImageSource::dcb_demosaic(int iterations, int dcb_enhance) } free(image); } + + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + //Emil's code for AMaZE +#include "amaze_interpolate_RT.cc"//AMaZE demosaic + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% } /* namespace */ diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index adc57f935..0a9c7d31e 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -139,6 +139,7 @@ class RawImageSource : public ImageSource { void hphd_demosaic (); void vng4_demosaic (); void ppg_demosaic(); + 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]); diff --git a/rtgui/options.cc b/rtgui/options.cc index 1c266316c..01d7e36b8 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -119,8 +119,8 @@ void Options::setDefaults () { baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); rtSettings.dualThreadEnabled = true; - rtSettings.demosaicMethod = "eahd"; - rtSettings.colorCorrectionSteps = 2; + rtSettings.demosaicMethod = "amaze";//Emil's code for AMaZE + rtSettings.colorCorrectionSteps = 0; rtSettings.dcb_iterations = 2; rtSettings.dcb_enhance = true; rtSettings.iccDirectory = "/usr/share/color/icc"; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 2204d4698..acf7ffd3b 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -263,7 +263,8 @@ Gtk::Widget* Preferences::getProcParamsPanel () { dmethod->append_text ("EAHD"); dmethod->append_text ("HPHD"); dmethod->append_text ("VNG-4"); - dmethod->append_text ("PPG"); + //dmethod->append_text ("PPG"); + dmethod->append_text ("AMaZE");//Emil's code for AMaZE dmethod->append_text ("DCB"); dmethod->append_text ("AHD"); Gtk::Label* cclab = Gtk::manage (new Gtk::Label (M("PREFERENCES_FALSECOLOR")+":")); @@ -707,8 +708,10 @@ void Preferences::storePreferences () { moptions.rtSettings.demosaicMethod = "hphd"; else if (dmethod->get_active_row_number()==2) moptions.rtSettings.demosaicMethod = "vng4"; - else if (dmethod->get_active_row_number()==3) - moptions.rtSettings.demosaicMethod = "ppg"; + //else if (dmethod->get_active_row_number()==3) + // moptions.rtSettings.demosaicMethod = "ppg"; + else if (dmethod->get_active_row_number()==3) + moptions.rtSettings.demosaicMethod = "amaze";//Emil's code for AMaZE else if (dmethod->get_active_row_number()==4) moptions.rtSettings.demosaicMethod = "dcb"; else if (dmethod->get_active_row_number()==5) @@ -800,7 +803,9 @@ void Preferences::fillPreferences () { dmethod->set_active (1); else if (moptions.rtSettings.demosaicMethod=="vng4") dmethod->set_active (2); - else if (moptions.rtSettings.demosaicMethod=="ppg") + //else if (moptions.rtSettings.demosaicMethod=="ppg") + // dmethod->set_active (3); + else if (moptions.rtSettings.demosaicMethod=="amaze")//Emil's code for AMaZE dmethod->set_active (3); else if (moptions.rtSettings.demosaicMethod=="dcb") dmethod->set_active (4);