diff --git a/src/Avalonia.Base/Media/Imaging/WriteableBitmap.cs b/src/Avalonia.Base/Media/Imaging/WriteableBitmap.cs
index a3dd88b075..868f4439c4 100644
--- a/src/Avalonia.Base/Media/Imaging/WriteableBitmap.cs
+++ b/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;
}
+ ///
+ /// Initializes a new instance of the class with existing pixel data
+ /// The data is copied to the bitmap
+ ///
+ /// The pixel format.
+ /// The alpha format.
+ /// The pointer to the source bytes.
+ /// The size of the bitmap in device pixels.
+ /// The DPI of the bitmap.
+ /// The number of bytes per row.
+ 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()
diff --git a/tests/Avalonia.RenderTests/Media/BitmapTests.cs b/tests/Avalonia.RenderTests/Media/BitmapTests.cs
index 5b85f98b70..c63a876d81 100644
--- a/tests/Avalonia.RenderTests/Media/BitmapTests.cs
+++ b/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);