WinRT图像处理

我和朋友在昨晚的大部分时间里都花了很多时间试图在地铁应用程序中使用一些图像。 我们将图像放入具有共享魅力的应用程序中,然后我想与它们进行一些其他工作,裁剪图像并将它们保存回appdata文件夹中。 这被certificate非常令人沮丧。

我的问题,在所有这一切的最后,将是“这样做的正确方法是什么,而不是感觉我正在拼凑一堆不匹配的拼图游戏?”

当与应用程序共享多个图像时,它们作为Windows.Storage.StorageFile的列表进入。 这是用于处理它的一些代码。

 var storageItems = await _shareOperation.Data.GetStorageItemsAsync(); foreach (StorageFile item in storageItems) { var stream = await item.OpenReadAsync(); var properties = await item.Properties.GetImagePropertiesAsync(); var image = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height); image.SetSource(stream); images.Add(image); } 

一些在线搜索表明,目前, Windows.UI.Xaml.Media.Imaging.WriteableBitmap是唯一能够让您访问图像中的像素数据的东西。 这个问题包含一个有用的答案,其中包含将图像保存到文件的扩展方法,因此我们使用了这些方法。

当我稍后再次尝试打开文件时,我们的问题最严重。 我做过类似的事情:

 var files = await ApplicationData.Current.LocalFolder.GetFilesAsync(); foreach (var file in files) { var fileStream = await file.OpenReadAsync(); var properties = await file.Properties.GetImagePropertiesAsync(); var bitmap = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height); bitmap.SetSource(fileStream); System.IO.Stream stream = bitmap.PixelBuffer.AsStream(); 

这是一个问题。 如果我想要字节数,这个流有多长?

  // CRASH! Length isn't supported on an IRandomAccessStream. var pixels = new byte[fileStream.Length]; 

好的,再试一次。

  var pixels = new byte[stream.Length]; 

这是有效的,除了…如果图像被压缩,流比你想象的短,所以你最终会得到一个越界exception。 现在假装它是一个未压缩的位图。

  await _stream.ReadAsync(pixels, 0, pixels.Length); 

好吧猜猜看。 即使我说过bitmap.SetSource(fileStream); 为了读入数据,我的字节数组仍然是零。 我不知道为什么。 如果我通过示例数据组将此相同的bitmap传递到我的UI中,则图像显示正常。 所以它显然已经在那个位图中得到了像素数据,但是我无法从bitmap.PixelBuffer读出它? 为什么不?

最后,这是最终实际工作的结果。

  var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.PngDecoderId, fileStream); var data = await decoder.GetPixelDataAsync(); var bytes = data.DetachPixelData(); /* process my data, finally */ } // end of that foreach I started a while ago 

所以现在我有图像数据,但我仍然有一个大问题。 为了对它做任何事情,我必须对其格式做出假设。 我不知道它是rgba,rgb,abgr,bgra,无论它们是什么。 如果我猜错了,我的处理就失败了。 我有几十个测试运行吐出零字节和损坏的图像,颠倒的图像(???),错误的颜色等。我本来期望在调用await file.Properties.GetImagePropertiesAsync();properties中找到一些这些信息await file.Properties.GetImagePropertiesAsync(); ,但没有运气。 它只包含图像的宽度和高度,以及其他一些无用的东西。 这里有最少的文档。

那么,为什么这个过程如此痛苦呢? 这只是反映了现在图书馆的不成熟,我能指望它会变得更好吗? 或者已经有一些标准的方法吗? 我希望它像System.Drawing一样简单。 这为您提供了所需的所有数据,并且可以正确地加载任何图像类型,而无需让您自己处理流。

  1. 从我所看到的 – 当您计划使用流加载WriteableBitmap时 – 您不需要检查图像尺寸 – 只需执行新的WriteableBitmap(1,1),然后调用SetSource()。
  2. 不确定为什么你在想var pixel = new byte [fileStream.Length]; 因为fileStream具有压缩的图像字节而不是像素数组,所以可以工作。
  3. 您可能需要寻找流的开头以获取像素数组:

     var pixelStream = pixelBuffer.AsStream(); var bytes = new byte[this.pixelStream.Length]; this.pixelStream.Seek(0, SeekOrigin.Begin); this.pixelStream.Read(bytes, 0, Bytes.Length); 
  4. 我已经开始使用WriteableBitmapEx的WinRT端口 – 也许它可以帮助你: http : //bit.ly/WriteableBitmapExWinRT 。 我没有测试它,它基于旧版本的WBX,但在function支持方面相当完整。 可能比可能的要慢一点。