-
Notifications
You must be signed in to change notification settings - Fork 0
/
Powershell Optimize Compress Images Photos in Batch
94 lines (84 loc) · 4.89 KB
/
Powershell Optimize Compress Images Photos in Batch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#### You will need to install or use a portable version of imagemagick (for images) and ffmpeg (for videos)
#### https://imagemagick.org/script/download.php
#### https://ffmpeg.org/download.html
####
#### Script is created to optimize videos and photos from mid-range phones. For high quality photos and videos,
#### I would recommend increasing some of the values. Feel free to experiment with the settings to get the optimal results.
####
#### To run this script, you can invoke it like this:
#### powershell C:\Path\NameOfThisScript.ps1 'C:\Path\A folder with photos/videos' 'C:\Path\LogFile.csv'
#### It will then process all jpgs and pngs in the "A folder with photos/videos" in C:\Path
#### The LogFile is optional. If not needed, but it helps not to process the same files again. To run without it, run command like this
#### powershell C:\Path\NameOfThisScript.ps1 'C:\Path\A folder with photos/videos'
####
#### The script will pause at the end with a summary table
#### If you don't want that (i.e. this script will run everyday at midnight) then remove the "pause" at the end
####
#### Most credits goes to https://gist.github.com/craigmaslowski as I based this script on his, adding some elements.
#### if you're using a portable version of Magick and ffmpeg then you need to specify the path, if installed just leave it as "Magick" or "ffmpeg"
$magick = "C:\Users\{username}\source\Magick\magick.exe" #path to portable
$magick = "magick" #installed
$magick = "C:\Users\{username}\source\ffmpeg\bin\ffmpeg.exe" #path to portable
$magick = "FFmpeg" #installed
param([string]$path, [string]$Outputfile)
function Get-Size
{
param([string]$pth)
(gci -path $pth -recurse | measure-object -property length -sum).sum /1mb
}
function Compress-Media([string]$type, [string]$mode) {
$params = switch ($type) {
"*.jpg" { "-compress jpeg -quality 82" } #quality can be adjusted as needed
"*.png" { "-depth 24 -define png:compression-filter=2 -define png:compression-level=9 -define png:compression-strategy=1" }
#### 3 things to adjust here:
#### crf-higher means lower quality, lower size
#### preset-how long it takes to convert, can be changed to "fast", "medium", "slower" etc = longer transcoding, better quality, bigger size
#### b:a - quality of the audio - higher number means higher quality, bigger size
"*.avi,*.mp4,*.mkv" { "-y -c:v libx265 -crf 22 -preset superfast -fps_mode passthrough -c:a libopus -b:a 128k" }
}
foreach ($f in $type.Split(",")) {
$ToBeOptimized |
Where {$_.FullName -ilike $f} |
ForEach-Object {
$file = $_.FullName
$InitialSize = Get-Size($file)
switch($mode) {
"Image" {iex "$magick '$file' $params '$file'"} # compress image
"Video" {$tempfile = "$file 2.mp4"
iex "$FFmpeg -i '$file' $params '$tempfile'" #compress video
$correcttimestamp = (gi $file | foreach {@($_.CreationTime, $_.LastAccessTime, $_.LastWriteTime)} | sort )[0]
(gi $tempfile).creationtime = $correcttimestamp
move $tempfile $file -Force
}
}
$EndSize = Get-Size($file)
$Row = New-Object PSObject
$Row | Add-Member -MemberType NoteProperty -Name Path -Value $file
$Row | Add-Member -MemberType NoteProperty -Name Time -Value $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")
$Row | Add-Member -MemberType NoteProperty -Name SizeBeforeMB -Value $InitialSize
$Row | Add-Member -MemberType NoteProperty -Name SizeAfterMB -Value $EndSize
$optimizedlist.Add($Row)
# if log file is specified, it will log the info about optimized images and videos
if($Outputfile.Length -gt 0) {$Row | Export-Csv -LiteralPath $Outputfile -NoTypeInformation -Append -Force -Encoding UTF8}
}
}
}
#checks if Log file is specified. If it is, and the file is missing, it will create it
$usingLogfile = $Outputfile.Length -gt 0
if($usingLogfile) {
$excludedlist = try {Import-Csv -LiteralPath $Outputfile}
catch {'"Path","Time","SizeBeforeMB","SizeAfterMB"' | Set-Content $Outputfile}
}
$ListOfFiles = Get-ChildItem $path -Recurse -Include *.jpg, *.png, *.avi, *.mp4, *.mkv
$ToBeOptimized = $ListOfFiles | where {$_.FullName -inotin $excludedlist.Path} #checks if the file is in the log file so it doesn't process it twice
$optimizedlist = New-Object collections.arraylist
#compress images, first jpgs then pngs
Compress-Media "*.jpg" "image"
Compress-Media "*.png" "image"
Compress-Media "*.avi,*.mp4,*.mkv" "video"
$optimizedlist
# removes information from log file for items that doesn't exists
if($usingLogfile) {$Content = Import-Csv -LiteralPath $Outputfile |
where {$_.Path -iin $ListOfFiles.FullName}}
if($usingLogfile) {$Content | Export-Csv -LiteralPath $Outputfile -NoTypeInformation -Force -Encoding UTF8}
pause