|
@@ -0,0 +1,92 @@
|
|
|
+using System.Diagnostics;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
+using Avalonia;
|
|
|
+using Avalonia.Controls;
|
|
|
+using Avalonia.LogicalTree;
|
|
|
+using Avalonia.Media;
|
|
|
+using Avalonia.Media.Imaging;
|
|
|
+using Avalonia.Media.Immutable;
|
|
|
+using Avalonia.Platform;
|
|
|
+using Avalonia.Threading;
|
|
|
+
|
|
|
+namespace RenderDemo.Pages
|
|
|
+{
|
|
|
+ public class WriteableBitmapPage : Control
|
|
|
+ {
|
|
|
+ private WriteableBitmap _unpremulBitmap;
|
|
|
+ private WriteableBitmap _premulBitmap;
|
|
|
+ private readonly Stopwatch _st = Stopwatch.StartNew();
|
|
|
+
|
|
|
+ protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
|
|
+ {
|
|
|
+ _unpremulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Unpremul);
|
|
|
+ _premulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Premul);
|
|
|
+
|
|
|
+ base.OnAttachedToLogicalTree(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
|
|
|
+ {
|
|
|
+ base.OnDetachedFromLogicalTree(e);
|
|
|
+
|
|
|
+ _unpremulBitmap?.Dispose();
|
|
|
+ _unpremulBitmap = null;
|
|
|
+
|
|
|
+ _premulBitmap?.Dispose();
|
|
|
+ _unpremulBitmap = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override void Render(DrawingContext context)
|
|
|
+ {
|
|
|
+ void FillPixels(WriteableBitmap bitmap, byte fillAlpha, bool premul)
|
|
|
+ {
|
|
|
+ using (var fb = bitmap.Lock())
|
|
|
+ {
|
|
|
+ var data = new int[fb.Size.Width * fb.Size.Height];
|
|
|
+
|
|
|
+ for (int y = 0; y < fb.Size.Height; y++)
|
|
|
+ {
|
|
|
+ for (int x = 0; x < fb.Size.Width; x++)
|
|
|
+ {
|
|
|
+ var color = new Color(fillAlpha, 0, 255, 0);
|
|
|
+
|
|
|
+ if (premul)
|
|
|
+ {
|
|
|
+ byte r = (byte) (color.R * color.A / 255);
|
|
|
+ byte g = (byte) (color.G * color.A / 255);
|
|
|
+ byte b = (byte) (color.B * color.A / 255);
|
|
|
+
|
|
|
+ color = new Color(fillAlpha, r, g, b);
|
|
|
+ }
|
|
|
+
|
|
|
+ data[y * fb.Size.Width + x] = (int) color.ToUint32();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Marshal.Copy(data, 0, fb.Address, fb.Size.Width * fb.Size.Height);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ base.Render(context);
|
|
|
+
|
|
|
+ byte alpha = (byte)((_st.ElapsedMilliseconds / 10) % 256);
|
|
|
+
|
|
|
+ FillPixels(_unpremulBitmap, alpha, false);
|
|
|
+ FillPixels(_premulBitmap, alpha, true);
|
|
|
+
|
|
|
+ context.FillRectangle(Brushes.Red, new Rect(0, 0, 256 * 3, 256));
|
|
|
+
|
|
|
+ context.DrawImage(_unpremulBitmap,
|
|
|
+ new Rect(0, 0, 256, 256),
|
|
|
+ new Rect(0, 0, 256, 256));
|
|
|
+
|
|
|
+ context.DrawImage(_premulBitmap,
|
|
|
+ new Rect(0, 0, 256, 256),
|
|
|
+ new Rect(256, 0, 256, 256));
|
|
|
+
|
|
|
+ context.FillRectangle(new ImmutableSolidColorBrush(Colors.Lime, alpha / 255d), new Rect(512, 0, 256, 256));
|
|
|
+
|
|
|
+ Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|