在运行时更新 PNG 图像会引发 GDI+ 溢出异常

Posted

技术标签:

【中文标题】在运行时更新 PNG 图像会引发 GDI+ 溢出异常【英文标题】:Update PNG Image at runtime throws GDI+ overflow exception 【发布时间】:2019-01-03 20:18:58 【问题描述】:

我制作了一个列表框,其中包含绑定了图像的项目(Binding BitmapSource、UpdateSourceTrigger=PropertyChanged)。他们在运行时更新,一切都很好,但他们的背景是黑色的,而不是我希望的透明。

现在我想拥有与 PNG 相同的功能。 所以现在我确实绑定到 PNG 的 URI 并尝试更改图像并随后通知,但我收到错误(可能是因为我想在图像已经打开时保存图像?)

我会尽力展示所有相关代码: XAML:

 <Image  Source="Binding Path=OutfitImageString, UpdateSourceTrigger=PropertyChanged"/>

C# URI 字符串,我想用它来判断 PNG 何时更改:

   private string _OutfitImageString;
    public string OutfitImageString
    
        get  return _OutfitImageString; 
        set
        
            _OutfitImageString = value;
            NotifyPropertyChanged("OutfitImageString");
        
    

每次我更改位图图片(它绑定到一个类的实例)时,我都会运行这个方法:

  public void UpdateImage()
    
        // new bitmap (transparent background by default)
        Bitmap nb = new Bitmap(100, 110, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        // [ ... ] Create the Bitmap

        // save to PNG to get a transparent background, every Person has a unique name
        string saveAt = Directory.GetCurrentDirectory() + Name + "_outfit.png";
        nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);

        // notify that we changed the image (even tho the URI string is the same)
         OutfitImageString = saveAt;
    

这一行一旦运行 2. 时间就会产生一个错误:

nb.Save(saveAt, System.Drawing.Imaging.ImageFormat.Png);

异常类型 -2147467259 GDI+ 中的 Allgemeiner Fehler。溢出异常:System.Runtime.InteropServices.ExternalException (0x80004005):GDI+ 中的 Allgemeiner Fehler。 bei System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) bei System.Drawing.Image.Save(String filename, ImageFormat format)

我之前存储了 Bitmap 的 BitmapSource 并绑定到那个,这曾经完美地工作(只是背景不透明)。

此外,由于这些图像是临时的,我不喜欢一直保存它们:/

感谢您的帮助,很抱歉描述有点混乱...如果您需要更多详细信息,请写!

【问题讨论】:

以前不透明,现在不更新-.- 错误是什么? 将位图保存到文件有什么特别的原因吗?您也可以直接从 Bitmap 转换为 BitmapSource。您可能会直接创建一个 BitmapSource,从而完全避免使用 Bitnap。顺便说一句,当您通过内置类型转换从字符串加载 BitmapImage 时,WPF 会保持图像文件打开。 @Bijan,错误是:异常类型 -2147467259 GDI+ 中的 Allgemeiner Fehler。溢出异常:System.Runtime.InteropServices.ExternalException (0x80004005):GDI+ 中的 Allgemeiner Fehler。 bei System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams) bei System.Drawing.Image.Save(String filename, ImageFormat format) @Clemens 我必须使用 PNG 才能使透明背景工作。当我使用 BitmapSource 时它是黑色的 【参考方案1】:

完全不需要保存位图文件。

将属性的类型从字符串更改为 ImageSource

private ImageSource _OutfitImage;
public ImageSource OutfitImage

    get  return _OutfitImage; 
    set
    
        _OutfitImage = value;
        NotifyPropertyChanged(nameof(OutfitImage));
    

并如下所示绑定到它(设置UpdateSourceTrigger=PropertyChange 毫无意义)。

<Image Source="Binding Path=OutfitImage"/>

然后像这样赋值:

OutfitImage = BitmapToBitmapSource(nb);
...

public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap bitmap)

    var bitmapImage = new BitmapImage();

    using (var stream = new MemoryStream())
    
        bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
        stream.Position = 0;

        bitmapImage.BeginInit();
        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
        bitmapImage.StreamSource = stream;
        bitmapImage.EndInit();
    

    return bitmapImage;

【讨论】:

@Clemes 谢谢!你是个巫师 :D,我只需要添加: System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => UpdateImage();));让它毫无例外地工作:D

以上是关于在运行时更新 PNG 图像会引发 GDI+ 溢出异常的主要内容,如果未能解决你的问题,请参考以下文章

基于GDI显示png图像

当字节数组的源是 jpg 时,从存储的字节数组创建位图并保存到磁盘会引发 GDI+ 异常

C++ gdi::Bitmap 到内存中的 PNG 图像

C++ gdi::Bitmap 到内存中的 PNG 图像

使用带有内存流的 c# 在控制台应用程序中保存图像时,GDI + 中发生一般错误

如何使用 Win32/GDI 加载 PNG 图像(如果可能,不要使用 GDI+)?