2

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

我使用了“Await Task.Delay(1000)”并且有效,但它似乎很棘手,因为 1000 毫秒可能或可能不够。我希望它等到加载位图后再继续。

任何人都可以看到我做错了什么,或者建议我如何确保在进行任何处理之前从图片库中加载 WriteableBitmap?这是我创建的示例代码片段:

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
4

3 回答 3

8

此方法从应用程序的内容中加载图像,对其进行解码并传回现成的 WriteableBitmap。取自WriteableBitmapEx 库

/// <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

于 2012-05-05T18:50:47.517 回答
2

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

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

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));
于 2012-04-17T20:32:34.513 回答
1

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

于 2012-04-17T23:40:24.507 回答