|
# --------------------------------------------------------- |
|
# Thumbnail Generator with Aspect Ratio Control (PowerShell) |
|
# --------------------------------------------------------- |
|
|
|
# Remove old thumbnails |
|
Remove-Item *-thumb.webp -Force -ErrorAction SilentlyContinue |
|
Remove-Item *-thumb.png -Force -ErrorAction SilentlyContinue |
|
|
|
# Aspect ratio mapping for specific images |
|
$aspectRatios = @{ |
|
"lr-demo-img-01" = "9:16" |
|
"lr-demo-img-02" = "16:9" |
|
# Add more mappings here if needed |
|
} |
|
|
|
# === Configuration === |
|
$fixedWidth = 400 # Width for all thumbnails |
|
$pngQuality = 1 # PNG: 1 (best) to 31 (worst) |
|
$webpQuality = 96 # WebP: 0 (worst) to 100 (best) |
|
|
|
# Optional: force all images to use this aspect ratio (e.g. "1:1") |
|
# Set to $null to disable global override |
|
$forceAspectRatio = $null |
|
# ====================== |
|
|
|
# Process each image |
|
Get-ChildItem -File | Where-Object { $_.Extension -match "\.(jpg|png|webp)$" } | ForEach-Object { |
|
$originalPath = $_.FullName |
|
$filename = $_.Name |
|
$cleanName = $_.BaseName |
|
|
|
try { |
|
# Get original dimensions |
|
$width = ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=p=0 "`"$originalPath`"" |
|
$height = ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=p=0 "`"$originalPath`"" |
|
$width = [int]$width |
|
$height = [int]$height |
|
|
|
if ($width -eq 0 -or $height -eq 0) { |
|
Write-Output "Error: Could not retrieve dimensions for $filename. Skipping." |
|
return |
|
} |
|
} catch { |
|
Write-Output "Error: Failed to run ffprobe on $filename. Skipping." |
|
return |
|
} |
|
|
|
$vfFilter = "" |
|
|
|
if ($forceAspectRatio) { |
|
$aspectRatio = $forceAspectRatio |
|
Write-Output "Processing $filename with GLOBAL FORCED aspect ratio $aspectRatio" |
|
} elseif ($aspectRatios.ContainsKey($cleanName)) { |
|
$aspectRatio = $aspectRatios[$cleanName] |
|
Write-Output "Processing $filename with MAPPED aspect ratio $aspectRatio" |
|
} else { |
|
Write-Output "Processing $filename with ORIGINAL aspect ratio (not in list)" |
|
$scaledHeight = [math]::Ceiling($fixedWidth * ($height / $width)) |
|
$vfFilter = "scale=${fixedWidth}:${scaledHeight},setsar=1" |
|
} |
|
|
|
if (-not $vfFilter) { |
|
# Aspect ratio logic |
|
$ratioParts = $aspectRatio -split ":" |
|
$aspectWidth = [int]$ratioParts[0] |
|
$aspectHeight = [int]$ratioParts[1] |
|
$targetHeight = [math]::Ceiling($fixedWidth * ($aspectHeight / $aspectWidth)) |
|
|
|
$OAR = $width / $height |
|
$TAR = $aspectWidth / $aspectHeight |
|
|
|
if ([math]::Round($OAR, 2) -eq [math]::Round($TAR, 2)) { |
|
$vfFilter = "scale=${fixedWidth}:-2,setsar=1" |
|
} elseif ($OAR -gt $TAR) { |
|
$vfFilter = "scale=-2:${targetHeight},crop=${fixedWidth}:${targetHeight}:(iw-${fixedWidth})/2:0,setsar=1" |
|
} else { |
|
$vfFilter = "scale=${fixedWidth}:-2,crop=${fixedWidth}:${targetHeight}:0:(ih-${targetHeight})/2,setsar=1" |
|
} |
|
} |
|
|
|
# Output file paths |
|
$outputPathPng = "$cleanName-thumb.png" |
|
$outputPathWebp = "$cleanName-thumb.webp" |
|
|
|
# FFmpeg commands with quality settings |
|
$ffmpegCommandPng = "ffmpeg -i `"$originalPath`" -vf `"$vfFilter`" -q:v ${pngQuality} `"$outputPathPng`" -y" |
|
$ffmpegCommandWebp = "ffmpeg -i `"$originalPath`" -vf `"$vfFilter`" -q:v ${webpQuality} `"$outputPathWebp`" -y" |
|
|
|
try { |
|
Invoke-Expression $ffmpegCommandPng |
|
Invoke-Expression $ffmpegCommandWebp |
|
Write-Output "✔️ Successfully created thumbnails for $filename" |
|
} catch { |
|
Write-Output "❌ Error generating thumbnails for $filename : $_" |
|
} |
|
} |
|
|
|
Write-Output "`n✅ Thumbnail generation complete." |