WinRT的图像处理 [英] WinRT image handling

查看:106
本文介绍了WinRT的图像处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我和一个朋友花了昨晚的大部分几乎撕裂我们的头发就试图在地铁应用中的一些图像工作。我们得到的图像与共享魅力的应用程序,然后我想要做一些其他的工作与他们,裁剪图像,并将其保存回AppData文件夹。事实证明,这非常令人沮丧。



我的问题,在这一切结束时,将是什么是这样做的正确方法,没有感觉就像我骂一起一堆不匹配的拼图块?



在与应用程序共享多个图像,他们在为 Windows.Storage的列表。 StorageFile 秒。 。下面是用于处理一些代码



  VAR storageItems =等待_shareOperation.Data.GetStorageItemsAsync(); 

的foreach(在storageItems StorageFile项)
{
VAR流=等待item.OpenReadAsync();
VAR性能=等待item.Properties.GetImagePropertiesAsync();

变种形象=新的WriteableBitmap的((Int32)已properties.Width,(Int32)已properties.Height);
image.SetSource(流);

images.Add(图片);
}



一些网上搜索表明,目前,一个视窗.UI.Xaml.Media.Imaging.WriteableBitmap 就能够让你访问图像中的像素数据的唯一的事情。 这个问题包括一个有用的答案充满了扩展方法保存图像文件,所以我们用那些。



我们的问题是,当我试图再次打开后文件的最糟糕的。我做了类似的事情之前:

  var中的文件=等待ApplicationData.Current.LocalFolder.GetFilesAsync(); 

的foreach(在文件var文件)
{
VAR FILESTREAM =等待file.OpenReadAsync();
VAR性能=等待file.Properties.GetImagePropertiesAsync();
VAR位=新的WriteableBitmap的((Int32)已properties.Width,(Int32)已properties.Height);
bitmap.SetSource(FILESTREAM);

的System.IO.Stream流= bitmap.PixelBuffer.AsStream();



这里谈到的一个问题。是多久此流,如果我想的字节出来的吗?



  //崩溃!长度不支持的IRandomAccessStream。 
变种像素=新的字节[fileStream.Length]



好再试。

  VAR像素=新的字节[stream.Length] 

这工作的,除非......如果图像被压缩,流短于你所期望,所以你最终会得到一个出界的异常。对于现在假装它是一个未压缩的位图

 等待_stream.ReadAsync(像素,0,pixels.Length); 



这是为啥。即使我说 bitmap.SetSource(FILESTREAM); 要想在数据读取,我的字节数组依然充满零的。我不知道为什么。如果我通过同样的位图成我通过样本数据组UI,图像显示出来就好了。因此,它显然已经得到了在该位图的像素数据的地方,但我不能宣读 bitmap.PixelBuffer 的?为什么不呢?



最后,这里是结束了实际工作。

  VAR解码器=等待BitmapDecoder.CreateAsync(BitmapDecoder.PngDecoderId,FILESTREAM); 
VAR数据=等待decoder.GetPixelDataAsync();
VAR字节= data.DetachPixelData();

/ *过程中我的数据,最后* /

} //那我的foreach开始前一阵子
结束

所以,现在我有图像数据,但我仍然有一个很大的问题。为了对它做任何事,我必须作出有关其格式的假设。我不知道它是否是RGBA,RGB,ABGR,BGRA,不管他们可能。如果我猜错了我的处理只是将失败。我有几十个测试运行的吐出零字节和损坏的图像,颠倒的图像(???),错误的颜色,等等。我本来期望找到一些在属性此信息的,我从调用有等待file.Properties.GetImagePropertiesAsync(); ,但没有运气。只包含图片的宽度和高度,再加上其他一些没用的东西。最小文档 rel=\"nofollow\">。



那么,为什么这个过程如此痛苦?这只是反映了图书馆的不成熟,现在,我可以期望它变得更好?或者是已经有这样的一些标准方式吗?我希望它是那么容易,因为在 System.Drawing中。这给了你所有你需要的数据,并愉快地加载正确的图像类型,而不会使你处理流自己。


