void TestBlackBodyRadiation( TEST_COLOR_PROFILES _type ) { ColorProfile sRGB = new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ); switch ( _type ) { // Load the color gamut and try and plot the locii of various white points // case TEST_COLOR_PROFILES.DRAW_WHITE_POINT_LOCI: { m_imageFile.Load( new System.IO.FileInfo( @"..\..\Images\In\xyGamut.png" ) ); float2 cornerZero = new float2( 114, 1336 ); // xy=(0.0, 0.0) float2 cornerPoint8Point9 = new float2( 1257, 49 ); // xy=(0.8, 0.9) // Check XYZ<->RGB and XYZ<->xyY converter code // float3 xyY = new float3(); // float3 XYZ = new float3(); // // float4 testRGB = new float4(); // float4 testXYZ = new float4(); // for ( int i=1; i <= 10; i++ ) { // float f = i / 10.0f; // testRGB.Set( 1*f, 1*f, 1*f, 1.0f ); // sRGB.RGB2XYZ( testRGB, ref testXYZ ); // // XYZ.Set( testXYZ.x, testXYZ.y, testXYZ.z ); // ColorProfile.XYZ2xyY( XYZ, ref xyY ); // ColorProfile.xyY2XYZ( xyY, ref XYZ ); // testXYZ.Set( XYZ, 1.0f ); // // sRGB.XYZ2RGB( testXYZ, ref testRGB ); // } float2 xy = new float2(); float4 color = new float4( 1, 0, 0, 1 ); float4 color2 = new float4( 0, 0.5f, 1, 1 ); for ( int locusIndex=0; locusIndex < 20; locusIndex++ ) { // float T = 1500.0f + (8000.0f - 1500.0f) * locusIndex / 20.0f; float T = 1500.0f + 500.0f * locusIndex; ColorProfile.ComputeWhitePointChromaticities( T, ref xy ); // Plot with the color of the white point // ColorProfile.xyY2XYZ( new float3( xy, 1.0f ), ref XYZ ); // sRGB.XYZ2RGB( new float4( XYZ, 1.0f ), ref color ); float2 fPos = cornerZero + (cornerPoint8Point9 - cornerZero) * new float2( xy.x / 0.8f, xy.y / 0.9f ); DrawPoint( (int) fPos.x, (int) fPos.y, 6, ref color ); ColorProfile.ComputeWhitePointChromaticitiesAnalytical( T, ref xy ); fPos = cornerZero + (cornerPoint8Point9 - cornerZero) * new float2( xy.x / 0.8f, xy.y / 0.9f ); DrawPoint( (int) fPos.x, (int) fPos.y, 3, ref color2 ); } } break; case TEST_COLOR_PROFILES.BUILD_WHITE_POINTS_GRADIENT_NO_BALANCE: case TEST_COLOR_PROFILES.BUILD_WHITE_POINTS_GRADIENT_BALANCE_D50_TO_D65: case TEST_COLOR_PROFILES.BUILD_WHITE_POINTS_GRADIENT_BALANCE_D65_TO_D50: { float3x3 whiteBalancingXYZ = float3x3.Identity; float whitePointCCT = 6500.0f; if ( _type == TEST_COLOR_PROFILES.BUILD_WHITE_POINTS_GRADIENT_BALANCE_D50_TO_D65 ) { // Compute white balancing from a D50 to a D65 illuminant whiteBalancingXYZ = ColorProfile.ComputeWhiteBalanceXYZMatrix( ColorProfile.Chromaticities.AdobeRGB_D50, ColorProfile.ILLUMINANT_D65 ); whitePointCCT = 5000.0f; } else if ( _type == TEST_COLOR_PROFILES.BUILD_WHITE_POINTS_GRADIENT_BALANCE_D65_TO_D50 ) { // Compute white balancing from a D65 to a D50 illuminant whiteBalancingXYZ = ColorProfile.ComputeWhiteBalanceXYZMatrix( ColorProfile.Chromaticities.sRGB, ColorProfile.ILLUMINANT_D50 ); whitePointCCT = 10000.0f; // ?? Actually we're already in D65 so assuming we're starting from a D50 illuminant instead actually pushes the white point far away... } // Build a gradient of white points from 1500K to 8000K m_imageFile.Init( 650, 32, ImageFile.PIXEL_FORMAT.RGBA8, sRGB ); float4 RGB = new float4( 0, 0, 0, 0 ); float3 XYZ = new float3( 0, 0, 0 ); float2 xy = new float2(); for ( uint X=0; X < 650; X++ ) { float T = 1500 + 10 * X; // From 1500K to 8000K ColorProfile.ComputeWhitePointChromaticities( T, ref xy ); ColorProfile.xyY2XYZ( new float3( xy, 1.0f ), ref XYZ ); // Apply white balancing XYZ *= whiteBalancingXYZ; sRGB.XYZ2RGB( new float4( XYZ, 1 ), ref RGB ); // "Normalize" //RGB /= Math.Max( Math.Max( RGB.x, RGB.y ), RGB.z ); // Isolate D65 if ( Math.Abs( T - whitePointCCT ) < 10.0f ) RGB.Set( 1, 0, 1, 1 ); for ( uint Y=0; Y < 32; Y++ ) { m_imageFile[X,Y] = RGB; } } // Check white balancing yields correct results // float3 XYZ_R_in = new float3(); // float3 XYZ_G_in = new float3(); // float3 XYZ_B_in = new float3(); // float3 XYZ_W_in = new float3(); // sRGB.RGB2XYZ( new float3( 1, 0, 0 ), ref XYZ_R_in ); // sRGB.RGB2XYZ( new float3( 0, 1, 0 ), ref XYZ_G_in ); // sRGB.RGB2XYZ( new float3( 0, 0, 1 ), ref XYZ_B_in ); // sRGB.RGB2XYZ( new float3( 1, 1, 1 ), ref XYZ_W_in ); // // float3 XYZ_R_out = XYZ_R_in * XYZ_D65_D50; // float3 XYZ_G_out = XYZ_G_in * XYZ_D65_D50; // float3 XYZ_B_out = XYZ_B_in * XYZ_D65_D50; // float3 XYZ_W_out = XYZ_W_in * XYZ_D65_D50; // // float3 xyY_R_out = new float3(); // float3 xyY_G_out = new float3(); // float3 xyY_B_out = new float3(); // float3 xyY_W_out = new float3(); // ColorProfile.XYZ2xyY( XYZ_R_out, ref xyY_R_out ); // ColorProfile.XYZ2xyY( XYZ_G_out, ref xyY_G_out ); // ColorProfile.XYZ2xyY( XYZ_B_out, ref xyY_B_out ); // ColorProfile.XYZ2xyY( XYZ_W_out, ref xyY_W_out ); } break; } panelColorProfile.Bitmap = m_imageFile.AsBitmap; }
/// <summary> /// Decodes a RGBE formatted image into a plain floating-point image /// </summary> /// <param name="_Source">The source RGBE formatted image</param> /// <param name="_bSourceIsXYZ">Tells if the source image is encoded as XYZE rather than RGBE</param> /// <param name="_Target">The target float4 image</param> /// <param name="_bTargetNeedsXYZ">Tells if the target needs to be in CIE XYZ space (true) or RGB (false)</param> /// <param name="_ColorProfile">The color profile for the image</param> public static void DecodeRGBEImage( PF_RGBE[,] _Source, bool _bSourceIsXYZ, float4[,] _Target, bool _bTargetNeedsXYZ, ColorProfile _ColorProfile ) { if ( _bSourceIsXYZ ^ _bTargetNeedsXYZ ) { // Requires conversion... if ( _bSourceIsXYZ ) { // Convert from XYZ to RGB for ( int Y=0; Y < _Source.GetLength( 1 ); Y++ ) for ( int X=0; X < _Source.GetLength( 0 ); X++ ) _Target[X,Y] = _ColorProfile.XYZ2RGB( new float4( _Source[X,Y].DecodedColor.x, _Source[X,Y].DecodedColor.y, _Source[X,Y].DecodedColor.z, 1.0f ) ); } else { // Convert from RGB to XYZ for ( int Y=0; Y < _Source.GetLength( 1 ); Y++ ) for ( int X=0; X < _Source.GetLength( 0 ); X++ ) _Target[X,Y] = _ColorProfile.RGB2XYZ( new float4( _Source[X,Y].DecodedColor.x, _Source[X,Y].DecodedColor.y, _Source[X,Y].DecodedColor.z, 1.0f ) ); } return; } // Simply decode vector and leave as-is for ( int Y=0; Y < _Source.GetLength( 1 ); Y++ ) for ( int X=0; X < _Source.GetLength( 0 ); X++ ) _Target[X,Y] = new float4( _Source[X,Y].DecodedColor.x, _Source[X,Y].DecodedColor.y, _Source[X,Y].DecodedColor.z, 1.0f ); }