未验证 提交 d83cfcd4 编写于 作者: M mergify[bot] 提交者: GitHub

Merge pull request #13070 from Youssef1313/render-target-bitmap

fix: Fix rendering of RenderTargetBitmap
......@@ -32,9 +32,7 @@ namespace Windows.UI.Composition
{
using var codec = SKCodec.Create(stream);
var info = codec.Info;
var bitmap = new SKBitmap(actualTargetWidth, actualTargetHeight, info.ColorType, info.IsOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul);
var bitmap = new SKBitmap(actualTargetWidth, actualTargetHeight, SKColorType.Bgra8888, SKAlphaType.Premul);
var result = codec.GetPixels(bitmap.Info, bitmap.GetPixels());
......
......@@ -97,5 +97,30 @@ namespace Windows.UI.Composition
return ret;
}
/// <summary>
/// This is an alternative to the built-in SKBitmap.FromImage.
/// The problem with SKBitmap.FromImage is that it ignores the color type of the input image, and
/// uses SKImageInfo.PlatformColorType.
/// The code is the same as SKBitmap.FromImage except for respecting color type.
/// See https://github.com/mono/SkiaSharp/blob/7d7766532a4666f56944e65bee1c2158c320f09c/binding/Binding/SKBitmap.cs#L830-L843
/// </summary>
public static SKBitmap ToSKBitmap(this SKImage image)
{
if (image == null)
{
throw new ArgumentNullException(nameof(image));
}
var info = new SKImageInfo(image.Width, image.Height, image.ColorType, image.AlphaType);
var bmp = new SKBitmap(info);
if (!image.ReadPixels(info, bmp.GetPixels(), info.RowBytes, 0, 0))
{
bmp.Dispose();
bmp = null;
}
return bmp!;
}
}
}
......@@ -88,10 +88,6 @@ namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Media_Imaging
[Ignore("Not implemented yet.")]
#elif __MACOS__
[Ignore("Currently fails on macOS, part of #9282 epic")]
#elif __SKIA__
[Ignore("Currently fails on CI for skia GTK (works locally)")]
#elif __ANDROID__
[Ignore("Currently fails on CI for Android https://github.com/unoplatform/uno/issues/9080")]
#endif
public async Task When_Render_Then_CanRenderOnCanvas()
{
......
......@@ -9,6 +9,7 @@ using Windows.Foundation;
using Java.Nio;
using Android.Views;
using Uno.UI.Xaml.Media;
using System.Runtime.InteropServices;
namespace Windows.UI.Xaml.Media.Imaging
{
......@@ -39,9 +40,27 @@ namespace Windows.UI.Xaml.Media.Imaging
/// <inheritdoc />
private protected override bool IsSourceReady => _buffer != null;
[StructLayout(LayoutKind.Explicit)]
private struct ByteArrayToIntArrayBridge
{
[FieldOffset(0)]
public byte[] ByteArray;
[FieldOffset(0)]
public int[] IntArray;
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public ByteArrayToIntArrayBridge(byte[] bytes)
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
{
ByteArray = bytes;
}
}
private static ImageData Open(byte[] buffer, int bufferLength, int width, int height)
{
return ImageData.FromBitmap(BitmapFactory.DecodeByteArray(buffer, 0, bufferLength));
var bitmap = Bitmap.CreateBitmap(new ByteArrayToIntArrayBridge(buffer).IntArray, width, height, Bitmap.Config.Argb8888!);
return ImageData.FromBitmap(bitmap);
}
private (int ByteCount, int Width, int Height) RenderAsBgra8_Premul(UIElement element, ref byte[]? buffer, Size? scaledSize = null)
......@@ -105,5 +124,20 @@ namespace Windows.UI.Xaml.Media.Imaging
SetSoftwareRendering(element, false);
}
}
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
private static void SwapRB(ref byte[] buffer, int byteCount)
{
for (var i = 0; i < byteCount; i += 4)
{
//Swap R and B chanal
Swap(ref buffer![i], ref buffer![i + 2]);
}
}
private static void Swap(ref byte a, ref byte b)
{
(a, b) = (b, a);
}
}
}
......@@ -172,23 +172,6 @@ namespace Windows.UI.Xaml.Media.Imaging
buffer = ArrayPool<byte>.Shared.Rent(length);
}
}
#if !__IOS__ && !__MACOS__
[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
private static void SwapRB(ref byte[] buffer, int byteCount)
{
for (var i = 0; i < byteCount; i += 4)
{
//Swap R and B chanal
Swap(ref buffer![i], ref buffer![i + 2]);
}
}
private static void Swap(ref byte a, ref byte b)
{
(a, b) = (b, a);
}
#endif
#endif
#endregion
}
......
......@@ -14,21 +14,8 @@ namespace Windows.UI.Xaml.Media.Imaging
private const int _bitsPerComponent = 8;
private const int _bytesPerPixel = _bitsPerPixel / _bitsPerComponent;
delegate void SwapColor(ref byte[] buffer, int byteCount);
private static readonly SwapColor? _platformSwap = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? SwapRB : default;
private static ImageData Open(byte[] buffer, int bufferLength, int width, int height)
{
if (_platformSwap is not null)
{
var swappedBuffer = default(byte[]);
EnsureBuffer(ref swappedBuffer, bufferLength);
Array.Copy(buffer, swappedBuffer!, bufferLength);
_platformSwap(ref swappedBuffer!, bufferLength);
buffer = swappedBuffer;
}
var bufferHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
......@@ -70,7 +57,7 @@ namespace Windows.UI.Xaml.Media.Imaging
var img = surface.Snapshot();
var bitmap = SKBitmap.FromImage(img);
var bitmap = img.ToSKBitmap();
if (scaledSize.HasValue)
{
var scaledBitmap = bitmap.Resize(
......@@ -84,8 +71,6 @@ namespace Windows.UI.Xaml.Media.Imaging
var byteCount = bitmap.ByteCount;
EnsureBuffer(ref buffer, byteCount);
bitmap.GetPixelSpan().CopyTo(buffer);
//On macOS color as stored as rgba
_platformSwap?.Invoke(ref buffer!, byteCount);
bitmap?.Dispose();
return (byteCount, width, height);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册