1

我正在尝试在 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))),恰好有相同的异常,但是当我读到它时,似乎他只有在他上传了很多图片,对于少量图片来说,这对他来说效果很好。所以我仍然对如何解决这个问题一无所知?

大家有什么建议吗?谢谢!

4

2 回答 2

3

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

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

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

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

我用它在原始图像下方添加了图像的副本。与原始图像相比,修改后的图像具有“褪色”的外观,如果我将所有 alpha 通道值减半,这正是我所期望的。

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

于 2012-08-13T21:20:13.140 回答
1

我之前遇到过这个异常:

  1. 将不支持的图像类型传递给 silverlight 时:BMP、... 仅支持 JPG 和 PNG。请参阅MSDN
  2. 传递不正确的数据时(不是所有的流或格式不正确)
于 2012-08-13T14:14:54.730 回答