# encoding: ascii
# api: powershell
# title: Get-ImageMetaData
# description: Get-ImageMetadata lets you access the EXIF, XMP and other metadata about image files … this should only be taken as an example and a reference, not for solid production work — in other words, I won’t take the blame if you zero out all your jpgs trying to modify this to ReadWrite instead of just Read :)
# version: 1.0
# type: function
# author: Joel Bennett
# license: CC0
# function: Get-ImageMetadata
# x-poshcode-id: 617
# x-archived: 2017-05-16T03:53:10
# x-published: 2009-09-30T19:22:00
#
#
## Get-ImageMetaData -- pull EXIF, XMP, and other data from images using the BitmapMetaData
## Usage: ls *.jpg | Get-ImageMetaData | ft Length, LastWriteTime, Name, "36867"
## Note that '36867' is the decimal value of (0x9003) the EXIF tag for DateTimeOriginal
## For more information see: http://owl.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
#####################################################################################################
## History:
## - v1.0 - First release, retrieves all the data and stacks it somehow onto a FileInfo object
#####################################################################################################
# filter Get-ImageMetadata {
PARAM($file)
BEGIN {
$null = [Reflection.Assembly]::LoadWithPartialName("PresentationCore");
function Get-ImageMetadata {
PARAM([System.Windows.Media.Imaging.BitmapFrame]$bitmapFrame, [string]$path)
PROCESS {
if($path -is [string]) {
## To read metadata, you use GetQuery. To write metadata, you use SetQuery
## To WRITE metadata, you need a writer,
## but first you have to open the file ReadWrite, instead of Read only
# $writer = $bitmapFrame.CreateInPlaceBitmapMetadataWriter();
# if ($writer.TrySave()){
# $writer.SetQuery("/tEXt/{str=Description}", "Have a nice day.");
# } else {
# Write-Host "Couldn't save data" -Fore Red
# }
$next=$bitmapFrame.MetaData.GetQuery($path);
if($next.Location){
$next | ForEach-Object {
Get-ImageMetadata $bitmapFrame "$($next.Location)$_"
}
} else {
if($path.Split("/")[-1] -match "{ushort=(?<code>\d+)}") {
# $path = "0x{0:X}" -f [int]$matches["code"]
$path = [int]$matches["code"]
}
Add-Member -in ($Global:ImageMetaData) -Type NoteProperty -Name $path -value $next -Force
# @{$path=$next}
}
} else {
$bitmapFrame.Metadata | ForEach-Object { Get-ImageMetadata $bitmapFrame $_ }
}
}
}
}
PROCESS {
if($_) { $file = $_ }
if($file -is [IO.FileInfo]) {
$file = [string]$file.FullName;
} elseif($file -is [String]) {
$file = [string](Resolve-Path $file)
}
$Global:ImageMetaData = New-Object IO.FileInfo $file
$stream = new-object IO.FileStream $file, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read);
& {
$decoder = [System.Windows.Media.Imaging.BitmapDecoder]::Create( $stream, "None", "Default" )
$bitmapFrame = $decoder.Frames[0];
$bitmapFrame.Metadata | ForEach-Object { Get-ImageMetadata $bitmapFrame $_ }
}
trap {
Write-Error "WARNING: $_"
continue;
}
$stream.Close()
$stream.Dispose()
Write-Output $Global:ImageMetaData
}