Browse Source

Correctly handle x,y offset for Bitmap.CopyPixels (#15510)

* Correctly handle x,y offset for Bitmap.CopyPixels

* Remove using
release/11.1.0-rc1
Benedikt Stebner 2 years ago
committed by Max Katz
parent
commit
2d0220f784
  1. 13
      src/Avalonia.Base/Media/Imaging/Bitmap.cs
  2. 29
      tests/Avalonia.RenderTests/Media/BitmapTests.cs

13
src/Avalonia.Base/Media/Imaging/Bitmap.cs

@ -182,12 +182,15 @@ namespace Avalonia.Media.Imaging
private protected unsafe void CopyPixelsCore(PixelRect sourceRect, IntPtr buffer, int bufferSize, int stride,
ILockedFramebuffer fb)
{
if (Format == null)
throw new NotSupportedException("CopyPixels is not supported for this bitmap type");
if ((sourceRect.Width <= 0 || sourceRect.Height <= 0) && (sourceRect.X != 0 || sourceRect.Y != 0))
throw new ArgumentOutOfRangeException(nameof(sourceRect));
if (sourceRect.X < 0 || sourceRect.Y < 0)
throw new ArgumentOutOfRangeException(nameof(sourceRect));
if (sourceRect.Width <= 0)
sourceRect = sourceRect.WithWidth(PixelSize.Width);
if (sourceRect.Height <= 0)
@ -195,7 +198,7 @@ namespace Avalonia.Media.Imaging
if (sourceRect.Right > PixelSize.Width || sourceRect.Bottom > PixelSize.Height)
throw new ArgumentOutOfRangeException(nameof(sourceRect));
int minStride = checked(((sourceRect.Width * fb.Format.BitsPerPixel) + 7) / 8);
if (stride < minStride)
throw new ArgumentOutOfRangeException(nameof(stride));
@ -204,14 +207,16 @@ namespace Avalonia.Media.Imaging
if (minBufferSize > bufferSize)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
var offsetX = checked(((sourceRect.X * Format.Value.BitsPerPixel) + 7) / 8);
for (var y = 0; y < sourceRect.Height; y++)
{
var srcAddress = fb.Address + fb.RowBytes * y;
var srcAddress = fb.Address + fb.RowBytes * (sourceRect.Y + y) + offsetX;
var dstAddress = buffer + stride * y;
Unsafe.CopyBlock(dstAddress.ToPointer(), srcAddress.ToPointer(), (uint)minStride);
}
}
public virtual void CopyPixels(PixelRect sourceRect, IntPtr buffer, int bufferSize, int stride)
{
if (

29
tests/Avalonia.RenderTests/Media/BitmapTests.cs

@ -246,5 +246,34 @@ namespace Avalonia.Direct2D1.RenderTests.Media
bmp.CopyPixels(default, new IntPtr(pCopyTo), data.Length, stride);
Assert.Equal(data, copyTo);
}
[Fact]
public unsafe void Should_CopyPixels_With_Source_Rect()
{
var size = 80;
var partSize = 20;
var bitmap = new RenderTargetBitmap(new PixelSize(size, size));
using (var context = bitmap.CreateDrawingContext())
{
context.FillRectangle(Brushes.Black,
new Rect(0, 0, bitmap.PixelSize.Width, bitmap.PixelSize.Height));
context.FillRectangle(Brushes.White, new Rect(partSize, partSize, partSize, partSize));
}
var bpp = bitmap.Format!.Value.BitsPerPixel / 8;
var buffer = new byte[partSize * partSize * bpp];
fixed (byte* pointer = buffer)
{
bitmap.CopyPixels(new PixelRect(partSize, partSize, partSize, partSize), (IntPtr)pointer,
buffer.Length, partSize * bpp);
}
foreach (var t in buffer)
{
Assert.Equal(byte.MaxValue, t);
}
}
}
}

Loading…
Cancel
Save