StandardizedDiffuseAlbedoMaps.CalibratedTexture.Capture C# (CSharp) Method

Capture() public method

Captures the calibrated texture
public Capture ( ImageUtility _Source, CameraCalibrationDatabase _Database, CaptureParms _Parms ) : void
_Source ImageUtility The source image to capture
_Database CameraCalibrationDatabase Database to perform proper calibration
_Parms CaptureParms Parameters for the capture
return void
        public void Capture( ImageUtility.Bitmap _Source, CameraCalibrationDatabase _Database, CaptureParms _Parms )
        {
            if ( _Source == null )
                throw new Exception( "Invalid source bitmap to build texture from!" );
            if ( _Database == null )
                throw new Exception( "Invalid calibration database found in parameters!" );
            if ( _Parms == null )
                throw new Exception( "Invalid calibration parameters!" );
            if ( m_SwatchWidth <= 0 || m_SwatchHeight <= 0 )
                throw new Exception( "Invalid swatch size! Must be > 0!" );

            // Save parameters as they're associated to this texture
            m_CaptureParameters = _Parms;
            m_WhiteReflectanceReference = _Database.WhiteReflectanceReference;
            m_WhiteReflectanceCorrectionFactor = _Database.WhiteReflectanceCorrectionFactor;
            m_SpatialCorrectionEnabled = _Database.WhiteReferenceImage != null;

            //////////////////////////////////////////////////////////////////////////
            // Setup the database to find the most appropriate calibration data for our image infos
            _Database.PrepareCalibrationFor( _Parms.ISOSpeed, _Parms.ShutterSpeed, _Parms.Aperture );

            //////////////////////////////////////////////////////////////////////////
            // Build target texture
            ImageUtility.float4	AvgXYZ = new ImageUtility.float4( 0, 0, 0, 0 );
            //DEBUG
            // float	MinLuminance_Raw = float.MaxValue;
            // float	MaxLuminance_Raw = -float.MaxValue;

            const int	EXTREME_VALUES_COUNT = 100;
            ImageUtility.float3[]	ArrayMin = new ImageUtility.float3[EXTREME_VALUES_COUNT];
            ImageUtility.float3[]	ArrayMax = new ImageUtility.float3[EXTREME_VALUES_COUNT];
            for ( int i=0; i < EXTREME_VALUES_COUNT; i++ )
            {
                ArrayMin[i] = new ImageUtility.float3( 0, 1, 0 );
                ArrayMax[i] = new ImageUtility.float3( 0, 0, 0 );
            }

            if ( _Parms.CropSource )
            {
                float	fImageWidth = 2.0f * _Parms.CropRectangleHalfSize.x * _Source.Height;
                float	fImageHeight = 2.0f * _Parms.CropRectangleHalfSize.y * _Source.Height;
                int		W = (int) Math.Floor( fImageWidth );
                int		H = (int) Math.Floor( fImageHeight );

                ImageUtility.float2	AxisX = new ImageUtility.float2( (float) Math.Cos( _Parms.CropRectangleRotation ), -(float) Math.Sin( _Parms.CropRectangleRotation ) );
                ImageUtility.float2	AxisY = new ImageUtility.float2( (float) Math.Sin( _Parms.CropRectangleRotation ), (float) Math.Cos( _Parms.CropRectangleRotation ) );

                ImageUtility.float2	TopLeftCorner = new ImageUtility.float2( 0.5f * (_Source.Width - _Source.Height) + _Parms.CropRectangleCenter.x * _Source.Height, _Source.Height * _Parms.CropRectangleCenter.y )
                                                  + _Source.Height * (-_Parms.CropRectangleHalfSize.x * AxisX - _Parms.CropRectangleHalfSize.y * AxisY);

                m_Texture = new ImageUtility.Bitmap( W, H, new ImageUtility.ColorProfile( ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB ) );
                ImageUtility.float4	XYZ;
                ImageUtility.float3	ShortXYZ;
                ImageUtility.float3	xyY;

                ImageUtility.float2	CurrentScanlinePixel = TopLeftCorner + 0.5f * (fImageWidth - W) * AxisX + 0.5f * (fImageHeight - H) * AxisY;
                if ( Math.Abs( _Parms.CropRectangleRotation ) < 1e-6f )
                {	// Use integer pixels to avoid attenuated values due to bilinear filtering
                    CurrentScanlinePixel.x = (float) Math.Floor( CurrentScanlinePixel.x );
                    CurrentScanlinePixel.y = (float) Math.Floor( CurrentScanlinePixel.y );
                }
                for ( int Y=0; Y < H; Y++ )
                {
                    ImageUtility.float2	CurrentPixel = CurrentScanlinePixel;
                    for ( int X=0; X < W; X++ )
                    {
                        float	U = CurrentPixel.x / _Source.Width;
                        float	V = CurrentPixel.y / _Source.Height;

                        XYZ = _Source.BilinearSample( CurrentPixel.x, CurrentPixel.y );

            //DEBUG
            // float	L = XYZ.y * _Database.GetSpatialLuminanceCorrectionFactor( U, V );
            // if ( L < MinLuminance_Raw )
            // 	MinLuminance_Raw = L;
            // if ( L > MaxLuminance_Raw )
            // 	MaxLuminance_Raw = L;
            //DEBUG

                        xyY = ImageUtility.ColorProfile.XYZ2xyY( (ImageUtility.float3) XYZ );
                        xyY = _Database.CalibrateWithSpatialCorrection( U, V, xyY );	// Apply luminance calibration
                        ShortXYZ = ImageUtility.ColorProfile.xyY2XYZ( xyY );
                        XYZ = new ImageUtility.float4( ShortXYZ, XYZ.w );
                        m_Texture.ContentXYZ[X,Y] = XYZ;

                        // Update min/max/avg values
                        InsertMinMax( ShortXYZ, ArrayMin, ArrayMax, EXTREME_VALUES_COUNT );
                        AvgXYZ += XYZ;

                        CurrentPixel += AxisX;
                    }
                    CurrentScanlinePixel += AxisY;
                }
            }
            else
            {	// Simple texture copy, with luminance calibration
                m_Texture = new ImageUtility.Bitmap( _Source.Width, _Source.Height, new ImageUtility.ColorProfile( ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB ) );
                ImageUtility.float4	XYZ;
                ImageUtility.float3	ShortXYZ;
                ImageUtility.float3	xyY;

                int	W = m_Texture.Width;
                int	H = m_Texture.Height;

                int	X0 = 0;
                int	X1 = W;
                int	Y0 = 0;
                int	Y1 = H;

            //DEBUG
            // X0 = 1088; Y0 = 764;
            // X1 = X0 + 1100; Y1 = Y0 + 632;

                for ( int Y=Y0; Y < Y1; Y++ )
                {
                    float	V = (float) Y / H;
                    for ( int X=X0; X < X1; X++ )
                    {
                        float	U = (float) X / W;

                        XYZ = _Source.ContentXYZ[X,Y];

            //DEBUG
            // float	L = XYZ.y * _Database.GetSpatialLuminanceCorrectionFactor( U, V );
            // if ( L < MinLuminance_Raw )
            // 	MinLuminance_Raw = L;
            // if ( L > MaxLuminance_Raw )
            // 	MaxLuminance_Raw = L;
            //DEBUG

                        xyY = ImageUtility.ColorProfile.XYZ2xyY( (ImageUtility.float3) XYZ );
                        xyY = _Database.CalibrateWithSpatialCorrection( U, V, xyY );	// Apply luminance calibration
                        ShortXYZ = ImageUtility.ColorProfile.xyY2XYZ( xyY );
                        XYZ = new ImageUtility.float4( ShortXYZ, XYZ.w );
                        m_Texture.ContentXYZ[X,Y] = XYZ;

                        // Update min/max/avg values
                        InsertMinMax( ShortXYZ, ArrayMin, ArrayMax, EXTREME_VALUES_COUNT );
                        AvgXYZ += XYZ;
                    }
                }
            }

            // Normalize average swatch color
            float	Normalizer = 1.0f / (m_Texture.Width*m_Texture.Height);
            ImageUtility.float3	avgxyY = ImageUtility.ColorProfile.XYZ2xyY( Normalizer * ((ImageUtility.float3) AvgXYZ) );
            m_SwatchAvg.xyY = avgxyY;

            // Compute min & max using statistical norm
             			ImageUtility.float3	BestXYZ_Min;
             			ImageUtility.float3	BestXYZ_Max;

            if ( _Parms.UseModeInsteadOfMean )
            {	// Use mode
                BestXYZ_Min = ComputeMode( ArrayMin );
                BestXYZ_Max = ComputeMode( ArrayMax );
            }
            else
            {	// Use mean
             				BestXYZ_Min = ComputeMean( ArrayMin );
             				BestXYZ_Max = ComputeMean( ArrayMax );
            }
            m_SwatchMin.xyY = ImageUtility.ColorProfile.XYZ2xyY( BestXYZ_Min );
            m_SwatchMax.xyY = ImageUtility.ColorProfile.XYZ2xyY( BestXYZ_Max );

            m_SwatchMin.Texture = BuildSwatch( m_SwatchWidth, m_SwatchHeight, m_SwatchMin.xyY );
            m_SwatchMax.Texture = BuildSwatch( m_SwatchWidth, m_SwatchHeight, m_SwatchMax.xyY );
            m_SwatchAvg.Texture = BuildSwatch( m_SwatchWidth, m_SwatchHeight, m_SwatchAvg.xyY );

            // Rebuild custom swatches
            foreach ( CustomSwatch CS in m_CustomSwatches )
                CS.Texture = BuildSwatch( m_SwatchWidth, m_SwatchHeight, CS.xyY );

            //////////////////////////////////////////////////////////////////////////
            // Feed some purely informational shot infos to the main texture, probably won't be saved anyway...
            m_Texture.HasValidShotInfo = true;
            m_Texture.ISOSpeed = _Parms.ISOSpeed;
            m_Texture.ShutterSpeed = _Parms.ShutterSpeed;
            m_Texture.Aperture = _Parms.Aperture;
        }

