How to get better image scaling in Xamarin Forms UWP?
Please refer UWP image files and performance document, If you are referencing an image file where you know that the source file is a large, high resolution image, but your app is displaying it in a UI region that's smaller than the image's natural size, you should set the DecodePixelWidth
property, or DecodePixelHeight
. For xamarin form project, we suggest you use effect to re-render image.
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(ImageFormsTest.UWP.ImageSourceEffect), nameof(ImageEffect))]
public class ImageSourceEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
var control = Control ?? Container;
if (control is DependencyObject)
{
var image = control as Windows.UI.Xaml.Controls.Image;
var uri = ImageEffect.GetText(Element);
var bitmap = new BitmapImage(new Uri(uri)) { DecodePixelHeight = 300, DecodePixelWidth = 600 };
image.Source = bitmap;
}
}
catch (Exception ex)
{
Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
protected override void OnDetached()
{
}
}
Forms code part
public static class ImageEffect
{
public static readonly BindableProperty TextProperty =
BindableProperty.CreateAttached("Text", typeof(string), typeof(ImageEffect), string.Empty, propertyChanged: OnTextChanged);
public static string GetText(BindableObject view)
{
return (string)view.GetValue(TextProperty);
}
public static void SetText(BindableObject view, string value)
{
view.SetValue(TextProperty, value);
}
static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
{
var view = bindable as View;
if (view == null)
{
return;
}
string text = (string)newValue;
if (!string.IsNullOrEmpty(text))
{
view.Effects.Add(new SourceEffect());
}
else
{
var toRemove = view.Effects.FirstOrDefault(e => e is SourceEffect);
if (toRemove != null)
{
view.Effects.Remove(toRemove);
}
}
}
}
public class SourceEffect : RoutingEffect
{
public SourceEffect() : base($"MyCompany.{nameof(ImageEffect)}")
{
}
}
Usage
<Image
x:Name="TitleImage" effect:ImageEffect.Text="https://xxxx.jpg"
/>
Update
public class ImageSourceEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
var control = Control ?? Container;
if (control is DependencyObject)
{
var image = control as Windows.UI.Xaml.Controls.Image;
var uri = ImageEffect.GetText(Element);
var bitmap = new BitmapImage(new Uri(uri));
bitmap.ImageOpened += Bitmap_ImageOpened;
image.Source = bitmap;
image.SizeChanged += Image_SizeChanged;
}
}
catch (Exception ex)
{
Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
private void Image_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (bitmapImage != null)
{
bitmapImage.DecodePixelType = DecodePixelType.Logical;
bitmapImage.DecodePixelHeight = (int)e.NewSize.Height;
bitmapImage.DecodePixelWidth = (int)e.NewSize.Width;
}
}
private BitmapImage bitmapImage;
private void Bitmap_ImageOpened(object sender, RoutedEventArgs e)
{
bitmapImage = sender as BitmapImage;
}
protected override void OnDetached()
{
}
}