2017-07-17 59 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