在 WinRT 中,我如何加载图像,然后在写入之前等待它加载所需的时间?

Posted

技术标签:

【中文标题】在 WinRT 中,我如何加载图像,然后在写入之前等待它加载所需的时间?【英文标题】:In WinRT, how do I load an image and then wait only as long as is needed for it to load before writing to it? 【发布时间】:2012-04-29 03:26:15 【问题描述】:

我在 WinRT 项目中使用 WriteableBitmapEx。我从用户图片库将图像加载到 WriteableBitmap 中。但是,我不能立即写入该图像,如果我这样做,它将被图像本身覆盖(看起来它是异步加载图像,然后它覆盖了我的绘图)。我不知道如何阻止它这样做(我尝试在 SetSource 上使用 Await ,但这不是 Async 方法)。

我使用了“Await Task.Delay(1000)”并且可以正常工作,但它看起来很笨拙,因为 1000 毫秒可能足够也可能不够。我希望它等到加载位图后再继续。

是否有人能看出我做错了什么,或者建议我如何确保在进行任何处理之前从图片库中加载 WriteableBitmap?这是我创建的示例代码 sn-p:

Dim file = Await picker.PickSingleFileAsync

If file Is Nothing Then
    Exit Sub
End If

Dim wbm As New WriteableBitmap(1, 1)
wbm.SetSource(Await file.OpenAsync(Windows.Storage.FileAccessMode.Read))

' If I don't have this, the DrawLine will not show up, if I do, it will.
Await Task.Delay(1000)

wbm.DrawLine(1, 1, 255, 255, Colors.Green)
wbm.Invalidate()

ImageMain.Source = wbm

【问题讨论】:

你正在使用这个项目? writeablebitmapex.codeplex.com 我认为这是我的 WinRT 版本 - bit.ly/WriteableBitmapExWinRT 我正在使用 Filip 的 WinRT 端口,我已经能够使用它来操作图形。顺便说一句,感谢菲利普。 :) 学习完所有这些后,我将发布源代码。 WinRT 现在由 WriteableBitmapEx 正式支持。 ;) 它仍在分支中,但我计划下周发布。现在只需从这里查看代码:writeablebitmapex.svn.codeplex.com/svn/branches/… 【参考方案1】:

此方法从应用程序的内容中加载图像,对其进行解码并传回可供使用的 WriteableBitmap。 取自WriteableBitmapEx library:

/// <summary>
/// Loads an image from the applications content and fills this WriteableBitmap with it.
/// </summary>
/// <param name="bmp">The WriteableBitmap.</param>
/// <param name="uri">The URI to the content file.</param>
/// <returns>The WriteableBitmap that was passed as parameter.</returns>
public static async Task<WriteableBitmap> FromContent(this WriteableBitmap bmp, Uri uri)

   // Decode pixel data
   var file = await StorageFile.GetFileFromApplicationUriAsync(uri);
   var decoder = await BitmapDecoder.CreateAsync(await file.OpenAsync(FileAccessMode.Read));
   var transform = new global::Windows.Graphics.Imaging.BitmapTransform();
   var pixelData = await decoder.GetPixelDataAsync(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, transform, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.ColorManageToSRgb);
   var pixels = pixelData.DetachPixelData();

   // Copy to WriteableBitmap
   bmp = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
   using (var bmpStream = bmp.PixelBuffer.AsStream())
   
      bmpStream.Seek(0, SeekOrigin.Begin);
      bmpStream.Write(pixels, 0, (int)bmpStream.Length);
      return bmp;
   

顺便说一句,WriteableBitmapEx 现在正式支持 WinRT。 ;) http://kodierer.blogspot.de/2012/05/one-bitmap-to-rule-them-all.html

【讨论】:

+1,但这种解决方法很糟糕。我真的希望他们能在 WinRT 发布之前实现这一目标。【参考方案2】:

返回的 OpenAsync 仅表示流可用,而不是实际从中读取数据。因此,您似乎希望先打开 + 阅读,然后就可以了。

由于 Filip 指出 ReadAsync 将要求您首先创建并传入缓冲区,因此我更新了下面的 sn-p 以使用 DataReader 在执行 OpenReadAsync 后将流实际加载到字节数组中以获取IRandomAccessStream。

var randomAccessStream = await file.OpenReadAsync();

var dataReader = new DataReader(randomAccessStream);
await dataReader.LoadAsync(randomAccessStream.Size);

byte[] imageBytes;
dataReader.ReadBytes(out imageBytes);

wbm.SetSource(new MemoryStream(imageBytes));

【讨论】:

我也要试试这个,谢谢詹姆斯的反馈。 很有趣,但是如果您从文件流中读取然后将内容作为 MemoryStream 提供,为什么会有不同呢?需要读取流的是 WriteableBitmap - 它似乎并不关心它得到什么类型的流。您的方法的好处是,如果您还关闭文件流 - 您可以在 WB 显示其内容之前删除文件。 @FilipSkakun - 我真的不想提供流 - 我最初发布了 sn-p 做 SetSource(imageBytes) ,然后碰巧注意到它没有这样的过载。可能有一种从字节数组创建 WritableBitmap 的方法,但我找不到它(也许使用 Image.Create?不确定),但实际上,你真的根本不想使用流。使用 MemoryStream 确实依赖于一个实现细节,即 SetSource 将足够快和/或与 MemoryStream 同步,以便在稍后的 DrawLine 之前完成。 等等,不带参数怎么调用ReadAsync? 抱歉,这就是我将它输入到 SO 中得到的结果 - 看起来您确实必须首先为文件内容分配一个缓冲区。 :)【参考方案3】:

我认为 WB 没有 BitmapImage 等待它打开的事件。我会尝试使用 BitmapDecoder/CreateAsync/GetPixelDataAsync/DetachPixelData 并将生成的字节数组复制到 WB 的像素缓冲区,而不是调用 wb.SetSource()。然后可能会调用 wb.Invalidate()。或者也许只是将延迟调用替换为无效调用。

【讨论】:

我会试试这两个。再次感谢 Filip 帮助我理解/学习。非常感谢。

以上是关于在 WinRT 中,我如何加载图像,然后在写入之前等待它加载所需的时间?的主要内容,如果未能解决你的问题,请参考以下文章

什么是无需在 WinRT、Win8 中使用 Open File Picker 即可打开文件进行写入的方法

如何将图像的名称及其坐标写入 save.txt 文件?

AngularJS:如何在页面完全加载之前显示预加载或加载?

如何实时防止图像大小调整(页面加载期间)

如何在不加载图像的情况下为文件系统上的现有图像写入或修改 EXIF 数据?

在 WinRT 中以任何图像格式捕获视频