如何在 .NET 中可靠地获取图像尺寸而不加载图像?

问题描述 投票:0回答:6

我知道如何获取图像的尺寸 (x,y)

Image.FromFile("cat.jpg").Size

但这需要从内存中加载图像。

当我在 Windows 资源管理器中查看图像时,它会显示尺寸。

  • 如何获取该尺寸?
  • 所有图像都可靠吗? Windows 资源管理器是否需要先“看到”该图像才能使用该大小。我不想将图像上传到服务器,并且如果我从未打开该文件夹,则没有可用的元数据。
.net image
6个回答
41
投票

您可以将

Image.FromStream(Stream, bool, bool)
与“false”第二个和第三个参数一起使用,以避免将文件加载到内存中。


11
投票

如果您想在不加载图像的情况下获取图像尺寸(宽度和高度),您需要自己读取 jpeg 文件的某些部分,如下所示。

这是一个开箱即用的方法给你:)

public static Size GetJpegImageSize(string filename) {
    FileStream stream=null;
    BinaryReader rdr=null;
    try {
        stream=File.OpenRead(filename);
        rdr=new BinaryReader(stream);
        // keep reading packets until we find one that contains Size info
        for(; ; ) {
            byte code=rdr.ReadByte();
            if(code!=0xFF) throw new ApplicationException(
                    "Unexpected value in file "+filename);
            code=rdr.ReadByte();
            switch(code) {
                // filler byte
                case 0xFF:
                    stream.Position--;
                    break;
                // packets without data
                case 0xD0: case 0xD1: case 0xD2: case 0xD3: case 0xD4: 
                case 0xD5: case 0xD6: case 0xD7: case 0xD8: case 0xD9:
                    break;
                // packets with size information
                case 0xC0: case 0xC1: case 0xC2: case 0xC3:
                case 0xC4: case 0xC5: case 0xC6: case 0xC7:
                case 0xC8: case 0xC9: case 0xCA: case 0xCB:
                case 0xCC: case 0xCD: case 0xCE: case 0xCF:
                    ReadBEUshort(rdr);
                    rdr.ReadByte();
                    ushort h=ReadBEUshort(rdr);
                    ushort w=ReadBEUshort(rdr);
                    return new Size(w, h);
                // irrelevant variable-length packets
                default:
                    int len=ReadBEUshort(rdr);
                    stream.Position+=len-2;
                    break;
            }
        }
    } finally {
        if(rdr!=null) rdr.Close();
        if(stream!=null) stream.Close();
    }
}

private static ushort ReadBEUshort(BinaryReader rdr) {
    ushort hi=rdr.ReadByte();
    hi<<=8;
    ushort lo=rdr.ReadByte();
    return (ushort)(hi|lo);
}

这不是我的代码,这个例子是在代码项目中得到的。我复制并将其保存到我的实用程序片段中,但不记得链接了。


4
投票

文章读取图像标题以获取宽度和高度提供了几种解决方案的可能性:

  • 多线程
  • 读取文件头,如果缺少头则恢复完整图像加载
  • 为图像属性创建自己的索引

3
投票

执行此操作通常涉及实际打开文件并仅读取其标头(前几个字节)以查找其格式和大小。您无需阅读整个文件即可了解其大小。有时,大小甚至位于文件中的特定偏移量中,因此查找大小仅读取 8 个字节。

您可以使用 filemon.exe 来实际了解 Windows 资源管理器本身如何查找大小。


1
投票

从我的头脑中 -

LoadImage()
有一个指定进度回调的覆盖。也许你可以用它来取消读取标题后的加载?


0
投票

Magick.NET 可以做到这一点并支持多种文件格式:

var info = new ImageMagick.MagickImageInfo(filename);

Console.WriteLine($"{info.Width} x {info.Height}");

更多这里

© www.soinside.com 2019 - 2024. All rights reserved.