Sfoglia il codice sorgente

Added a ctor for populating WriteableBitmap with initial data

Nikita Tsukanov 2 anni fa
parent
commit
a0adee3d00

+ 26 - 0
src/Avalonia.Base/Media/Imaging/WriteableBitmap.cs

@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using System.Runtime.CompilerServices;
 using Avalonia.Platform;
 
 namespace Avalonia.Media.Imaging
@@ -36,6 +37,31 @@ namespace Avalonia.Media.Imaging
             _pixelFormatMemory = pixelFormatMemory;
         }
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="WriteableBitmap"/> class with existing pixel data
+        /// The data is copied to the bitmap
+        /// </summary>
+        /// <param name="format">The pixel format.</param>
+        /// <param name="alphaFormat">The alpha format.</param>
+        /// <param name="data">The pointer to the source bytes.</param>
+        /// <param name="size">The size of the bitmap in device pixels.</param>
+        /// <param name="dpi">The DPI of the bitmap.</param>
+        /// <param name="stride">The number of bytes per row.</param>
+        public unsafe WriteableBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
+            : this(size, dpi, format, alphaFormat)
+        {
+            var minStride = (format.BitsPerPixel * size.Width + 7) / 8;
+            if (minStride > stride)
+                throw new ArgumentOutOfRangeException(nameof(stride));
+
+            using (var locked = Lock())
+            {
+                for (var y = 0; y < size.Height; y++)
+                    Unsafe.CopyBlock((locked.Address + locked.RowBytes * y).ToPointer(),
+                        (data + y * stride).ToPointer(), (uint)minStride);
+            }
+        }
+
         public override PixelFormat? Format => _pixelFormatMemory?.Format ?? base.Format;
         
         public ILockedFramebuffer Lock()

+ 21 - 9
tests/Avalonia.RenderTests/Media/BitmapTests.cs

@@ -167,10 +167,17 @@ namespace Avalonia.Direct2D1.RenderTests.Media
             if (!File.Exists(Path.Combine(OutputPath, expectedName + ".expected.png")))
                 expectedName = Path.Combine(relativeFilesDir, "Default");
 
-            foreach (var writable in new[] { false, true })
+            var names = new[]
+            {
+                "_Writeable",
+                "_WriteableInitialized",
+                "_Normal"
+            };
+            
+            foreach (var step in new[] { 0,1,2 })
             {
-                var testName = nameof(BitmapsShouldSupportTranscoders_Lenna) + "_" + formatName +
-                               (writable ? "_Writeable" : "_Normal");
+
+                var testName = nameof(BitmapsShouldSupportTranscoders_Lenna) + "_" + formatName + names[step];
 
                 var path = System.IO.Path.Combine(OutputPath, testName + ".out.png");
                 fixed (byte* pData = data)
@@ -178,7 +185,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
                     Bitmap? b = null;
                     try
                     {
-                        if (writable)
+                        if (step == 0)
                         {
                             var bmp = new WriteableBitmap(size, new Vector(96, 96), new PixelFormat(format),
                                 alphaFormat);
@@ -194,15 +201,20 @@ namespace Avalonia.Direct2D1.RenderTests.Media
                             }
 
                             b = bmp;
-                            var copyTo = new byte[data.Length];
-                            fixed (byte* pCopyTo = copyTo)
-                                b.CopyPixels(default, new IntPtr(pCopyTo), copyTo.Length, stride);
-                            Assert.Equal(data.ToArray(), copyTo);
                         }
+                        else if (step == 1)
+                            b = new WriteableBitmap(new PixelFormat(format), alphaFormat, new IntPtr(pData),
+                                size, new Vector(96, 96), stride);
                         else
-                        {
                             b = new Bitmap(new PixelFormat(format), alphaFormat, new IntPtr(pData),
                                 size, new Vector(96, 96), stride);
+
+                        if (step < 2)
+                        {
+                            var copyTo = new byte[data.Length];
+                            fixed (byte* pCopyTo = copyTo)
+                                b.CopyPixels(default, new IntPtr(pCopyTo), copyTo.Length, stride);
+                            Assert.Equal(data.ToArray(), copyTo);
                         }
 
                         b.Save(path);