public float4 XYZ2RGB( float4 _XYZ ) { // Transform into RGB return _XYZ * MAT_XYZ2RGB; }
void UpdateGraph() { double time = (DateTime.Now - m_startTime).TotalSeconds; TestTransform( time ); m_image.Clear( float4.One ); float2 rangeX = new float2( 0.0f, 1024.0f ); float2 rangeY = new float2( -1, 1 ); // Plot input signal // m_image.PlotGraphAutoRangeY( m_black, rangeX, ref rangeY, ( float x ) => { m_image.PlotGraph( m_black, rangeX, rangeY, ( float x ) => { int X = Math.Max( 0, Math.Min( 1023, (int) x ) ); return (float) m_signalSource[X].r; } ); // Plot reconstructed signals (Real and Imaginary parts) m_image.PlotGraph( m_red, rangeX, rangeY, ( float x ) => { int X = Math.Max( 0, Math.Min( 1023, (int) x ) ); return (float) m_signalReconstructed[X].r; } ); m_image.PlotGraph( m_blue, rangeX, rangeY, ( float x ) => { int X = Math.Max( 0, Math.Min( 1023, (int) x ) ); return (float) m_signalReconstructed[X].i; } ); m_image.PlotAxes( m_black, rangeX, rangeY, 16.0f, 0.1f ); ////////////////////////////////////////////////////////////////////////// // Render spectrum as (Real=Red, Imaginary=Blue) vertical lines for each frequency float2 cornerMin = m_image.RangedCoordinates2ImageCoordinates( rangeX, rangeY, new float2( rangeX.x, -1.0f ) ); float2 cornerMax = m_image.RangedCoordinates2ImageCoordinates( rangeX, rangeY, new float2( rangeX.y, +1.0f ) ); float2 delta = cornerMax - cornerMin; float zeroY = cornerMin.y + 0.5f * delta.y; float2 Xr0 = new float2( 0, zeroY ); float2 Xr1 = new float2( 0, 0 ); float2 Xi0 = new float2( 0, zeroY ); float2 Xi1 = new float2( 0, 0 ); float scale = 10.0f; float4 spectrumColorRe = new float4( 1, 0.25f, 0, 1 ); float4 spectrumColorIm = new float4( 0, 0.5f, 1, 1 ); int size = m_spectrum.Length; int halfSize = size >> 1; for ( int i=0; i < m_spectrum.Length; i++ ) { float X = cornerMin.x + i * delta.x / m_spectrum.Length; // int frequencyIndex = i; // Show spectrum as output by FFT int frequencyIndex = (i + halfSize) % size; // Show offset spectrum with DC term in the middle Xr0.x = X; Xr1.x = X; Xr1.y = cornerMin.y + 0.5f * (scale * (float) m_spectrum[frequencyIndex].r + 1.0f) * delta.y; Xi0.x = X+1; Xi1.x = X+1; Xi1.y = cornerMin.y + 0.5f * (scale * (float) m_spectrum[frequencyIndex].i + 1.0f) * delta.y; m_image.DrawLine( spectrumColorRe, Xr0, Xr1 ); m_image.DrawLine( spectrumColorIm, Xi0, Xi1 ); } imagePanel.Bitmap = m_image.AsBitmap; }
protected void DrawPoint( int _X, int _Y, int _size, ref float4 _color ) { uint minX = (uint) Math.Max( 0, _X-_size ); uint minY = (uint) Math.Max( 0, _Y-_size ); uint maxX = (uint) Math.Min( m_imageFile.Width, _X + _size+1 ); uint maxY = (uint) Math.Min( m_imageFile.Height, _Y + _size+1 ); for ( uint Y=minY; Y < maxY; Y++ ) for ( uint X=minX; X < maxX; X++ ) m_imageFile[X,Y] = _color; }
public static float4 Parse( string v ) { string[] Components = v.Split( ';' ); if ( Components.Length < 4 ) throw new Exception( "Not enough vector components!" ); float4 Result = new float4(); if ( !float.TryParse( Components[0].Trim(), out Result.x ) ) throw new Exception( "Can't parse X field!" ); if ( !float.TryParse( Components[1].Trim(), out Result.y ) ) throw new Exception( "Can't parse Y field!" ); if ( !float.TryParse( Components[2].Trim(), out Result.z ) ) throw new Exception( "Can't parse Z field!" ); if ( !float.TryParse( Components[3].Trim(), out Result.w ) ) throw new Exception( "Can't parse W field!" ); return Result; }
private static int[] ms_Index = { 0, 1, 2, 3, 0, 1, 2 }; // This array gives the index of the current component #endregion Fields #region Constructors public float4x4( float[] _a ) { row0 = new float4( _a[0], _a[1], _a[2], _a[3] ); row1 = new float4( _a[4], _a[5], _a[6], _a[7] ); row2 = new float4( _a[8], _a[9], _a[10], _a[11] ); row3 = new float4( _a[12], _a[13], _a[14], _a[15] ); }
public void Write( float4 _Color ) { R = _Color.x; G = _Color.y; }
public void Write( float4 _Color ) { R = PF_Empty.ToUShort(_Color.x); G = PF_Empty.ToUShort(_Color.y); B = PF_Empty.ToUShort(_Color.z); A = PF_Empty.ToUShort(_Color.w); }
/// <summary> /// Converts a RGB color to a CIEXYZ color /// </summary> /// <param name="_RGB"></param> /// <returns></returns> public float4 RGB2XYZ( float4 _RGB ) { return m_InternalConverter.RGB2XYZ( _RGB ); }
/// <summary> /// Converts a RGB color to a CIEXYZ color /// </summary> /// <param name="_RGB"></param> public void RGB2XYZ( float4[,] _RGB, float4[,] _XYZ ) { m_InternalConverter.RGB2XYZ( _RGB, _XYZ ); }
public float4 XYZ2RGB( float4 _XYZ ) { // Transform into RGB _XYZ = _XYZ * MAT_XYZ2RGB; // Gamma correct _XYZ.x = _XYZ.x > 0.0031308f ? 1.055f * (float) Math.Pow( _XYZ.x, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * _XYZ.x; _XYZ.y = _XYZ.y > 0.0031308f ? 1.055f * (float) Math.Pow( _XYZ.y, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * _XYZ.y; _XYZ.z = _XYZ.z > 0.0031308f ? 1.055f * (float) Math.Pow( _XYZ.z, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * _XYZ.z; return _XYZ; }
public void XYZ2RGB( float4[,] _XYZ, float4[,] _RGB ) { int W = _XYZ.GetLength( 0 ); int H = _XYZ.GetLength( 1 ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { float4 XYZ = _XYZ[X,Y]; // Transform into RGB XYZ = XYZ * MAT_XYZ2RGB; // Gamma correct _RGB[X,Y].x = XYZ.x > 0.0031308f ? 1.055f * (float) Math.Pow( XYZ.x, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * XYZ.x; _RGB[X,Y].y = XYZ.y > 0.0031308f ? 1.055f * (float) Math.Pow( XYZ.y, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * XYZ.y; _RGB[X,Y].z = XYZ.z > 0.0031308f ? 1.055f * (float) Math.Pow( XYZ.z, 1.0f / GAMMA_EXPONENT_sRGB ) - 0.055f : 12.92f * XYZ.z; _RGB[X,Y].w = XYZ.w; } }
public void RGB2XYZ( float4[,] _RGB, float4[,] _XYZ ) { int W = _RGB.GetLength( 0 ); int H = _RGB.GetLength( 1 ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { float4 RGB = _RGB[X,Y]; // Gamma un-correct RGB.x = RGB.x < 0.04045f ? RGB.x / 12.92f : (float) Math.Pow( (RGB.x + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); RGB.y = RGB.y < 0.04045f ? RGB.y / 12.92f : (float) Math.Pow( (RGB.y + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); RGB.z = RGB.z < 0.04045f ? RGB.z / 12.92f : (float) Math.Pow( (RGB.z + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); // Transform into XYZ _XYZ[X,Y] = RGB * MAT_RGB2XYZ; } }
public float4 RGB2XYZ( float4 _RGB ) { // Gamma un-correct _RGB.x = _RGB.x < 0.04045f ? _RGB.x / 12.92f : (float) Math.Pow( (_RGB.x + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); _RGB.y = _RGB.y < 0.04045f ? _RGB.y / 12.92f : (float) Math.Pow( (_RGB.y + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); _RGB.z = _RGB.z < 0.04045f ? _RGB.z / 12.92f : (float) Math.Pow( (_RGB.z + 0.055f) / 1.055f, GAMMA_EXPONENT_sRGB ); // Transform into XYZ return _RGB * MAT_RGB2XYZ; }
public void XYZ2RGB( float4[,] _XYZ, float4[,] _RGB ) { int W = _XYZ.GetLength( 0 ); int H = _XYZ.GetLength( 1 ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) _RGB[X,Y] = _XYZ[X,Y] * MAT_XYZ2RGB; }
public void Write( float4 _Color ) { }
/// <summary> /// Converts a CIEXYZ color to a RGB color /// </summary> /// <param name="_XYZ"></param> /// <returns></returns> public float4 XYZ2RGB( float4 _XYZ ) { return m_InternalConverter.XYZ2RGB( _XYZ ); }
public void Write( float4 _Color ) { R = PF_Empty.ToUShort(_Color.x); }
/// <summary> /// Converts a CIEXYZ color to a RGB color /// </summary> /// <param name="_XYZ"></param> public void XYZ2RGB( float4[,] _XYZ, float4[,] _RGB ) { m_InternalConverter.XYZ2RGB( _XYZ, _RGB ); }
public void Write( float4 _Color ) { R = PF_Empty.ToByte(_Color.x); G = PF_Empty.ToByte(_Color.y); }
/// <summary> /// Builds the RGB<->XYZ transforms from chromaticities /// (refer to http://wiki.nuaj.net/index.php/Color_Transforms#XYZ_Matrices for explanations) /// </summary> protected void BuildTransformFromChroma( bool _bCheckGammaCurveOverride ) { float3 xyz_R = new float3( m_Chromaticities.R.x, m_Chromaticities.R.y, 1.0f - m_Chromaticities.R.x - m_Chromaticities.R.y ); float3 xyz_G = new float3( m_Chromaticities.G.x, m_Chromaticities.G.y, 1.0f - m_Chromaticities.G.x - m_Chromaticities.G.y ); float3 xyz_B = new float3( m_Chromaticities.B.x, m_Chromaticities.B.y, 1.0f - m_Chromaticities.B.x - m_Chromaticities.B.y ); float3 XYZ_W = xyY2XYZ( new float3( m_Chromaticities.W.x, m_Chromaticities.W.y, 1.0f ) ); float4x4 M_xyz = new float4x4() { row0 = new float4( xyz_R, 0.0f ), row1 = new float4( xyz_G, 0.0f ), row2 = new float4( xyz_B, 0.0f ), row3 = new float4( 0.0f, 0.0f, 0.0f, 1.0f ) }; M_xyz.Invert(); float4 Sum_RGB = new float4( XYZ_W, 1.0f ) * M_xyz; // Finally, we can retrieve the RGB->XYZ transform m_RGB2XYZ.row0 = new float4( Sum_RGB.x * xyz_R, 0.0f ); m_RGB2XYZ.row1 = new float4( Sum_RGB.y * xyz_G, 0.0f ); m_RGB2XYZ.row2 = new float4( Sum_RGB.z * xyz_B, 0.0f ); // And the XYZ->RGB transform m_XYZ2RGB = m_RGB2XYZ; m_XYZ2RGB.Invert(); // ============= Attempt to recognize a standard profile ============= STANDARD_PROFILE RecognizedChromaticity = m_Chromaticities.RecognizedChromaticity; if ( _bCheckGammaCurveOverride ) { // Also ensure the gamma ramp is correct before assigning a standard profile bool bIsGammaCorrect = true; switch ( RecognizedChromaticity ) { case STANDARD_PROFILE.sRGB: bIsGammaCorrect = EnsureGamma( GAMMA_CURVE.sRGB, GAMMA_EXPONENT_sRGB ); break; case STANDARD_PROFILE.ADOBE_RGB_D50: bIsGammaCorrect = EnsureGamma( GAMMA_CURVE.STANDARD, GAMMA_EXPONENT_ADOBE ); break; case STANDARD_PROFILE.ADOBE_RGB_D65: bIsGammaCorrect = EnsureGamma( GAMMA_CURVE.STANDARD, GAMMA_EXPONENT_ADOBE ); break; case STANDARD_PROFILE.PRO_PHOTO: bIsGammaCorrect = EnsureGamma( GAMMA_CURVE.PRO_PHOTO, GAMMA_EXPONENT_PRO_PHOTO ); break; case STANDARD_PROFILE.RADIANCE: bIsGammaCorrect = EnsureGamma( GAMMA_CURVE.STANDARD, 1.0f ); break; } if ( !bIsGammaCorrect ) RecognizedChromaticity = STANDARD_PROFILE.CUSTOM; // A non-standard gamma curves fails our pre-defined design... } // ============= Assign the internal converter depending on the profile ============= switch ( RecognizedChromaticity ) { case STANDARD_PROFILE.sRGB: m_GammaCurve = GAMMA_CURVE.sRGB; m_Gamma = GAMMA_EXPONENT_sRGB; m_InternalConverter = new InternalColorConverter_sRGB(); break; case STANDARD_PROFILE.ADOBE_RGB_D50: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = GAMMA_EXPONENT_ADOBE; m_InternalConverter = new InternalColorConverter_AdobeRGB_D50(); break; case STANDARD_PROFILE.ADOBE_RGB_D65: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = GAMMA_EXPONENT_ADOBE; m_InternalConverter = new InternalColorConverter_AdobeRGB_D65(); break; case STANDARD_PROFILE.PRO_PHOTO: m_GammaCurve = GAMMA_CURVE.PRO_PHOTO; m_Gamma = GAMMA_EXPONENT_PRO_PHOTO; m_InternalConverter = new InternalColorConverter_ProPhoto(); break; case STANDARD_PROFILE.RADIANCE: m_GammaCurve = GAMMA_CURVE.STANDARD; m_Gamma = 1.0f; m_InternalConverter = new InternalColorConverter_Radiance(); break; default: // Switch to one of our generic converters switch ( m_GammaCurve ) { case GAMMA_CURVE.sRGB: m_InternalConverter = new InternalColorConverter_Generic_sRGBGamma( m_RGB2XYZ, m_XYZ2RGB ); break; case GAMMA_CURVE.PRO_PHOTO: m_InternalConverter = new InternalColorConverter_Generic_ProPhoto( m_RGB2XYZ, m_XYZ2RGB ); break; case GAMMA_CURVE.STANDARD: if ( Math.Abs( m_Gamma - 1.0f ) < 1e-3f ) m_InternalConverter = new InternalColorConverter_Generic_NoGamma( m_RGB2XYZ, m_XYZ2RGB ); else m_InternalConverter = new InternalColorConverter_Generic_StandardGamma( m_RGB2XYZ, m_XYZ2RGB, m_Gamma ); break; } break; } }
public void Write( float4 _Color ) { R = _Color.x; G = _Color.y; B = _Color.z; A = _Color.w; }
public float4 RGB2XYZ( float4 _RGB ) { // Gamma un-correct _RGB.x = (float) Math.Pow( _RGB.x, GAMMA_EXPONENT_ADOBE ); _RGB.y = (float) Math.Pow( _RGB.y, GAMMA_EXPONENT_ADOBE ); _RGB.z = (float) Math.Pow( _RGB.z, GAMMA_EXPONENT_ADOBE ); // Transform into XYZ return _RGB * MAT_RGB2XYZ; }
public float dot( float4 b ) { return x*b.x + y*b.y + z*b.z + w*b.w; }
public void RGB2XYZ( float4[,] _RGB, float4[,] _XYZ ) { int W = _RGB.GetLength( 0 ); int H = _RGB.GetLength( 1 ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { float4 RGB = _RGB[X,Y]; // Gamma un-correct RGB.x = (float) Math.Pow( RGB.x, GAMMA_EXPONENT_ADOBE ); RGB.y = (float) Math.Pow( RGB.y, GAMMA_EXPONENT_ADOBE ); RGB.z = (float) Math.Pow( RGB.z, GAMMA_EXPONENT_ADOBE ); // Transform into XYZ _XYZ[X,Y] = RGB * MAT_RGB2XYZ; } }
public void Invert() { float fDet = Determinant(); if ( (float) System.Math.Abs(fDet) < float.Epsilon ) throw new Exception( "Matrix is not invertible!" ); // The matrix is not invertible! Singular case! float fIDet = 1.0f / fDet; float4x4 Temp = new float4x4(); Temp[0, 0] = CoFactor( 0, 0 ) * fIDet; Temp[1, 0] = CoFactor( 0, 1 ) * fIDet; Temp[2, 0] = CoFactor( 0, 2 ) * fIDet; Temp[3, 0] = CoFactor( 0, 3 ) * fIDet; Temp[0, 1] = CoFactor( 1, 0 ) * fIDet; Temp[1, 1] = CoFactor( 1, 1 ) * fIDet; Temp[2, 1] = CoFactor( 1, 2 ) * fIDet; Temp[3, 1] = CoFactor( 1, 3 ) * fIDet; Temp[0, 2] = CoFactor( 2, 0 ) * fIDet; Temp[1, 2] = CoFactor( 2, 1 ) * fIDet; Temp[2, 2] = CoFactor( 2, 2 ) * fIDet; Temp[3, 2] = CoFactor( 2, 3 ) * fIDet; Temp[0, 3] = CoFactor( 3, 0 ) * fIDet; Temp[1, 3] = CoFactor( 3, 1 ) * fIDet; Temp[2, 3] = CoFactor( 3, 2 ) * fIDet; Temp[3, 3] = CoFactor( 3, 3 ) * fIDet; row0 = Temp.row0; row1 = Temp.row1; row2 = Temp.row2; row3 = Temp.row3; }
// NOTE: Alpha is ignored, RGB is encoded in RGBE public void Write( float4 _Color ) { float fMaxComponent = Math.Max( _Color.x, Math.Max( _Color.y, _Color.z ) ); if ( fMaxComponent < 1e-16f ) { // Too low to encode... R = G = B = E = 0; return; } double CompleteExponent = Math.Log( fMaxComponent ) / Math.Log( 2.0 ); int Exponent = (int) Math.Ceiling( CompleteExponent ); double Mantissa = fMaxComponent / Math.Pow( 2.0f, Exponent ); if ( Mantissa == 1.0 ) { // Step to next order Mantissa = 0.5; Exponent++; } double Debug0 = Mantissa * Math.Pow( 2.0, Exponent ); fMaxComponent = (float) Mantissa * 255.99999999f / fMaxComponent; R = (byte) (_Color.x * fMaxComponent); G = (byte) (_Color.y * fMaxComponent); B = (byte) (_Color.z * fMaxComponent); E = (byte) (Exponent + 128 ); }
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; }
public void Write( float4 _Color ) { D = _Color.x; }
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 ); } }
public void RGB2XYZ( float4[,] _RGB, float4[,] _XYZ ) { int W = _RGB.GetLength( 0 ); int H = _RGB.GetLength( 1 ); for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) _XYZ[X,Y] = _RGB[X,Y] * MAT_RGB2XYZ; }