C# 擷取圖片的EXIF 資訊分類: 自創2010-04-10 12:48 1793人閱讀 評論(8) 收藏 舉報c#stringbyteimage製造演算法
關於 EXIF 資訊的介紹。
1 EXIF,是英文Exchangeable Image File(可交換影像檔)的縮寫。EXIF是一種影像檔格式,只是檔案的尾碼名為jpg。EXIF資訊是由數位相機在拍攝過程中採集一系列的資訊,然後把資訊放置在jpg檔案的頭部,也就是說EXIF資訊是鑲嵌在JPEG影像檔格式內的一組拍攝參數,主要包括攝影時的光圈、快門、ISO、日期時間等各種與當時攝影條件相關的訊息,相機品牌型號,色彩編碼,拍攝時錄製的聲音以及全球定位系統(GPS)等資訊。不管是硬體廠商的配套軟體還是專業名門的看圖工具,所有這些軟體都是為了方便數位攝影者能更方便地儲存查看攝影映像的重要訊息。
2 如何擷取EXIF資訊
在.NET中,我們可以用PropertyItem對象來擷取jpg 圖片的EXIF資訊。取得PropertyItem很簡單。
Image img = Image.FromFile("支援Exif的圖片檔案路徑");
PropertyItem[] pt = img.PropertyItems;
這樣就可以了,Exif資訊都已載入到PropertyItem數組中了。其中PropertyItem的ID,Type,Value屬性是最重要的。
ID可以唯一表明當前PropertyItem的含義。比如,0x010F代表相機製造商,0x8827代表ISO速度,0x829D代表相機。
Value永遠都是位元組數組,但具體內容的取值方法隨Type不同而不同。
Type是個整數,表示的類型在MSDN中是這麼描述的:
1 指定 Value 為位元組數組。
2 指定 Value 為空白終止 ASCII 字串。如果將類型資料成員設定為 ASCII 類型,則應該將 Len 屬性設定為包括空終止的字串長度。例如,字串“Hello”的長度為 6
3 指定 Value 為無符號的短(16 位)整型數組。
4 指定 Value 為無符號的長(32 位)整型數組。
5 指定 Value 資料成員為無符號的長整型對數組。每一對都表示一個分數;第一個整數是分子,第二個整數是分母。
6 指定 Value 為可以包含任何資料類型的值的位元組數組。
7 指定 Value 為有符號的長(32 位)整型數組。
10 指定 Value 為有符號的長整型對數組。每一對都表示一個分數;第一個整數是分子,第二個整數是分母。
所以擷取Exif資訊的演算法重點在於如何根據Type值將Value位元組數組變成人類可以理解的值。
public void FindExifinfo(string filePath)
{
Image img = Image.FromFile(filePath);
PropertyItem[] pt = img.PropertyItems;
for (int i = 0; i < pt.Length; i++)
{
PropertyItem p = pt[i];
switch (pt[i].Id)
{ // 裝置製造商 20.
case 0x010F:
this.textBox1.Text = System.Text.ASCIIEncoding.ASCII.GetString(pt[i].Value);
break;
case 0x0110: // 裝置型號 25.
this.textBox4.Text = GetValueOfType2(p.Value);
break;
case 0x0132: // 拍照時間 30.
this.textBox2.Text = GetValueOfType2(p.Value);
break;
case 0x829A: // .曝光時間
this.textBox3.Text = GetValueOfType5(p.Value)+" sec";
break;
case 0x8827: // ISO 40.
this.textBox5.Text = GetValueOfType3(p.Value);
break;
case 0x010E: // 映像說明info.description
this.textBox6.Text = GetValueOfType2(p.Value);
break;
case 0x920a: //相片的焦距
this.textBox7.Text = GetValueOfType5A(p.Value) + " mm";
break;
case 0x829D: //相片的光圈值
this.textBox8.Text = GetValueOfType5A(p.Value);
break;
default:
break;
}
}
}
public string GetValueOfType2(byte[] b)// 對type=2 的value值進行讀取
{
return System.Text.Encoding.ASCII.GetString(b);
}
private static string GetValueOfType3(byte[] b) //對type=3 的value值進行讀取
{
if (b.Length != 2) return "unknow";
return Convert.ToUInt16(b[1] << 8 | b[0]).ToString();
}
private static string GetValueOfType5(byte[] b) //對type=5 的value值進行讀取
{
if (b.Length != 8) return "unknow";
UInt32 fm, fz;
fm = 0;
fz = 0;
fz = Convert.ToUInt32(b[7] << 24 | b[6] << 16 | b[5] << 8 | b[4]);
fm = Convert.ToUInt32(b[3] << 24 | b[2] << 16 | b[1] << 8 | b[0]);
return fm.ToString() + "/" + fz.ToString()+" sec";
}
private static string GetValueOfType5A(byte[] b)//擷取光圈的值
{
if (b.Length != 8) return "unknow";
UInt32 fm, fz;
fm = 0;
fz = 0;
fz = Convert.ToUInt32(b[7] << 24 | b[6] << 16 | b[5] << 8 | b[4]);
fm = Convert.ToUInt32(b[3] << 24 | b[2] << 16 | b[1] << 8 | b[0]);
double temp = (double)fm / fz;
return (temp).ToString();
}
一下是運行: