前面介紹過Windows Phone 解析圖片格式,通過解析圖片格式,我們可以根據圖片格式使用相關控制項展示。在Windows Phone開發中,無論是系統Image控制項,還是ImageTools中提供的圖片控制項,載入圖片都是非同步過程,這樣就使得我們無法立即獲得圖片的尺寸大小,而必須等圖片載入完成後才能獲得。然後在開發過程中,有時候我們需要在載入圖片完成之前就擷取圖片的尺寸。同前面解析圖片格式的處理方法類似,我們需要解析圖片檔案的頭資訊,並從中擷取圖片的寬度和高度資訊。
要解析Png圖片的寬度和高度資訊,首先需要瞭解Png圖片的資料區塊結構,Png圖片的尺寸資訊存放在檔案頭資料區塊中,所以我們需要瞭解檔案頭的資料區塊結構。
檔案頭資料區塊IHDR(header chunk):它包含有PNG檔案中儲存的映像資料的基本資料,並要作為第一個資料區塊出現在PNG資料流中,而且一個PNG資料流中只能有一個檔案頭資料區塊。 檔案頭資料區塊由13位元組組成,其中前8個位元組即為圖片的寬度和高度資訊,各佔4個位元組。
檔案頭資料區塊是第一個資料區塊,但是在資料區塊前,也就是PNG圖片檔案的最開始位置首先儲存的是PNG檔案署名域,佔8個位元組,即:89 50 4e 47 0d 0a 1a 0a ( .PNG....),通過這個可以判斷圖片是否為PNG格式,接下來是檔案頭資料區塊的長度和標識,各佔4個位元組,檔案頭資料區塊的長度為13,所以檔案頭資料區塊的長度固定為 00 00 00 0D,而檔案頭資料區塊的標識為49 48 44 52,即“IHDR”。
通過上面的解析,我們可以分一下幾步來解析PNG圖片的寬度和高度。
1.首先讀取起始位的8個位元組,即PNG檔案署名域,判斷圖片是否為PNG格式,如果不是,則退出。
View Code
//讀取圖片檔案頭8個位元組,並根據這8個位元組來判斷是否為PNG圖片
byte[] header = new byte[8];
stream.Read(header, 0, 8);
//Png圖片 8位元組:89 50 4E 47 0D 0A 1A 0A
if (!(header[0] == 0x89 &&
header[1] == 0x50 && // P
header[2] == 0x4E && // N
header[3] == 0x47 && // G
header[4] == 0x0D &&
header[5] == 0x0A &&
header[6] == 0x1A &&
header[7] == 0x0A))
{
//不是PNG圖片
return;
}
2.然後跳過8個位元組,即檔案頭資料區塊的長度值 00 00 00 0D,以及檔案頭資料區塊標識 49 48 44 52(IHDR)。
View Code
//資料域長度 4 指定資料域的長度,固定為00 00 00 0D
//資料區塊符號 4 49 48 44 52,是“IHDR”的 Ascii 碼
stream.Seek(8, SeekOrigin.Current);
3.接下來要讀取就是圖片的寬度和高度值,讀取8個位元組,由於是按照高低位調換儲存,所以需要做高低位轉換,轉換後通過BitConverter類直接將位元組類型轉換為整數型即為圖片的尺寸。
View Code
//讀取寬度,高度 各4位元組
byte[] buffer = new byte[8];
stream.Read(buffer, 0, buffer.Length);
Array.Reverse(buffer, 0, 4);
Array.Reverse(buffer, 4, 4);
width_ = BitConverter.ToInt32(buffer, 0);
height_ = BitConverter.ToInt32(buffer, 4);