【问题标题】:Problems overwriting (re-saving) image when it was set as image source将图像设置为图像源时覆盖(重新保存)图像的问题
【发布时间】:2024-01-13 11:34:01
【问题描述】:

大家好,

我在图像权限方面遇到了一些问题。

我正在从文件加载图像,调整其大小,然后将其保存到另一个文件夹。 然后我这样显示:

    uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);

    imgAsset.Source = new BitmapImage(uriSource);

这工作正常,如果用户随后立即选择另一个图像并尝试将其保存在原始文件之上,则会出现问题。

保存我的图片时出现异常"ExternalException: A generic error occurred in GDI+."

经过一番尝试,我将错误缩小到imgAsset.Source = new BitmapImage(uriSource);,因为删除此行而不设置图像源将允许我多次覆盖此文件。

我还尝试将源设置为其他内容,然后重新保存以希望旧的引用会被处理掉,但事实并非如此。

我怎样才能克服这个错误?

谢谢, 可汗

编辑

现在使用此代码我没有收到异常,但是图像源没有更新。另外,由于我没有使用 SourceStream,我不确定我需要处理什么才能使其正常工作。

       uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);

       imgTemp = new BitmapImage();
       imgTemp.BeginInit();
       imgTemp.CacheOption = BitmapCacheOption.OnLoad;
       imgTemp.UriSource = uriSource;
       imgTemp.EndInit();

       imgAsset.Source = imgTemp;

【问题讨论】:

    标签: c# wpf image save


    【解决方案1】:

    你快到了。

    • 使用 BitmapCacheOption.OnLoad 是防止文件被锁定的最佳解决方案。

    • 要使其每次重新读取文件,您还需要添加 BitmapCreateOptions.IgnoreImageCache。

    在你的代码中添加一行就可以了:

      imgTemp.CreateOption = BitmapCreateOptions.IgnoreImageCache;
    

    因此产生了以下代码:

      uriSource = new Uri(Combine(imagesDirectoryTemp, generatedFileName), UriKind.Absolute);
      imgTemp = new BitmapImage();
      imgTemp.BeginInit();
      imgTemp.CacheOption = BitmapCacheOption.OnLoad;
      imgTemp.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
      imgTemp.UriSource = uriSource;
      imgTemp.EndInit();
      imgAsset.Source = imgTemp;
    

    【讨论】:

    • imgTemp.CreateOption 应该是 imgTemp.CreateOptions
    【解决方案2】:

    当您在任何 WPF 控件中加载图像时,它会处理您的图像,并且在您关闭应用程序之前不会释放它。原因......我不知道确切,可能是在幕后中继一些 DirectX 代码,这些代码永远不知道 WPF 应用程序何时发布图像.. 使用此代码加载图像..

            MemoryStream mstream = new MemoryStream();
            System.Drawing.Bitmap bitmap = new Bitmap(imgName);
            bitmap.Save(mstream, System.Drawing.Imaging.ImageFormat.Jpeg);
            bitmap.Dispose(); // Releases the file.
    
            mstream.Position = 0;
    
            image.BeginInit();
            image.StreamSource = mstream;
            image.EndInit();
            this.img.Source = image ;   
    

    它对我有用..

    【讨论】:

    • 这可行,但比使用 BitmapCacheOptions.OnLoad 和 BitmapCreateOptions.IgnoreImageCache 效率要低得多,因为:1. 它在 RAM 中保留了两个数据副本,2. 因为有很多解析,所以速度较慢和 System.Drawing.Bitmap.Save 调用期间的处理。如果 imgName 是仅由 WPF 处理的 URI,它也将不起作用。
    【解决方案3】:

    听起来很像我在开发Intuipic 时遇到的问题,WPF 不会处理图像,从而锁定文件。查看this converter我写的来解决这个问题。

    【讨论】:

    • 您好,谢谢,我不再产生错误,但更新后图像源没有更新。我是否需要按照您的示例处理某些内容,还是需要以某种方式刷新图像源?谢谢。