Exemplo n.º 1
0
        /// <summary>
        /// Prepares the interpolated calibration table to process the pixels in an image shot with the specified shot infos
        /// </summary>
        /// <param name="_Image"></param>
        public void     PrepareCalibrationFor(ImageUtility.Bitmap _Image)
        {
            if (!_Image.HasValidShotInfo)
            {
                throw new Exception("Can't prepare calibration for specified image since it doesn't have valid shot infos!");
            }

            PrepareCalibrationFor(_Image.ISOSpeed, _Image.ShutterSpeed, _Image.Aperture);
        }
Exemplo n.º 2
0
        private unsafe void     UpdateProgress(ImageUtility.Bitmap _Image, int Y, bool _Bias)
        {
            const int REFRESH_EVERY_N_SCANLINES = 4;

            if (Y == 0 || (Y & (REFRESH_EVERY_N_SCANLINES - 1)) != 0)
            {
                return;
            }

            viewportPanelResult.Image = _Image;
            Application.DoEvents();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Builds a swatch bitmap
        /// </summary>
        /// <param name="_Width"></param>
        /// <param name="_Height"></param>
        /// <param name="_xyY"></param>
        /// <returns></returns>
        private ImageUtility.Bitmap     BuildSwatch(int _Width, int _Height, ImageUtility.float3 _xyY)
        {
            ImageUtility.Bitmap Result = new ImageUtility.Bitmap(_Width, _Height, new ImageUtility.ColorProfile(ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB));
            ImageUtility.float4 XYZ    = new ImageUtility.float4(ImageUtility.ColorProfile.xyY2XYZ(_xyY), 1.0f);
            for (int Y = 0; Y < _Height; Y++)
            {
                for (int X = 0; X < _Width; X++)
                {
                    Result.ContentXYZ[X, Y] = XYZ;
                }
            }

            return(Result);
        }
Exemplo n.º 4
0
        private void buttonTestBilateral_Click(object sender, EventArgs e)
        {
            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, 100);

                progressBar.Value = progressBar.Maximum;

                //////////////////////////////////////////////////////////////////////////
                // 2] Copy target to staging for CPU readback and update the resulting bitmap
                m_TextureTarget_CPU.CopyFrom(m_TextureTarget0);

                if (m_BitmapResult != null)
                {
                    m_BitmapResult.Dispose();
                }
                m_BitmapResult          = null;
                m_BitmapResult          = new ImageUtility.Bitmap(W, H, m_ProfileLinear);
                m_BitmapResult.HasAlpha = true;

                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();
                            ImageUtility.float4 Color = new ImageUtility.float4(AO, AO, AO, AO);
                            Color = m_ProfileLinear.RGB2XYZ(Color);
                            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;
            }
        }
