//////////////////////////////////////////////////////////////// // // 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 }