2017-07-17 101 views
0

我希望從圖像文件的EXIF屬性中提取GPS位置數據。我正在使用System.Drawing.Bitmap類來獲取原始值。我能夠提取我正在查找的值,但它們會以字節或可能的字節數組的形式返回,並且需要將字節轉換爲合理的數字。以下是我迄今爲止:使用PowerShell從字節數組中提取GPS數值

$imagePath = 'C:\temp\picTest\WP_20150918_003.jpg' 
$imageProperties = New-Object -TypeName System.Drawing.Bitmap -ArgumentList $imagePath 

從我知道我要找的屬性標記是EXIF GPS Tag Reference

  • ×0001 - GPSLatitudeRef - 表示緯度是否北部或南部緯度。
  • 0x0002 - GPSLatitude - 表示緯度。
  • 0x0003 - GPSLongitudeRef - 指示經度是東經或西經。
  • 0x0004 - GPSLongitude - 表示經度。
  • 0x0005 - GPSAltitudeRef - 表示用作參考高度的高度。
  • 0x0006 - GPSAltitude - 指示基於GPSAltitudeRef中參考的高度。

首先,我得到GPSLatitudeRef

$imageProperies.PropertyItems | ? ID -eq 0x0001 

,我也得到:

Id Len Type Value 
-- --- ---- ----- 
1 2 2 {78, 0} 

根據MSDN文檔System.Drawing library, 「2」 是ASCII PropertyItem.Type。

我值加載到一個變量:

$GPSLatRef = $imageProperties.PropertyItems| Where ID -eq 0x0001 
$GPSLatRef = $GPSLatRef.Value 
$GPSLatRef 
78 
0 

獲取會員的變量返回類型爲System.Byte。我知道如何字節轉換回ASCII:

$GPSLatRef = [System.Text.Encoding]::ASCII.GetString($GPSLatRef.Value) 
$GPSLatRef 

回報:

N 

但事情變得棘手,我與GPSLatitude值(0×0002):

$imageProperies.PropertyItems | ? ID -eq 0x0002 

回報:

Id Len Type Value 
-- --- ---- ----- 
2 24 5 {37, 0, 0, 0...} 

加載值成一個變量:

$GPSLatitiude = $imageProperties.PropertyItems| Where ID -eq 0x0002 
$GPSLatitiude.Value 

返回的值是:

37 
0 
0 
0 
1 
0 
0 
0 
40 
0 
0 
0 
1 
0 
0 
0 
220 
182 
0 
0 
232 
3 
0 
0 

根據上面引用的MSDN文檔,PropertyItem.Type的 「5」 「指定價值數據成員是數組的無符號長整數。 每一對代表一個分數;第一個整數是分子,第二個整數是分母。

在Windows資源管理器中查看文件本身的屬性我以十進制形式查看GPS位置值。

"37;40;46.812000000005156" 

從上面的數值數據,從文檔中的數據類型的描述,並比較從Windows資源管理器的十進制值我可以推測,$ GPSLatitude.Value實際上表明瞭我三套不同的兩個整數一塊。例如,

37 
0 
0 
0 

= 37

1 
0 
0 
0 

= 1

和37/1 = 37,從Windows資源管理器,所以我知道我在正確的軌道上匹配的十進制值。

如何從GPSLatitude屬性中找到的(數組?)字節拆分三組值?即使字節中的數據被描述爲長整數,Windows資源管理器中顯示的十進制值也會顯示結果可能是小數點右側的十五位數字,這讓我認爲,來自屬性值的字節中的兩個長整數可能需要存儲在[double]或可能[decimal]中?

回答

0

這個片段會給你的經度和緯度的細節,我使用BitConverter提取從字節數組中的數據:

[double]$LatDegrees = (([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 0))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 4))); 
[double]$LatMinutes = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 8))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 12)); 
[double]$LatSeconds = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 16))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(2).Value, 20)); 
[double]$LonDegrees = (([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 0))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 4))); 
[double]$LonMinutes = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 8))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 12)); 
[double]$LonSeconds = ([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 16))/([System.BitConverter]::ToInt32($imageProperties.GetPropertyItem(4).Value, 20)); 
"Latitude: $LatDegrees;$LatMinutes;$LatSeconds" 
"Longitude: $LonDegrees;$LonMinutes;$LonSeconds" 
+0

感謝 - 我認爲這是有道理的,讓我知道我的理解: – osboy1

+0

感謝你 - 我相信這是有道理的,讓我確保我明白:值是長整型,因此32位長,因此4個字節長。所以括號引用數字是我們轉換的int32數組中的起始字節。我知道了。我唯一的問題是爲什麼在我的例子中,在Windows資源管理器中顯示的GPS緯度秒數的十進制值是「46」。812000000005156「,但是[double] $ LatSeconds的乘積是」46.812「。對我而言,精確度較低的值實際工作,但我希望瞭解它們之間的差異。 – osboy1