Change Image Size Using Microsoft PowerShell

Ray Turner
Ray Turner used Ask the Experts™
on
I have a set of photos that where taken using a typical 35mm camera to be displayed on a website.  The jpg's are quite large and I'd like to reduced the size of each of the photos before uploading them.  Is there a to shrink the size of the files using Microsoft PowerShell?

If so,  please provide the code.

Thanks
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Sam Simon NasserIT Support Professional

Commented:
if you have Photoshop, you can do batch processing (https://digital-photography-school.com/how-to-batch-resize-in-photoshop/)
or you use photo resizer software (https://www.faststone.org/FSResizerDetail.htm)
in my opinion, you don't need complex code to do that!
NoahHardware Tester and Debugger

Commented:
Hi there! :)

You may refer to this file for an example. You can view and edit it with Notepad++.

Resize-Image.psm1
Shaun VermaakSenior Consultant
Awarded 2017
Distinguished Expert 2018

Commented:
I have used TinyPNG API (yes it supports JPEG), 500 free per month and you do not need to resize or lose quality
https://github.com/TobiasWust/TinyPNG-batch
Ray TurnerSenior Consultant

Author

Commented:
For my clarification.  I only want to reduce the size of the file without changing its dimensions.  Can this be done with the PowerShell script?
Shaun VermaakSenior Consultant
Awarded 2017
Distinguished Expert 2018

Commented:
I understand your requirements. That is what TinyPNG is for. Visit their site
https://tinypng.com/
NoahHardware Tester and Debugger

Commented:
Sorry, I misunderstood your question. The Powershell script resizes the resolution.
Most Valuable Expert 2018
Distinguished Expert 2018
Commented:
PowerShell approach, using .NET; save as Convert-ImageQuality.ps1 or Whatever.ps1
Get-Help is supported, so you can run Get-Help .\Convert-ImageQuality.ps1 -ShowWindow once the script is saved.
<#
.SYNOPSIS
Reduces the size of an image by lowering its quality and saving it as .jpg.
.DESCRIPTION
The function Convert-ImageQuality reduces the size of an image by lowering its quality and saving it as .jpg.
By default, the converted images are by default stored in the original directory, with a suffix indicating the quality used.
An output directory to store the converted pictures in can be specified using the -Destination parameter.
.PARAMETER Path
The path to the image(s) to convert. You can specify a folder or file names, or objects returned from Get-item or Get-ChildItem (anything Get-ChildItem accepts as input).
Files that can not be opened as image will be skipped, and a warning written.
You can pipe objects to this parameter.
.PARAMETER Quality
The level of compression (0-100).
The lower the number specified, the higher the compression and therefore the lower the quality of the image. Zero would give you the lowest quality image and 100 the highest.
.PARAMETER Suffix
The suffix that will be attached to the original file's BaseName.
Use the placeholder %Quality% to insert the selected quality as a three-digit number with leading zeros, if required.
.PARAMETER Destination
The target directory for the converted image(s); the directory must exist before running the function.
Default is the original image's directory.
.EXAMPLE
'C:\Windows\Web\Screen' | .\Convert-ImageQuality.ps1 -Quality 50 -Destination C:\Temp\Reduced -Verbose
Will save all images from 'C:\Windows\Web\Screen' to 'C:\Temp\Reduced' as jpg with a quality of 50, adding "_050" (the default suffix which adds the quality) to each file name.
.LINK
Image.Save Method
https://docs.microsoft.com/en-us/dotnet/api/system.drawing.image.save
#>
[CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName='Width_Locked', ConfirmImpact='Low')]
Param(
	[Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
	[PSObject]$Path = (Get-Location -PSProvider FileSystem).Path,
	[ValidateRange(0, 100)]
	[Parameter(Mandatory=$true)]
	[Int]$Quality,
	[Parameter()]
	[String]$Suffix = '_%Quality%',
	[Parameter()]
	[ValidateScript({Test-Path -Path $_ -PathType Container})]
	[String]$Destination
)
Begin {
	Add-Type -AssemblyName System.Drawing
	$encoder = [System.Drawing.Imaging.Encoder]::Quality
	$encoderParams = New-Object -TypeName System.Drawing.Imaging.EncoderParameters -ArgumentList 1 
	$encoderParams.Param[0] = New-Object -TypeName System.Drawing.Imaging.EncoderParameter -ArgumentList $encoder, $Quality
	$imageCodecInfo = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object {$_.Clsid -eq '557cf401-1a04-11d3-9a73-0000f81ef32e'}
	$targetExt = '.jpg'
	If ($Suffix) {
		$Suffix = $Suffix -replace '%Quality%', $Quality.ToString('D3')
	}
}
Process {
	$Path | Get-ChildItem | ForEach-Object {
		Try {
			$item = $_
			$image = [System.Drawing.Image]::FromFile($item.FullName)
			$targetDir = If ($Destination) {$Destination} Else {$item.DirectoryName}
			If ($PSCmdlet.ShouldProcess($item.FullName, "Convert quality to $($Quality)% of the original")) {
				[void]$image.Save("$($targetDir)\$($item.BaseName)$($Suffix)$($targetExt)", $imageCodecInfo, $encoderParams)
				[void]$image.Dispose()
			}
		} Catch {
			If ($_.Exception.InnerException.StackTrace -like '*System.Drawing.Image.FromFile*') {
				Write-Warning "[$($MyInvocation.MyCommand.Name)] Not an image: '$($item.FullName)'"
			} Else {
				$PSCmdlet.WriteError($_)
			}
		}
	}
}

Open in new window

Shaun VermaakSenior Consultant
Awarded 2017
Distinguished Expert 2018

Commented:
Better of using TinyPNG API IMO if you want lowest size without loss in quality

Original (57kb)
example-orig.png
Using Convert-ImageQuality.ps1  (6kb but looks crap and lost transparency)
example-orig_050.jpg
Using TinyPNG (15kb no visual difference)
example-shrunk.png
Ray TurnerSenior Consultant

Author

Commented:
Thanks!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial