/////////////////////////////////////////////////////////////////////////////// // Gain function // /////////////////////////////////////////////////////////////////////////////// GEM_EXTERN float gainFunc(float x, float a) { if (x < 0.5f) return( biasFunc(2.f * x, 1.f - a) / 2.f); else return(1.f - biasFunc(2.f - 2.f*x, 1.f - a) / 2.f); // return(0.f); }
void ToneMappingDrago03::calctoneMapping_Drago03CPU() { const float LOG05 = -0.693147f; // log(0.5) // Normal tone mapping of every pixel int i, j; for(j = 0; j < image->getHeight(); j++) for(i = 0; i < image->getWidth(); i++) { float Yw = image->getImage()[j * image->getWidth() * 3 + 3 * i + 1] / *avLuminance; float interpol = log (2.0f + biasFunc(biasP, Yw / normMaxLum) * 8.0f); float yg = ( log(Yw+1.0f)/interpol ) / divider; float scale = yg / image->getImage()[j * image->getWidth() * 3 + 3 * i + 1]; picture[j * image->getWidth() * 3 + 3 * i + 0] = (unsigned int)(clampq(image->getImage()[j * image->getWidth() * 3 + 3 * i + 0] * scale, 0.0f, 1.0f) * 255); picture[j * image->getWidth() * 3 + 3 * i + 1] = (unsigned int)(clampq(image->getImage()[j * image->getWidth() * 3 + 3 * i + 1] * scale, 0.0f, 1.0f) * 255); picture[j * image->getWidth() * 3 + 3 * i + 2] = (unsigned int)(clampq(image->getImage()[j * image->getWidth() * 3 + 3 * i + 2] * scale, 0.0f, 1.0f) * 255); } }
void tmo_drago03(float* Y, float* L, int height, int width, float maxLum, float avLum, float bias) { const float LOG05 = -0.693147f; // log(0.5) //assert(Y!=NULL); //assert(L!=NULL); int nrows = height; // image size int ncols = width; //assert(nrows==L->getRows() && ncols==L->getCols() ); maxLum /= avLum; // normalize maximum luminance by average luminance float divider = log10(maxLum+1.0f); float biasP = log(bias)/LOG05; #if !FAST // Normal tone mapping of every pixel for( int y=0 ; y<nrows; y++) for( int x=0 ; x<ncols; x++) { float Yw = Y[x+y*ncols] / avLum; float interpol = log (2.0f + biasFunc(biasP, Yw / maxLum) * 8.0f); L[x+y*ncols] = ( log(Yw+1.0f)/interpol ) / divider; } #else // Approximation of log(x+1) // x(6+x)/(6+4x) good if x < 1 // x*(6 + 0.7662x)/(5.9897 + 3.7658x) between 1 and 2 // http://users.pandora.be/martin.brown/home/consult/logx.htm int i,j; for(int y=0; y<nrows; y+=3) for(int x=0; x<ncols; x+=3) { float average = 0.0f; for (i=0; i<3; i++) for (j=0; j<3; j++) average += Y[x+i + (y+j)*ncols] / avLum; average = average / 9.0f - Y[x+y*ncols]; if (average>-1.0f && average<1.0f ) { float interpol = log(2.0f + biasFunc(biasP, Y[x+1 + (y+1)*ncols]/maxLum) * 8.0f); for (i=0; i<3; i++) for (j=0; j<3; j++) { float Yw = Y[x+i + (y+j)*ncols]; if( Yw<1.0f ) { float L = Yw*(6.0f+Yw) / (6.0f+4.0f*Yw); Yw = (L/interpol) / divider; } else if( Yw>=1.0f && Yw<2.0f ) { float L = Yw*(6.0f+0.7662*Yw) / (5.9897f+3.7658f*Yw); Yw = (L/interpol) / divider; } else Yw = ( log(Yw+1.0f)/interpol ) / divider; L[x+i + (y+j)*ncols] = Yw; } } else { for (i=0; i<3; i++) for (j=0; j<3; j++) { float Yw = Y[x+i + (y+j)*ncols]; float interpol = log(2.0f+biasFunc(biasP, Yw/maxLum)*8.0f); L[x+i + (y+j)*ncols] = ( log(Yw+1.0f)/interpol ) / divider; } } } #endif // #else #ifndef FAST }
void tmo_drago03(unsigned int width, unsigned int height, const float* _Y, float* _L, float maxLum, float avLum, float bias) { const float LOG05 = -0.693147f; // log(0.5) assert(_Y!=NULL); assert(_L!=NULL); const pfstmo::Array2D* Y = new pfstmo::Array2D(width, height, const_cast<float*>(_Y)); pfstmo::Array2D* L = new pfstmo::Array2D(width, height, _L); int nrows = Y->getRows(); // image size int ncols = Y->getCols(); assert(nrows==L->getRows() && ncols==L->getCols() ); maxLum /= avLum; // normalize maximum luminance by average luminance float divider = log10(maxLum+1.0f); float biasP = log(bias)/LOG05; #if !FAST // Normal tone mapping of every pixel for( int y=0 ; y<nrows; y++) for( int x=0 ; x<ncols; x++) { float Yw = (*Y)(x,y) / avLum; float interpol = log (2.0f + biasFunc(biasP, Yw / maxLum) * 8.0f); (*L)(x,y) = ( log(Yw+1.0f)/interpol ) / divider; } #else // Approximation of log(x+1) // x(6+x)/(6+4x) good if x < 1 // x*(6 + 0.7662x)/(5.9897 + 3.7658x) between 1 and 2 // http://users.pandora.be/martin.brown/home/consult/logx.htm int i,j; for(int y=0; y<nrows; y+=3) for(int x=0; x<ncols; x+=3) { float average = 0.0f; for (i=0; i<3; i++) for (j=0; j<3; j++) average += (*Y)(x+i,y+j) / avLum; average = average / 9.0f - (*Y)(x,y); if (average>-1.0f && average<1.0f ) { float interpol = log(2.0f + biasFunc(biasP, (*Y)(x+1,y+1)/maxLum) * 8.0f); for (i=0; i<3; i++) for (j=0; j<3; j++) { float Yw = (*Y)(x+i,y+j); if( Yw<1.0f ) { float L = Yw*(6.0f+Yw) / (6.0f+4.0f*Yw); Yw = (L/interpol) / divider; } else if( Yw>=1.0f && Yw<2.0f ) { float L = Yw*(6.0f+0.7662*Yw) / (5.9897f+3.7658f*Yw); Yw = (L/interpol) / divider; } else Yw = ( log(Yw+1.0f)/interpol ) / divider; (*L)(x+i,y+j) = Yw; } } else { for (i=0; i<3; i++) for (j=0; j<3; j++) { float Yw = (*Y)(x+i,y+j); float interpol = log(2.0f+biasFunc(biasP, Yw/maxLum)*8.0f); (*L)(x+i,y+j) = ( log(Yw+1.0f)/interpol ) / divider; } } } #endif // #else #ifndef FAST delete L; delete Y; }