diff --git a/samples/ControlCatalog/Pages/ImagePage.xaml b/samples/ControlCatalog/Pages/ImagePage.xaml
index c20f76cedd..f61931ed72 100644
--- a/samples/ControlCatalog/Pages/ImagePage.xaml
+++ b/samples/ControlCatalog/Pages/ImagePage.xaml
@@ -23,7 +23,7 @@
Crop
-
+
None
Center
TopLeft
@@ -31,7 +31,11 @@
BottomLeft
BottomRight
-
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ImagePage.xaml.cs b/samples/ControlCatalog/Pages/ImagePage.xaml.cs
index d637c88102..d8f4d6d5a2 100644
--- a/samples/ControlCatalog/Pages/ImagePage.xaml.cs
+++ b/samples/ControlCatalog/Pages/ImagePage.xaml.cs
@@ -13,7 +13,6 @@ namespace ControlCatalog.Pages
private readonly Image _bitmapImage;
private readonly Image _drawingImage;
private readonly Image _croppedImage;
- private readonly IBitmap _croppedBitmapSource;
public ImagePage()
{
@@ -21,8 +20,6 @@ namespace ControlCatalog.Pages
_bitmapImage = this.FindControl("bitmapImage");
_drawingImage = this.FindControl("drawingImage");
_croppedImage = this.FindControl("croppedImage");
- _croppedBitmapSource = LoadBitmap("avares://ControlCatalog/Assets/delicate-arch-896885_640.jpg");
- _croppedImage.Source = new CroppedBitmap(_croppedBitmapSource, default);
}
private void InitializeComponent()
@@ -53,15 +50,16 @@ namespace ControlCatalog.Pages
if (_croppedImage != null)
{
var comboxBox = (ComboBox)sender;
- _croppedImage.Source = new CroppedBitmap( _croppedBitmapSource, GetCropRect(comboxBox.SelectedIndex));
+ var croppedBitmap = _croppedImage.Source as CroppedBitmap;
+ croppedBitmap.SourceRect = GetCropRect(comboxBox.SelectedIndex);
}
}
private PixelRect GetCropRect(int index)
{
- var bitmapWidth = _croppedBitmapSource.PixelSize.Width;
- var bitmapHeight = _croppedBitmapSource.PixelSize.Height;
- var cropSize = new PixelSize(bitmapWidth / 2, bitmapHeight / 2);
+ var bitmapWidth = 640;
+ var bitmapHeight = 426;
+ var cropSize = new PixelSize(320, 240);
return index switch
{
1 => new PixelRect(new PixelPoint((bitmapWidth - cropSize.Width) / 2, (bitmapHeight - cropSize.Width) / 2), cropSize),
@@ -73,11 +71,5 @@ namespace ControlCatalog.Pages
};
}
-
- private IBitmap LoadBitmap(string uri)
- {
- var assets = AvaloniaLocator.Current.GetService();
- return new Bitmap(assets.Open(new Uri(uri)));
- }
}
}
diff --git a/src/Avalonia.Visuals/Media/Imaging/CroppedBitmap.cs b/src/Avalonia.Visuals/Media/Imaging/CroppedBitmap.cs
index 6bdee24c03..70823e114c 100644
--- a/src/Avalonia.Visuals/Media/Imaging/CroppedBitmap.cs
+++ b/src/Avalonia.Visuals/Media/Imaging/CroppedBitmap.cs
@@ -1,25 +1,77 @@
using System;
-using System.Collections.Generic;
-using System.Text;
using Avalonia.Visuals.Media.Imaging;
namespace Avalonia.Media.Imaging
{
- public class CroppedBitmap : IImage, IDisposable
+ ///
+ /// Crops a Bitmap.
+ ///
+ public class CroppedBitmap : AvaloniaObject, IImage, IAffectsRender, IDisposable
{
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty SourceProperty =
+ AvaloniaProperty.Register(nameof(Source));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty SourceRectProperty =
+ AvaloniaProperty.Register(nameof(SourceRect));
+
+ public event EventHandler Invalidated;
+
+ static CroppedBitmap()
+ {
+ SourceRectProperty.Changed.AddClassHandler((x, e) => x.SourceRectChanged(e));
+ SourceProperty.Changed.AddClassHandler((x, e) => x.SourceChanged(e));
+ }
+
+ ///
+ /// Gets or sets the source for the bitmap.
+ ///
+ public IImage Source
+ {
+ get => GetValue(SourceProperty);
+ set => SetValue(SourceProperty, value);
+ }
+
+ ///
+ /// Gets or sets the rectangular area that the bitmap is cropped to.
+ ///
+ public PixelRect SourceRect
+ {
+ get => GetValue(SourceRectProperty);
+ set => SetValue(SourceRectProperty, value);
+ }
+
public CroppedBitmap()
{
Source = null;
SourceRect = default;
}
- public CroppedBitmap(IBitmap source, PixelRect sourceRect)
+
+ public CroppedBitmap(IImage source, PixelRect sourceRect)
{
Source = source;
SourceRect = sourceRect;
}
+
+ private void SourceChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ if (e.NewValue == null)
+ return;
+ if (!(e.NewValue is IBitmap))
+ throw new ArgumentException("Only IBitmap supported as source");
+ Invalidated?.Invoke(this, e);
+ }
+
+ private void SourceRectChanged(AvaloniaPropertyChangedEventArgs e) => Invalidated?.Invoke(this, e);
+
public virtual void Dispose()
{
- Source?.Dispose();
+ (Source as IBitmap)?.Dispose();
}
public Size Size {
@@ -29,7 +81,7 @@ namespace Avalonia.Media.Imaging
return Size.Empty;
if (SourceRect.IsEmpty)
return Source.Size;
- return SourceRect.Size.ToSizeWithDpi(Source.Dpi);
+ return SourceRect.Size.ToSizeWithDpi((Source as IBitmap).Dpi);
}
}
@@ -37,11 +89,8 @@ namespace Avalonia.Media.Imaging
{
if (Source == null)
return;
- var topLeft = SourceRect.TopLeft.ToPointWithDpi(Source.Dpi);
+ var topLeft = SourceRect.TopLeft.ToPointWithDpi((Source as IBitmap).Dpi);
Source.Draw(context, sourceRect.Translate(new Vector(topLeft.X, topLeft.Y)), destRect, bitmapInterpolationMode);
}
-
- public IBitmap Source { get; }
- public PixelRect SourceRect { get; }
}
}
diff --git a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
index 05c3d7e62a..8f08bc5f44 100644
--- a/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
+++ b/src/Avalonia.Visuals/Properties/AssemblyInfo.cs
@@ -8,7 +8,8 @@ using Avalonia.Metadata;
[assembly: InternalsVisibleTo("Avalonia.Visuals.UnitTests")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media")]
+[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Media.Imaging")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia")]
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests")]
-[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("Avalonia.Skia.RenderTests")]