前面介紹過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格式,如果不是,則退出。
//讀取圖片檔案頭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)。
//資料域長度 4 指定資料域的長度,固定為00 00 00 0D
//資料區塊符號 4 49 48 44 52,是“IHDR”的 Ascii 碼
stream.Seek(8, SeekOrigin.Current);
3.接下來要讀取就是圖片的寬度和高度值,讀取8個位元組,由於是按照高低位調換儲存,所以需要做高低位轉換,轉換後通過BitConverter類直接將位元組類型轉換為整數型即為圖片的尺寸。
//讀取寬度,高度 各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); |