Silverlight:将byte []转换为BitmapImage以“灾难性故障”结束

时间:2012-08-13 13:47:17

标签: silverlight bitmapimage writeablebitmap writeablebitmapex

我正在尝试在Silverlight中修改BitmapImage,但碰巧遇到了“灾难性的失败”!

首先,我加载图像并将其添加到LayoutRoot。

BitmapImage source = new BitmapImage(new Uri("image.jpg", UriKind.Relative));
Image imageElement = new Image();
imageElement.Name = "imageElement";
imageElement.Source = source;
imageElement.Stretch = Stretch.None;
LayoutRoot.Children.Add(imageElement);

此工作正常,图像正确显示在屏幕上。

接下来我要修改图像(例如:点击按钮后)。

在按钮单击方法中,首先,我从LayoutRoot中获取图像,然后使用WriteableBitmap类对其进行修改:

Image imageElement = (Image) LayoutRoot.Children[1];
WriteableBitmap writeableBitmap = new WriteableBitmap(imageElement, null);
writeableBitmap.ForEach((x,y,color) => Color.FromArgb((byte)(color.A / 2), color.R, color.G, color.B));

接下来,我使用给定的方法将其保存到字节数组缓冲区中:

byte[] buffer = writeableBitmap.ToByteArray();  

这看起来也不错。缓冲区显示所有ARGB值,甚至alpha值都是127的常用值的一半,就像它应该的那样!

在下一步中,我想将修改后的数据加载回BitmapImage,最后加载到Image中,然后将其重新添加到LayoutRoot中:

BitmapImage modifiedSource = null;
try
{
    using (MemoryStream stream = new MemoryStream(buffer))
    {
        stream.Seek(0, SeekOrigin.Begin);
        BitmapImage b = new BitmapImage();
        b.SetSource(stream);
        modifiedSource = b;
    }
}
catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}

我在这里找到了这段代码:byte[] to BitmapImage in silverlight

作为最后一步,我只需再次创建一个Image并将其添加到LayoutRoot中(正如我在开始时所做的那样:

Image modifiedImageElement = new Image();
modifiedImageElement.Name = "newImageElement";
modifiedImageElement.Source = modifiedSource;
modifiedImageElement.Stretch = Stretch.None;
LayoutRoot.Children.Add(modifiedImageElement);

但最后一部分永远不会到达,因为

上发生了“灾难性的失败”
b.SetSource(stream);

行,说:

{System.Exception: Catastrophic failure (Ausnahme von HRESULT: 0x8000FFFF (E_UNEXPECTED))
   at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
   at MS.Internal.XcpImports.BitmapSource_SetSource(BitmapSource bitmapSource, CValue& byteStream)
   at System.Windows.Media.Imaging.BitmapSource.SetSourceInternal(Stream streamSource)
   at System.Windows.Media.Imaging.BitmapImage.SetSourceInternal(Stream streamSource)
   at System.Windows.Media.Imaging.BitmapSource.SetSource(Stream streamSource)
   at SilverlightApplication1.MainPage.button1_Click(Object sender, RoutedEventArgs e)}

我不知道出了什么问题。我在这里找到了一篇文章 Silverlight: BitmapImage from stream throws exception (Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))),碰巧有相同的异常,但正如我读到的那样,似乎只有当他上传大量图像时他才会遇到这个问题,而且对于他来说,只需要一点点图像就可以了。所以我仍然对如何解决这个问题一无所知?

你们可能有任何建议吗?谢谢!

2 个答案:

答案 0 :(得分:3)

我认为您正在崩溃,因为您重建图像的字节数组是ARGB值的“原始”数组,而Source属性期望构成有效的字节流PNG或JPG文件。原始ARGB数据极不可能是有效的PNG或JPG文件,因为它几乎肯定不包含每种格式所需的有效标头。

我无法重现崩溃;相反,我运行代码时创建的BitmapImage PixelWidthPixelHeight都为零。这可能是因为我正在使用与您正在使用的图像不同的图像。无论哪种方式,崩溃或没有崩溃,这都不是行为。

如果要将修改后的数据加载回Image,则无需创建byte数组。只需从Image对象创建WriteableBitmap

        Image modifiedImage = new Image()
        {
            Source = writeableBitmap,
            Stretch = Stretch.None
        };

我用它来添加原始图像下方的图像副本。修改后的图像与原始图像相比具有“褪色”外观,正如我将所有alpha通道值减半所预测的那样。

如果确实需要将字节数组转换回图像,可以在WriteableBitmapEx中使用FromByteArray扩展方法。然后,您可以如上所述创建Image

答案 1 :(得分:1)

我之前遇到过这个例外:

  1. 将不受支持的图像类型传递给silverlight时:BMP,...仅支持JPG和PNG。请参阅the MSDN
  2. 传递错误数据(不是所有流或格式不正确)时