如何在UWP应用中同步获取图像的尺寸?

时间:2016-10-07 18:27:29

标签: c# .net windows windows-10 windows-10-universal

我想在OnLoaded()方法中显示图像之前获得图像的尺寸。我想同步(非异步)这样做,因为我需要在程序继续之前知道图像的尺寸。我正在制作一个映射程序,其中背景图像的坐标,比例和平移偏移很重要,并且都取决于从应用程序的最开始就知道图像的尺寸。

我已经阅读了有关StorageFile,SoftwareBitmap和异步方法调用的大部分msdn文档,并尝试了许多我在网上找到的方法但没有成功。 https://msdn.microsoft.com/en-us/windows/uwp/threading-async/asynchronous-programming-universal-windows-platform-apps

https://msdn.microsoft.com/en-us/windows/uwp/threading-async/call-asynchronous-apis-in-csharp-or-visual-basic

基本上我正在寻找一个同步c#函数,它接受一个图像文件的uri并返回一个包含维度的Point。即 public Point getImageDimensions(Uri u){...}

此功能在Android应用中很容易实现,我不明白为什么在UWP应用中这么难。

如果需要,我可以提供更多详细信息,提前谢谢。

我的代码出现以下错误:
抛出异常:' System.Exception'在App1.exe中 抛出异常:' System.AggregateException'在mscorlib.ni.dll中

App1.xaml.cs

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Shapes;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.Loaded += OnLoaded;

            Point p = Task.Run(() => getImageDimensions("ms-appx:///Assets/NewSpaceBackground.png")).Result;
            Debug.WriteLine("p.X: " + p.X + " p.Y: " + p.Y);
        }

        void OnLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            Rectangle backgroundRect1 = new Rectangle();
            ImageBrush imgBrushBackground1 = new ImageBrush();
            imgBrushBackground1.ImageSource = new BitmapImage(new Uri(@"ms-appx:///Assets/NewSpaceBackground.png"));
            backgroundRect1.Fill = imgBrushBackground1;
            //backgroundMap.Add(backgroundRect1);
        }

        public async Task<Point> getImageDimensions(string strURI)
        {
            Point p;
            StorageFile photo;
            try
            {
                var uri = new Uri(strURI);
                photo = await StorageFile.GetFileFromApplicationUriAsync(uri);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.StackTrace);
                return p;
            }
            //read in the bitmap stream
            IRandomAccessStream stream = await photo.OpenAsync(FileAccessMode.Read);
            BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
            SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync();

            //convert the image to a bitmap
            SoftwareBitmap softwareBitmapBGR8 = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
            SoftwareBitmapSource bitmapSource = new SoftwareBitmapSource();
            await bitmapSource.SetBitmapAsync(softwareBitmapBGR8);

            //print out the dimensions
            Debug.WriteLine(softwareBitmapBGR8.PixelWidth + " " + softwareBitmapBGR8.PixelHeight);
            p.X = softwareBitmapBGR8.PixelWidth;
            p.Y = softwareBitmapBGR8.PixelHeight;

            return p;
        }
    }
}

2 个答案:

答案 0 :(得分:7)

  

我想在OnLoaded()方法中显示图像之前获取图像的尺寸。我想同步(非异步)这样做,因为我需要在程序继续之前知道图像的尺寸。

当您想在构造函数中调用异步函数时会出现一些问题,有关详细信息,请参阅Stephen Cleary的博客:Async OOP 2: Constructors

在UWP中,您可以将页面初始化代码(getImageDimensions和显示图像的代码)放在Page.OnNavigatedTo方法中,并在其中使用await

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    Point p = await getImageDimensions("ms-appx:///Assets/NewSpaceBackground.png");
    Debug.WriteLine("p.X: " + p.X + " p.Y: " + p.Y);

    Rectangle backgroundRect1 = new Rectangle();
    ImageBrush imgBrushBackground1 = new ImageBrush();
    imgBrushBackground1.ImageSource = new BitmapImage(new Uri(@"ms-appx:///Images/image03.jpg"));
    backgroundRect1.Fill = imgBrushBackground1;
    ...
}

<强>更新

  

您是否建议使用更简单,同步的方式来获取尺寸?

大多数与文件相关的操作都是异步的,用户可以使用/不使用await来选择同步或异步执行操作。

确实有一种简单的方法可以获得图像的维度:

StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///images/image01.png"));
var properties=await file.Properties.GetImagePropertiesAsync();
var width = properties.Width;
var height = properties.Height;

答案 1 :(得分:0)

可以将它加载到System.Drawing.Image中,而不是将其流式传输到Bitmap中,而不是这样吗?:

let myGroup = this.groupFactory.createGroup();
myGroup.name = 'foo';
myGroup.save();

然后您可以访问System.Drawing.Image的Size属性,该属性可以为您提供所需的内容,以及轻松访问大小调整。如果内存服务,所有这些都可以在.NET Core和UWP中使用。