使用PowerShell

时间:2017-07-17 05:59:25

标签: arrays powershell gps byte type-conversion

我希望从图像文件的EXIF属性中提取GPS位置数据。我正在使用System.Drawing.Bitmap类来获取原始值。我能够提取我正在寻找的值,但它们会以字节或字节数组的形式返回,我需要帮助将字节转换为合理的数字。以下是我到目前为止的情况:

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

EXIF GPS Tag Reference我知道我正在寻找的属性标签是:

  • 0x0001 - 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}

根据System.Drawing library的MSDN文档,PropertyItem.Type为“2”是ASCII。

我将值加载到变量中:

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

Get-Member on变量返回类型System.Byte。我知道如何将字节转换回ASCII:

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

返回:

N

但是对于我来说,使用 GPSLatitude 值(0x0002)会让事情变得棘手:

$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]中?

1 个答案:

答案 0 :(得分: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"