What Focal Lengths do I take photos at?

I’ve been working with PowerShell for sometime and I have recently been encouraged to share some of the work that I’ve been doing.  So I thought I’d start out with a fun one. 

I have a SLR camera and I’m considering buying a new Lens, but what I’d like to know before I go and purchase one is: What Focal Lengths do I take my Photos at?  More importantly what focal length do I take most of my photos at; so I can focus my money on a lens that I’m going to use a lot!  Here’s what I came up with:

What the script will do:

  • Find all the files in a directory structure with a given file extension
  • Load each image and gather up it’s focal length and the type of camera that took it
  • If the camera type matches what we are looking for, add the focal length to the running score
  • Print the frequency distribution on focal length to screen


# setup default parameters if none were specified param([string]$path = (get-location), # current path [string]$fileType = ".jpg", # search for .jpg [string]$model = "Canon EOS 550D") # default camera type # Clear the Screen clear ##### Assemblies # load the .NET Assembly we will be using Add-Type -AssemblyName System.Drawing ##### Constants $filter = "*" + $fileType # clean up the search filter $Encode = new-object System.Text.ASCIIEncoding # find all the image files we are interested in $files = get-childitem -recurse $path -filter $filter # and how many we found $totalFiles = $files.count ##### Varibles $image = $null $imageHash = @{} $i = 0 $focalLength = $null ##### Main # if some files were returned if ($files -ne $null) { foreach ($file in $files) { # load image by statically calling a method from .NET $image = [System.Drawing.Imaging.Metafile]::FromFile($file.FullName) # try to get the ExIf data (silently fail if the data can't be found) # http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html try { # get the Focal Length from the Metadata code 37386 $focalLength = $image.GetPropertyItem(37386).Value[0] # get model data from the Metadata code 272 $modelByte = $image.GetPropertyItem(272) # convert the model data to a String from a Byte Array $imageModel = $Encode.GetString($modelByte.Value) # unload image $image.Dispose() } catch { #do nothing with the catch } # if the file contained both focalLength and A modelName if(($focalLength -ne $null) -and ($imageModel -eq $model)) { if($imageHash.containsKey($focalLength)) { # incriment count by 1 if focal length is already in hash table $count = $imageHash.Get_Item($focalLength) $count++ $imageHash.Set_Item($focalLength,$count) } else { # Add focal length to Hash Table if it doesn't exist $imageHash.add($focalLength,1) } } # Calculate the current percentage complete $i++ $percentComplete = [math]::round((($i/$totalFiles) * 100), 0) # Update that lovely percentage bar... Write-Progress -Activity:"Loading Focal Lengths" -status "$i of $totalFiles Complete:" -PercentComplete $percentComplete } # print results in ascending order of focal length $imageHash.GetEnumerator() | Sort-Object Name } else { Write-Host "No files found" }


Copy the script into a ps1 file and call it like so:

.\get-Focallengths –Path “c:\images” –fileType “.png” –model “Canon EOS 7D”

or drop the parameters you don’t need and let the script use it’s defaults e.g.

.\get-Focallengths –Path “c:\images”


I started out thinking this script was going to be trivial, but it’s turned into quite a good demonstration project of a lot of PowerShell’s abilities, specifically it’s ability to access the .NET framework.