Exemplo n.º 5
0
        private void    LoadNormalMap(System.IO.FileInfo _FileName)
        {
            try {
                // Dispose of existing resources
                if (m_BitmapSourceNormal != null)
                {
                    m_BitmapSourceNormal.Dispose();
                }
                m_BitmapSourceNormal = null;

                if (m_TextureSourceNormal != null)
                {
                    m_TextureSourceNormal.Dispose();
                }
                m_TextureSourceNormal = null;

                // Load the source image assuming it's in linear space (all normal maps should be in linear space, with the default value being (0.5, 0.5, 1))
                m_BitmapSourceNormal = new ImageUtility.Bitmap(_FileName, m_ProfileLinear);
//				outputPanelInputHeightMap.Image = m_BitmapSourceNormal;

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

                // Build the source texture
                ImageUtility.float4[,]  ContentRGB = m_BitmapSourceNormal.ConvertedContentRGB;

                RendererManaged.PixelsBuffer SourceNormalMap = new RendererManaged.PixelsBuffer(W * H * 4 * 4);
                using (System.IO.BinaryWriter Wr = SourceNormalMap.OpenStreamWrite())
                    for (int Y = 0; Y < H; Y++)
                    {
                        for (int X = 0; X < W; X++)
                        {
                            float Nx = 2.0f * ContentRGB[X, Y].x - 1.0f;
                            float Ny = 1.0f - 2.0f * ContentRGB[X, Y].y;
                            float Nz = 2.0f * ContentRGB[X, Y].z - 1.0f;
                            Wr.Write(Nx);
                            Wr.Write(Ny);
                            Wr.Write(Nz);
                            Wr.Write(1.0f);
                        }
                    }

                m_TextureSourceNormal = new RendererManaged.Texture2D(m_Device, W, H, 1, 1, RendererManaged.PIXEL_FORMAT.RGBA32_FLOAT, false, false, new RendererManaged.PixelsBuffer[] { SourceNormalMap });
            } catch (Exception _e) {
                MessageBox("An error occurred while opening the image:\n\n", _e);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates an embeddable thumbnail of the reference image
        /// </summary>
        /// <param name="_Image"></param>
        public void             CreateThumbnail(ImageUtility.Bitmap _Image)
        {
            int MaxDim        = Math.Max(_Image.Width, _Image.Height);
            int ThumbnailSize = 256;

            int W = ThumbnailSize * _Image.Width / MaxDim;
            int H = ThumbnailSize * _Image.Height / MaxDim;

            // Build the thumbnail
            m_Thumbnail = new byte[W, H];
            for (int Y = 0; Y < H; Y++)
            {
                for (int X = 0; X < W; X++)
                {
                    ImageUtility.float4 XYZ = _Image.ContentXYZ[X * _Image.Width / W, Y *_Image.Height / H];
                    m_Thumbnail[X, Y] = (byte)Math.Min(255, Math.Max(0, 255.0f * XYZ.y));
                }
            }
        }
Exemplo n.º 7
0
        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"));
        }
Exemplo n.º 8
0
        /// <summary>
        /// Reads image size and other informations, doesn't read content
        /// </summary>
        public void             ReadImageInfos()
        {
            m_usage = FindUsage(m_fileName);

            if (m_fileName.Extension.ToLower().StartsWith(".bimage"))
            {
                // Can't read!
                m_fileType    = FILE_TYPE.BIMAGE;
                m_couldBeRead = false;
                return;
            }

            try {
                using (ImageUtility.Bitmap B = new ImageUtility.Bitmap(m_fileName)) {
                    m_error       = null;
                    m_couldBeRead = true;
                    m_width       = B.Width;
                    m_height      = B.Height;
                    switch (B.Type)
                    {
                    case ImageUtility.Bitmap.FILE_TYPE.PNG: m_fileType = FILE_TYPE.PNG; break;

                    case ImageUtility.Bitmap.FILE_TYPE.TGA: m_fileType = FILE_TYPE.TGA; break;

//						case ImageUtility.Bitmap.FILE_TYPE.DDS: m_fileType = FILE_TYPE.DDS; break;	// DDS not supported?
                    case ImageUtility.Bitmap.FILE_TYPE.JPEG: m_fileType = FILE_TYPE.JPG; break;

                    case ImageUtility.Bitmap.FILE_TYPE.TIFF: m_fileType = FILE_TYPE.TIFF; break;
                    }
                }
            } catch (Exception _e) {
                m_couldBeRead = false;
                m_error       = _e;
                throw _e;
            }
        }
Exemplo n.º 9
0
        /// <summary>
        /// Captures the calibrated texture
        /// </summary>
        /// <param name="_Source">The source image to capture</param>
        /// <param name="_Database">Database to perform proper calibration</param>
        /// <param name="_Parms">Parameters for the capture</param>
        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;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Builds a swatch bitmap
        /// </summary>
        /// <param name="_Width"></param>
        /// <param name="_Height"></param>
        /// <param name="_xyY"></param>
        /// <returns></returns>
        private ImageUtility.Bitmap BuildSwatch( int _Width, int _Height, ImageUtility.float3 _xyY )
        {
            ImageUtility.Bitmap	Result = new ImageUtility.Bitmap( _Width, _Height, new ImageUtility.ColorProfile( ImageUtility.ColorProfile.STANDARD_PROFILE.sRGB ) );
            ImageUtility.float4	XYZ = new ImageUtility.float4( ImageUtility.ColorProfile.xyY2XYZ( _xyY ), 1.0f );
            for ( int Y=0; Y < _Height; Y++ )
                for ( int X=0; X < _Width; X++ )
                    Result.ContentXYZ[X,Y] = XYZ;

            return Result;
        }
Exemplo n.º 11
0
        /// <summary>
        /// Loads the white reference image file
        /// </summary>
        /// <param name="_FileName"></param>
        /// <param name="_AlertIfFailed"></param>
        private void LoadWhiteReferenceImage( System.IO.FileInfo _FileName, bool _AlertIfFailed )
        {
            buttonSaveWhiteRefImage.Enabled = false;
            buttonResetWhiteRefImage.Enabled = false;
            try
            {
                ImageUtility.Bitmap	RefImg = new ImageUtility.Bitmap( _FileName );
                m_CalibrationDatabase.WhiteReferenceImage = RefImg;

                UpdateWhiteReferenceImageUI();
            }
            catch ( Exception _e )
            {
                if ( _AlertIfFailed )
                    MessageBox( "An error occurred while loading the white reference image \"" + _FileName.FullName + "\":\r\n\r\n", _e );
            }
        }
Exemplo n.º 12
0
        private void buttonLoadImage_Click( object sender, EventArgs e )
        {
            string	OldFileName = GetRegKey( "LastImageFilename", m_ApplicationPath );
            openFileDialogSourceImage.InitialDirectory = System.IO.Path.GetDirectoryName( OldFileName );
            openFileDialogSourceImage.FileName = System.IO.Path.GetFileName( OldFileName );

            if ( openFileDialogSourceImage.ShowDialog( this ) != DialogResult.OK )
             				return;

            SetRegKey( "LastImageFilename", openFileDialogSourceImage.FileName );

            try
            {
                // Load
                System.IO.FileInfo	ImageFileName = new System.IO.FileInfo( openFileDialogSourceImage.FileName );
                ImageUtility.Bitmap	NewBitmap = new ImageUtility.Bitmap( ImageFileName );

                // Safely assign once loaded
                m_ImageFileName = ImageFileName;
                m_BitmapXYZ = NewBitmap;

                this.Text = APP_TITLE + " (" + ImageFileName.Name + ")";

                // Setup camera shot info if it exists
                if ( m_BitmapXYZ.HasValidShotInfo )
                {
                    groupBoxCameraShotInfos.Enabled = false;
                    floatTrackbarControlISOSpeed.Value = m_BitmapXYZ.ISOSpeed;			floatTrackbarControlISOSpeed.SimulateValueChange();	// So we get notified even if value is the same as default slider value
                    floatTrackbarControlShutterSpeed.Value = m_BitmapXYZ.ShutterSpeed;	floatTrackbarControlShutterSpeed.SimulateValueChange();	// So we get notified even if value is the same as default slider value
                    floatTrackbarControlAperture.Value = m_BitmapXYZ.Aperture;			floatTrackbarControlAperture.SimulateValueChange();	// So we get notified even if value is the same as default slider value
                    floatTrackbarControlFocalLength.Value = m_BitmapXYZ.FocalLength;	floatTrackbarControlFocalLength.SimulateValueChange();	// So we get notified even if value is the same as default slider value
                }
                else
                    groupBoxCameraShotInfos.Enabled = true;

                // Clear calibrated texture & UI
                if ( m_Texture != null )
                    m_Texture.Dispose();
                m_Texture = null;
                resultTexturePanel.CalibratedTexture = null;
                buttonSaveCalibratedImage.Enabled = false;

                foreach ( CustomSwatch S in m_CustomSwatches )
                {
                    S.m_CheckBox.Checked = false;
                    S.m_Panel.BackColor = Color.DimGray;
                }

                // Prepare database with new camera shot infos
                PrepareDatabase( false );

                // Re-apply white reflectance reference if it's adapted to the
                if (	Math.Abs(m_CalibrationDatabase.PreparedForISOSpeed - m_WhiteReflectanceISOSpeed) < 1e-6f
                    && Math.Abs(m_CalibrationDatabase.PreparedForShutterSpeed - m_WhiteReflectanceShutterSpeed) < 1e-6f
                    && Math.Abs(m_CalibrationDatabase.PreparedForAperture - m_WhiteReflectanceAperture) < 1e-6f )
                {
                    m_CalibrationDatabase.WhiteReflectanceReference = m_WhiteReflectanceReference;
                }
                UpdateWhiteReflectanceUI();			// If the shot infos are different from the ones from which the white reflectance was picked then the values got reset so update UI

                RebuildImage();						// Finally, rebuild the image and show it in the output panel
                outputPanel.ResetCropRectangle();	// Previous crop rectangle is not valid anymore
            }
            catch ( Exception _e )
            {
                MessageBox( "An error occurred while loading the image:\r\n\r\n", _e );
            }
        }
Exemplo n.º 13
0
        //////////////////////////////////////////////////////////////////////////
        // White Reference Image
        //
        private void buttonPickWhiteRefImage_Click( object sender, EventArgs e )
        {
            if ( m_BitmapXYZ == null )
            {	// No image loaded you moron!
                MessageBox( "Can't pick white reference as no image is currently loaded!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation );
                return;
            }

            try
            {
                int	W, H;
                if ( m_BitmapXYZ.Width > m_BitmapXYZ.Height )
                {
                    W = DEFAULT_WHITE_REFERENCE_IMAGE_SIZE;
                    H = W * m_BitmapXYZ.Height / m_BitmapXYZ.Width;
                }
                else
                {
                    H = DEFAULT_WHITE_REFERENCE_IMAGE_SIZE;
                    W = H * m_BitmapXYZ.Width / m_BitmapXYZ.Height;
                }

                // Find the maximum luminance in the image that we'll use as a normalizer
                ImageUtility.Bitmap	WhiteRef = new ImageUtility.Bitmap( W, H, m_sRGBProfile );
                for ( int Y=0; Y < H; Y++ )
                    for ( int X=0; X < W; X++ )
                    {
                        float	x0 = m_BitmapXYZ.Width * (float) X / W;
                        float	x1 = m_BitmapXYZ.Width * (float) (X+1) / W;
                        float	y0 = m_BitmapXYZ.Height * (float) Y / H;
                        float	y1 = m_BitmapXYZ.Height * (float) (Y+1) / H;

                        ImageUtility.float4	SumXYZ = new ImageUtility.float4( 0, 0, 0, 0 );
                        int		Count = 0;
                        float	y = y0;
                        while ( y < y1 )
                        {
                            float	x = x0;
                            while ( x < x1 )
                            {
                                SumXYZ += m_BitmapXYZ.BilinearSample( x, y );
                                Count++;
                                x++;
                            }
                            y++;
                        }
                        float	Test = (float) (Math.Ceiling(x1-x0) * Math.Ceiling(y1-y0));	// Should equal Count
                        SumXYZ = (1.0f / Math.Max( 1, Count)) * SumXYZ;

                        ImageUtility.float3	xyY = ImageUtility.ColorProfile.XYZ2xyY( (ImageUtility.float3) SumXYZ );
                                xyY.x = m_sRGBProfile.Chromas.W.x;	// B&W
                                xyY.y = m_sRGBProfile.Chromas.W.y;
                        ImageUtility.float4	XYZ = new ImageUtility.float4( ImageUtility.ColorProfile.xyY2XYZ( xyY ), SumXYZ.w );

                        WhiteRef.ContentXYZ[X,Y] = XYZ;
                    }

                // Assign to the database
                m_CalibrationDatabase.WhiteReferenceImage = WhiteRef;

                UpdateWhiteReferenceImageUI();
            }
            catch ( Exception _e )
            {
                MessageBox( "An error occurred while creating the white reference image:\r\n\r\n", _e );
            }
        }
Exemplo n.º 14
0
        private void buttonWhiteRefTest3_Click( object sender, EventArgs e )
        {
            int	W = DEFAULT_WHITE_REFERENCE_IMAGE_SIZE;
            int	H = DEFAULT_WHITE_REFERENCE_IMAGE_SIZE;
            ImageUtility.Bitmap	WhiteRef = new ImageUtility.Bitmap( W, H, m_sRGBProfile );
            ImageUtility.float3	xyY = new ImageUtility.float3( m_sRGBProfile.Chromas.W.x, m_sRGBProfile.Chromas.W.y, 0.0f );
            for ( int Y=0; Y < H; Y++ )
            {
                float	V = (float) Y / H;
                for ( int X=0; X < W; X++ )
                {
                    float	U = (float) X / W;
                    xyY.z = Math.Min( 1.0f, 1.0f - 0.5f * V );

                    ImageUtility.float4	XYZ = new ImageUtility.float4( ImageUtility.ColorProfile.xyY2XYZ( xyY ), 1.0f );
                    WhiteRef.ContentXYZ[X,Y] = XYZ;
                }
            }

            // Assign to the database
            m_CalibrationDatabase.WhiteReferenceImage = WhiteRef;

            UpdateWhiteReferenceImageUI();
        }
Exemplo n.º 15
0
        private void Generate()
        {
            try {
                panelParameters.Enabled = false;

                //////////////////////////////////////////////////////////////////////////
                // 1] Apply bilateral filtering to the input texture as a pre-process
                ApplyBilateralFiltering( m_textureSourceHeightMap, 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_GenerateAOMap.Use() )
                    throw new Exception( "Can't generate self-shadowed bump map as compute shader failed to compile!" );

                uint	h = Math.Max( 1, MAX_LINES*1024 / W );
                uint	CallsCount = (uint) 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_GenerateAOMap.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)
                ImageUtility.ColorProfile	profile = m_profileLinear;

                float3	whitePoint_xyY = new float3( profile.Chromas.White, 0 );
                float3	whitePoint_XYZ = new float3();

                ImageUtility.Bitmap		tempBitmap = new ImageUtility.Bitmap( W, H );
                Renderer.PixelsBuffer	Pixels = m_textureTarget_CPU.Map( 0, 0 );
                using ( System.IO.BinaryReader R = Pixels.OpenStreamRead() )
                    for ( uint Y=0; Y < H; Y++ ) {
                        R.BaseStream.Position = Y * Pixels.RowPitch;
                        for ( uint X=0; X < W; X++ ) {
                            whitePoint_xyY.z = R.ReadSingle();		// Linear value
                            ImageUtility.ColorProfile.xyY2XYZ( whitePoint_xyY, ref whitePoint_XYZ );
                            tempBitmap[X,Y] = new float4( whitePoint_XYZ, 1 );
                        }
                    }

                Pixels.Dispose();
                m_textureTarget_CPU.UnMap( 0, 0 );

                // Convert to RGB
                ImageUtility.ImageFile	temmpImageRGBA32F = new ImageUtility.ImageFile();
                tempBitmap.ToImageFile( temmpImageRGBA32F, profile );

                if ( m_imageResult == null )
                    m_imageResult = new ImageUtility.ImageFile();
                m_imageResult.ToneMapFrom( temmpImageRGBA32F, ( float3 _HDR, ref float3 _LDR ) => {
                    _LDR = _HDR;	// Return as-is..
                } );

                // Assign result
                viewportPanelResult.Bitmap = m_imageResult.AsBitmap;

            } catch ( Exception _e ) {
                MessageBox( "An error occurred during generation!\r\n\r\nDetails: ", _e );
            } finally {
                panelParameters.Enabled = true;
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// Generates a (diffuse+gloss) texture from 2 distinct textures
        /// </summary>
        public void GenerateDiffuseGlossTexture()
        {
            if (m_diffuse == null)
            {
                throw new Exception("Invalid source diffuse image file!");
            }
            if (!m_diffuse.m_fileName.Exists)
            {
                throw new Exception("Source diffuse image file \"" + m_diffuse.m_fileName.FullName + "\" does not exist on disk!");
            }

            string   targetFileNameString = TextureFileInfo.GetOptimizedDiffuseGlossNameFromDiffuseName(m_diffuse.m_fileName.FullName);
            FileInfo targetFileName       = new FileInfo(targetFileNameString);

            using (ImageUtility.Bitmap diffuse = new ImageUtility.Bitmap(m_diffuse.m_fileName)) {
                int W = diffuse.Width;
                int H = diffuse.Height;

                ImageUtility.Bitmap gloss = null;
                if (m_gloss != null)
                {
                    gloss = new ImageUtility.Bitmap(m_gloss.m_fileName);

//                  int	gW = gloss.Width;
//                  int	gH = gloss.Height;
//                  for ( int Y=0; Y < gH; Y++ )
//                      for ( int X=0; X < gW; X++ ) {
//                          gloss.ContentXYZ[X,Y].x = ImageUtility.ColorProfile.sRGB2Linear( gloss.ContentXYZ[X,Y].x );
//                      }
                }
                bool needsScale = false;
                if (gloss != null && (gloss.Width != W || gloss.Height != H))
                {
                    needsScale = true;
                }

                if (gloss != null)
                {
                    if (needsScale)
                    {
                        // Set gloss as alpha with re-scaling
                        float scaleX = (float)gloss.Width / W;
                        float scaleY = (float)gloss.Height / H;
                        for (int Y = 0; Y < H; Y++)
                        {
                            float Y2 = scaleY * Y;
                            for (int X = 0; X < W; X++)
                            {
                                diffuse.ContentXYZ[X, Y].w = gloss.BilinearSample(scaleX * X, Y2).x;
                            }
                        }
                    }
                    else
                    {
                        // Set gloss as alpha without re-scaling
                        for (int Y = 0; Y < H; Y++)
                        {
                            for (int X = 0; X < W; X++)
                            {
//								diffuse.ContentXYZ[X,Y].w = gloss.ContentXYZ[X,Y].x;

                                diffuse.ContentXYZ[X, Y].w = 0.3f * gloss.ContentXYZ[X, Y].x
                                                             + 0.5f * gloss.ContentXYZ[X, Y].y
                                                             + 0.2f * gloss.ContentXYZ[X, Y].z;
                            }
                        }
                    }
                }
                else
                {
                    for (int Y = 0; Y < H; Y++)
                    {
                        for (int X = 0; X < W; X++)
                        {
                            diffuse.ContentXYZ[X, Y].w = 1.0f;
                        }
                    }
                }

                // Save diffuse as target
                diffuse.HasAlpha = gloss != null;
                diffuse.Save(targetFileName);
            }

            // Save optimized filename + timestamps of source files
            m_diffuseFileName.Refresh();
            if (m_glossFileName != null)
            {
                m_glossFileName.Refresh();
            }

            m_optimizedDiffuseGlossFileName = targetFileName;
            m_diffuseTimeAtGeneration       = m_diffuseFileName.LastWriteTime;
            m_glossTimeAtGeneration         = m_glossFileName != null ? m_glossFileName.LastWriteTime : DateTime.MinValue;
        }
Exemplo n.º 17
0
        private void    LoadHeightMap(System.IO.FileInfo _FileName)
        {
            try
            {
                tabControlGenerators.Enabled = false;

                // Dispose of existing resources
                if (m_BitmapSource != null)
                {
                    m_BitmapSource.Dispose();
                }
                m_BitmapSource = null;

                if (m_TextureTarget_CPU != null)
                {
                    m_TextureTarget_CPU.Dispose();
                }
                m_TextureTarget_CPU = null;
                if (m_TextureTarget0 != null)
                {
                    m_TextureTarget0.Dispose();
                }
                m_TextureTarget0 = null;
                if (m_TextureTarget1 != null)
                {
                    m_TextureTarget1.Dispose();
                }
                m_TextureTarget1 = null;
                if (m_TextureSource != null)
                {
                    m_TextureSource.Dispose();
                }
                m_TextureSource = null;

                // Load the source image assuming it's in linear space
                m_SourceFileName = _FileName;
                m_BitmapSource   = new ImageUtility.Bitmap(_FileName, m_LinearProfile);
                outputPanelInputHeightMap.Image = m_BitmapSource;

                W = m_BitmapSource.Width;
                H = m_BitmapSource.Height;

                // Build the source texture
                RendererManaged.PixelsBuffer SourceHeightMap = new RendererManaged.PixelsBuffer(W * H * 4);
                using (System.IO.BinaryWriter Wr = SourceHeightMap.OpenStreamWrite())
                    for (int Y = 0; Y < H; Y++)
                    {
                        for (int X = 0; X < W; X++)
                        {
                            Wr.Write(m_BitmapSource.ContentXYZ[X, Y].y);
                        }
                    }

                m_TextureSource = new RendererManaged.Texture2D(m_Device, W, H, 1, 1, RendererManaged.PIXEL_FORMAT.R32_FLOAT, false, false, new RendererManaged.PixelsBuffer[] { SourceHeightMap });

                // Build the target UAV & staging texture for readback
                m_TextureTarget0    = new RendererManaged.Texture2D(m_Device, W, H, 1, 1, RendererManaged.PIXEL_FORMAT.R32_FLOAT, false, true, null);
                m_TextureTarget1    = new RendererManaged.Texture2D(m_Device, W, H, 1, 1, RendererManaged.PIXEL_FORMAT.RGBA32_FLOAT, false, true, null);
                m_TextureTarget_CPU = new RendererManaged.Texture2D(m_Device, W, H, 1, 1, RendererManaged.PIXEL_FORMAT.RGBA32_FLOAT, true, false, null);

                tabControlGenerators.Enabled = true;
                buttonGenerate.Focus();
            }
            catch (Exception _e)
            {
                MessageBox("An error occurred while opening the image:\n\n", _e);
            }
        }
Exemplo n.º 18
0
        /// <summary>
        /// Captures the calibrated texture
        /// </summary>
        /// <param name="_Source">The source image to capture</param>
        /// <param name="_Database">Database to perform proper calibration</param>
        /// <param name="_Parms">Parameters for the capture</param>
        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;
        }
Exemplo n.º 19
0
 /// <summary>
 /// Saves a texture to disk
 /// </summary>
 /// <param name="_Texture"></param>
 /// <param name="_FileName"></param>
 /// <param name="_FileType"></param>
 /// <param name="_Format"></param>
 private void    SaveImage(ImageUtility.Bitmap _Texture, System.IO.FileInfo _FileName, ImageUtility.Bitmap.FILE_TYPE _FileType, ImageUtility.Bitmap.FORMAT_FLAGS _Format)
 {
     using (System.IO.FileStream S = _FileName.Create())
         _Texture.Save(S, _FileType, _Format, null);
 }
Exemplo n.º 20
0
        /// <summary>
        /// Generates a (diffuse+gloss) texture from 2 distinct textures
        /// </summary>
        public void GenerateDiffuseGlossTexture()
        {
            if ( m_diffuse == null )
                throw new Exception( "Invalid source diffuse image file!" );
            if ( !m_diffuse.m_fileName.Exists )
                throw new Exception( "Source diffuse image file \"" + m_diffuse.m_fileName.FullName + "\" does not exist on disk!" );

            FileInfo	targetFileName = GetDiffuseGlossTextureFileName();

            using ( ImageUtility.Bitmap diffuse = new ImageUtility.Bitmap( m_diffuse.m_fileName ) ) {

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

                ImageUtility.Bitmap	gloss = null;
                if ( m_gloss != null ) {
                    gloss = new ImageUtility.Bitmap( m_gloss.m_fileName );

            // 					int	gW = gloss.Width;
            // 					int	gH = gloss.Height;
            // 					for ( int Y=0; Y < gH; Y++ )
            // 						for ( int X=0; X < gW; X++ ) {
            // 							gloss.ContentXYZ[X,Y].x = ImageUtility.ColorProfile.sRGB2Linear( gloss.ContentXYZ[X,Y].x );
            // 						}
                }
                bool	needsScale = false;
                if ( gloss != null && (gloss.Width != W || gloss.Height != H) ) {
                    needsScale = true;
                }

                if ( gloss != null ) {
                    if ( needsScale ) {
                        // Set gloss as alpha with re-scaling
                        int			W2 = gloss.Width;
                        int			H2 = gloss.Height;
                        float[,]	source = new float[W2,H2];
                        for ( int Y=0; Y < H2; Y++ )
                            for ( int X=0; X < W2; X++ )
                                source[X,Y] = 0.3f * gloss.ContentXYZ[X,Y].x
                                            + 0.5f * gloss.ContentXYZ[X,Y].y
                                            + 0.2f * gloss.ContentXYZ[X,Y].z;

                        // Downscale first
                        while ( W2 > W ) {
                            int			halfW2 = W2 >> 1;
                            float[,]	temp = new float[halfW2,H2];
                            for ( int Y=0; Y < H2; Y++ )
                                for ( int X=0; X < halfW2; X++ )
                                    temp[X,Y] = 0.5f * (source[2*X+0,Y] + source[2*X+1,Y]);

                            source = temp;
                            W2 = halfW2;
                        }
                        while ( H2 > H ) {
                            int			halfH2 = H2 >> 1;
                            float[,]	temp = new float[W2,halfH2];
                            for ( int Y=0; Y < halfH2; Y++ )
                                for ( int X=0; X < W2; X++ )
                                    temp[X,Y] = 0.5f * (source[X,2*Y+0] + source[X,2*Y+1]);

                            source = temp;
                            H2 = halfH2;
                        }

                        // Upscale then
                        while ( W2 < W ) {
                            int			doubleW2 = W2 << 1;
                            float[,]	temp = new float[doubleW2,H2];
                            for ( int Y=0; Y < H2; Y++ )
                                for ( int X=0; X < W2; X++ ) {
                                    temp[2*X+0,Y] = source[X,Y];
                                    temp[2*X+1,Y] = 0.5f * (source[X,Y] + source[Math.Min( W2-1, X+1 ),Y]);
                                }

                            source = temp;
                            W2 = doubleW2;
                        }
                        while ( H2 < H ) {
                            int			doubleH2 = H2 << 1;
                            float[,]	temp = new float[W2,doubleH2];
                            for ( int Y=0; Y < H2; Y++ )
                                for ( int X=0; X < W2; X++ ) {
                                    temp[X,2*Y+0] = source[X,Y];
                                    temp[X,2*Y+1] = 0.5f * (source[X,Y] + source[X,Math.Min( H2-1, Y+1 )]);
                                }

                            source = temp;
                            H2 = doubleH2;
                        }

                        for ( int Y=0; Y < H; Y++ )
                            for ( int X=0; X < W; X++ )
                                diffuse.ContentXYZ[X,Y].w = source[X,Y];

                    } else {
                        // Set gloss as alpha without re-scaling
                        for ( int Y=0; Y < H; Y++ )
                            for ( int X=0; X < W; X++ ) {
            //								diffuse.ContentXYZ[X,Y].w = gloss.ContentXYZ[X,Y].x;

                                diffuse.ContentXYZ[X,Y].w = 0.3f * gloss.ContentXYZ[X,Y].x
                                                          + 0.5f * gloss.ContentXYZ[X,Y].y
                                                          + 0.2f * gloss.ContentXYZ[X,Y].z;
                            }
                    }
                } else {
                    for ( int Y=0; Y < H; Y++ )
                        for ( int X=0; X < W; X++ )
                            diffuse.ContentXYZ[X,Y].w = 1.0f;
                }

                // Save diffuse as target
                diffuse.HasAlpha = gloss != null;
                diffuse.Save( targetFileName );
            }

            // Save optimized filename + timestamps of source files
            m_diffuseFileName.Refresh();
            if ( m_glossFileName != null )
                m_glossFileName.Refresh();

            m_optimizedDiffuseGlossFileName = targetFileName;
            m_diffuseTimeAtGeneration = m_diffuseFileName.LastWriteTime;
            m_glossTimeAtGeneration = m_glossFileName != null ? m_glossFileName.LastWriteTime : DateTime.MinValue;
        }
Exemplo n.º 21
0
        /// <summary>
        /// Generates a (diffuse+gloss) texture from 2 distinct textures
        /// </summary>
        public void GenerateDiffuseGlossTexture()
        {
            if (m_diffuse == null)
            {
                throw new Exception("Invalid source diffuse image file!");
            }
            if (!m_diffuse.m_fileName.Exists)
            {
                throw new Exception("Source diffuse image file \"" + m_diffuse.m_fileName.FullName + "\" does not exist on disk!");
            }

            FileInfo targetFileName = GetDiffuseGlossTextureFileName();

            using (ImageUtility.Bitmap diffuse = new ImageUtility.Bitmap(m_diffuse.m_fileName)) {
                int W = diffuse.Width;
                int H = diffuse.Height;

                ImageUtility.Bitmap gloss = null;
                if (m_gloss != null)
                {
                    gloss = new ImageUtility.Bitmap(m_gloss.m_fileName);

//                  int	gW = gloss.Width;
//                  int	gH = gloss.Height;
//                  for ( int Y=0; Y < gH; Y++ )
//                      for ( int X=0; X < gW; X++ ) {
//                          gloss.ContentXYZ[X,Y].x = ImageUtility.ColorProfile.sRGB2Linear( gloss.ContentXYZ[X,Y].x );
//                      }
                }
                bool needsScale = false;
                if (gloss != null && (gloss.Width != W || gloss.Height != H))
                {
                    needsScale = true;
                }

                if (gloss != null)
                {
                    if (needsScale)
                    {
                        // Set gloss as alpha with re-scaling
                        int W2 = gloss.Width;
                        int H2 = gloss.Height;
                        float[,]        source = new float[W2, H2];
                        for (int Y = 0; Y < H2; Y++)
                        {
                            for (int X = 0; X < W2; X++)
                            {
                                source[X, Y] = 0.3f * gloss.ContentXYZ[X, Y].x
                                               + 0.5f * gloss.ContentXYZ[X, Y].y
                                               + 0.2f * gloss.ContentXYZ[X, Y].z;
                            }
                        }

                        // Downscale first
                        while (W2 > W)
                        {
                            int halfW2 = W2 >> 1;
                            float[,]        temp = new float[halfW2, H2];
                            for (int Y = 0; Y < H2; Y++)
                            {
                                for (int X = 0; X < halfW2; X++)
                                {
                                    temp[X, Y] = 0.5f * (source[2 * X + 0, Y] + source[2 * X + 1, Y]);
                                }
                            }

                            source = temp;
                            W2     = halfW2;
                        }
                        while (H2 > H)
                        {
                            int halfH2 = H2 >> 1;
                            float[,]        temp = new float[W2, halfH2];
                            for (int Y = 0; Y < halfH2; Y++)
                            {
                                for (int X = 0; X < W2; X++)
                                {
                                    temp[X, Y] = 0.5f * (source[X, 2 * Y + 0] + source[X, 2 * Y + 1]);
                                }
                            }

                            source = temp;
                            H2     = halfH2;
                        }

                        // Upscale then
                        while (W2 < W)
                        {
                            int doubleW2 = W2 << 1;
                            float[,]        temp = new float[doubleW2, H2];
                            for (int Y = 0; Y < H2; Y++)
                            {
                                for (int X = 0; X < W2; X++)
                                {
                                    temp[2 * X + 0, Y] = source[X, Y];
                                    temp[2 * X + 1, Y] = 0.5f * (source[X, Y] + source[Math.Min(W2 - 1, X + 1), Y]);
                                }
                            }

                            source = temp;
                            W2     = doubleW2;
                        }
                        while (H2 < H)
                        {
                            int doubleH2 = H2 << 1;
                            float[,]        temp = new float[W2, doubleH2];
                            for (int Y = 0; Y < H2; Y++)
                            {
                                for (int X = 0; X < W2; X++)
                                {
                                    temp[X, 2 * Y + 0] = source[X, Y];
                                    temp[X, 2 * Y + 1] = 0.5f * (source[X, Y] + source[X, Math.Min(H2 - 1, Y + 1)]);
                                }
                            }

                            source = temp;
                            H2     = doubleH2;
                        }

                        for (int Y = 0; Y < H; Y++)
                        {
                            for (int X = 0; X < W; X++)
                            {
                                diffuse.ContentXYZ[X, Y].w = source[X, Y];
                            }
                        }
                    }
                    else
                    {
                        // Set gloss as alpha without re-scaling
                        for (int Y = 0; Y < H; Y++)
                        {
                            for (int X = 0; X < W; X++)
                            {
//								diffuse.ContentXYZ[X,Y].w = gloss.ContentXYZ[X,Y].x;

                                diffuse.ContentXYZ[X, Y].w = 0.3f * gloss.ContentXYZ[X, Y].x
                                                             + 0.5f * gloss.ContentXYZ[X, Y].y
                                                             + 0.2f * gloss.ContentXYZ[X, Y].z;
                            }
                        }
                    }
                }
                else
                {
                    for (int Y = 0; Y < H; Y++)
                    {
                        for (int X = 0; X < W; X++)
                        {
                            diffuse.ContentXYZ[X, Y].w = 1.0f;
                        }
                    }
                }

                // Save diffuse as target
                diffuse.HasAlpha = gloss != null;
                diffuse.Save(targetFileName);
            }

            // Save optimized filename + timestamps of source files
            m_diffuseFileName.Refresh();
            if (m_glossFileName != null)
            {
                m_glossFileName.Refresh();
            }

            m_optimizedDiffuseGlossFileName = targetFileName;
            m_diffuseTimeAtGeneration       = m_diffuseFileName.LastWriteTime;
            m_glossTimeAtGeneration         = m_glossFileName != null ? m_glossFileName.LastWriteTime : DateTime.MinValue;
        }
Exemplo n.º 22
0
        private void    Generate()
        {
            try {
                tabControlGenerators.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);


                //////////////////////////////////////////////////////////////////////////
                // 2] Compute directional occlusion
                m_TextureTarget1.RemoveFromLastAssignedSlots();

                // Prepare computation parameters
                m_TextureTarget0.SetCS(0);
                m_TextureTarget1.SetCSUAV(0);
                m_SB_Rays.SetInput(1);

                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);

                if (m_BitmapResult != null)
                {
                    m_BitmapResult.Dispose();
                }
                m_BitmapResult          = null;
                m_BitmapResult          = new ImageUtility.Bitmap(W, H, m_LinearProfile);
                m_BitmapResult.HasAlpha = true;

                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++)
                        {
                            ImageUtility.float4 Color = new ImageUtility.float4(R.ReadSingle(), R.ReadSingle(), R.ReadSingle(), R.ReadSingle());
                            Color = m_LinearProfile.RGB2XYZ(Color);
                            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 {
                tabControlGenerators.Enabled = true;
            }
        }
Exemplo n.º 23
0
        /// <summary>
        /// Reads image size and other informations, doesn't read content
        /// </summary>
        public void ReadImageInfos()
        {
            m_usage = FindUsage( m_fileName );

            if ( m_fileName.Extension.ToLower().StartsWith( ".bimage" ) ) {
                // Can't read!
                m_fileType = FILE_TYPE.BIMAGE;
                m_couldBeRead = false;
                return;
            }

            try {
                using ( ImageUtility.Bitmap B = new ImageUtility.Bitmap( m_fileName ) ) {
                    m_error = null;
                    m_couldBeRead = true;
                    m_width = B.Width;
                    m_height = B.Height;
                    switch ( B.Type ) {
                        case ImageUtility.Bitmap.FILE_TYPE.PNG: m_fileType = FILE_TYPE.PNG; break;
                        case ImageUtility.Bitmap.FILE_TYPE.TGA: m_fileType = FILE_TYPE.TGA; break;
            //						case ImageUtility.Bitmap.FILE_TYPE.DDS: m_fileType = FILE_TYPE.DDS; break;	// DDS not supported?
                        case ImageUtility.Bitmap.FILE_TYPE.JPEG: m_fileType = FILE_TYPE.JPG; break;
                        case ImageUtility.Bitmap.FILE_TYPE.TIFF: m_fileType = FILE_TYPE.TIFF; break;
                    }
                }
            } catch ( Exception _e ) {
                m_couldBeRead = false;
                m_error = _e;
                throw _e;
            }
        }
Exemplo n.º 24
0
        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" ) );
        }
