void LocalLaplacianFilter( const MatrixF& src, float sigma, float alpha, MatrixF& dest) { //our remapping function Remapping remapFunction(sigma,alpha); //compute input gaussian pyramid MatrixFArray gpyramid, lpyramid; GaussianPyramid( src, gpyramid ); //resize the laplacian pyramid lpyramid.resize( gpyramid.size() - 1 ); for( int i = 0; i < lpyramid.size(); ++i ) lpyramid[i].Resize( gpyramid[i].Rows(), gpyramid[i].Cols() ); //no optimization //take the whole subregion cout << "Beginning" << endl; for( int i = 0; i < gpyramid.size() - 1; ++i ) { for( int y = 0; y < gpyramid[i].Rows(); ++y ) { for( int x = 0; x < gpyramid[i].Cols(); ++x ) { lpyramid[i][y][x] = FindLaplacianValue( src, remapFunction, gpyramid[i][y][x], i, y, x); } } } cout << "Ending" << endl; lpyramid.push_back( gpyramid[gpyramid.size()-1] ); //collapse the pyramid CollapseLaplacianPyramid( lpyramid, dest ); }
/** Gradient Domain HDR tone mapping operator @param Y Image luminance values @param alpha Parameter alpha of the paper (suggested value is 0.1) @param beta Parameter beta of the paper (suggested value is between 0.8 and 0.9) @return returns the tone mapped luminance */ static FIBITMAP* tmoFattal02(FIBITMAP *Y, float alpha, float beta) { const unsigned MIN_PYRAMID_SIZE = 32; // minimun size (width or height) of the coarsest level of the pyramid FIBITMAP *H = NULL; FIBITMAP **pyramid = NULL; FIBITMAP **gradients = NULL; FIBITMAP *phy = NULL; FIBITMAP *divG = NULL; FIBITMAP *U = NULL; float *avgGrad = NULL; int k; int nlevels = 0; try { // get the normalized luminance FIBITMAP *H = LogLuminance(Y); if(!H) throw(1); // get the number of levels for the pyramid const unsigned width = FreeImage_GetWidth(H); const unsigned height = FreeImage_GetHeight(H); unsigned minsize = MIN(width, height); while(minsize >= MIN_PYRAMID_SIZE) { nlevels++; minsize /= 2; } // create the Gaussian pyramid pyramid = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*)); if(!pyramid) throw(1); memset(pyramid, 0, nlevels * sizeof(FIBITMAP*)); if(!GaussianPyramid(H, pyramid, nlevels)) throw(1); // calculate gradient magnitude and its average value on each pyramid level gradients = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*)); if(!gradients) throw(1); memset(gradients, 0, nlevels * sizeof(FIBITMAP*)); avgGrad = (float*)malloc(nlevels * sizeof(float)); if(!avgGrad) throw(1); if(!GradientPyramid(pyramid, nlevels, gradients, avgGrad)) throw(1); // free the Gaussian pyramid for(k = 0; k < nlevels; k++) { if(pyramid[k]) FreeImage_Unload(pyramid[k]); } free(pyramid); pyramid = NULL; // compute the gradient attenuation function PHI(x, y) phy = PhiMatrix(gradients, avgGrad, nlevels, alpha, beta); if(!phy) throw(1); // free the gradient pyramid for(k = 0; k < nlevels; k++) { if(gradients[k]) FreeImage_Unload(gradients[k]); } free(gradients); gradients = NULL; free(avgGrad); avgGrad = NULL; // compute gradients in x and y directions, attenuate them with the attenuation matrix, // then compute the divergence div G from the attenuated gradient. divG = Divergence(H, phy); if(!divG) throw(1); // H & phy no longer needed FreeImage_Unload(H); H = NULL; FreeImage_Unload(phy); phy = NULL; // solve the PDE (Poisson equation) using a multigrid solver and 3 cycles FIBITMAP *U = FreeImage_MultigridPoissonSolver(divG, 3); if(!U) throw(1); FreeImage_Unload(divG); // perform exponentiation and recover the log compressed image ExpLuminance(U); return U; } catch(int) { if(H) FreeImage_Unload(H); if(pyramid) { for(int i = 0; i < nlevels; i++) { if(pyramid[i]) FreeImage_Unload(pyramid[i]); } free(pyramid); } if(gradients) { for(int i = 0; i < nlevels; i++) { if(gradients[i]) FreeImage_Unload(gradients[i]); } free(gradients); } if(avgGrad) free(avgGrad); if(phy) FreeImage_Unload(phy); if(divG) FreeImage_Unload(divG); if(U) FreeImage_Unload(U); return NULL; } }