WriteableBitmapPage.cs 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. using System.Diagnostics;
  2. using System.Runtime.InteropServices;
  3. using Avalonia;
  4. using Avalonia.Controls;
  5. using Avalonia.LogicalTree;
  6. using Avalonia.Media;
  7. using Avalonia.Media.Imaging;
  8. using Avalonia.Media.Immutable;
  9. using Avalonia.Platform;
  10. using Avalonia.Threading;
  11. namespace RenderDemo.Pages
  12. {
  13. public class WriteableBitmapPage : Control
  14. {
  15. private WriteableBitmap _unpremulBitmap;
  16. private WriteableBitmap _premulBitmap;
  17. private readonly Stopwatch _st = Stopwatch.StartNew();
  18. protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
  19. {
  20. _unpremulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Unpremul);
  21. _premulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Premul);
  22. base.OnAttachedToLogicalTree(e);
  23. }
  24. protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
  25. {
  26. base.OnDetachedFromLogicalTree(e);
  27. _unpremulBitmap?.Dispose();
  28. _unpremulBitmap = null;
  29. _premulBitmap?.Dispose();
  30. _unpremulBitmap = null;
  31. }
  32. public override void Render(DrawingContext context)
  33. {
  34. void FillPixels(WriteableBitmap bitmap, byte fillAlpha, bool premul)
  35. {
  36. using (var fb = bitmap.Lock())
  37. {
  38. var data = new int[fb.Size.Width * fb.Size.Height];
  39. for (int y = 0; y < fb.Size.Height; y++)
  40. {
  41. for (int x = 0; x < fb.Size.Width; x++)
  42. {
  43. var color = new Color(fillAlpha, 0, 255, 0);
  44. if (premul)
  45. {
  46. byte r = (byte) (color.R * color.A / 255);
  47. byte g = (byte) (color.G * color.A / 255);
  48. byte b = (byte) (color.B * color.A / 255);
  49. color = new Color(fillAlpha, r, g, b);
  50. }
  51. data[y * fb.Size.Width + x] = (int) color.ToUInt32();
  52. }
  53. }
  54. Marshal.Copy(data, 0, fb.Address, fb.Size.Width * fb.Size.Height);
  55. }
  56. }
  57. base.Render(context);
  58. byte alpha = (byte)((_st.ElapsedMilliseconds / 10) % 256);
  59. FillPixels(_unpremulBitmap, alpha, false);
  60. FillPixels(_premulBitmap, alpha, true);
  61. context.FillRectangle(Brushes.Red, new Rect(0, 0, 256 * 3, 256));
  62. context.DrawImage(_unpremulBitmap,
  63. new Rect(0, 0, 256, 256),
  64. new Rect(0, 0, 256, 256));
  65. context.DrawImage(_premulBitmap,
  66. new Rect(0, 0, 256, 256),
  67. new Rect(256, 0, 256, 256));
  68. context.FillRectangle(new ImmutableSolidColorBrush(Colors.Lime, alpha / 255d), new Rect(512, 0, 256, 256));
  69. Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
  70. }
  71. }
  72. }