Usage Example

Example #1
0
        private void buttonCapture_Click( object sender, EventArgs e )
        {
            if ( m_BitmapXYZ == null )
            {	// No image loaded you moron!
                MessageBox( "Can't capture as no image is currently loaded!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                return;
            }
            if ( !PrepareDatabase() )
                return;

            //////////////////////////////////////////////////////////////////////////
            // Prepare parameters
            CalibratedTexture.CaptureParms	Parms = new CalibratedTexture.CaptureParms() {
                SourceImageName = m_ImageFileName.FullName,

                ISOSpeed = floatTrackbarControlISOSpeed.Value,
                ShutterSpeed = floatTrackbarControlShutterSpeed.Value,
                Aperture = floatTrackbarControlAperture.Value,

                CropSource = !outputPanel.IsDefaultCropRectangle,
                CropRectangleCenter = new ImageUtility.float2( outputPanel.CropRectangeCenter.x, outputPanel.CropRectangeCenter.y ),
                CropRectangleHalfSize = new ImageUtility.float2( outputPanel.CropRectangeHalfSize.x, outputPanel.CropRectangeHalfSize.y ),
                CropRectangleRotation = outputPanel.CropRectangeRotation,

                UseModeInsteadOfMean = checkBoxUseMeanMode.Checked,
            };

            //////////////////////////////////////////////////////////////////////////
            // Go!
            try
            {
                CalibratedTexture	Tex = new CalibratedTexture();
                Tex.Capture( m_BitmapXYZ, m_CalibrationDatabase, Parms );
                m_Texture = Tex;

                // Use the form's swatch panels as default swatch size
                m_Texture.SwatchWidth = panelCustomSwatch0.Width-2;
                m_Texture.SwatchHeight = panelCustomSwatch0.Height-2;

                // Update UI
                resultTexturePanel.CalibratedTexture = m_Texture;
                buttonSaveCalibratedImage.Enabled = true;
                labelCaptureWhiteReflectanceCorrection.Text = "White Correction " + Tex.WhiteReflectanceCorrectionFactor.ToString( "G4" );
                labelCaptureSpatialCorrectionStatus.Text = "Spatial Correction is " + (Tex.SpatialCorrectionEnabled ? "enabled" : "disabled");

                m_SwatchMin.m_xyY = m_Texture.SwatchMin.xyY;
                m_SwatchMin.UpdateSwatchColor();
                m_SwatchMax.m_xyY = m_Texture.SwatchMax.xyY;
                m_SwatchMax.UpdateSwatchColor();
                m_SwatchAvg.m_xyY = m_Texture.SwatchAvg.xyY;
                m_SwatchAvg.UpdateSwatchColor();

                foreach ( CustomSwatch S in m_CustomSwatches )
                    S.UpdateSwatchColor();
            }
            catch ( Exception _e )
            {
                MessageBox( "An error occurred during capture:\r\n\r\n", _e );
            }
        }