Added CroppedBitmap

This commit is contained in:
TheXamlGuy
2024-10-11 14:00:03 +01:00
parent cecf514140
commit 464d3d9c14
@@ -5,11 +5,16 @@ using Avalonia.Interactivity;
using Avalonia; using Avalonia;
using Avalonia.Media; using Avalonia.Media;
using Path = Avalonia.Controls.Shapes.Path; using Path = Avalonia.Controls.Shapes.Path;
using Avalonia.Media.Imaging;
namespace Toolkit.UI.Controls.Avalonia; namespace Toolkit.UI.Controls.Avalonia;
public class ContentCropper : ContentControl public class ContentCropper : ContentControl
{ {
public static readonly DirectProperty<ContentCropper, Bitmap?> CroppedBitmapProperty =
AvaloniaProperty.RegisterDirect<ContentCropper, Bitmap?>(nameof(CroppedBitmap),
o => o.CroppedBitmap);
public static readonly StyledProperty<Rect> CropRectangleProperty = public static readonly StyledProperty<Rect> CropRectangleProperty =
AvaloniaProperty.Register<ContentCropper, Rect>(nameof(CropRectangle)); AvaloniaProperty.Register<ContentCropper, Rect>(nameof(CropRectangle));
@@ -23,29 +28,35 @@ public class ContentCropper : ContentControl
AvaloniaProperty.Register<ContentCropper, Size>(nameof(ScaleSize), new Size(2, 1)); AvaloniaProperty.Register<ContentCropper, Size>(nameof(ScaleSize), new Size(2, 1));
private Border? border; private Border? border;
private Thumb? bottomButton;
private Thumb? bottomLeftButton; private Thumb? bottomLeftButton;
private Thumb? bottomRightButton; private Thumb? bottomRightButton;
private Canvas? canvas; private Canvas? canvas;
private double cropHeightRatio; private double cropHeightRatio;
private double cropLeftRatio; private double cropLeftRatio;
private Bitmap? croppedBitmap;
private double cropTopRatio; private double cropTopRatio;
private double cropWidthRatio; private double cropWidthRatio;
private bool isDragging; private bool isDragging;
private Thumb? leftButton;
private double offsetX; private double offsetX;
private double offsetY; private double offsetY;
private Path? overlayPath; private Path? overlayPath;
private Thumb? topLeftButton;
private Thumb? topRightButton;
private Thumb? leftButton;
private Thumb? rightButton; private Thumb? rightButton;
private Thumb? topButton; private Thumb? topButton;
private Thumb? bottomButton; private Thumb? topLeftButton;
private Thumb? topRightButton;
static ContentCropper() static ContentCropper()
{ {
AffectsRender<ContentCropper>(RectScaleProperty, ContentProperty); AffectsRender<ContentCropper>(RectScaleProperty, ContentProperty);
} }
public Bitmap? CroppedBitmap
{
get => croppedBitmap;
private set => SetAndRaise(CroppedBitmapProperty, ref croppedBitmap, value);
}
public Rect CropRectangle public Rect CropRectangle
{ {
get => GetValue(CropRectangleProperty); get => GetValue(CropRectangleProperty);
@@ -139,7 +150,7 @@ public class ContentCropper : ContentControl
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property == IsRatioScaleProperty || if (change.Property == IsRatioScaleProperty ||
change.Property == RectScaleProperty || change.Property == RectScaleProperty ||
change.Property == ContentProperty) change.Property == ContentProperty)
{ {
InitializeCropRect(); InitializeCropRect();
@@ -213,7 +224,7 @@ public class ContentCropper : ContentControl
RenderOverLays(); RenderOverLays();
} }
private void OnBorderPointerMoved(object? sender, private void OnBorderPointerMoved(object? sender,
PointerEventArgs args) PointerEventArgs args)
{ {
if (!isDragging || canvas is null || border is null) if (!isDragging || canvas is null || border is null)
@@ -260,9 +271,9 @@ public class ContentCropper : ContentControl
{ {
return; return;
} }
double minimumWidth = 20; double minimumWidth = 20;
double minimumHeight = 20; double minimumHeight = 20;
double deltaX = args.Vector.X; double deltaX = args.Vector.X;
double deltaY = args.Vector.Y; double deltaY = args.Vector.Y;
@@ -460,16 +471,16 @@ public class ContentCropper : ContentControl
double borderWidth = border.Width; double borderWidth = border.Width;
double borderHeight = border.Height; double borderHeight = border.Height;
RectangleGeometry outerRect = new(new Rect(0, 0, RectangleGeometry outerRect = new(new Rect(0, 0,
canvas.Width, canvas.Width,
canvas.Height)); canvas.Height));
RectangleGeometry innerRect = new(new Rect(borderLeft, RectangleGeometry innerRect = new(new Rect(borderLeft,
borderTop, borderTop,
borderWidth, borderWidth,
borderHeight)); borderHeight));
CombinedGeometry punchThroughGeometry = new(GeometryCombineMode.Exclude, CombinedGeometry punchThroughGeometry = new(GeometryCombineMode.Exclude,
outerRect, outerRect,
innerRect); innerRect);
@@ -518,6 +529,32 @@ public class ContentCropper : ContentControl
border.PointerReleased += OnBorderPointerReleased; border.PointerReleased += OnBorderPointerReleased;
} }
private void UpdateCroppedBitmap(Visual visual,
double centreX,
double centreY)
{
int width = (int)border.Width;
int height = (int)border.Height;
double x = Math.Max(centreX - width / 2, 0);
double y = Math.Max(centreY - height / 2, 0);
x = Math.Min(x, visual.Bounds.Width - width);
y = Math.Min(y, visual.Bounds.Height - height);
PixelSize pixelSize = new(width, height);
RenderTargetBitmap renderTarget = new(pixelSize);
using (DrawingContext drawingContext = renderTarget.CreateDrawingContext())
{
drawingContext.PushClip(new Rect(0, 0, width, height));
drawingContext.FillRectangle(new VisualBrush(visual), new Rect(-x, -y,
visual.Bounds.Width, visual.Bounds.Height));
}
CroppedBitmap = renderTarget;
}
private void UpdateCropRatios() private void UpdateCropRatios()
{ {
if (canvas == null || border == null) if (canvas == null || border == null)
@@ -542,5 +579,6 @@ public class ContentCropper : ContentControl
double top = Canvas.GetTop(border); double top = Canvas.GetTop(border);
CropRectangle = new Rect(left, top, border.Width, border.Height); CropRectangle = new Rect(left, top, border.Width, border.Height);
UpdateCroppedBitmap(canvas, border.Width, border.Height);
} }
} }