static void SaveTestsRGB() { ImageUtility.ColorProfile Profile_sRGB = new ImageUtility.ColorProfile(ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB); ImageUtility.ColorProfile Profile_Linear = new ImageUtility.ColorProfile(ImageUtility.ColorProfile.Chromaticities.sRGB, ImageUtility.ColorProfile.GAMMA_CURVE.STANDARD, 1.0f); ImageUtility.Bitmap Gray_sRGB = new ImageUtility.Bitmap(64, 64, Profile_sRGB); ImageUtility.Bitmap Gray_Linear = new ImageUtility.Bitmap(64, 64, Profile_Linear); ImageUtility.Bitmap Gradient_sRGB = new ImageUtility.Bitmap(128, 16, Profile_sRGB); ImageUtility.Bitmap Gradient_Linear = new ImageUtility.Bitmap(128, 16, Profile_Linear); for (int Y = 0; Y < Gray_sRGB.Height; Y++) { for (int X = 0; X < Gray_sRGB.Width; X++) { Gray_sRGB.ContentXYZ[X, Y] = Profile_Linear.RGB2XYZ(new ImageUtility.float4(0.5f, 0.5f, 0.5f, 1.0f)); Gray_Linear.ContentXYZ[X, Y] = Profile_Linear.RGB2XYZ(new ImageUtility.float4(0.5f, 0.5f, 0.5f, 1.0f)); } } int W = Gradient_sRGB.Width; for (int Y = 0; Y < Gradient_sRGB.Height; Y++) { for (int X = 0; X < Gradient_sRGB.Width; X++) { float C = (float)(X + 0.5f) / W; Gradient_sRGB.ContentXYZ[X, Y] = Profile_Linear.RGB2XYZ(new ImageUtility.float4(C, C, C, 1.0f)); Gradient_Linear.ContentXYZ[X, Y] = Profile_Linear.RGB2XYZ(new ImageUtility.float4(C, C, C, 1.0f)); } } Gray_sRGB.Save(new FileInfo("./Gray128_sRGB.png")); Gray_Linear.Save(new FileInfo("./Gray128_Linear.png")); Gradient_sRGB.Save(new FileInfo("./Gradient_sRGB.png")); Gradient_Linear.Save(new FileInfo("./Gradient_Linear.png")); }
void TestChromaRanges() { ImageUtility.ColorProfile profile = new ImageUtility.ColorProfile(ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB); float3 tempFloat3 = new float3(0, 0, 0); float4 tempFloat4 = new float4(0, 0, 0, 1); float Ygo, Cg, Co; ranges_t[] ranges = new ranges_t[4]; for (int lumaIndex = 0; lumaIndex < ranges.Length; lumaIndex++) { ranges_t range = new ranges_t(); ranges[lumaIndex] = range; float L = (1 + lumaIndex) / 255.0f; for (int R = 0; R < 256; R++) { for (int G = 0; G < 256; G++) { for (int B = 0; B < 256; B++) { tempFloat4.x = L * R; tempFloat4.y = L * G; tempFloat4.z = L * B; // Convert to YCoCg // Ygo = 0.25f * tempFloat4.x + 0.5f * tempFloat4.y + 0.25f * tempFloat4.z; // Cg = -0.25f * tempFloat4.x + 0.5f * tempFloat4.y - 0.25f * tempFloat4.z; // Co = 0.50f * tempFloat4.x + 0.0f * tempFloat4.y - 0.50f * tempFloat4.z; RGB2YCoCg(tempFloat4.x, tempFloat4.y, tempFloat4.z, out Ygo, out Co, out Cg); YCoCg2RGB(Ygo, Co, Cg, out tempFloat3.x, out tempFloat3.y, out tempFloat3.z); if (Math.Abs(tempFloat3.x - tempFloat4.x) > 1e-6) { throw new Exception("RHA!"); } if (Math.Abs(tempFloat3.y - tempFloat4.y) > 1e-6) { throw new Exception("RHA!"); } if (Math.Abs(tempFloat3.z - tempFloat4.z) > 1e-6) { throw new Exception("RHA!"); } // Convert to xyY float4 XYZ = float4.Zero; profile.RGB2XYZ(tempFloat4, ref XYZ); tempFloat3.x = XYZ.x; tempFloat3.y = XYZ.y; tempFloat3.z = XYZ.z; float3 xyY = float3.Zero; ImageUtility.ColorProfile.XYZ2xyY(tempFloat3, ref xyY); // Update ranges range.Ygo_min = Math.Min(range.Ygo_min, Ygo); range.Ygo_max = Math.Max(range.Ygo_max, Ygo); range.Cg_min = Math.Min(range.Cg_min, Cg); range.Cg_max = Math.Max(range.Cg_max, Cg); range.Co_min = Math.Min(range.Co_min, Co); range.Co_max = Math.Max(range.Co_max, Co); range.Y_min = Math.Min(range.Y_min, xyY.z); range.Y_max = Math.Max(range.Y_max, xyY.z); range.x_min = Math.Min(range.x_min, xyY.x); range.x_max = Math.Max(range.x_max, xyY.x); range.y_min = Math.Min(range.y_min, xyY.y); range.y_max = Math.Max(range.y_max, xyY.y); } } } } }
/// <summary> /// Rebuilds and assigns the bitmap for the output panel from the loaded image /// </summary> private void RebuildImage() { if ( m_BitmapXYZ == null ) return; bool sRGB = checkBoxsRGB.Checked; bool SpatialCorrection = checkBoxSpatialLuminanceCorrection.Checked; ImageUtility.float4[,] Image = new ImageUtility.float4[m_BitmapXYZ.Width,m_BitmapXYZ.Height]; int W = m_BitmapXYZ.Width; int H = m_BitmapXYZ.Height; if ( checkBoxLuminance.Checked ) { // Convert into luminances only for ( int Y = 0; Y < H; Y++ ) for ( int X = 0; X < W; X++ ) { float L = m_BitmapXYZ.ContentXYZ[X, Y].y; if ( SpatialCorrection ) L*= m_CalibrationDatabase.GetSpatialLuminanceCorrectionFactor( (float) X / W, (float) Y / H ); if ( sRGB ) L = ImageUtility.ColorProfile.Linear2sRGB( L ); Image[X, Y].x = L; Image[X, Y].y = L; Image[X, Y].z = L; } } else { // RGB ImageUtility.float4[,] Content = m_BitmapXYZ.ContentXYZ; if ( checkBoxSpatialLuminanceCorrection.Checked ) { Content = new ImageUtility.float4[m_BitmapXYZ.Width,m_BitmapXYZ.Height]; Array.Copy( m_BitmapXYZ.ContentXYZ, Content, Content.LongLength ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { ImageUtility.float4 XYZ = Content[X,Y]; ImageUtility.float3 xyY = ImageUtility.ColorProfile.XYZ2xyY( (ImageUtility.float3) XYZ ); xyY.z *= m_CalibrationDatabase.GetSpatialLuminanceCorrectionFactor( (float) X / W, (float) Y / H ); XYZ = new ImageUtility.float4( ImageUtility.ColorProfile.xyY2XYZ( xyY ), XYZ.w ); Content[X,Y] = XYZ; } } // Build conversion profile ImageUtility.ColorProfile Profile = new ImageUtility.ColorProfile( ImageUtility.ColorProfile.Chromaticities.sRGB, // Always use standard sRGB illuminant sRGB ? ImageUtility.ColorProfile.GAMMA_CURVE.sRGB : ImageUtility.ColorProfile.GAMMA_CURVE.STANDARD, // Either use sRGB linear toe or a standard gamma sRGB ? ImageUtility.ColorProfile.GAMMA_EXPONENT_sRGB : 1.0f ); // Either use sRGB gamma or linear gamma // Convert Profile.XYZ2RGB( Content, Image ); } outputPanel.Image = Image; }
static void SaveTestsRGB() { ImageUtility.ColorProfile Profile_sRGB = new ImageUtility.ColorProfile( ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB ); ImageUtility.ColorProfile Profile_Linear = new ImageUtility.ColorProfile( ImageUtility.ColorProfile.Chromaticities.sRGB, ImageUtility.ColorProfile.GAMMA_CURVE.STANDARD, 1.0f ); ImageUtility.Bitmap Gray_sRGB = new ImageUtility.Bitmap( 64, 64, Profile_sRGB ); ImageUtility.Bitmap Gray_Linear = new ImageUtility.Bitmap( 64, 64, Profile_Linear ); ImageUtility.Bitmap Gradient_sRGB = new ImageUtility.Bitmap( 128, 16, Profile_sRGB ); ImageUtility.Bitmap Gradient_Linear = new ImageUtility.Bitmap( 128, 16, Profile_Linear ); for ( int Y=0; Y < Gray_sRGB.Height; Y++ ) for ( int X=0; X < Gray_sRGB.Width; X++ ) { Gray_sRGB.ContentXYZ[X,Y] = Profile_Linear.RGB2XYZ( new ImageUtility.float4( 0.5f, 0.5f, 0.5f, 1.0f ) ); Gray_Linear.ContentXYZ[X,Y] = Profile_Linear.RGB2XYZ( new ImageUtility.float4( 0.5f, 0.5f, 0.5f, 1.0f ) ); } int W = Gradient_sRGB.Width; for ( int Y=0; Y < Gradient_sRGB.Height; Y++ ) for ( int X=0; X < Gradient_sRGB.Width; X++ ) { float C = (float) (X+0.5f) / W; Gradient_sRGB.ContentXYZ[X,Y] = Profile_Linear.RGB2XYZ( new ImageUtility.float4( C, C, C, 1.0f ) ); Gradient_Linear.ContentXYZ[X,Y] = Profile_Linear.RGB2XYZ( new ImageUtility.float4( C, C, C, 1.0f ) ); } Gray_sRGB.Save( new FileInfo( "./Gray128_sRGB.png" ) ); Gray_Linear.Save( new FileInfo( "./Gray128_Linear.png" ) ); Gradient_sRGB.Save( new FileInfo( "./Gradient_sRGB.png" ) ); Gradient_Linear.Save( new FileInfo( "./Gradient_Linear.png" ) ); }
void TestChromaRanges() { ImageUtility.ColorProfile profile = new ImageUtility.ColorProfile(ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB ); ImageUtility.float3 tempFloat3 = new ImageUtility.float3( 0, 0, 0 ); ImageUtility.float4 tempFloat4 = new ImageUtility.float4( 0, 0, 0, 1 ); float Ygo, Cg, Co; ranges_t[] ranges = new ranges_t[4]; for ( int lumaIndex=0; lumaIndex < ranges.Length; lumaIndex++ ) { ranges_t range = new ranges_t(); ranges[lumaIndex] = range; float L = (1+lumaIndex) / 255.0f; for ( int R=0; R < 256; R++ ) { for ( int G=0; G < 256; G++ ) { for ( int B=0; B < 256; B++ ) { tempFloat4.x = L * R; tempFloat4.y = L * G; tempFloat4.z = L * B; // Convert to YCoCg // Ygo = 0.25f * tempFloat4.x + 0.5f * tempFloat4.y + 0.25f * tempFloat4.z; // Cg = -0.25f * tempFloat4.x + 0.5f * tempFloat4.y - 0.25f * tempFloat4.z; // Co = 0.50f * tempFloat4.x + 0.0f * tempFloat4.y - 0.50f * tempFloat4.z; RGB2YCoCg( tempFloat4.x, tempFloat4.y, tempFloat4.z, out Ygo, out Co, out Cg ); YCoCg2RGB( Ygo, Co, Cg, out tempFloat3.x, out tempFloat3.y, out tempFloat3.z ); if ( Math.Abs( tempFloat3.x - tempFloat4.x ) > 1e-6 ) throw new Exception( "RHA!" ); if ( Math.Abs( tempFloat3.y - tempFloat4.y ) > 1e-6 ) throw new Exception( "RHA!" ); if ( Math.Abs( tempFloat3.z - tempFloat4.z ) > 1e-6 ) throw new Exception( "RHA!" ); // Convert to xyY ImageUtility.float4 XYZ = profile.RGB2XYZ( tempFloat4 ); tempFloat3.x = XYZ.x; tempFloat3.y = XYZ.y; tempFloat3.z = XYZ.z; ImageUtility.float3 xyY = ImageUtility.ColorProfile.XYZ2xyY( tempFloat3 ); // Update ranges range.Ygo_min = Math.Min( range.Ygo_min, Ygo ); range.Ygo_max = Math.Max( range.Ygo_max, Ygo ); range.Cg_min = Math.Min( range.Cg_min, Cg ); range.Cg_max = Math.Max( range.Cg_max, Cg ); range.Co_min = Math.Min( range.Co_min, Co ); range.Co_max = Math.Max( range.Co_max, Co ); range.Y_min = Math.Min( range.Y_min, xyY.z ); range.Y_max = Math.Max( range.Y_max, xyY.z ); range.x_min = Math.Min( range.x_min, xyY.x ); range.x_max = Math.Max( range.x_max, xyY.x ); range.y_min = Math.Min( range.y_min, xyY.y ); range.y_max = Math.Max( range.y_max, xyY.y ); } } } } }
private void Generate() { try { panelParameters.Enabled = false; ////////////////////////////////////////////////////////////////////////// // 1] Apply bilateral filtering to the input texture as a pre-process ApplyBilateralFiltering(m_TextureSource, m_TextureTarget0, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, checkBoxWrap.Checked, BILATERAL_PROGRESS); ////////////////////////////////////////////////////////////////////////// // 2] Compute directional occlusion m_TextureTarget1.RemoveFromLastAssignedSlots(); // Prepare computation parameters m_TextureTarget0.SetCS(0); m_TextureTarget1.SetCSUAV(0); m_SB_Rays.SetInput(1); m_TextureSourceNormal.SetCS(2); m_CB_Input.m.RaysCount = (UInt32)Math.Min(MAX_THREADS, integerTrackbarControlRaysCount.Value); m_CB_Input.m.MaxStepsCount = (UInt32)integerTrackbarControlMaxStepsCount.Value; m_CB_Input.m.Tile = (uint)(checkBoxWrap.Checked ? 1 : 0); m_CB_Input.m.TexelSize_mm = TextureSize_mm / Math.Max(W, H); m_CB_Input.m.Displacement_mm = TextureHeight_mm; // Start if (!m_CS_GenerateSSBumpMap.Use()) { throw new Exception("Can't generate self-shadowed bump map as compute shader failed to compile!"); } int h = Math.Max(1, MAX_LINES * 1024 / W); int CallsCount = (int)Math.Ceiling((float)H / h); for (int i = 0; i < CallsCount; i++) { m_CB_Input.m.Y0 = (UInt32)(i * h); m_CB_Input.UpdateData(); m_CS_GenerateSSBumpMap.Dispatch(W, h, 1); m_Device.Present(true); progressBar.Value = (int)(0.01f * (BILATERAL_PROGRESS + (100 - BILATERAL_PROGRESS) * (i + 1) / (CallsCount)) * progressBar.Maximum); // for ( int a=0; a < 10; a++ ) Application.DoEvents(); } m_TextureTarget1.RemoveFromLastAssignedSlotUAV(); // So we can use it as input for next stage progressBar.Value = progressBar.Maximum; // Compute in a single shot (this is madness!) // m_CB_Input.m.y = 0; // m_CB_Input.UpdateData(); // m_CS_GenerateSSBumpMap.Dispatch( W, H, 1 ); ////////////////////////////////////////////////////////////////////////// // 3] Copy target to staging for CPU readback and update the resulting bitmap m_TextureTarget_CPU.CopyFrom(m_TextureTarget1); ImageUtility.ColorProfile Profile = m_ProfilesRGB; // AO maps are sRGB! (although strange, that's certainly to have more range in dark values) if (m_BitmapResult != null) { m_BitmapResult.Dispose(); } m_BitmapResult = null; m_BitmapResult = new ImageUtility.Bitmap(W, H, Profile); m_BitmapResult.HasAlpha = false; RendererManaged.PixelsBuffer Pixels = m_TextureTarget_CPU.Map(0, 0); using (System.IO.BinaryReader R = Pixels.OpenStreamRead()) for (int Y = 0; Y < H; Y++) { R.BaseStream.Position = Y * Pixels.RowPitch; for (int X = 0; X < W; X++) { float AO = R.ReadSingle(); // Linear value ImageUtility.float4 Color = new ImageUtility.float4(AO, AO, AO, AO); Color = Profile.RGB2XYZ(Color); // Now sRGB value, converted as XYZ m_BitmapResult.ContentXYZ[X, Y] = Color; } } Pixels.Dispose(); m_TextureTarget_CPU.UnMap(0, 0); // Assign result viewportPanelResult.Image = m_BitmapResult; } catch (Exception _e) { MessageBox("An error occurred during generation!\r\n\r\nDetails: ", _e); } finally { panelParameters.Enabled = true; } }