提交 e58d641c 编写于 作者: D David

test: Imrpove image comparision tool

上级 cf1dae7e
......@@ -50,19 +50,24 @@ public static partial class ImageAssert
public static void HasColorInRectangle(RawBitmap screenshot, Rectangle rect, Color expectedColor, byte tolerance = 0, [CallerLineNumber] int line = 0)
{
var bitmap = screenshot;
(int x, int y, int diff, Color color) min = (-1, -1, int.MaxValue, default);
for (var x = rect.Left; x < rect.Right; x++)
{
for (var y = rect.Top; y < rect.Bottom; y++)
{
var pixel = bitmap.GetPixel(x, y);
if (AreSameColor(expectedColor, pixel, tolerance, out _))
if (AreSameColor(expectedColor, pixel, tolerance, out var diff))
{
return;
}
else if (diff < min.diff)
{
min = (x, y, diff, pixel);
}
}
}
Assert.Fail($"Expected '{ToArgbCode(expectedColor)}' in rectangle '{rect}'.");
Assert.Fail($"Expected '{ToArgbCode(expectedColor)}' in rectangle '{rect}', but no pixel has this color. The closest pixel found is '{ToArgbCode(min.color)}' at '{min.x},{min.y}' with a (exclusive) difference of {min.diff}.");
}
/// <summary>
......@@ -76,9 +81,9 @@ public static partial class ImageAssert
for (var y = rect.Top; y < rect.Bottom; y++)
{
var pixel = bitmap.GetPixel(x, y);
if (AreSameColor(excludedColor, pixel, tolerance, out _))
if (AreSameColor(excludedColor, pixel, tolerance, out var diff))
{
Assert.Fail($"Color '{ToArgbCode(excludedColor)}' was found at ({x}, {y}) in rectangle '{rect}'.");
Assert.Fail($"Color '{ToArgbCode(excludedColor)}' was found at ({x}, {y}) in rectangle '{rect}' (Exclusive difference of {diff}).");
}
}
}
......
......@@ -117,8 +117,7 @@ namespace Uno.UI.RuntimeTests.Helpers
throw new InvalidOperationException("Populate must be invoked first");
}
_altered = true;
ImageHelper.MakeOpaque(_pixels, background);
_altered = ImageHelper.MakeOpaque(_pixels, background);
}
internal async Task<ImageSource> GetImageSource(bool preferOriginal = false)
......
......@@ -45,7 +45,7 @@ public static class UITestHelper
/// <param name="opaque">Indicates if the resulting image should be make opaque (i.e. all pixels has an opacity of 0xFF) or not.</param>
/// <param name="scaling">Indicates the scaling strategy to apply for the image (when screen is not using a 1.0 scale, usually 4K screens).</param>
/// <returns></returns>
public static async Task<RawBitmap> ScreenShot(FrameworkElement element, bool opaque = true, ScreenShotScalingMode scaling = ScreenShotScalingMode.UsePhysicalPixelsWithImplicitScaling)
public static async Task<RawBitmap> ScreenShot(FrameworkElement element, bool opaque = false, ScreenShotScalingMode scaling = ScreenShotScalingMode.UsePhysicalPixelsWithImplicitScaling)
{
var renderer = new RenderTargetBitmap();
element.UpdateLayout();
......@@ -115,10 +115,12 @@ public static class UITestHelper
BorderBrush = new SolidColorBrush(Windows.UI.Colors.Black),
BorderThickness = new Thickness(1),
Background = new SolidColorBrush(Windows.UI.Colors.Gray),
Width = bitmap.Width * bitmap.ImplicitScaling + 2,
Height = bitmap.Height * bitmap.ImplicitScaling + 2,
Child = img = new Image
{
Width = bitmap.Width,
Height = bitmap.Height,
Width = bitmap.Width * bitmap.ImplicitScaling,
Height = bitmap.Height * bitmap.ImplicitScaling,
Source = await bitmap.GetImageSource(),
Stretch = Stretch.None,
ManipulationMode = ManipulationModes.Scale
......@@ -126,6 +128,7 @@ public static class UITestHelper
| ManipulationModes.TranslateX
| ManipulationModes.TranslateY
| ManipulationModes.TranslateInertia,
RenderTransformOrigin = new Point(.5, .5),
RenderTransform = imgTr = new CompositeTransform()
}
},
......
#nullable enable
using System;
using System.Linq;
using Windows.UI;
namespace Uno.Helpers;
internal static class ColorExtensions
{
/// <summary>
/// Returns the color that results from blending the color with the given background color.
/// </summary>
/// <param name="color">The color to blend.</param>
/// <param name="background">The background color to use. This is assumed to be opaque (not checked for perf reason when used on pixel buffer).</param>
/// <returns>The color that results from blending the color with the given background color.</returns>
internal static Color ToOpaque(this Color color, Color background)
=> new(
255,
(byte)(((byte.MaxValue - color.A) * background.R + color.A * color.R) / 255),
(byte)(((byte.MaxValue - color.A) * background.G + color.A * color.G) / 255),
(byte)(((byte.MaxValue - color.A) * background.B + color.A * color.B) / 255)
);
}
......@@ -13,7 +13,7 @@ internal static class ImageHelper
/// </summary>
/// <param name="rgba8PixelsBuffer">The pixels buffer (must not be pre-multiplied!).</param>
/// <param name="background">The **opaque** background to use.</param>
public static void MakeOpaque(byte[] rgba8PixelsBuffer, Color? background = null)
public static bool MakeOpaque(byte[] rgba8PixelsBuffer, Color? background = null)
{
if (background is { A: not 255 })
{
......@@ -22,9 +22,15 @@ internal static class ImageHelper
background ??= Colors.White;
var modified = false;
for (var i = 0; i < rgba8PixelsBuffer.Length; i += 4)
{
var a = rgba8PixelsBuffer[i + 3];
if (a == 255)
{
continue;
}
var r = rgba8PixelsBuffer[i + 2];
var g = rgba8PixelsBuffer[i + 1];
var b = rgba8PixelsBuffer[i + 0];
......@@ -35,7 +41,11 @@ internal static class ImageHelper
rgba8PixelsBuffer[i + 2] = opaque.R;
rgba8PixelsBuffer[i + 1] = opaque.G;
rgba8PixelsBuffer[i + 0] = opaque.B;
modified = true;
}
return modified;
}
/// <summary>
......
......@@ -76,19 +76,6 @@ namespace Windows.UI
/// </summary>
internal double Luminance => (0.299 * _r + 0.587 * _g + 0.114 * _b) / 255;
/// <summary>
/// Returns the color that results from blending the color with the given background color.
/// </summary>
/// <param name="background">The background color to use. This is assumed to be opaque (not checked for perf reason when used on pixel buffer).</param>
/// <returns>The color that results from blending the color with the given background color.</returns>
internal Color ToOpaque(Color background)
=> new(
255,
(byte)(((byte.MaxValue - _a) * background._r + _a * _r) / 255),
(byte)(((byte.MaxValue - _a) * background._g + _a * _g) / 255),
(byte)(((byte.MaxValue - _a) * background._b + _a * _b) / 255)
);
internal Color WithOpacity(double opacity) => new((byte)(_a * opacity), _r, _g, _b);
internal uint AsUInt32() => _color;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册