void TestBuildImage( BUILD_TESTS _type ) { try { switch ( _type ) { case BUILD_TESTS.FILL_PIXEL: // Write pixel per pixel m_imageFile = new ImageFile( 378, 237, ImageFile.PIXEL_FORMAT.RGB16, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); for ( uint Y=0; Y < m_imageFile.Height; Y++ ) { for ( uint X=0; X < m_imageFile.Width; X++ ) { float R = (float) (1+X) / m_imageFile.Width; float G = (float) (1+Y) / m_imageFile.Height; m_imageFile[X,Y] = new float4( R, G, 1.0f-0.5f*(R+G), 1 ); } } break; case BUILD_TESTS.FILL_SCANLINE: // Write scanline per scanline m_imageFile = new ImageFile( 378, 237, ImageFile.PIXEL_FORMAT.RGB16, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); float4[] scanline = new float4[m_imageFile.Width]; for ( uint Y=0; Y < m_imageFile.Height; Y++ ) { for ( uint X=0; X < m_imageFile.Width; X++ ) { float R = 1.0f - (float) (1+X) / m_imageFile.Width; float G = (float) (1+Y) / m_imageFile.Height; scanline[X].Set( R, G, 1.0f-0.5f*(R+G), 1 ); } m_imageFile.WriteScanline( Y, scanline ); } break; // Buddhabrot case BUILD_TESTS.ADDITIVE_BUDDHABROT: { m_imageFile = new ImageFile( 378, 237, ImageFile.PIXEL_FORMAT.RGB16, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); uint W = m_imageFile.Width; uint H = m_imageFile.Height; float2 Z, Z0; int iterations = 50; float4 inc = (1.0f / iterations) * float4.One; float zoom = 2.0f; float invZoom = 1.0f / zoom; #if DIRECT_WRITE // Either directly accumulate to image for ( uint Y=0; Y < H; Y++ ) { Z0.y = zoom * (Y - 0.5f * H) / H; for ( uint X=0; X < W; X++ ) { Z0.x = zoom * (X - 0.5f * W) / H; Z = Z0; for ( int i=0; i < iterations; i++ ) { Z.Set( Z.x*Z.x - Z.y*Z.y + Z0.x, 2.0f * Z.x * Z.y + Z0.y ); int Nx = (int) (invZoom * Z.x * H + 0.5f * W); int Ny = (int) (invZoom * Z.y * H + 0.5f * H); if ( Nx >= 0 && Nx < W && Ny >= 0 && Ny < H ) { // float4 tagada = (float4) m_imageFile[(uint)Nx,(uint)Ny]; // tagada += inc; // m_imageFile[(uint)Nx,(uint)Ny] = tagada; m_imageFile.Add( (uint)Nx, (uint)Ny, inc ); } } } } #else // Or accumulate to a temp array and write result (this is obviously faster!) float[,] accumulators = new float[W,H]; for ( uint Y=0; Y < H; Y++ ) { Z0.y = zoom * (Y - 0.5f * H) / H; for ( uint X=0; X < W; X++ ) { Z0.x = zoom * (X - 0.5f * W) / H; Z = Z0; for ( int i=0; i < iterations; i++ ) { Z.Set( Z.x*Z.x - Z.y*Z.y + Z0.x, 2.0f * Z.x * Z.y + Z0.y ); int Nx = (int) (invZoom * Z.x * H + 0.5f * W); int Ny = (int) (invZoom * Z.y * H + 0.5f * H); if ( Nx >= 0 && Nx < W && Ny >= 0 && Ny < H ) accumulators[Nx, Ny] += inc.x; } } } float4 temp = new float4(); for ( uint Y=0; Y < H; Y++ ) { for ( uint X=0; X < W; X++ ) { float a = accumulators[X,Y]; temp.Set( a, a, a, 1 ); m_imageFile[X,Y] = temp; } } #endif } break; case BUILD_TESTS.STRESS_BUILD: ImageFile.PIXEL_FORMAT[] formats = new ImageFile.PIXEL_FORMAT[] { ImageFile.PIXEL_FORMAT.R8, ImageFile.PIXEL_FORMAT.RG8, ImageFile.PIXEL_FORMAT.RGB8, ImageFile.PIXEL_FORMAT.RGBA8, ImageFile.PIXEL_FORMAT.R16, // ImageFile.PIXEL_FORMAT.RG16, ImageFile.PIXEL_FORMAT.RGB16, ImageFile.PIXEL_FORMAT.RGBA16, ImageFile.PIXEL_FORMAT.R16F, ImageFile.PIXEL_FORMAT.RG16F, ImageFile.PIXEL_FORMAT.RGB16F, ImageFile.PIXEL_FORMAT.RGBA16F, ImageFile.PIXEL_FORMAT.R32F, // ImageFile.PIXEL_FORMAT.RG32F, ImageFile.PIXEL_FORMAT.RGB32F, ImageFile.PIXEL_FORMAT.RGBA32F, }; Random RNG = new Random( 1 ); for ( int i=0; i < 1000; i++ ) { uint W = 100 + (uint) (1000 * RNG.NextDouble()); uint H = 100 + (uint) (1000 * RNG.NextDouble()); ImageFile.PIXEL_FORMAT format = formats[RNG.Next( formats.Length-1 )]; m_imageFile = new ImageFile( W, H,format, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); m_imageFile.Dispose(); } m_imageFile = new ImageFile( 1000, 1000, ImageFile.PIXEL_FORMAT.RGBA8, new ColorProfile( ColorProfile.STANDARD_PROFILE.sRGB ) ); m_imageFile.Clear( new float4( 0, 1, 0.2f, 1 ) ); break; } panelBuild.Bitmap = m_imageFile.AsBitmap; } catch ( Exception _e ) { MessageBox.Show( "Error: " + _e.Message ); } }
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; }