Exemplo n.º 25
0
        private void buttonTestBilateral_Click( object sender, EventArgs e )
        {
            try {
                panelParameters.Enabled = false;

                //////////////////////////////////////////////////////////////////////////
                // 1] Apply bilateral filtering to the input texture as a pre-process
                ApplyBilateralFiltering( m_textureSourceHeightMap, m_textureTarget0, floatTrackbarControlBilateralRadius.Value, floatTrackbarControlBilateralTolerance.Value, checkBoxWrap.Checked, 100 );

                progressBar.Value = progressBar.Maximum;

                //////////////////////////////////////////////////////////////////////////
                // 2] Copy target to staging for CPU readback and update the resulting bitmap
                m_textureTarget_CPU.CopyFrom( m_textureTarget0 );

                ImageUtility.Bitmap		tempBitmap = new ImageUtility.Bitmap( W, H );
                Renderer.PixelsBuffer	Pixels = m_textureTarget_CPU.Map( 0, 0 );
                using ( System.IO.BinaryReader R = Pixels.OpenStreamRead() )
                    for ( uint Y=0; Y < H; Y++ ) {
                        R.BaseStream.Position = Y * Pixels.RowPitch;
                        for ( uint X=0; X < W; X++ ) {
                            float	AO = R.ReadSingle();
                            tempBitmap[X,Y] = new float4( AO, AO, AO, 1 );
                        }
                    }

                Pixels.Dispose();
                m_textureTarget_CPU.UnMap( 0, 0 );

                // Convert to RGB
            //				ImageUtility.ColorProfile	Profile = m_ProfilesRGB;	// AO maps are sRGB! (although strange, that's certainly to have more range in dark values)
                ImageUtility.ColorProfile	Profile = m_profilesRGB;	// AO maps are sRGB! (although strange, that's certainly to have more range in dark values)

                if ( m_imageResult != null )
                    m_imageResult.Dispose();
                m_imageResult = new ImageUtility.ImageFile();
                tempBitmap.ToImageFile( m_imageResult, Profile );

                // Assign result
                viewportPanelResult.Bitmap = m_imageResult.AsCustomBitmap( ( ref float4 _color ) => {} );

            } catch ( Exception _e ) {
                MessageBox( "An error occurred during generation!\r\n\r\nDetails: ", _e );
            } finally {
                panelParameters.Enabled = true;
            }
        }