【问题标题】:Unlock file generated from Bitmap object解锁从位图对象生成的文件
【发布时间】:2023-03-20 08:45:01
【问题描述】:

我有这种方法可以从磁盘上的图像中获取缩略图:

public static BitmapImage GetThumbnail()
{
    var dlg = new OpenFileDialog {Filter = "Imágenes|" + extensionesImagenes};
    var result = dlg.ShowDialog();

    if (result == true)
    {
        var tempFolder = Path.GetTempPath() + "MyTempFolder\\";

        if (!Directory.Exists(tempFolder))
            Directory.CreateDirectory(tempFolder);

        using (var thumbnail = new Bitmap(170, 170))
        {
            using (var gr = Graphics.FromImage(thumbnail))
            {
                gr.SmoothingMode = SmoothingMode.HighQuality;
                gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
                gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
                gr.DrawImage(new Bitmap(dlg.FileName), new Rectangle(0, 0, 170, 170));
            }

            thumbnail.Save(tempFolder + "foto.jpg", ImageFormat.Jpeg);
        }

        return new BitmapImage(new Uri(tempFolder + "foto.jpg"));
    }

    return null;
}

如果我第一次运行它没有问题。但是当我第二次运行它时,我收到“GDI+ 中发生一般错误”异常,因为我的应用正在使用该文件。

根据用户所做的操作,可以多次调用该方法,并且应该覆盖该文件。事实上,如果文件在我第一次调用该方法时存在,则它已成功覆盖。

文件是由 Bitmap 类的 Save() 方法生成的,我没有使用任何流。

如何解锁文件?

TIA

编辑

我没有使用 MemoryStream,因为我需要其他方法中的文件:当用户调用 GetThumbnail 方法时,缩略图将显示在 StackPanel 中(缩略图是 StackPanel 的 ImageSource。)

稍后用户可以将WPF表单中显示的信息(包括图像)保存到数据库中,并且保存到数据库的方法需要从保存的图像中读取字节。

编辑 2

在使用缩略图之前,我使用的是这种方法:

public static BitmapImage GetImage()
{
    var dlg = new OpenFileDialog {Filter = "Imágenes|" + extensionesImagenes};
    var result = dlg.ShowDialog();
    return result == true ? new BitmapImage(new Uri(dlg.FileName)) : null;
}

一切正常。

现在我使用缩略图,MemoryStream 的问题是我无法为图像设置 Uri。

例如我使用的是:

imagenNueva = InterfazUtil.GetImage(); // GetImage() is now GetThumbnail()
var rutaFoto = (imagenNueva != null) ? imagenNueva.ToString() : null;

字符串 rutaFoto 被传递给将信息保存到数据库的方法,并使用此变量从磁盘读取图像。

在 GetThumbnail 方法中,我确实将 Image 缩略图转换为 BitmapImage,并尝试设置 SourceUri 和 BaseUri:

新的 Uri(dialog.FileName);

但是当我调用 imagenNueva.ToString() 时,我没有得到有效的 Uri。

【问题讨论】:

  • 结果何时为真?你永远不会关闭你的对话框,所以我不知道这是否与它有关(我怀疑)(using(var dlg...)。我认为.Save 可能无法覆盖现有文件
  • 谢谢。对话框关闭,当用户关闭对话框时,结果 == true 条件才真正被评估。
  • 对话框是关闭的,但它没有被释放
  • 对话框没有实现 IDisposable。如果我尝试在 using 语句中使用它,则会出现错误。
  • 抱歉,我认为使用 showdialog 打开的所有对话框都需要处理。编辑 我注意到您在绘制图像时仍然有一个未处理的位图。如果你逐步完成你的方法,你会在哪一行得到错误

标签: c# file bitmap gdi+


【解决方案1】:
 gr.DrawImage(new Bitmap(dlg.FileName), new Rectangle(0, 0, 170, 170));

使用这样的位图非常麻烦。它会锁定“dlg.FileName”文件,并且在垃圾收集器释放它之前需要一段时间。你需要这样写:

 using (var bmp = new Bitmap(dlg.FileName)) {
     gr.DrawImage(bmp, new Rectangle(0, 0, 170, 170));
 }

现在它在使用后立即被释放,并且也释放了对文件的锁定。

顺便说一句,如果您改用 MemoryStream,您可以完全避免编写这样的代码。只需将图像保存到 MemoryStream 中,就不需要文件了。假设图像不是那么大,或者您可以指望在 64 位操作系统上运行。否则不是避免处理位图的理由。

【讨论】:

  • 谢谢。我确实用 using 版本替换了该行,但我仍然在同一行收到相同的错误。我没有使用 MemoryStream,因为其他地方需要该文件。我将编辑 OP 来解释它。
  • 好吧,也许这不是您忘记放置图像的唯一地方。您在此评论中也是这么说的。
  • 我写了第二个编辑。我希望它能澄清我在做什么。
  • 汉斯,第二次编辑我写得很快,有点不清楚。我确实修改了它,现在(我希望)它更清楚了。如果你读过它,也许你可以给我一个提示,让我使用 MemoryStream 解决我的问题。感谢您的帮助。
  • “有点不清楚”是轻描淡写。我不知道你在做什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-10
  • 2011-07-04
  • 1970-01-01
  • 2016-11-13
  • 2017-11-07
  • 2021-09-05
  • 2016-04-14
相关资源
最近更新 更多