Skip to content

Instantly share code, notes, and snippets.

@Timberfang
Last active August 22, 2022 12:24
Show Gist options
  • Save Timberfang/249e3a3093c7ecea0f0c56bf0793e185 to your computer and use it in GitHub Desktop.
Save Timberfang/249e3a3093c7ecea0f0c56bf0793e185 to your computer and use it in GitHub Desktop.
Convert images to other formats using ImageMagick.
Set-StrictMode -Version 3.0
#Requires -Version 5.1
Function Invoke-Mogrify {
<#
.SYNOPSIS
Convert images to other formats using ImageMagick.
.DESCRIPTION
This function will convert given images into the specified format.
The converted images will be saved to the same location as the original images by default.
While PowerShell 5.1 is supported, use ofPowerShell 7 is strongly recommended due to a
large speed increase in image processing times.
.PARAMETER Path
Source directory or directories files will be taken from.
Must be a valid path that exists on the computer.
.PARAMETER Format
Target format for images.
.PARAMETER Destination
Destination directory converted images will be placed in.
.PARAMETER Filter
Regex Filter to search by for files to convert.
Use to only convert only certain files, instead of the full contents of the source folders.
.EXAMPLE
Invoke-Mogrify -Path $PSScriptRoot\Input -Destination $PSScriptRoot\Output -Format PNG
Convert all pictures from one folder into PNG images.
.EXAMPLE
Invoke-Mogrify -Path $PSScriptRoot\Input,~\Gallery,~\user\pictures -Destination $PSScriptRoot\Output -Format jpg
Convert all pictures from multiple folders into jpg images.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory,ValueFromPipeline)]
[string]$Path,
[Parameter(Mandatory)]
[string]$Format,
[string]$Destination = $Path,
[string]$Filter = '.'
)
begin {
Write-Verbose -Message "Checking for ImageMagick."
if ($null -eq (Get-Command "magick" -ErrorAction SilentlyContinue)) {
Throw "ImageMagick not installed. Please install ImageMagick."
}
else {
Write-Verbose -Message "ImageMagick is installed."
}
}
process {
foreach ($Directory in $Path) {
Write-Verbose -Message "Renaming .jfif & .jpeg files to .jpg."
Get-ChildItem $Directory\* -Include ('*.jfif', '*.jpeg') | Rename-Item -NewName { $_.Name -Replace "\.(jfif|jpeg)$", ".jpg" }
Write-Verbose -Message "Searching for files..."
Get-ChildItem $Directory\* -Filter "$Filter" -Recurse -Include "*.$Format" | Move-Item -Destination $Destination
}
<# ImageMagick normally converts ALL images, even if they are already in the target format.
This will reduce quality if converting to lossy formats such as jpg.
ImageMagick does not have a parameter to filter out images, so Where-Object is used.
This does run about 25% more slowly than sending all images to ImageMagick, unfortunately.
This can be fixed on systems running at least PowerShell 7,
as the command can then be run in parallel. #>
# Still want to support 5.1, so the script will fall back to a slower sequential method when needed.
Write-Verbose -Message "Converting images to $Format"
if ($PSVersionTable.PSVersion -ge 7) {
Get-ChildItem $Path\* | Where-Object {
$_.Extension -match 'jpg' -or 'png' -or 'heic' -or 'webp' -or 'tiff' -and
$_.Extension -notmatch "$Format"
} | Foreach-Object -ThrottleLimit 5 -Parallel {
magick mogrify -path $USING:Destination -format $USING:Format $_ -define preserve-timestamp=true
}
}
else {
Get-ChildItem $Path\* | Where-Object {
$_.Extension -match 'jpg' -or 'png' -or 'heic' -or 'webp' -or 'tiff' -and
$_.Extension -notmatch "$Format"
} | ForEach-Object {
magick mogrify -path $Destination -format $Format $_ -define preserve-timestamp=true
}
}
}
end {
Write-Verbose -Message "Images Converted."
Write-Output -InputObject (Get-ChildItem $Destination\*.$Format -File)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment