forked from DavidAnson/ConvertTo-Jpeg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ConvertTo-Jpeg.ps1
113 lines (106 loc) · 4.89 KB
/
ConvertTo-Jpeg.ps1
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# ConvertTo-Jpeg - Converts RAW (and other) image files to the widely-supported JPEG format
# https://github.com/DavidAnson/ConvertTo-Jpeg
Param (
[Parameter(
Mandatory = $true,
Position = 1,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
ValueFromRemainingArguments = $true,
HelpMessage = "Array of image file names to convert to JPEG")]
[Alias("FullName")]
[String[]]
$Files,
[Parameter(
HelpMessage = "Fix extension of JPEG files without the .jpg extension")]
[Switch]
$FixExtensionIfJpeg
)
Begin
{
# Technique for await-ing WinRT APIs: https://fleexlab.blogspot.com/2018/02/using-winrts-iasyncoperation-in.html
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$runtimeMethods = [System.WindowsRuntimeSystemExtensions].GetMethods()
$asTaskGeneric = ($runtimeMethods | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0]
Function AwaitOperation ($WinRtTask, $ResultType)
{
$asTaskSpecific = $asTaskGeneric.MakeGenericMethod($ResultType)
$netTask = $asTaskSpecific.Invoke($null, @($WinRtTask))
$netTask.Wait() | Out-Null
$netTask.Result
}
$asTask = ($runtimeMethods | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncAction' })[0]
Function AwaitAction ($WinRtTask)
{
$netTask = $asTask.Invoke($null, @($WinRtTask))
$netTask.Wait() | Out-Null
}
# Reference WinRT assemblies
[Windows.Storage.StorageFile, Windows.Storage, ContentType=WindowsRuntime] | Out-Null
[Windows.Graphics.Imaging.BitmapDecoder, Windows.Graphics, ContentType=WindowsRuntime] | Out-Null
}
Process
{
# Summary of imaging APIs: https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/imaging
foreach ($file in $Files)
{
Write-Host $file -NoNewline
try
{
try
{
# Get SoftwareBitmap from input file
$file = Resolve-Path -LiteralPath $file
$inputFile = AwaitOperation ([Windows.Storage.StorageFile]::GetFileFromPathAsync($file)) ([Windows.Storage.StorageFile])
$inputFolder = AwaitOperation ($inputFile.GetParentAsync()) ([Windows.Storage.StorageFolder])
$inputStream = AwaitOperation ($inputFile.OpenReadAsync()) ([Windows.Storage.Streams.IRandomAccessStreamWithContentType])
$decoder = AwaitOperation ([Windows.Graphics.Imaging.BitmapDecoder]::CreateAsync($inputStream)) ([Windows.Graphics.Imaging.BitmapDecoder])
}
catch
{
# Ignore non-image files
Write-Host " [Unsupported]"
continue
}
if ($decoder.DecoderInformation.CodecId -eq [Windows.Graphics.Imaging.BitmapDecoder]::JpegDecoderId)
{
$extension = $inputFile.FileType
if ($FixExtensionIfJpeg -and ($extension -ne ".jpg") -and ($extension -ne ".jpeg"))
{
# Rename JPEG-encoded files to have ".jpg" extension
$newName = $inputFile.Name -replace ($extension + "$"), ".jpg"
AwaitAction ($inputFile.RenameAsync($newName))
Write-Host " => $newName"
}
else
{
# Skip JPEG-encoded files
Write-Host " [Already JPEG]"
}
continue
}
$bitmap = AwaitOperation ($decoder.GetSoftwareBitmapAsync()) ([Windows.Graphics.Imaging.SoftwareBitmap])
# Write SoftwareBitmap to output file
$outputFileName = $inputFile.Name + ".jpg";
$outputFile = AwaitOperation ($inputFolder.CreateFileAsync($outputFileName, [Windows.Storage.CreationCollisionOption]::ReplaceExisting)) ([Windows.Storage.StorageFile])
$outputStream = AwaitOperation ($outputFile.OpenAsync([Windows.Storage.FileAccessMode]::ReadWrite)) ([Windows.Storage.Streams.IRandomAccessStream])
$encoder = AwaitOperation ([Windows.Graphics.Imaging.BitmapEncoder]::CreateAsync([Windows.Graphics.Imaging.BitmapEncoder]::JpegEncoderId, $outputStream)) ([Windows.Graphics.Imaging.BitmapEncoder])
$encoder.SetSoftwareBitmap($bitmap)
$encoder.IsThumbnailGenerated = $true
# Do it
AwaitAction ($encoder.FlushAsync())
Write-Host " -> $outputFileName"
}
catch
{
# Report full details
throw $_.Exception.ToString()
}
finally
{
# Clean-up
if ($inputStream -ne $null) { [System.IDisposable]$inputStream.Dispose() }
if ($outputStream -ne $null) { [System.IDisposable]$outputStream.Dispose() }
}
}
}