Image Dimensions Scanner

Posted:

I work on a project that handles images with very high pixel resolutions.  Loading one of these images into memory for editing can be extremely memory-intensive.  To illustrate this to the client I needed to figure out what the largest-by-pixels image in a given set was, so that I could do some calculations on a real-world example.  With DeepAI's assistance I came up with this script that will scan all images within a directory and its subdirectories to collect the images' dimensions, calculate their areas, and sort the list by image area.

The more files you have to scan, the slower this will run of course.  The test case for which I created this contained 27,668 files in 279 directories, totallying 100 GB, and took 18 minutes to run its course.

Save this script to a file named scan_images.ps1, then run it from PowerShell.

# Image Dimensions Scanner # (C)2025 The House of Waffles # www.houseofwaffles.net # # Created 2025.05.09 # Modified 2025.06.28 # # Usage: # .\scan_images.ps1 # or # .\scan_images.ps1 -dir "C:\Path\To\Images"

param( [string]$dir = $PSScriptRoot, # Optional parameter for alternate directory; defaults to script location [string]$dump = "scan_results.csv" )
# Start measuring elapsed time $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
Write-Host "Preparing to scan..."
# Resolve the scan directory (for scanning) $scanDir = Resolve-Path -Path $dir
# Define output files in the script's directory $scriptDir = $PSScriptRoot $csvFile = Join-Path -Path $scriptDir -ChildPath $dump
# Check if output CSV is writable (or can be created) try { "" | Out-File -FilePath $csvFile -Encoding utf8 -Force } catch { Write-Error "Cannot write to CSV file: $csvFile. $_" exit 1 }
# Load the System.Drawing assembly for image processing Add-Type -AssemblyName System.Drawing
# Get all image files in the specified directory Write-Host "Scanning for files..." $images = Get-ChildItem -Path $scanDir -Include *.bmp, *.gif, *.jpeg, *.jpg, *.png, *.tiff -File -Recurse $total = $images.Count $i = 0
$results = foreach ($img in $images) { $i++ try { $imgObj = [System.Drawing.Image]::FromFile($img.FullName) $width = $imgObj.Width $height = $imgObj.Height $totalPixels = $width * $height $imgObj.Dispose()
[PSCustomObject]@{ Path = $img.FullName Width = $width Height = $height TotalPixels = $totalPixels } } catch { Write-Warning "Failed to process $($img.FullName): $_" # Skip adding to results if processing fails }
if ($i % 100 -eq 0) { # Write-Host "Processed $i of $total images..." Write-Host ("Processed {0:N0} of {1:N0} images..." -f $i, $total) } }
# Sort results by TotalPixels descending Write-Host "Sorting results..." $sortedResults = $results | Sort-Object -Property TotalPixels -Descending
# Export results to CSV in the script's directory $sortedResults | Export-Csv -Path $csvFile -NoTypeInformation -Encoding utf8
# Stop the stopwatch and output elapsed time $stopwatch.Stop() $elapsed = $stopwatch.Elapsed Write-Host "Scan complete in $($elapsed.Hours)h $($elapsed.Minutes)m $($elapsed.Seconds)s." Write-Host "Results saved to: $csvFile"

Usage:  Scan from current directory:

.\scan_images.ps1

or specify an alternate base directory:

.\scan_images.ps1 -dir "C:\Path\To\Images"

A CSV file is output, the contents of which may look something like this (number formatting added here):

PathWidthHeightTotalPixels
C:\Sample\1971-1992\1981\1971-1992\1980\1980_scan_0045.jpg14,96211,102166,108,124
C:\Sample\1971-1992\1981\1981_scan_0001_69.jpg13,8548,492117,648,168
C:\Sample\1971-1992\1981\1981_scan_0001_68.jpg13,8668,416116,696,256
C:\Sample\1995-2008\1997\scan_0030.jpg8,92912,406110,773,174
C:\Sample\1995-2008\1995\1995_95-78.jpg9,4448,41679,480,704

(I was then able to show the client that an application that allocates 8 bytes per pixel, like his project uses, would need over 1.2 gigabytes to process a fully decompressed image that is 14,962 pixels wide by 11,102 pixels tall.)