/// <summary>
        /// Converts a System.Drawing.Bitmap to a DirectX 11 texture object.
        /// </summary>
        /// <param name="device">Device on which the resource should be created.</param>
        /// <param name="bitmap">The source bitmap.</param>
        internal static D3D11.ID3D11Texture2D LoadTextureFromBitmap(EngineDevice device, GDI.Bitmap bitmap)
        {
            device.EnsureNotNull(nameof(device));
            bitmap.EnsureNotNull(nameof(bitmap));

            return(LoadTextureFromBitmap(device, bitmap, 1));
        }
Пример #2
0
        /// <summary>
        /// Calculate a difference between two pictures
        /// </summary>
        /// <param name="bitmapLeft">The first bitmap for the comparison.</param>
        /// <param name="bitmapRight">The second bitmap for the comparison.</param>
        /// <returns>Difference of both bitmaps in percent</returns>
        public static float CalculatePercentageDifference(GDI.Bitmap bitmapLeft, GDI.Bitmap bitmapRight)
        {
            bitmapLeft.EnsureNotNull(nameof(bitmapLeft));
            bitmapRight.EnsureNotNull(nameof(bitmapRight));
            if (bitmapLeft.Size != bitmapRight.Size)
            {
                throw new SeeingSharpException("Both bitmaps musst have the same size!");
            }

            var totalDiffPercent = 0M;

            var lockRect = new GDI.Rectangle(
                new GDI.Point(0, 0),
                bitmapLeft.Size);
            var dataLeft  = bitmapLeft.LockBits(lockRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            var dataRight = bitmapRight.LockBits(lockRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            try
            {
                unsafe
                {
                    var     dataLeftP  = (byte *)dataLeft.Scan0.ToPointer();
                    var     dataRightP = (byte *)dataRight.Scan0.ToPointer();
                    decimal pixelCount = lockRect.Width * lockRect.Height;

                    for (var loopY = 0; loopY < lockRect.Height; loopY++)
                    {
                        for (var loopX = 0; loopX < lockRect.Width; loopX++)
                        {
                            // Calculate the memory location of the current pixel
                            var currentLoc = loopY * lockRect.Height * 4 + loopX * 4;

                            // Get the maximum difference on this pixel on one color channel
                            var diffA   = Math.Abs(dataLeftP[currentLoc] - dataRightP[currentLoc]);
                            var diffR   = Math.Abs(dataLeftP[currentLoc + 1] - dataRightP[currentLoc + 1]);
                            var diffG   = Math.Abs(dataLeftP[currentLoc + 2] - dataRightP[currentLoc + 2]);
                            var diffB   = Math.Abs(dataLeftP[currentLoc + 3] - dataRightP[currentLoc + 3]);
                            var maxDiff = Math.Max(diffA, Math.Max(diffR, Math.Max(diffG, diffB)));
                            if (maxDiff > MAX_PER_PIXEL_DIFF)
                            {
                                maxDiff = MAX_PER_PIXEL_DIFF;
                            }

                            // Calculate the difference factor on this pixel and add it to the total difference value
                            var pixelDiffPercent =
                                maxDiff / MAX_PER_PIXEL_DIFF_DEC;
                            totalDiffPercent += pixelDiffPercent / pixelCount;
                        }
                    }
                }
            }
            finally
            {
                bitmapLeft.UnlockBits(dataLeft);
                bitmapRight.UnlockBits(dataRight);
            }

            return((float)totalDiffPercent);
        }
        /// <summary>
        /// Converts a System.Drawing.Bitmap to a DirectX 11 texture object.
        /// </summary>
        /// <param name="device">Device on which the resource should be created.</param>
        /// <param name="bitmap">The source bitmap.</param>
        /// <param name="mipLevels">Total count of levels for mipmapping.</param>
        internal static D3D11.ID3D11Texture2D LoadTextureFromBitmap(EngineDevice device, GDI.Bitmap bitmap, int mipLevels)
        {
            device.EnsureNotNull(nameof(device));
            bitmap.EnsureNotNull(nameof(bitmap));
            mipLevels.EnsurePositiveOrZero(nameof(mipLevels));

            D3D11.ID3D11Texture2D?result = null;

            // Lock bitmap so it can be accessed for texture loading
            var bitmapData = bitmap.LockBits(
                new GDI.Rectangle(0, 0, bitmap.Width, bitmap.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            try
            {
                // Open a reading stream for bitmap memory
                var dataRectangle = new D3D11.SubresourceData(bitmapData.Scan0, bitmap.Width * 4);

                // Load the texture
                result = device.Internals.DeviceD3D11_1.CreateTexture2D(
                    new D3D11.Texture2DDescription
                {
                    BindFlags         = D3D11.BindFlags.ShaderResource | D3D11.BindFlags.RenderTarget,
                    CpuAccessFlags    = D3D11.CpuAccessFlags.None,
                    Format            = GraphicsHelper.Internals.DEFAULT_TEXTURE_FORMAT,
                    OptionFlags       = D3D11.ResourceOptionFlags.None | D3D11.ResourceOptionFlags.GenerateMips,
                    MipLevels         = 0,
                    Usage             = D3D11.ResourceUsage.Default,
                    Width             = bitmap.Width,
                    Height            = bitmap.Height,
                    ArraySize         = 1,
                    SampleDescription = new SampleDescription(1, 0)
                },
                    new[]
                {
                    dataRectangle, dataRectangle, dataRectangle, dataRectangle,
                    dataRectangle, dataRectangle, dataRectangle, dataRectangle,
                    dataRectangle, dataRectangle, dataRectangle, dataRectangle
                });

                // Workaround for now... auto generate mip-levels
                using var shaderResourceView = device.Internals.DeviceD3D11_1.CreateShaderResourceView(result);
                device.Internals.DeviceImmediateContextD3D11.GenerateMips(shaderResourceView);
            }
            finally
            {
                // Free bitmap-access resources
                bitmap.UnlockBits(bitmapData);
            }

            return(result);
        }