首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 讀取 JPEG EXIF 資訊完整指南:PropertyItem 解析與常用標籤對照表

     編輯:關於C語言

EXIF 簡介

EXIF (Exchangeable Image File Format) 嵌入 JPEG 影像檔頭,記錄拍攝參數 (光圈、快門、ISO、白平衡)、時間、相機型號、GPS 座標等。.NET 透過 Image.PropertyItems 存取。

核心類別與屬性

成員說明
Image.PropertyItems傳回 PropertyItem[],每項含 Id (標籤)、Type (資料型別)、Len (長度)、Value (位元組陣列)
PropertyItem.IdEXIF 標籤 ID (十六進位),如 0x010F = Make (製造商)
PropertyItem.Type1=Byte, 2=ASCII, 3=Short, 4=Long, 5=Rational, 7=Undefined, 9=SLONG, 10=SRATIONAL

常用 EXIF 標籤對照表

完整解析程式碼


using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;

public class ExifReader
{
    public ExifData Read(string filePath)
    {
        using (var img = Image.FromFile(filePath))
        {
            var data = new ExifData();
            foreach (var prop in img.PropertyItems)
            {
                switch (prop.Id)
                {
                    case 0x010F: data.Make = GetString(prop); break;
                    case 0x0110: data.Model = GetString(prop); break;
                    case 0x0132: data.DateTime = GetString(prop); break;
                    case 0x9003: data.DateTimeOriginal = GetString(prop); break;
                    case 0x829A: data.ExposureTime = GetRational(prop); break;
                    case 0x829D: data.FNumber = GetRational(prop); break;
                    case 0x8827: data.ISOSpeed = GetShort(prop); break;
                    case 0x920A: data.FocalLength = GetRational(prop); break;
                    case 0xA432: data.LensModel = GetString(prop); break;
                    case 0x8825: data.GpsInfo = ParseGps(prop, img.PropertyItems); break;
                }
            }
            return data;
        }
    }

    private string GetString(PropertyItem prop)
    {
        // ASCII 字串以 null 結尾,移除結尾 \0
        return Encoding.ASCII.GetString(prop.Value).TrimEnd('\0');
    }

    private double GetRational(PropertyItem prop)
    {
        // Rational = 兩個 uint (分子、分母)
        if (prop.Value.Length < 8) return 0;
        uint num = BitConverter.ToUInt32(prop.Value, 0);
        uint den = BitConverter.ToUInt32(prop.Value, 4);
        return den == 0 ? 0 : (double)num / den;
    }

    private short GetShort(PropertyItem prop)
    {
        return BitConverter.ToInt16(prop.Value, 0);
    }

    private GpsData ParseGps(PropertyItem gpsPtr, PropertyItem[] allProps)
    {
        // GPS 資訊存放在子 IFD,需對應子標籤 (0x0001~0x001D)
        // 這裡簡化:實際需遞迴解析子目錄,建議使用 MetadataExtractor 套件
        return new GpsData();
    }
}

public class ExifData
{
    public string Make { get; set; }
    public string Model { get; set; }
    public string DateTime { get; set; }
    public string DateTimeOriginal { get; set; }
    public double ExposureTime { get; set; } // 秒
    public double FNumber { get; set; }
    public short ISOSpeed { get; set; }
    public double FocalLength { get; set; } // mm
    public string LensModel { get; set; }
    public GpsData GpsInfo { get; set; }

    public override string ToString()
    {
        return $"{Make} {Model}\n拍攝時間: {DateTimeOriginal}\n光圈: f/{FNumber:F1}\n快門: 1/{1/ExposureTime:F0}s\nISO: {ISOSpeed}\n焦距: {FocalLength}mm\n鏡頭: {LensModel}";
    }
}

public class GpsData
{
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public double Altitude { get; set; }
}

使用範例


var reader = new ExifReader();
var exif = reader.Read(@"C:\Photos\DSC_001.jpg");
Console.WriteLine(exif);

// 輸出範例:
// NIKON D850
// 拍攝時間: 2024:03:15 14:30:22
// 光圈: f/2.8
// 快門: 1/250s
// ISO: 100
// 焦距: 85mm
// 鏡頭: AF-S NIKKOR 85mm f/1.4G

進階建議:使用 MetadataExtractor 套件

手寫解析 GPS、MakerNote (廠商私有標籤) 非常繁瑣。建議安裝 NuGet:


Install-Package MetadataExtractor

using MetadataExtractor;
using MetadataExtractor.Formats.Exif;

var directories = ImageMetadataReader.ReadMetadata(filePath);
var exifDir = directories.OfType().FirstOrDefault();
var model = exifDir?.GetDescription(ExifDirectoryBase.TagModel);
var dateTime = exifDir?.GetDescription(ExifDirectoryBase.TagDateTime);

var gpsDir = directories.OfType().FirstOrDefault();
var lat = gpsDir?.GetGeoLocation()?.Latitude;
var lon = gpsDir?.GetGeoLocation()?.Longitude;

注意事項

  • Image.FromFile 會鎖定檔案至物件 Dispose,若需移動/刪除檔案,請先複製到 MemoryStream:using var ms = new MemoryStream(File.ReadAllBytes(path)); using var img = Image.FromStream(ms);
  • 部分影像無 EXIF (截圖、網頁圖片),PropertyItems 可能為空或拋例外,需 try-catch。
  • 大量批次處理時,考慮平行化 Parallel.ForEach。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
ID (Hex)名稱說明型別
0x010EImageDescription影像描述ASCII
0x010FMake相機製造商ASCII
0x0110Model相機型號ASCII
0x0131Software處理軟體ASCII
0x0132DateTime修改時間 (YYYY:MM:DD HH:MM:SS)ASCII
0x829AExposureTime曝光時間 (秒,有理數)RATIONAL
0x829DFNumber光圈值 (F-number,有理數)RATIONAL
0x8827ISOSpeedRatingsISO 感光度SHORT
0x9000ExifVersionEXIF 版本UNDEFINED
0x9003DateTimeOriginal原始拍攝時間ASCII
0x9004DateTimeDigitized數位化時間ASCII
0x920AFocalLength焦距 (mm,有理數)RATIONAL
0xA001ColorSpace色彩空間 (1=sRGB)SHORT
0xA432LensModel鏡頭型號ASCII
0x8825GPSInfoGPS 資訊子 IFD 指標LONG