Image files can contain a variety of data tags embedded with the pictures data. You can see that metadata when you look at the images property details in Windows. You can see various info on camera settings, image formatting, even location info via GPS. There are several formats including Exif (Exchangeable image file format) from JEITA (Japanese Electronics and Information Technology Industries Association). Besides the standards, digital camera manufacturers have extended the standard to support their own cameras functions. The specification is available here. A sampling of the tags and links to manufacturers sites is available here.

In a WinForms form I setup the Labels and TextBoxes for the metadata returned from the image files.

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Main Form
$mainForm = New-Object System.Windows.Forms.Form
$mainForm.Font = "Comic Sans MS,8.25"
$mainForm.Text = " Image File Exif MetaData"
$mainForm.ForeColor = "White"
$mainForm.BackColor = "DarkBlue"
$mainForm.width = 400
$mainForm.height = 680

# Form Labels
$cameraMakerLabel = New-Object System.Windows.Forms.Label
$cameraMakerLabel.Font = "Comic Sans MS,8"
$cameraMakerLabel.Location = "20,50"
$cameraMakerLabel.Size = "120,15"
$cameraMakerLabel.Text = "Camera Maker"
$mainForm.Controls.Add($cameraMakerLabel)

# Form TextBoxes
$cameraMakerTextBox = New-Object System.Windows.Forms.TextBox
$cameraMakerTextBox.Font = "Comic Sans MS,8"
$cameraMakerTextBox.Location = "140,50"
$cameraMakerTextBox.Size = "200,15"
$mainForm.Controls.Add($cameraMakerTextBox)

Next, using OpenFileDialog, I open a file browser window to select an image file.

function selectFile {
    $selectForm = New-Object System.Windows.Forms.OpenFileDialog
    $selectForm.Filter = "All Files (*.*)|*.*"
    $selectForm.InitialDirectory = ".\"
    $selectForm.Title = "Select a Image File to Process"
    $getKey = $selectForm.ShowDialog()

After selection, the image file is loaded as an array using the FromFile method of System.Drawing.Image.

    If ($getKey -eq "OK") {
        $filename = $selectForm.FileName
        $photo = [System.Drawing.Image]::FromFile($filename)

You get the data by reading a specific tag with GetPropertyItem. For example Color Space data is Exif tag number 40961. The properties are stored in different number or string formats and need to be decoded to be readable. Color Space is an unsigned 16bit integer. Others can be an array of bytes or an unsigned 32bit integer, for example. Each tag is different and will need to be converted accordingly. I then test the numeric values returned and replace with the text description. That description is inserted into the TextBox.Text value to populate the form.

        # Color Space
        $colorProperty = $photo.GetPropertyItem(40961)
        if ($colorProperty -ne $null){
            $colorSpace = [System.BitConverter]::ToUInt16($colorProperty.Value, 0)}
        if ($colorSpace -eq "1") {$colorSpace = "sRGB"}
        if ($colorSpace -eq "2") {$colorSpace = "Adobe RGB"}
        if ($colorSpace -eq "65535") {$colorSpace = "Uncalibrated"}
        $colorSpaceTextBox.Text = $colorSpace

As an example of a text string property, the Date Taken property is a string taken from UTF-8 encoded Unicode characters.

        # Date Taken
        $dateProperty = $photo.GetPropertyItem(36867)
        $dateTaken = (New-Object System.Text.UTF8Encoding).GetString($dateProperty.Value)
        $dateTakenTextBox.Text = $dateTaken

Some of the returned numbers need additional processing because they are in an array (Rational numbers – number,number) or to avoid divide by zero errors when the second number is 0 and to properly format in normal photography informaton display, like a fraction instead of a decimal value. I used the MakeNumber function from James O’Neill’s Blog to process those values.

# F-Stop
$fstopProperty = $photo.GetPropertyItem(33437)
if ($fstopProperty -ne $null){
     $fstop = MakeNumber($fstopProperty)}
$fstopTextBox.Text = "f/" + $fstop

function MakeNumber {
    $first =$args[0].value[0] + 256 * $args[0].value[1] + 65536 * $args[0].value[2] + 16777216 * $args[0].value[3] ;
    $second=$args[0].value[4] + 256 * $args[0].value[5] + 65536 * $args[0].value[6] + 16777216 * $args[0].value[7] ;
    if ($first -gt 2147483648) {$first  = $first  - 4294967296} ;
    if ($second -gt 2147483648) {$second= $second - 4294967296} ;
    if ($second -eq 0) {$second= 1} ;
    if (($first –eq 1) -and ($second -ne 1)) {
        write-output ("1/" + $second)}
    else {
        write-output ($first / $second)}
} # End Function MakeNumber

These are just a sampling of the hundreds of tags potentially available. Not all tags are used by all manufacturers and some tags seem to never be used. The tags in this script are generally the same ones in Windows Property/Details of an image.

ExifInfo

ExifInfo.ps1

Advertisements