private ImageUtility.float3 IntegrateLuminance( float _X, float _Y, float _Radius, out ImageUtility.float3 _MinXYZ, out ImageUtility.float3 _MaxXYZ, out float _PercentOfBlackValues, out float _PercentOfSaturatedValues )
{
float Radius = Math.Max( 1, _Radius * m_BitmapXYZ.Width );
float CenterX = _X * m_BitmapXYZ.Width;
float CenterY = _Y * m_BitmapXYZ.Height;
float SqRadius = Radius*Radius;
int X0 = Math.Max( 0, Math.Min( m_BitmapXYZ.Width-1, (int) Math.Floor( CenterX - Radius ) ) );
int X1 = Math.Max( 0, Math.Min( m_BitmapXYZ.Width-1, (int) Math.Ceiling( CenterX + Radius ) ) );
int Y0 = Math.Max( 0, Math.Min( m_BitmapXYZ.Height-1, (int) Math.Floor( CenterY - Radius ) ) );
int Y1 = Math.Max( 0, Math.Min( m_BitmapXYZ.Height-1, (int) Math.Ceiling( CenterY + Radius ) ) );
const float SMOOTHSTEP_MAX_RADIUS = 0.2f; // We reach max weight 1 at 20% of the border of the circle
bool ApplySpatialCorrection = checkBoxSpatialLuminanceCorrection.Checked;
int TotalBlackValuesCount = 0;
int TotalSaturatedValuesCount = 0;
int TotalValuesCount = 0;
ImageUtility.float3 SumXYZ = new ImageUtility.float3( 0, 0, 0 );
_MinXYZ = new ImageUtility.float3( 0, +float.MaxValue, 0 );
_MaxXYZ = new ImageUtility.float3( 0, 0, 0 );
float SumWeights = 0.0f;
for ( int Y=Y0; Y < Y1; Y++ )
for ( int X=X0; X < X1; X++ )
{
float SqR = (X-CenterX)*(X-CenterX) + (Y-CenterY)*(Y-CenterY);
if ( SqR > SqRadius )
continue;
float r = (float) Math.Sqrt( SqR ) / Radius; // Nomalized radius
// float Weight = Math.Min( 1.0f, floatTrackbarControl1.Value * (float) Math.Exp( -floatTrackbarControl2.Value * r ) );
float x = Math.Max( 0.0f, Math.Min( 1.0f, (1.0f - r) / SMOOTHSTEP_MAX_RADIUS ) );
float Weight = x*x*(3.0f - 2.0f*x);
//DEBUG m_BitmapXYZ.ContentXYZ[X,Y].y = Weight;
ImageUtility.float3 XYZ = (ImageUtility.float3) m_BitmapXYZ.ContentXYZ[X,Y];
if ( ApplySpatialCorrection )
{
ImageUtility.float3 xyY = ImageUtility.ColorProfile.XYZ2xyY( XYZ );
xyY.z *= m_CalibrationDatabase.GetSpatialLuminanceCorrectionFactor( (float) X / m_BitmapXYZ.Width, (float) Y / m_BitmapXYZ.Height );
XYZ = ImageUtility.ColorProfile.xyY2XYZ( xyY );
}
if ( XYZ.y < 0.001f )
TotalBlackValuesCount++; // Warning!
if ( XYZ.y > 0.999f )
TotalSaturatedValuesCount++; // Warning!
TotalValuesCount++;
if ( XYZ.y < _MinXYZ.y )
_MinXYZ = XYZ;
if ( XYZ.y > _MaxXYZ.y )
_MaxXYZ = XYZ;
SumXYZ += Weight * XYZ;
SumWeights += Weight;
}
//DEBUG RebuildImage();
_PercentOfBlackValues = (float) TotalBlackValuesCount / TotalValuesCount;
_PercentOfSaturatedValues = (float) TotalSaturatedValuesCount / TotalValuesCount;
SumXYZ = (1.0f/SumWeights) * SumXYZ;
return SumXYZ;
}