Friday, July 4, 2008

I have recently been developing a consistant way to insert metadata into images. There are of course a number of GUI tools for doing this but what I wanted was a simple script or batch file solution that would work with large collections of images. I focused on writable tags for JPEGs although I think that the solution I have developed is likely to work for other image types... (I just haven't tested this!)

After some investigation I decided to use the very capable ExifTool by Phil Harvey. Once I had downloaded the Windows Executable version of this tool and renamed it to "Exiftool.exe". I copied it into the Windows directory so as to be able to just call it from a script. I then identified the range of metadata tags I wanted to target and inserted both the tag and the data into a text file using the Exiftool syntax. I then used Windows Powershell... to write a short script to do the actual work!

A shortened version of the script follows:



# Author: Peter Stone
# Organisation: University of Waikatio
# Department: Library, Technology Support Services
# Written: 26/06/2008
# Updated: July 04, 2008
# Filename: SetImagedata_v3.ps1
# Purpose: To insert metadata into (JPEG) images using the Exiftool utility developed by
# Phil Harvey at http://www.sno.phy.queensu.ca/~phil/exiftool/

# get the tag values from file
if ($args[0] -ne $null) {
[string]$tagvaluepath = $args[0]

#Does the file exist?
if (test-path $tagvaluepath -pathType leaf) {
write-host "Getting Exiftool tags and values: $tagvaluepath" -foregroundcolor "yellow"
write-host
$tags = get-content -Path $tagvaluepath

}else{
write-error "No file at $tagvaluepath Specify a path to a file containing Exiftool syntax tags and values"
}

}else{
write-error 'Specify a path to a file containing Exiftool syntax tags and values'
}

# Get the image(s) filepath
if ($args[1] -ne $null) {
[string]$imagepath = $args[1]

}else{
write-error 'Specify a path to a directory of images or an image file'
}

#Does the file(s) exist?
if (test-path $imagepath -pathType leaf) {
# Single file
$file = $imagepath
write-host "Metadata being entered onto image $file" -foregroundcolor "yellow"
write-host
foreach ($tag in $tags) {
# Write the tag to file
if ($tag -notlike '#*') {exiftool $file $tag -overwrite_original}
}

}else{
# Get any valid files from the directory
$imagepaths = get-childitem $imagepath -Include *.JPG -Recurse sort-object
foreach ($file in $imagepaths) {
write-host "Metadata being entered onto image $file" -foregroundcolor "yellow"
write-host
foreach ($tag in $tags) {
# Write the tag to file
if ($tag -notlike '#*') {exiftool $file $tag -overwrite_original}
}
}
}



The script requires 2 arguments:
The first argument is the path to the datafile I mention above.
The second argument is to an image file OR a directory of image files.

When run the script uploads the data in the data text file. It then locates and uploads the location(s) of the file(s) to be processed. The script then writes to each image that has been targeted the metadata from the data file. In this way I now have a simple and elegant way to ensure that the images have appropriate metadata inserted into them before I upload them to the web.

A copy of the full Powershell script and the data file together with details for downloading is available from http://www.newgrove.co.nz/stuff/exiftool_script.html

1 comment:

Anonymous said...

Great minds think alike. :-)

I recently did a similar investigation and concluded that this was the best approach as well.

Thanks for sharing (though I wished you had done so a month ago :-) ).

Cheers!
Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx