获取位图文件名

8
我用以下代码创建位图:

我使用这行代码来创建我的位图:

Bitmap b = new Bitmap(@"C:\<file name>");

在我修改了这个位图后,我想将其保存为以下行内:

b.Save(@"C:\\<other file name>")

我的问题是 - 如何从属性中获取位图文件名。
简单地说,我需要使用与我初始化位图相同的名称保存位图。谢谢。

4
Bitmap不能提供文件名信息,也不一定需要从文件创建Bitmap,有多种构造函数可用。你需要使用一个字符串变量自行跟踪文件名。 - Hans Passant
6个回答

8
被点赞的答案会给你带来麻烦。从文件中加载位图会在文件上加锁。您不能在不先处理位图的情况下将其保存回去。这是一个鸡生蛋的问题,您无法解决,除非克隆位图。这本身就有点棘手,Bitmap.Clone()方法是一个优化版本,它使用了与第一次对文件进行锁定相同的内存部分。因此并没有真正释放锁定。
这里有一个小类可以处理创建深层克隆并记住原始位图的路径和格式:
    class EditableBitmap : IDisposable {
        public EditableBitmap(string filepath) {
            using (var bmp = new Bitmap(filepath)) {
                this.bitmap = new Bitmap(bmp);
                this.bitmap.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
            }
            this.path = System.IO.Path.GetFullPath(filepath);
            this.format = bitmap.RawFormat;
        }

        public Bitmap Bitmap { get { return bitmap; } }

        public void Save() {
            bitmap.Save(path, format);
            this.Dispose();
        }

        public void Dispose() {
            if (bitmap != null) {
                bitmap.Dispose();
                bitmap = null;
            }
        }
        private Bitmap bitmap;
        private System.Drawing.Imaging.ImageFormat format;
        private string path;
    }

然后像这样使用:

        using (var bmp = new EditableBitmap(@"c:\temp\test.png")) {
            DoSomething(bmp.Bitmap);
            bmp.Save();
        }

为什么需要存储ImageFormat? - gliderkite
通常情况下,您希望以相同的图像格式保存修改后的位图。当使用Image.Save(string)时,它并不会自动保存为相同格式,而是默认保存为PNG格式。 - Hans Passant

6
也许你可以使用元数据来实现这个功能 - 但我对这个主题不熟悉,所以我不完全确定它是否可能,也不知道如何做。
我建议的是创建一个类型。

例如,您可以创建一个类,该类将具有用于图像的位图(1)属性和文件路径的字符串。

class LocalBitmap
{
    public Bitmap Bitmap { get; set; }
    public String Path { get; set; }

    public LocalBitmap(String path)
    {
        Path = path;
        Bitmap = new Bitmap(path);
    }
}

然后像这样使用:

LocalBitmapimage = new LocalBitmap(@"C:\myImage.bmp");

考虑使用Image类,它是Bitmap的基类。如果您不确定要使用哪个,请问自己您的类是否需要一个图像或该确切格式的图像(即位图)。

5

您可以使用变量:

var name = @"C:\<file name>";

然后:
using (Bitmap b = new Bitmap(name))
{
    ...
    b.Save(name);
}

同时请注意,我已经将Bitmap实例包装在一个using语句中,以便在完成后释放与其相关联的非托管资源。您应该始终将IDisposable对象包装在using语句中。


2
代码发布后永远无法正常工作,它总是抛出ExternalException异常。从文件中加载位图会在文件上放置一个锁,这是由内存映射文件部分创建的锁,GDI+使用该锁将像素数据映射到内存中。必须处理位图以释放锁定。这里有个好玩的鸡生蛋问题 :) 使用Bitmap(Image)构造函数创建所需的副本。 - Hans Passant

2
一种可能的解决方法是在创建Bitmap时使用其Tag属性来存储路径。
string pathToBitmap = @"C:\myImage.bmp";
Bitmap myBitmap = new Bitmap(pathToBitmap) { Tag = pathToBitmap };

..然后稍后检索路径..
string pathFromBitmap = (string)myBitmap.Tag;

只需确保将标签转换为字符串,并将标签复制到从源位图创建的任何实例中即可。


0

你不需要。基本上位图不会记住文件 -这是你的工作。

你基本上在问:“我收到了UPS发送的一张图片,在几天后拆包后,如何在图片中找到运单号?”- 你做不到。


0

解决 Hans 描述的锁定文件问题的另一种方法是 冻结 图像。

public PhotoImageSource GetImage()
{
    string filename = "c:\Images\myimage.png";
    var image = new BitmapImage();
    using (var stream = new FileStream(fileName, FileMode.Open))
    {
        image.BeginInit();
        image.CacheOption = BitmapCacheOption.OnLoad;
        image.StreamSource = stream;
        image.EndInit();
    }
    image.Freeze(); //prevent error "Must create DependencySource on same Thread as the DependencyObject"
    return new PhotoImageSource(image, filename);
}

public class PhotoImageSource
{
    public PhotoImageSource(ImageSource image, string filename)
    {
        Image = image;
        Filename = filename;
    }
    public ImageSource Image { get; set; }
    public string Filename { get; set; }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接