image - 在 PowerShell 中提取 EXIF 数据的简便方法?

标签 image date powershell exif

我一直在寻找可以使用 PowerShell 提取 EXIF 数据的各种方法,但到目前为止我发现它非常复杂。 一些herehere .

我正在寻找一种(相对)简单的方法来使用 powershell 提取基本 EXIF 数据,以便我可以在 native 使用它。

特别是,我对 Date Taken 属性特别感兴趣,我正在尝试找到一种方法,我可以通过 Get-Date 运行它,并自定义格式为了我自己的需要。 像这样的东西:

$exifdatetaken = $mypicture.'Date taken' | Get-Date -Format yyyyMMdd-HHmmss

有谁知道是否有办法在 PowerShell 中本地执行此操作?

最佳答案

提取 EXIF 元数据通常如此复杂的原因是因为 image 元数据作为文件内容的一部分存储(与 file 元数据相反,它存储并由操作系统与文件分开索引)。除此之外,EXIF 是一种可扩展格式,制造商经常使用(和滥用)这种格式来以专有格式存储数据,因此情况很快就会变得困惑。

您链接的两个引用都使用来自 GDI+ Win32 API 的 [System.Drawing] 类,它公开了 200 多个图像属性,其中不止一个可能反射(reflect)了图片的日期时间采取。它们还针对单个属性 36867 (0x9003) 进行硬编码,这是 PropertyTagExifDTOrig 值。

利用 [System.Drawing.Bitmap] 类来公开所有可用的元数据相当简单,例如:

$path   = 'C:\my\images\Canon.jpg'
$bitmap = [System.Drawing.Bitmap]::new($path)
$bitmap.PropertyItems

这将给出一组这样的结果:

   Id  Len Type Value
   --  --- ---- -----
  271    6    2 {67, 97, 110, 111, 110, 0}
  272   24    2 {67, 97, 110, 111, 110, 32, 69, 79, 83, 32…}
  274    2    3 {1, 0}
  282    8    5 {180, 0, 0, 0, 1, 0, 0, 0}
  283    8    5 {180, 0, 0, 0, 1, 0, 0, 0}
  296    2    3 {2, 0}
  306   20    2 {50, 48, 48, 51, 58, 49, 50, 58, 48, 52…}
  531    2    3 {1, 0}
33434    8    5 {4, 0, 0, 0, 1, 0, 0, 0}
33437    8    5 {14, 0, 0, 0, 1, 0, 0, 0}
34855    2    3 {100, 0}
36864    4    7 {48, 50, 50, 49}
# etc.

这是简单的部分。从这些数据中获取有用的东西是棘手的。 Id 引用 property tag告诉您您正在查看的特性。 Value 是一个字节数组,需要将其解码为有意义的值(它本身可能是一个或两个步骤的过程)。要了解如何解码字节,您需要查看可用于查找 data typeType 值。 .一旦你解码了字节,你可能会留下:

  • 一个有意义的值(例如,包含相机制造商名称的 ASCII 字符串)
  • 一个值,它是对 EXIF standard 中查找的引用(例如,对于 Id 37383 (0x9207 PropertyTagExifMeteringMode),值 0 表示“未知”,1 表示“平均”,依此类推),或者需要一些额外的计算才能获得有意义的值
  • 可以从一些外部引用(例如 ExifTool's list of tags)解码的未知值
  • 无法解码(或需要原始软件解码)的未知值

例如,要使用 Id 306 (0x0132 PropertyTagDateTime) 获取创建图像的日期和时间(ASCII 字符串),如下所示:

$pi        = $bitmap.GetPropertyItem(306)
$ascii     = [System.Text.ASCIIEncoding]::new()
$piDecoded = $ascii.GetString($pi.Value[0..$($pi.Len-2)]) # trim off the trailing null terminator
$piDecoded
$piDecoded.GetType().FullName

返回例如:

2022:06:11 13:25:36
System.String

然后您可以直接将其操作成您想要的格式,或者解析它并将其发送到 Get-Date 以获取 DateTime 对象。

另一个示例,使用 Id 34855 (0x8827 PropertyTagExifISOSpeed) 获取图像(SHORT (UInt16) 类型)的 ISO:

$pi        = $bitmap.GetPropertyItem(34855)
$piDecoded = [System.BitConverter]::ToUInt16($pi.Value,0)
$piDecoded
$piDecoded.GetType().FullName

返回例如:

100
System.UInt16

等等。

我曾想解决完全相同的问题,主要是对我的个人文件中的图像进行大量重命名,但也有一种简单的方法来过滤图像,例如,我内置的图像方向一个 PowerShell 模块。你可以在this中看到我上面描述的逻辑的具体实现。功能。

关于image - 在 PowerShell 中提取 EXIF 数据的简便方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34913250/

相关文章:

java - 如何将高清图像缩小为标清图像?

使用 numpy 操作数组后 Python OpenCV 绘图错误

javascript - JavaScript 如何比较日期字符串?

powershell - 为什么 Write-Host "$PSCommandPath"没有输出我当前的路径?

powershell - 导入 CSV GroupBy Sum

html - 无法使用图像设置 anchor <a> 的样式

html - 加载大量图像的最佳方式

r - 如何将日期放在 barplot() x Axis 上?

r - 时区在R系统时间的输出中消失

sql-server - 使 Azure 防火墙规则自动过期