如何将编辑好的System.Drawing.Bitmap保存到同一个文件中?

问题描述 投票:-1回答:1

我正在开发一个简单的图形应用程序。上传图片,编辑图片,然后保存。我尝试了各种方法,但都以某种方式失败。

我首先尝试了像这样加载位图。

imageFromName = new Bitmap(FileName1);

然后像这样保存

imageFromName.Save(FileName1);

但它抛出了一个 "GDI +. "的异常.另外,此时windows资源管理器不允许我删除文件,所以我认为问题是 "imageFromName "对象保持文件打开,不允许覆盖它,所以我修改了这样的代码。

imageFromName = new Bitmap(FileName1);
imageCloned = (Bitmap)imageFromName.Clone();
imageFromName.Dispose();
imageCloned.Save(FileName1);

程序一直在抛出同样的异常 imageCloned.Save (FileName1)于是我在Stackoverflow上寻找帮助,看到了几个类似的问题,答案都是建议检查应用是否有写权限。于是我修改了代码,像这样检查。

imageFromName = new Bitmap(FileName1);
imageFromName.Save(FileName2);

在这种情况下,程序在保存文件的时候没有抛出任何异常 但我还是不能修改原来的文件 也不能用Windows资源管理器删除它。它只是为我创建了一个文件的副本。

所以我想用另一种方式加载位图,并修改了这样的代码。

 try
 {
       System.IO.FileStream fs = new System.IO.FileStream(FileName1, System.IO.FileMode.Open);
       imageFromStream = new System.Drawing.Bitmap(fs);
       fs.Close();
 }
 catch (Exception ex)
 {
       Console.WriteLine("Error loading Bitmap.", ex);
 }

在这种情况下,应用程序没有抛出任何异常,位图在PictureBox中也能很好地被看到。另外,资源管理器允许我删除文件。然而,当我用 imageFromStream.Save (imageFromStream) 它一直为我生成一个异常。

这次的不同之处在于 Save () 方法,尽管抛出了异常,但还是会覆盖原始文件,反而生成了一个包含头信息的 54 字节文件。

用十六进制编辑器打开原始文件和副本文件,我验证了除了图像大小和BITMAPINFOHEADER的偏移量之外,头信息是一样的。只有图纸的信息没有了。

我已经阅读了微软官方文档中关于 System.Drawing.Bitmap.Save () 方法,并且没有发现任何形式的限制。但我想说,它对某些像素格式有问题。

然而,我希望不必将我的应用程序限制在32bpp文件上,那么。

1 -什么是最好的方法来保存一个图像的图像?System.Drawing.Bitmap 对象到一个24bpp文件?

2-System.Drawing.Bitmap.Save()还有什么限制吗?

c# file exception bitmap gdi+
1个回答
0
投票

当你从存储在硬盘上的图像中初始化一个位图对象时,它会在底层图像文件上创建一个锁。由于锁定,当你尝试保存修改后的位图时,它会抛出这个错误。

有两种方法可以解决这个问题

  • 不要覆盖文件,而是保存一个与原文件不同名称的新文件。
  • 只有当Bitmap对象被处理时,文件上的底层锁才会被移除。一旦锁定被移除,你可以覆盖文件。如果您必须覆盖现有的文件,从现有的位图对象中创建一个单独的位图对象。现在处理旧的位图对象,这将释放图像文件上的锁。继续在新的位图对象中进行所需的修改,并将新的位图对象保存为原始图像文件名。

保存图像到24bpp文件的最好方法是使用以下方法 PixelFormat.Format24bppRgb 为新的位图对象。

这里是一个例子。

using Bitmap imageCopy = null;
using(var imageFromName = new Bitmap(FileName1))
{
    // you can modify your image here
    ...
    // Before this block ends we need to copy Bitmap
    imageCopy = new Bitmap(imageFromName); // or imageFromName.Clone with expected format
}

imageCopy.Save(FileName1);

另一种方法是在编辑时没有文件系统锁定的情况下即时读取图像。

using(var ms = new MemoryStream(File.ReadAllBytes(FileName1))
using(var image = new Bitmap(ms))
{
    // you can modify your image here
    ...
    image.Save(FileName1); 
}
© www.soinside.com 2019 - 2024. All rights reserved.