解决方案

  1. 从我所看到的 - 你不必检查图像尺寸 - - 当你在与流加载WriteableBitmap的规划只是做新的WriteableBitmap的(1,1),然后调用的SetSource ()

  2. 不知道为什么你在想VAR像素=新的字节[fileStream.Length]。会的工作,因为FILESTREAM有压缩图像字节,而不是一个像素阵列

  3. 您可能需要寻求到流来获得像素阵列的开头:

      VAR pixelStream = pixelBuffer.AsStream(); 
    变种字节=新的字节[this.pixelStream.Length]
    this.pixelStream.Seek(0,SeekOrigin.Begin);
    this.pixelStream.Read(字节,0,Bytes.Length);


  4. 我已经开始的 WriteableBitmapEx - 也许它可以帮助你:的http:// bit.ly/WriteableBitmapExWinRT 。我没有测试过它好,它是基于一个旧版本的WBX,但它是在功能支持方面还算齐全。也许是一点点比它慢也是可能的。



A friend and I spent the better part of last night nearly tearing our hair out trying to work with some images in a metro app. We got images into the app with the share charm, and then I wanted to do some other work with them, cropping the images and saving them back into the appdata folder. This proved extremely frustrating.

My question, at the end of all this, is going to be "What's the proper way of doing this, without feeling like I'm hammering together a bunch of mismatched jigsaw puzzle pieces?"

When sharing multiple images with the app, they come in as a list of Windows.Storage.StorageFiles. Here's some code used to handle that.

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);
}

Some searching online has indicated that currently, a Windows.UI.Xaml.Media.Imaging.WriteableBitmap is the only thing capable of letting you access the pixel data in the image. This question includes a helpful answer full of extension methods for saving images to a file, so we used those.

Our problems were the worst when I tried opening the files again later. I did something similar to before:

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();

Here comes a problem. How long is this stream, if I want the bytes out of it?

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

Ok try again.

    var pixels = new byte[stream.Length];

This works, except... if the image is compressed, the stream is shorter than you would expect, so you will eventually get an out of bounds exception. For now pretend it's an uncompressed bitmap.

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

Well guess what. Even though I said bitmap.SetSource(fileStream); in order to read in the data, my byte array is still full of zeroes. I have no idea why. If I pass this same bitmap into a my UI through the sample data group, the image shows up just fine. So it has clearly got the pixel data in that bitmap somewhere, but I can't read it out of bitmap.PixelBuffer? Why not?

Finally, here's what ended up actually working.

    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

So now I have by image data, but I still have a big problem. In order to do anything with it, I have to make assumptions about its format. I have no idea whether it's rgba, rgb, abgr, bgra, whatever they can be. If I guess wrong my processing just fails. I've had dozens of test runs spit out zero byte and corrupted images, upside down images (???), wrong colors, etc. I would have expected to find some of this info in the properties that I got from calling await file.Properties.GetImagePropertiesAsync();, but no luck. That only contains the image width and height, plus some other useless things. Minimal documentation here.

So, why is this process so painful? Is this just reflecting the immaturity of the libraries right now, and can I expect it to get better? Or is there already some standard way of doing this? I wish it were as easy as in System.Drawing. That gave you all the data you ever needed, and happily loaded any image type correctly, without making you deal with streams yourself.

解决方案

  1. From what I have seen - when you are planning on loading the WriteableBitmap with a stream - you don't need to check the image dimensions - just do new WriteableBitmap(1,1), then call SetSource().
  2. Not sure why you were thinking var pixels = new byte[fileStream.Length]; would work, since the fileStream has the compressed image bytes and not a pixel array.
  3. You might need to seek to the beginning of the stream to get the pixels array:

    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. I had started working on a WinRT port of WriteableBitmapEx - maybe it could help you: http://bit.ly/WriteableBitmapExWinRT. I have not tested it well and it is based on an older version of WBX, but it is fairly complete in terms of feature support. Might be a tad slower than it is possible too.

这篇关于WinRT的图像处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