[C#] 無需讀取整個文件即可獲取圖像尺寸


Answers

你有沒有嘗試過使用WPF圖像類? System.Windows.Media.Imaging.BitmapDecoder等?

我相信一些努力是確保這些編解碼器只讀取文件的一個子集以確定標題信息。 這值得檢查。

Question

有沒有廉價的方式來獲得圖像的尺寸(JPG,PNG,...)? 最好,我只想使用標準類庫(因為託管限制)來實現此目的。 我知道,閱讀圖片標題並自己解析它應該相對容易,但似乎這樣的東西應該​​已經存在了。 另外,我已經驗證下面的一段代碼可以讀取整個圖像(我不想):

using System;
using System.Drawing;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Image img = new Bitmap("test.png");
            System.Console.WriteLine(img.Width + " x " + img.Height);
        }
    }
}



這將取決於文件​​格式。 通常他們會在文件的早期字節中聲明它。 而且,通常,一個好的圖像閱讀實施將考慮到這一點。 儘管我不能指出你使用.NET。




我為PNG文件做了這個

  var buff = new byte[32];
        using (var d =  File.OpenRead(file))
        {            
            d.Read(buff, 0, 32);
        }
        const int wOff = 16;
        const int hOff = 20;            
        var Widht =BitConverter.ToInt32(new[] {buff[wOff + 3], buff[wOff + 2], buff[wOff + 1], buff[wOff + 0],},0);
        var Height =BitConverter.ToInt32(new[] {buff[hOff + 3], buff[hOff + 2], buff[hOff + 1], buff[hOff + 0],},0);



幾個月前我正在尋找類似的東西。 我想讀取GIF圖像的類型,版本,高度和寬度,但無法在網上找到任何有用的信息。

幸運的是,在GIF的情況下,所有必需的信息都在前10個字節中:

Type: Bytes 0-2
Version: Bytes 3-5
Height: Bytes 6-7
Width: Bytes 8-9

PNG稍微複雜一點(寬度和高度各為4字節):

Width: Bytes 16-19
Height: Bytes 20-23

如上所述,雖然pnglib中的PNG規範更為詳細,但pnglib是圖像和數據格式詳細規範的好網站。 不過,我認為維基百科對PNGGIF格式的入口是最好的開始。

這是我的原始代碼,用於檢查GIF,我還為PNG拍了一些東西:

using System;
using System.IO;
using System.Text;

public class ImageSizeTest
{
    public static void Main()
    {
        byte[] bytes = new byte[10];

        string gifFile = @"D:\Personal\Images&Pics\iProduct.gif";
        using (FileStream fs = File.OpenRead(gifFile))
        {
            fs.Read(bytes, 0, 10); // type (3 bytes), version (3 bytes), width (2 bytes), height (2 bytes)
        }
        displayGifInfo(bytes);

        string pngFile = @"D:\Personal\Images&Pics\WaveletsGamma.png";
        using (FileStream fs = File.OpenRead(pngFile))
        {
            fs.Seek(16, SeekOrigin.Begin); // jump to the 16th byte where width and height information is stored
            fs.Read(bytes, 0, 8); // width (4 bytes), height (4 bytes)
        }
        displayPngInfo(bytes);
    }

    public static void displayGifInfo(byte[] bytes)
    {
        string type = Encoding.ASCII.GetString(bytes, 0, 3);
        string version = Encoding.ASCII.GetString(bytes, 3, 3);

        int width = bytes[6] | bytes[7] << 8; // byte 6 and 7 contain the width but in network byte order so byte 7 has to be left-shifted 8 places and bit-masked to byte 6
        int height = bytes[8] | bytes[9] << 8; // same for height

        Console.WriteLine("GIF\nType: {0}\nVersion: {1}\nWidth: {2}\nHeight: {3}\n", type, version, width, height);
    }

    public static void displayPngInfo(byte[] bytes)
    {
        int width = 0, height = 0;

        for (int i = 0; i <= 3; i++)
        {
            width = bytes[i] | width << 8;
            height = bytes[i + 4] | height << 8;            
        }

        Console.WriteLine("PNG\nWidth: {0}\nHeight: {1}\n", width, height);  
    }
}