如何在 Xamarin Forms UWP 中获得更好的图像缩放?

问题描述

当我的应用中的图像元素被 UI 缩小到 UWP 中的小尺寸时,缩放看起来质量很差,就像它是通过旧的“最近邻”样式缩放的一样,这使得它非常像素化:>

UWP Scaling

当我在 Android 上运行相同的应用程序时,它看起来不错:

Android Scaling

这些图像是使用 TMDB API 从 URL 显示的。有什么方法可以控制它使用的图像缩放算法吗?

解决方法

如何在 Xamarin Forms UWP 中获得更好的图像缩放?

请参考 UWP 图像文件和性能 document,如果您引用的图像文件知道源文件是大的高分辨率图像,但您的应用在较小的 UI 区域中显示它比图像的自然大小,您应该设置 DecodePixelWidth 属性,或 DecodePixelHeight。对于 xamarin 表单项目,我们建议您使用 effect 重新渲染图像。

[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()
    {

    }
}

表单代码部分

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)}")
    {
    }
}

使用

<Image
    x:Name="TitleImage" effect:ImageEffect.Text="https://xxxx.jpg"
   />

更新

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()
    {

    }
}