99 lines
3.3 KiB
PowerShell
99 lines
3.3 KiB
PowerShell
# Explorer context-menu helper: resize images (single file, multiple files, or folder tree) via media-img.exe
|
|
# Multi-select: Explorer uses MultiSelectModel Player + %* — this script receives all paths in one invocation.
|
|
# Uses Start-Process -WindowStyle Hidden so no console window (VIPS stderr is redirected to a temp file).
|
|
param(
|
|
[Parameter(Mandatory)][string]$MediaImg,
|
|
[Parameter(Mandatory)][int]$MaxWidth,
|
|
[Parameter(Mandatory)][ValidateSet('InPlace', 'Copy')][string]$Mode,
|
|
[Parameter(Mandatory, ValueFromRemainingArguments = $true)][string[]]$InputPaths
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$InputPaths = @($InputPaths | Where-Object { $_ -and $_.Trim() -ne '' })
|
|
if ($InputPaths.Length -eq 0) {
|
|
exit 1
|
|
}
|
|
|
|
# Canonical list — keep in sync with register_explorer.cpp (k_canonical_ext + case-insensitive match)
|
|
$imageExt = @(
|
|
'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.tiff', '.tif', '.jpe', '.jfif',
|
|
'.avif', '.arw'
|
|
)
|
|
|
|
function Test-ImageExt([string]$ext) {
|
|
$e = $ext.ToLowerInvariant()
|
|
return $script:imageExt -contains $e
|
|
}
|
|
|
|
function Invoke-MediaImgResize([string[]]$ArgList) {
|
|
$outF = [System.IO.Path]::GetTempFileName()
|
|
$errF = [System.IO.Path]::GetTempFileName()
|
|
try {
|
|
$p = Start-Process -FilePath $MediaImg -ArgumentList $ArgList -Wait -PassThru `
|
|
-WindowStyle Hidden -RedirectStandardOutput $outF -RedirectStandardError $errF
|
|
if ($p.ExitCode -ne 0) {
|
|
$e = if (Test-Path -LiteralPath $errF) { Get-Content -Raw -LiteralPath $errF } else { '' }
|
|
throw "media-img failed (exit $($p.ExitCode)): $e"
|
|
}
|
|
}
|
|
finally {
|
|
Remove-Item -LiteralPath $outF, $errF -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
function Resize-SingleFile([string]$File) {
|
|
$w = $MaxWidth
|
|
if ($Mode -eq 'Copy') {
|
|
$dst = '${SRC_DIR}/${SRC_NAME}_' + $w + '${SRC_FILE_EXT}'
|
|
Invoke-MediaImgResize @('resize', '--src', $File, '--dst', $dst, '--max-width', "$w", '--fit', 'inside', '--no-cache')
|
|
}
|
|
else {
|
|
$ext = [System.IO.Path]::GetExtension($File)
|
|
$tmp = Join-Path $env:TEMP ('media-img-' + [Guid]::NewGuid().ToString('n') + $ext)
|
|
try {
|
|
Invoke-MediaImgResize @('resize', '--src', $File, '--dst', $tmp, '--max-width', "$w", '--fit', 'inside', '--no-cache')
|
|
Move-Item -LiteralPath $tmp -Destination $File -Force
|
|
}
|
|
finally {
|
|
if (Test-Path -LiteralPath $tmp) {
|
|
Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Process-OnePath([string]$Path) {
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
|
exit 1
|
|
}
|
|
$item = Get-Item -LiteralPath $Path
|
|
if ($item.PSIsContainer) {
|
|
$files = Get-ChildItem -LiteralPath $Path -Recurse -File -ErrorAction Stop |
|
|
Where-Object { Test-ImageExt $_.Extension }
|
|
if (-not $files) {
|
|
exit 0
|
|
}
|
|
foreach ($f in $files) {
|
|
Resize-SingleFile $f.FullName
|
|
}
|
|
}
|
|
else {
|
|
if (-not (Test-ImageExt $item.Extension)) {
|
|
exit 0
|
|
}
|
|
Resize-SingleFile $item.FullName
|
|
}
|
|
}
|
|
|
|
if ($InputPaths.Length -gt 1) {
|
|
foreach ($p in $InputPaths) {
|
|
Process-OnePath $p
|
|
}
|
|
exit 0
|
|
}
|
|
|
|
Process-OnePath $InputPaths[0]
|
|
exit 0
|