Powershell: Bilder verkleinern oder an bestimmte Größe anpassen
Für alle die es gebrauchen können:
Native Powershell-Funktion zum Anpassen der Größe von Bildern der Formate *.jpg / *.png / *.gif / *.tiff / *.bmp ohne zusätzliche Tools mit .NET inkl. Pipeline-Support.
Der optionale Parameter
Der optionale switch Parameter
Viel Spaß damit
Grüße @colinardo
Native Powershell-Funktion zum Anpassen der Größe von Bildern der Formate *.jpg / *.png / *.gif / *.tiff / *.bmp ohne zusätzliche Tools mit .NET inkl. Pipeline-Support.
Powershell-CMDLet Resize-Image für das Anpassen der Größe von Bildern.
function Resize-Image{
param(
[parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName='A')][parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName='B')][alias("FullName")][string[]]$images,
[parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName='A')][parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName='B')][alias("DirectoryName")][string]$OutPath,
[parameter(mandatory=$true,ParameterSetName='A')][parameter(mandatory=$true,ParameterSetName='B')][int32]$NewWidth,
[parameter(mandatory=$true,ParameterSetName='A')][parameter(mandatory=$true,ParameterSetName='B')][int32]$NewHeight,
[parameter(mandatory=$false,ParameterSetName='A')][switch]$AppendSizeToFilename,
[parameter(mandatory=$true,ParameterSetName='B')][switch]$ReplaceOriginal,
[parameter(mandatory=$false)][switch]$DownSizeOnly,
[parameter(mandatory=$false)][ValidateSet('Original','Scale')][string]$AspectRatio = 'Original',
[parameter(mandatory=$false)][switch]$RotateByExifOrientation
)
begin{
Add-Type -AssemblyName System.Drawing
if($rotatebyexiforientation.IsPresent){
$shell = New-Object -com Shell.Application
}
}
process{
foreach($imagepath in $images){
$finfo = Get-Item -LiteralPath $imagepath
$newImagePath = ""
if ($finfo.Extension -match "\.(bmp|jpe?g|gif|tiff?|png)$"){
Try{
$img = [System.Drawing.Bitmap]::FromFile($imagepath)
$percentWidth = $newWidth / $img.Width
$percentHeight = $newHeight / $img.Height
if ($percentWidth -lt $percentHeight){$ratio = $percentWidth}else{$ratio = $percentHeight}
switch ($aspectratio){
'Original' {
[int32]$nWidth = $img.Width * $ratio
[int32]$nHeight = $img.Height * $ratio
}
'Scale' {
[int32]$nWidth = $newWidth
[int32]$nHeight = $newHeight
}
}
if ($replaceoriginal.IsPresent -and $ratio -ge 1){
continue
}
if($DownSizeOnly.IsPresent -and $ratio -ge 1){
if (!(Test-Path -LiteralPath (join-path $outPath $finfo.Name))){
copy-item -LiteralPath $imagepath -Destination $outPath
}else{
Write-Warning "Image '$($finfo.Name)' already exists in destination directory, skipping image."
}
continue
}
$newImg = new-Object System.Drawing.Bitmap($nWidth,$nHeight)
([System.Drawing.Graphics]::FromImage($newImg)).DrawImage($img,0,0,$newImg.Width,$newImg.Height)
# respect exif orientation information if desired
if($rotatebyexiforientation.IsPresent){
# get rotation information (https:{{comment_single_line_double_slash:0}}
[int]$rotation = $shell.NameSpace($finfo.DirectoryName).ParseName($finfo.Name).ExtendedProperty("{14B81DA1-0135-4D31-96D9-6CBFC9671A99} 274")
# rotate image when needed
switch -Regex ($rotation){
6 {$newImg.RotateFlip([System.Drawing.RotateFlipType]::Rotate90FlipNone);$oldw = $nWidth; $nWidth = $nHeight; $nHeight = $oldw}
8 {$newImg.RotateFlip([System.Drawing.RotateFlipType]::Rotate270FlipNone);$oldw = $nWidth; $nWidth = $nHeight; $nHeight = $oldw}
3 {$newImg.RotateFlip([System.Drawing.RotateFlipType]::Rotate180FlipNone)}
}
}
if ($replaceoriginal.IsPresent){
$newImagePath = Join-Path $outPath ([IO.Path]::GetRandomFileName())
while(Test-Path $newImagePath){
$newImagePath = Join-Path $outPath ([IO.Path]::GetRandomFileName())
}
}elseif($AppendSizeToFilename.IsPresent){
$newImagePath = join-path $outPath "$($finfo.Basename)_${nWidth}x${nHeight}$($finfo.Extension)"
}else{
$newImagePath = join-path $outPath $finfo.Name
}
if(!(Test-Path $outPath)){new-item -ItemType Dir -Path $outPath -Force}
$newImg.Save($newImagePath,$img.RawFormat)
if ($replaceoriginal.IsPresent){
$img.Dispose()
Remove-Item -LiteralPath $imagepath -Force
Rename-Item -LiteralPath $newImagePath -NewName $finfo.Name
}
}catch{
Write-Error -Message $_.Exception.Message
}finally{
if ($img){$img.Dispose()}
if ($newImg){$newImg.Dispose()}
}
}else{
Write-Error -Message "The image '$imagepath' uses an unsupported format. Only the following image types are supported: bmp|jpg|gif|tif|png"
}
}
}
end{
if ($img){$img.Dispose()}
if ($newImg){$newImg.Dispose()}
[System.GC]::Collect()
}
}
Anwendungsbeispiele
Alle jpg's eines Ordners unter Beibehaltung des Seitenverhältnisses auf 800x600 Pixel (nur verkleinern) und im Pfad "D:\Bilder\klein" speichern
Get-ChildItem -Path "D:\Bilder\*.jpg" -File | Resize-Image -OutPath "D:\Bilder\klein" -NewWidth 800 -NewHeight 600 -DownSizeOnly
Alle jpg's eines Ordners inkl. Unterordner unter Beibehaltung des Seitenverhältnisses auf 800x600 Pixel (nur verkleinern) und im Pfad "D:\Bilder\klein" speichern und dem Namen des Bildes die neue Größe anhängen.
Get-ChildItem -Path "D:\Bilder" -File -Filter *.jpg -recurse | Resize-Image -OutPath "D:\Bilder\klein" -NewWidth 800 -NewHeight 600 -DownSizeOnly -AppendSizeToFileName
Alle jpg's und png's eines Ordners inkl. Unterordner unter Beibehaltung des Seitenverhältnisses auf 800x600 Pixel anpassen und im Pfad "D:\Bilder\klein" speichern und dem Namen des Bildes die neue Größe anhängen.
Get-ChildItem -Path "D:\Bilder" -include "*.jpg","*.png" -recurse -file | Resize-Image -OutPath "D:\Bilder\klein" -NewWidth 800 -NewHeight 600 -AppendSizeToFileName
Ein einzelnes Bild unter Beibehaltung des Seitenverhältnisses auf 320x240 Pixel anpassen und im Pfad "D:\Bilder\klein" speichern.
Resize-Image -images "D:\Bilder\testbild.jpg" -OutPath "D:\Bilder\klein" -NewWidth 320 -NewHeight 240
Alle Bilder einer Ordnerstruktur unter Beibehaltung des Seitenverhältnisses auf 320x240 Pixel anpassen und das Original ersetzen.
Get-ChildItem -Path "D:\Bilder" -include "*.jpg","*.png" -recurse -file | Resize-Image -NewWidth 320 -NewHeight 240 -ReplaceOriginal
Der optionale Parameter
-AspectRatio
dient dazu das Seitenverhältnis des Originals entweder beizubehalten (Wert: Original
) oder das Bild auf die Zielgröße zu skalieren (Wert: Scale
).Der optionale switch Parameter
-RotateByExifOrientation
dient dazu das Bild anhand der Orientierungsinformationen (Rotation 90/180/270°) aus den EXIF-Daten zu rotieren.Viel Spaß damit
Grüße @colinardo
Please also mark the comments that contributed to the solution of the article
Content-Key: 268427
Url: https://administrator.de/contentid/268427
Printed on: April 18, 2024 at 04:04 o'clock
23 Comments
Latest comment
Vielen Dank für das Script!
Ich hatte nur das Problem, dass das Bild nicht gefunden wurde. Gelöst habe ich das dadurch, dass ich direkt den FullName übergebe. Damit liefs dann
Grüße
SirMank
Ich hatte nur das Problem, dass das Bild nicht gefunden wurde. Gelöst habe ich das dadurch, dass ich direkt den FullName übergebe. Damit liefs dann
(Get-ChildItem $Quelle -recurse).FullName| Resize-Image -OutPath $Ziel -NewWidth $MaxBreite -NewHeight $MaxHoehe -DownSizeOnly #Bilder aus Quelle und allen Unterordnern
Grüße
SirMank
Hallo Uwe,
danke für die schnelle Reaktion.
ich hab es direkt noch mal ausprobiert
Leider bekomme ich weiterhin die Fehlermeldung
Resize-Image : Ausnahme beim Aufrufen von "FromFile" mit 1 Argument(en): "2019-01-09 09_08_23.png"
Wenn ich direkt den FullName übergebe läuft der Aufruf durch.
Ich habe aber auch den Fullname nicht in den Atributen, wenn ich mir die Ausgabe von GCI an FL übergebe. Ist das vielleicht ein Problem von meinem System?
Grüße
SirMank
danke für die schnelle Reaktion.
ich hab es direkt noch mal ausprobiert
Get-ChildItem $Quelle -recurse| Resize-Image -OutPath $Ziel -NewWidth $MaxBreite -NewHeight $MaxHoehe -DownSizeOnly
Leider bekomme ich weiterhin die Fehlermeldung
Resize-Image : Ausnahme beim Aufrufen von "FromFile" mit 1 Argument(en): "2019-01-09 09_08_23.png"
Wenn ich direkt den FullName übergebe läuft der Aufruf durch.
Ich habe aber auch den Fullname nicht in den Atributen, wenn ich mir die Ausgabe von GCI an FL übergebe. Ist das vielleicht ein Problem von meinem System?
Grüße
SirMank
Hall colinardo
Besten Dank für dieses tolle Skript.
Eine kleine Frage:
Ich müsste eine grosse Menge von Bildern verarbeiten, welche in einer Ordnungsstruktur abgelegt sind. Haupt Ordner ist Fotos dann das Jahr, Monat und am Schluss dem jeweiligen Ereignis zugeteilt.
Gibt es die Möglichkeit, anstatt die Bilder in einen separaten Ordner komprimiert auszugeben, diese direkt wieder in den entsprechenden Pfad abzulegen und die originale zu löschen?
Ich habe mir schon überlegt, etwas zu schreiben, was dann den Namen, der komprimierten Dateien sucht und ersetzt.
Wenn es jedoch mit -OutPath gleich eine Möglichkeit gäbe, welche ich nicht kenne, wäre natürlich super.
Besten Dank schon mal fürs lesen.
Gruss vom Newbie
Demech
Besten Dank für dieses tolle Skript.
Eine kleine Frage:
Ich müsste eine grosse Menge von Bildern verarbeiten, welche in einer Ordnungsstruktur abgelegt sind. Haupt Ordner ist Fotos dann das Jahr, Monat und am Schluss dem jeweiligen Ereignis zugeteilt.
Gibt es die Möglichkeit, anstatt die Bilder in einen separaten Ordner komprimiert auszugeben, diese direkt wieder in den entsprechenden Pfad abzulegen und die originale zu löschen?
Ich habe mir schon überlegt, etwas zu schreiben, was dann den Namen, der komprimierten Dateien sucht und ersetzt.
Wenn es jedoch mit -OutPath gleich eine Möglichkeit gäbe, welche ich nicht kenne, wäre natürlich super.
Besten Dank schon mal fürs lesen.
Gruss vom Newbie
Demech
Hallo Uwe
Das ist perfekt. Habe es gleich ausprobiert. Funktioniert wunderbar und das beste ist, dass die Qualität der Bilder immer noch sehr gut bleibt.
Nun habe ich noch die Aufgabe vor mir, den Code zu studieren, damit ich auch verstehe, was da gemacht wird und etwas daraus lerne.
Besten Dank
Grüsse Bruno
Das ist perfekt. Habe es gleich ausprobiert. Funktioniert wunderbar und das beste ist, dass die Qualität der Bilder immer noch sehr gut bleibt.
Nun habe ich noch die Aufgabe vor mir, den Code zu studieren, damit ich auch verstehe, was da gemacht wird und etwas daraus lerne.
Besten Dank
Grüsse Bruno
Hi Colinardo
das ist ja ein super Script, vielen Dank.
Ich habe es eben ausprobiert und es hat funktioniert. Mir ist Aufgefallen, dass Bilder im Hochformat nun im Querformat dargestellt werden (gedreht), gibt es eine Möglichkeit dass die Ausrichtung beibehalten wird trotz dem verkleinern?
vielen Dank für deine Hilfe.
Tobi
das ist ja ein super Script, vielen Dank.
Ich habe es eben ausprobiert und es hat funktioniert. Mir ist Aufgefallen, dass Bilder im Hochformat nun im Querformat dargestellt werden (gedreht), gibt es eine Möglichkeit dass die Ausrichtung beibehalten wird trotz dem verkleinern?
vielen Dank für deine Hilfe.
Tobi
Hi Uwe,
vielen Dank für deine rasche Rückmeldung.
Ich habe eben eine komprimierte Datei angeschaut in den Details der Eigenschaften im Explorer. Dabei habe ich festgestellt das praktisch alle Werte verloren gingen. Es ist auch kein Wert mehr vorhanden in der EXIF-Version, kein Kameramodell, keine Brennweite usw.
Ich habe zwar nicht viel Ahnung von Programmierung, aber vlt. hast Du mir einen Tipp wie ich das angehen könnte, resp. wo suchen?
Viele Grüsse
Tobi
vielen Dank für deine rasche Rückmeldung.
Ich habe eben eine komprimierte Datei angeschaut in den Details der Eigenschaften im Explorer. Dabei habe ich festgestellt das praktisch alle Werte verloren gingen. Es ist auch kein Wert mehr vorhanden in der EXIF-Version, kein Kameramodell, keine Brennweite usw.
Ich habe zwar nicht viel Ahnung von Programmierung, aber vlt. hast Du mir einen Tipp wie ich das angehen könnte, resp. wo suchen?
Viele Grüsse
Tobi
Zitat von @colinardo:
Na das ist ja mal eine nette Anfrage 😐.
Discussion guidelines - The rules for our content
Zwischen Zeile 51 und 52 hinzufügen
Gruß @colinardo
Na das ist ja mal eine nette Anfrage 😐.
Discussion guidelines - The rules for our content
Zwischen Zeile 51 und 52 hinzufügen
(get-Item $newImagePath).CreationTime = (Get-Item $_).CreationTime
Hallo Colinardo,
Sorry dafür. War trotzdem sehr lieb und Nett, das du darauf geantwortet hast. Ich gelobe Besserung´.
Beste Grüße
@raffnix
Hallo colinardo,
das Skript ist echt genial, vor allem kann man es so individuell einsetzen und so auf fast jeden Einsatzzweck anpassen 👍👏
Was mir noch nicht klar ist, wodurch die Erhaltung des Seitenverhältnisses angegeben wird? Also wenn ich z.B. diese Beispiele vergleiche:
und
Bei dem ersten soll das Seitenverhältnis bestehen bleiben, beim anderen nicht. Welcher Parameter bestimmt das? Oder kommt das von dem replaceoriginal?
Gruß - Markus
das Skript ist echt genial, vor allem kann man es so individuell einsetzen und so auf fast jeden Einsatzzweck anpassen 👍👏
Was mir noch nicht klar ist, wodurch die Erhaltung des Seitenverhältnisses angegeben wird? Also wenn ich z.B. diese Beispiele vergleiche:
gci "D:\Bilder" -include "*.jpg","*.png" -recurse -file | Resize-Image -OutPath "D:\Bilder\klein" -NewWidth 800 -NewHeight 600 -AppendSizeToFileName
und
gci "D:\Bilder" -include "*.jpg","*.png" -recurse -file | Resize-Image -NewWidth 320 -NewHeight 240 -replaceoriginal
Bei dem ersten soll das Seitenverhältnis bestehen bleiben, beim anderen nicht. Welcher Parameter bestimmt das? Oder kommt das von dem replaceoriginal?
Gruß - Markus
Hi,
das Skript funktioniert super, nur das -replaceoriginal funktioniert bei mir nicht wie gewünscht.
Folgende Zeile habe ich zum, Test geschrieben:
Und dann kommt folgende Fehlermeldung
Was kann ich tun? Vielen Dank für die freundliche Hilfe
das Skript funktioniert super, nur das -replaceoriginal funktioniert bei mir nicht wie gewünscht.
Folgende Zeile habe ich zum, Test geschrieben:
gci "C:\Users\nico1991\Desktop\Teileliste\Klein\*.jpg" -File -recurse | Resize-Image -NewWidth 320 -NewHeight 240 -DownSizeOnly -replaceoriginal
Und dann kommt folgende Fehlermeldung
Rename-Item : Eine Datei kann nicht erstellt werden, wenn sie bereits vorhanden ist.
In Zeile:62 Zeichen:25
+ ... Rename-Item $newImagePath -NewName ($finfo.Name)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\Users\nico1991\r2dls2rk.lw5:String) [Rename-Item], IOException
+ FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand
Was kann ich tun? Vielen Dank für die freundliche Hilfe