コード例 #1
0
ファイル: tmoColorConvert.cpp プロジェクト: Antranilan/Sparky
/**
Clipping function<br>
Remove any extremely bright and/or extremely dark pixels 
and normalize between 0 and 1. 
@param Y Input/Output image
@param minPrct Minimum percentile
@param maxPrct Maximum percentile
*/
void 
NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct) {
	int x, y;
	float maxLum, minLum;

	if(minPrct > maxPrct) {
		// swap values
		float t = minPrct; minPrct = maxPrct; maxPrct = t;
	}
	if(minPrct < 0) minPrct = 0;
	if(maxPrct > 1) maxPrct = 1;

	int width = FreeImage_GetWidth(Y);
	int height = FreeImage_GetHeight(Y);
	int pitch = FreeImage_GetPitch(Y);

	// find max & min luminance values
	if((minPrct > 0) || (maxPrct < 1)) {
		maxLum = 0, minLum = 0;
		findMaxMinPercentile(Y, minPrct, &minLum, maxPrct, &maxLum);
	} else {
		maxLum = -1e20F, minLum = 1e20F;
		BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
		for(y = 0; y < height; y++) {
			const float *pixel = (float*)bits;
			for(x = 0; x < width; x++) {
				const float value = pixel[x];
				maxLum = (maxLum < value) ? value : maxLum;	// max Luminance in the scene
				minLum = (minLum < value) ? minLum : value;	// min Luminance in the scene
			}
			// next line
			bits += pitch;
		}
	}
	if(maxLum == minLum) return;

	// normalize to range 0..1 
	const float divider = maxLum - minLum;
	BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
	for(y = 0; y < height; y++) {
		float *pixel = (float*)bits;
		for(x = 0; x < width; x++) {
			pixel[x] = (pixel[x] - minLum) / divider;
			if(pixel[x] <= 0) pixel[x] = EPSILON;
			if(pixel[x] > 1) pixel[x] = 1;
		}
		// next line
		bits += pitch;
	}
}
コード例 #2
0
ファイル: tmo_durand02.cpp プロジェクト: DINKIN/LuminanceHDR
void tmo_durand02(pfs::Array2Df& R, pfs::Array2Df& G, pfs::Array2Df& B,
                  float sigma_s, float sigma_r, float baseContrast, int downsample,
                  bool color_correction,
                  pfs::Progress &ph)
{
    int w = R.getCols();
    int h = R.getRows();
    int size = w*h;

    pfs::Array2Df I(w,h); // intensities
    pfs::Array2Df BASE(w,h); // base layer
    pfs::Array2Df DETAIL(w,h); // detail layer

    float min_pos = 1e10f; // minimum positive value (to avoid log(0))
    for (int i = 0 ; i < size ; i++)
    {
        I(i) = 1.0f/61.0f * ( 20.0f*R(i) + 40.0f*G(i) + B(i) );
        if ( I(i) < min_pos && I(i) > 0.0f )
        {
            min_pos = I(i);
        }
    }

    for (int i = 0 ; i < size ; i++)
    {
        float L = I(i);
        if ( L <= 0.0f )
        {
            L = min_pos;
        }

        R(i) /= L;
        G(i) /= L;
        B(i) /= L;

        I(i) = std::log( L );
    }

#ifdef HAVE_FFTW3F
    fastBilateralFilter( I, BASE, sigma_s, sigma_r, downsample, ph );
#else
    bilateralFilter( &I, &BASE, sigma_s, sigma_r, ph );
#endif

    //!! FIX: find minimum and maximum luminance, but skip 1% of outliers
    float maxB;
    float minB;
    findMaxMinPercentile(&BASE, 0.01f, 0.99f, minB, maxB);

    float compressionfactor = baseContrast / (maxB - minB);

    // Color correction factor
    const float k1 = 1.48f;
    const float k2 = 0.82f;
    const float s = ( (1 + k1)*pow(compressionfactor,k2) )/( 1 + k1*pow(compressionfactor,k2) );

    for (int i = 0 ; i < size ; i++)
    {
        DETAIL(i) = I(i) - BASE(i);
        I(i) = BASE(i) * compressionfactor + DETAIL(i);

        //!! FIX: this to keep the output in normalized range 0.01 - 1.0
        //intensitites are related only to minimum luminance because I
        //would say this is more stable over time than using maximum
        //luminance and is also robust against random peaks of very high
        //luminance
        I(i) -=  4.3f+minB*compressionfactor;

        if ( color_correction )
        {
            R(i) = decode( std::pow( R(i), s ) *  std::exp( I(i) ) );
            G(i) = decode( std::pow( G(i), s ) *  std::exp( I(i) ) );
            B(i) = decode( std::pow( B(i), s ) *  std::exp( I(i) ) );
        }
        else
        {
            R(i) *= decode( std::exp( I(i) ) );
            G(i) *= decode( std::exp( I(i) ) );
            B(i) *= decode( std::exp( I(i) ) );
        }
    }

    if (!ph.canceled())
    {
        ph.setValue( 100 );
    }
}