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