Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/tmoReinhard05.cpp view on Meta::CPAN
// IEEE Transactions on Visualization and Computer Graphics, 11(1), Jan/Feb 2005.
// [2] Erik Reinhard, 'Parameter estimation for photographic tone reproduction',
// Journal of Graphics Tools, vol. 7, no. 1, pp. 4551, 2003.
// ----------------------------------------------------------
/**
Tone mapping operator
@param dib Input / Output RGBF image
@param Y Input luminance image version of dib
@param f Overall intensity in range [-8:8] : default to 0
@param m Contrast in range [0.3:1) : default to 0
@param a Adaptation in range [0:1] : default to 1
@param c Color correction in range [0:1] : default to 0
@return Returns TRUE if successful, returns FALSE otherwise
@see LuminanceFromY
*/
static BOOL
ToneMappingReinhard05(FIBITMAP *dib, FIBITMAP *Y, float f, float m, float a, float c) {
float Cav[3]; // channel average
float Lav = 0; // average luminance
float Llav = 0; // log average luminance
float minLum = 1; // min luminance
float maxLum = 1; // max luminance
float L; // pixel luminance
float I_g, I_l; // global and local light adaptation
float I_a; // interpolated pixel light adaptation
float k; // key (low-key means overall dark image, high-key means overall light image)
// check input parameters
if((FreeImage_GetImageType(dib) != FIT_RGBF) || (FreeImage_GetImageType(Y) != FIT_FLOAT)) {
return FALSE;
}
if(f < -8) f = -8; if(f > 8) f = 8;
if(m < 0) m = 0; if(m > 1) m = 1;
if(a < 0) a = 0; if(a > 1) a = 1;
if(c < 0) c = 0; if(c > 1) c = 1;
const unsigned width = FreeImage_GetWidth(dib);
const unsigned height = FreeImage_GetHeight(dib);
const unsigned dib_pitch = FreeImage_GetPitch(dib);
const unsigned y_pitch = FreeImage_GetPitch(Y);
int i;
unsigned x, y;
BYTE *bits = NULL, *Ybits = NULL;
// get statistics about the data (but only if its really needed)
f = exp(-f);
if((m == 0) || (a != 1) && (c != 1)) {
// avoid these calculations if its not needed after ...
LuminanceFromY(Y, &maxLum, &minLum, &Lav, &Llav);
k = (log(maxLum) - Llav) / (log(maxLum) - log(minLum));
if(k < 0) {
// pow(k, 1.4F) is undefined ...
// there's an ambiguity about the calculation of Llav between Reinhard papers and the various implementations ...
// try another world adaptation luminance formula using instead 'worldLum = log(Llav)'
k = (log(maxLum) - log(Llav)) / (log(maxLum) - log(minLum));
if(k < 0) m = 0.3F;
}
}
m = (m > 0) ? m : (float)(0.3 + 0.7 * pow(k, 1.4F));
float max_color = -1e6F;
float min_color = +1e6F;
// tone map image
bits = (BYTE*)FreeImage_GetBits(dib);
Ybits = (BYTE*)FreeImage_GetBits(Y);
if((a == 1) && (c == 0)) {
// when using default values, use a fastest code
for(y = 0; y < height; y++) {
float *Y = (float*)Ybits;
float *color = (float*)bits;
for(x = 0; x < width; x++) {
I_a = Y[x]; // luminance(x, y)
for (i = 0; i < 3; i++) {
*color /= ( *color + pow(f * I_a, m) );
max_color = (*color > max_color) ? *color : max_color;
min_color = (*color < min_color) ? *color : min_color;
color++;
}
}
// next line
bits += dib_pitch;
Ybits += y_pitch;
}
} else {
// complete algorithm
// channel averages
Cav[0] = Cav[1] = Cav[2] = 0;
if((a != 1) && (c != 0)) {
// channel averages are not needed when (a == 1) or (c == 0)
bits = (BYTE*)FreeImage_GetBits(dib);
for(y = 0; y < height; y++) {
float *color = (float*)bits;
for(x = 0; x < width; x++) {
for(i = 0; i < 3; i++) {
Cav[i] += *color;
color++;
}
}
// next line
bits += dib_pitch;
}
const float image_size = (float)width * height;
for(i = 0; i < 3; i++) {
Cav[i] /= image_size;
}
( run in 1.220 second using v1.01-cache-2.11-cpan-70e19b8f4f1 )