使用 PowerShell 从字节数组中提取 GPS 数值
Extracting GPS numerical values from byte array using PowerShell
我想从图像文件的 EXIF 属性中提取 GPS 位置数据。我正在使用 System.Drawing.Bitmap class 来获取原始值。我能够提取我正在寻找的值,但它们以字节或可能的字节数组形式返回,我需要帮助将字节转换为合理的数字。这是我目前所拥有的:
$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 文档,“2”的 PropertyItem.Type 是 ASCII。
我将值加载到一个变量中:
$GPSLatRef = $imageProperties.PropertyItems| Where ID -eq 0x0001
$GPSLatRef = $GPSLatRef.Value
$GPSLatRef
78
0
Get-Member 在变量 returns 上键入 System.Byte。我知道如何将字节转换回 ASCII:
$GPSLatRef = [System.Text.Encoding]::ASCII.GetString($GPSLatRef.Value)
$GPSLatRef
returns:
N
但是 GPSLatitude 值 (0x0002):
$imageProperies.PropertyItems | ? ID -eq 0x0002
returns:
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 Explorer 中的十进制值进行比较,我可以推测 $GPSLatitude.Value 实际上向我展示了三个不同的每组两个整数。例如,
37
0
0
0
= 37
1
0
0
0
= 1
和 37/1 = 37,与 Windows Explorer 中的十进制值相匹配,所以我知道我在正确的轨道上。
如何从 GPSLatitude 属性 中找到的(数组?)字节拆分三组值?尽管字节中的数据被描述为长整数,但 Windows Explorer 中显示的十进制值显示结果可能是小数点右边十五位的数字,这让我认为乘积来自 属性 值的字节中两个长整数的除法可能需要存储在 [double] 或 [decimal]?
中
此代码段将为您提供纬度和经度详细信息,我正在使用 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"
我想从图像文件的 EXIF 属性中提取 GPS 位置数据。我正在使用 System.Drawing.Bitmap class 来获取原始值。我能够提取我正在寻找的值,但它们以字节或可能的字节数组形式返回,我需要帮助将字节转换为合理的数字。这是我目前所拥有的:
$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 文档,“2”的 PropertyItem.Type 是 ASCII。
我将值加载到一个变量中:
$GPSLatRef = $imageProperties.PropertyItems| Where ID -eq 0x0001
$GPSLatRef = $GPSLatRef.Value
$GPSLatRef
78
0
Get-Member 在变量 returns 上键入 System.Byte。我知道如何将字节转换回 ASCII:
$GPSLatRef = [System.Text.Encoding]::ASCII.GetString($GPSLatRef.Value)
$GPSLatRef
returns:
N
但是 GPSLatitude 值 (0x0002):
$imageProperies.PropertyItems | ? ID -eq 0x0002
returns:
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 Explorer 中的十进制值进行比较,我可以推测 $GPSLatitude.Value 实际上向我展示了三个不同的每组两个整数。例如,
37
0
0
0
= 37
1
0
0
0
= 1
和 37/1 = 37,与 Windows Explorer 中的十进制值相匹配,所以我知道我在正确的轨道上。
如何从 GPSLatitude 属性 中找到的(数组?)字节拆分三组值?尽管字节中的数据被描述为长整数,但 Windows Explorer 中显示的十进制值显示结果可能是小数点右边十五位的数字,这让我认为乘积来自 属性 值的字节中两个长整数的除法可能需要存储在 [double] 或 [decimal]?
中此代码段将为您提供纬度和经度详细信息,我正在使用 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"