Esempio n. 1
0
        private unsafe void buttonConvertOld_Click( object sender, EventArgs args )
        {
            if ( openFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;
            if ( saveFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;

            FileInfo	SourceFileName = new FileInfo( openFileDialog.FileName );
            FileInfo	TargetFileName = new FileInfo( saveFileDialog.FileName );

            int			W, H;
            float3[,]	Vectors;
            float		x, y, z;
            using ( TargaImage TGA = new TargaImage( SourceFileName.FullName, false ) )
            {
                // Convert
                byte[]		ImageContent = Bitmap.LoadBitmap( TGA.Image, out W, out H );
                Vectors = new float3[W,H];
                int		rha = 0;
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ )
                    {
                        x = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        y = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        z = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        rha++;	// Skip alpha

                        z = Math.Max( 0.0f, z );

                        float	Norm = 1.0f / (float) Math.Sqrt( x*x + y*y + z*z );
                        Vectors[X,Y].x = x * Norm;
                        Vectors[X,Y].y = y * Norm;
                        Vectors[X,Y].z = z * Norm;
                    }
            }

            // Convert to RG slightly less improved normal
            double	Nx, Ny;
            double	a, b, c = -1.0, d, t;

            ushort[,]	PackedNormal = new ushort[W,H];
            for ( int Y=0; Y < H; Y++ )
                for ( int X=0; X < W; X++ )
                {
                    x = Vectors[X,Y].x;
                    y = Vectors[X,Y].y;
                    z = Vectors[X,Y].z;

                    // Here I'm using the exact algorithm described by http://rgba32.blogspot.fr/2011/02/improved-normal-map-distributions.html
                    a = (x * x) + (y * y);
                    b = z;
                    d = b*b - 4.0*a*c;
                    t = (-b + Math.Sqrt( d )) / (2.0 * a);

                    Nx = x * t;
                    Ny = y * t;

                    Vectors[X,Y].x = (float) (0.5 * (1.0 + Nx));
                    Vectors[X,Y].y = (float) (0.5 * (1.0 + Ny));
                    Vectors[X,Y].z = 0.0f;
                }

            // Save as target PNG
            using ( System.Drawing.Bitmap B = new System.Drawing.Bitmap( W, H, System.Drawing.Imaging.PixelFormat.Format32bppRgb ) )
            {
                System.Drawing.Imaging.BitmapData	LockedBitmap = B.LockBits( new System.Drawing.Rectangle( 0, 0, W, H ), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb );

                for ( int Y=0; Y < H; Y++ )
                {
                    byte*	pScanline = (byte*) LockedBitmap.Scan0 + LockedBitmap.Stride * Y;
                    for ( int X=0; X < W; X++ )
                    {
                        *pScanline++ = 0;
                        *pScanline++ = (byte) (255 * Vectors[X,Y].y);
                        *pScanline++ = (byte) (255 * Vectors[X,Y].x);
                        *pScanline++ = 0xFF;
                    }
                }

                B.UnlockBits( LockedBitmap );

                B.Save( TargetFileName.FullName );
            }
        }
Esempio n. 2
0
        private unsafe void buttonConvertNew_Click( object sender, EventArgs _e )
        {
            if ( openFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;
            if ( saveFileDialog.ShowDialog( this ) != DialogResult.OK )
                return;

            FileInfo	SourceFileName = new FileInfo( openFileDialog.FileName );
            FileInfo	TargetFileName = new FileInfo( saveFileDialog.FileName );

            int			W, H;
            float3[,]	Vectors;
            float		x, y, z;
            using ( TargaImage TGA = new TargaImage( SourceFileName.FullName, false ) )
            {
                // Convert
                byte[]		ImageContent = Bitmap.LoadBitmap( TGA.Image, out W, out H );
                Vectors = new float3[W,H];
                int		rha = 0;
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ )
                    {
                        x = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        y = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        z = 2.0f * ImageContent[rha++] / 255 - 1.0f;
                        rha++;	// Skip alpha

                        z = Math.Max( 0.0f, z );

                        float	Norm = 1.0f / (float) Math.Sqrt( x*x + y*y + z*z );
                        Vectors[X,Y].x = x * Norm;
                        Vectors[X,Y].y = y * Norm;
                        Vectors[X,Y].z = z * Norm;
                    }
            }

            // Convert to RG improved normal
            double	Nx, Ny;
            double	CosPhi, SinPhi, CosTheta, SinTheta, Normalizer;
            double	a = 1.0, b, c, d = 0.0, e, t;

            ushort[,]	PackedNormal = new ushort[W,H];
            for ( int Y=0; Y < H; Y++ )
                for ( int X=0; X < W; X++ )
                {
                    x = Vectors[X,Y].x;
                    y = Vectors[X,Y].y;
                    z = Vectors[X,Y].z;

                    CosTheta = z;
                    SinTheta = Math.Sqrt( 1 - z*z );
                    Normalizer = 1.0 / Math.Max( 1e-10, SinTheta );
                    CosPhi = x * Normalizer;
                    SinPhi = y * Normalizer;

                    e = SinTheta*SinTheta*SinTheta*SinTheta * CosPhi*CosPhi * SinPhi*SinPhi;
                    c = -SinTheta*SinTheta;
                    b = -CosTheta;

                    double[]	roots = Polynomial.solvePolynomial( a, b, c, d, e );

                    t = Math.Sqrt( 2.0 );
                    for ( int i=0; i < roots.Length; i++ )
                        if ( !double.IsNaN( roots[i] ) && roots[i] >= 0.0 )
                            t = Math.Min( t, roots[i] );

            // 					Nx = t * CosPhi * SinTheta;
            // 					Ny = t * SinPhi * SinTheta;
                    Nx = t * x;
                    Ny = t * y;

                    Vectors[X,Y].x = (float) (0.5 * (1.0 + Nx));
                    Vectors[X,Y].y = (float) (0.5 * (1.0 + Ny));
                    Vectors[X,Y].z = 0.0f;
                }

            // Save as target PNG
            using ( System.Drawing.Bitmap B = new System.Drawing.Bitmap( W, H, System.Drawing.Imaging.PixelFormat.Format32bppRgb ) )
            {
                System.Drawing.Imaging.BitmapData	LockedBitmap = B.LockBits( new System.Drawing.Rectangle( 0, 0, W, H ), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb );

                for ( int Y=0; Y < H; Y++ )
                {
                    byte*	pScanline = (byte*) LockedBitmap.Scan0 + LockedBitmap.Stride * Y;
                    for ( int X=0; X < W; X++ )
                    {
                        *pScanline++ = 0;
                        *pScanline++ = (byte) (255 * Vectors[X,Y].y);
                        *pScanline++ = (byte) (255 * Vectors[X,Y].x);
                        *pScanline++ = 0xFF;
                    }
                }

                B.UnlockBits( LockedBitmap );

                B.Save( TargetFileName.FullName );
            }
        }
Esempio n. 3
0
 public float4( float3 _xyz, float _w )
 {
     x = _xyz.x; y = _xyz.y; z = _xyz.z; w = _w;
 }
Esempio n. 4
0
 public static float3 Parse( string v )
 {
     string[]	Components = v.Split( ';' );
     if ( Components.Length < 3 )
         throw new Exception( "Not enough vector components!" );
     float3		Result = new float3();
     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!" );
     return Result;
 }
Esempio n. 5
0
        /// <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;
            }
        }
Esempio n. 6
0
 /// <summary>
 /// Converts from XYZ to xyY
 /// </summary>
 /// <param name="_XYZ"></param>
 /// <returns></returns>
 public static float3 XYZ2xyY( float3 _XYZ )
 {
     float	InvSum = 1.0f / Math.Max( 1e-8f, _XYZ.x + _XYZ.y + _XYZ.z);
     return new float3( _XYZ.x * InvSum, _XYZ.y * InvSum, _XYZ.y );
 }
Esempio n. 7
0
 /// <summary>
 /// Converts from xyY to XYZ
 /// </summary>
 /// <param name="_xyY"></param>
 /// <returns></returns>
 public static float3 xyY2XYZ( float3 _xyY )
 {
     float	Y_y = _xyY.y > 1e-8f ? _xyY.z / _xyY.y : 0.0f;
     return new float3( _xyY.x * Y_y, _xyY.z, (1.0f - _xyY.x - _xyY.y) * Y_y );
 }