如何在不加载图像的情况下可靠地获取.NET中的图像尺寸?

时间:2009-02-16 07:15:58

标签: .net image

我知道如何获得图像的大小(x,y)

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

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

当我在Windows资源管理器中查看图像时,它显示了我的大小。

  • 如何访问该尺寸?
  • 所有图片都可靠吗? Windows资源管理器是否需要首先“看到”图像以获得可用的大小。在将其加载到Internet Explorer之前,我不想上传到服务器并且没有可用的元数据。

修改:我将主题从'尺寸'更改为'尺寸',以澄清我想要的尺寸。

5 个答案:

答案 0 :(得分:34)

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

答案 1 :(得分: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);
}

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

答案 2 :(得分:4)

文章Reading Image Headers to Get Width and Height提供了几种解决方案:

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

答案 3 :(得分:3)

这样做通常涉及实际打开文件并只读取其标题(前几个字节)以查找其格式和大小。您无需读取整个文件即可找出它的大小。有时大小甚至在文件中的特定偏移量中,因此查找大小只读取8个字节。

您可以使用filemon.exe来实际找出Windows资源管理器本身可以找到的大小。

答案 4 :(得分:1)

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