如何在UWP应用程序中通过异步流设置image.Source?

时间:2019-06-24 16:36:06

标签: xaml uwp

我想通过UWP应用程序中的异步流设置image.Source。否则,当切换到其他图像源时,图像将闪烁。 我的代码如下。日志显示它有效。当然,在测试演示代码之前,我将2个图像文件放在相应的路径中。 但是实际上我没有看到任何图片,为什么?

日志:

111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444

代码:

        private async void setImageSource(string imageFilePath)
        {
            StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
            Debug.WriteLine("111111111111 image file path = " + imageFilePath);
            Stream fileStream = await sFile.OpenStreamForReadAsync();
            Debug.WriteLine("22222222222");
            InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
            Debug.WriteLine("33333333333333");
            await fileStream.CopyToAsync(ras.AsStreamForRead());
            Debug.WriteLine("4444444444444");
            BitmapImage bi = new BitmapImage();
            bi.SetSource(ras);
            image1.Source = bi;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            string fullFolder = ApplicationData.Current.LocalFolder.Path;

            if (count % 2 == 1)
            {
                setImageSource(fullFolder + @"\1.jpg");
                //image1.Source = new BitmapImage(new Uri(@"ms-appx:///Assets/1.jpg"));
            }
            else
            {
                setImageSource(fullFolder + @"\2.jpg");
                //image1.Source = new BitmapImage(new Uri(@"ms-appx:///Assets/2.jpg"));
            }

            count++;
        }

2 个答案:

答案 0 :(得分:0)

这里是如何将base64图像字符串转换为BitmapImage的示例。

var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;

尝试我在那做的一些事情。就像我注意到的那样,您的代码未设置InMemoryReadAccessStream

的搜索

答案 1 :(得分:0)

对于您的问题,我有一些要澄清的事情。

  1. 您的图片始终位于应用程序数据文件夹中。如果要通过编程在运行时显示它,最简单的方法是使用ms-appdata URI方案来引用来自应用程序的本地,漫游和临时数据文件夹的文件。然后,您可以使用此URL初始化BitmapImage对象。通过这种方式,您无需手动操作文件流。
private void setImageSource(int i)
{
    BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
    image1.Source = bi;
}

private int count = 0;

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (count % 2 == 1)
    {
        setImageSource(1);
    }
    else
    {
        setImageSource(2);
    }
    count++;
}
  1. 如果您说必须操纵文件流来初始化BitmaImage,请添加一些断点来调试代码。如果在调用InMemoryRandomAccessStream方法后添加断点以检查CopyToAsync,则会看到其大小为0。这意味着尚未向其写入文件流。要解决此问题,您需要为其设置缓冲区大小。 注意:您使用了ras.AsStreamForRead()方法,这是不正确的。您正在向其中写入流,因此需要调用ras.AsStreamForWrite()

代码如下:

private async void setImageSource(string imageFilePath)
{
    StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);

    using (Stream fileStream = await sFile.OpenStreamForReadAsync())
    {
        using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
        {
            await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
            ras.Seek(0);
            BitmapImage bi = new BitmapImage();
            bi.SetSource(ras);
            img.Source = bi;
        }
    }
}

private int count = 0;

private void Button_Click(object sender, RoutedEventArgs e)
{
    string fullFolder = ApplicationData.Current.LocalFolder.Path;
    if (count % 2 == 1)
    {
        setImageSource(fullFolder + @"\1.jpg");
    }
    else
    {
        setImageSource(fullFolder + @"\2.jpg");
    }
    count++;
}

此外,就像@visc所说的那样,您需要调用ras.Seek(0)方法将流重置为开始,否则图像将不会在那里显示。