colinardo
Goto Top

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.

back-to-topPowershell-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,
        [parameter(mandatory=$false)][switch]$KeepOriginalDates
    )
    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 | out-null}

                    $newImg.Save($newImagePath,$img.RawFormat)
                    
                    if($KeepOriginalDates.IsPresent){
                        Get-Item -LiteralPath $newImagePath | %{
                            $_.CreationTime = $finfo.CreationTime
                            $_.LastWriteTime = $finfo.LastWriteTime
                        }
                    }
                    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()
    }
}
back-to-topAnwendungsbeispiele
back-to-topAlle 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
back-to-topAlle 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
back-to-topAlle 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
back-to-topEin 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
back-to-topAlle 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.

Mit dem optionalen Switch-Parameter -KeepOriginalDates werden Erstell- und Änderungsdatum der Originaldateien im Dateisystem auf die neuen Dateien übertragen.

Viel Spaß damit
Grüße @colinardo

Content-ID: 268427

Url: https://administrator.de/contentid/268427

Ausgedruckt am: 21.11.2024 um 12:11 Uhr

SirMank
SirMank 05.06.2019 um 13:43:22 Uhr
Goto Top
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
(Get-ChildItem $Quelle -recurse).FullName| Resize-Image -OutPath $Ziel -NewWidth $MaxBreite -NewHeight $MaxHoehe -DownSizeOnly #Bilder aus Quelle und allen Unterordnern

Grüße
SirMank
colinardo
colinardo 05.06.2019, aktualisiert am 06.06.2019 um 11:43:59 Uhr
Goto Top
Zitat von @SirMank:

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
(Get-ChildItem $Quelle -recurse).FullName| Resize-Image -OutPath $Ziel -NewWidth $MaxBreite -NewHeight $MaxHoehe -DownSizeOnly #Bilder aus Quelle und allen Unterordnern
Servus @SirMank.
Das ist nicht nötig wenn man mit Get-ChildItem arbeitet, Die Funktion holt sich den vollen Pfad der Bilder automatisch aus den übergebenen Infos von Get-ChildItem aus der Pipeline !
Siehe Parameter Info
[parameter(mandatory=$true,ValueFromPipeline=$true)][alias("FullName")][string[]]$images
Der Alias "FullName" besagt das er sich den Pfad für die Bilder aus der in der Pipeline übergebenen Property FullName holen kann. Das von dir gemachte ist also überflüssig.

Grüße Uwe
SirMank
SirMank 06.06.2019 um 11:11:57 Uhr
Goto Top
Hallo Uwe,
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
colinardo
colinardo 06.06.2019 aktualisiert um 11:44:31 Uhr
Goto Top
Ich habe aber auch den Fullname nicht in den Atributen, wenn ich mir die Ausgabe von GCI an FL übergebe.
Das ist normal das wird nur angezeigt wenn du fl * schreibst sonst listet er dir nur einen Default Satz an Attributen.

Es war noch ein kleiner Parameter-Definitionsfehler drin, habe ihn oben im Skript korrigiert, sorry für die Umstände, aber Danke für die Rückmeldung.

Grüße Uwe
SirMank
SirMank 06.06.2019 um 13:52:51 Uhr
Goto Top
Jetzt klappt alles so wie gedacht.
Schon wieder was gelernt :D
Vielen Dank
Demech
Demech 19.08.2019 um 13:08:58 Uhr
Goto Top
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
colinardo
colinardo 19.08.2019 aktualisiert um 15:08:22 Uhr
Goto Top
Servus @Demech , willkommen auf Administrator.de!
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?
Habe den Code des CMDLets oben noch um einen Parameter ergänzt und zusätzlich ein Beispiel eingetragen. Siehe letztes Beispiel:
Get-ChildItem  "D:\Bilder" -include "*.jpg","*.png" -recurse -file | Resize-Image -NewWidth 320 -NewHeight 240 -replaceoriginal  
Das verkleinert im Beispiel alle jpg und png und ersetzt damit die Originale
Grüße Uwe
Demech
Demech 19.08.2019 um 15:38:49 Uhr
Goto Top
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
Tobiko
Tobiko 24.02.2020 um 19:31:04 Uhr
Goto Top
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
colinardo
colinardo 24.02.2020 aktualisiert um 21:22:48 Uhr
Goto Top
Zitat von @Tobiko:

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?
Servus Tobi,
die Ausrichtung der Bilder wird im Skript nicht verändert. Die Bilder werden so verarbeitet wie sie "tatsächlich" vorliegen.
Du lässt dich da von deinem Anzeige-Programm täuschen, das vermutlich die Exifdaten der Bilder nur für die Anzeige auswertet und sie so darstellt wie sie aufgenommen wurden (Portrait/Landscape), obwohl sie in Wirklichkeit anders auf der Platte liegen.

Wenn man wollte kann man die Kameradrehung natürlich auch aus den Exif-Daten lesen, kannst du aber auch mit dem Bildbearbeitungsprogramm deiner Wahl einfach dauerhaft auf deine Bilder vorher anwenden.

Werde die Exif Drehung vielleicht bei Zeiten mal ins Skript oben aufnehmen. Habe momentan aber leider zu wenig Zeit für die Spielereien face-wink.

Grüße Uwe
Tobiko
Tobiko 25.02.2020 aktualisiert um 08:04:46 Uhr
Goto Top
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
colinardo
colinardo 25.02.2020 aktualisiert um 09:05:17 Uhr
Goto Top
Zitat von @Tobiko:

Ich habe eben eine komprimierte Datei angeschaut in den Details der Eigenschaften im Explorer. Dabei habe ich festgestellt das praktisch alle Werte verloren gingen.
Das ist normal und im o.g. Skript so auch nicht vorgesehen.
Das Skript ist primär dafür gedacht um z.B. Vorschauen für Webseiten usw. zu erstellen und da sind Exif-Daten ja schon aus Datenschutzgründen nicht erwünscht.
Es ist nicht als AllInOne-Tool zu verstehen sondern rein als Verkleinerungsmaschine ohne Schnickschnack.

Persönliche Anpassungen nehme ich aber als Auftrag gerne entgegen.
raffnix
raffnix 25.07.2023 um 09:51:40 Uhr
Goto Top
Wie könnte man das Skript ergänzen, damit das erstell Datum nicht geändert wird?
colinardo
colinardo 25.07.2023 aktualisiert um 10:34:46 Uhr
Goto Top
Na das ist ja mal eine nette Anfrage 😐.
Diskussionsrichtlinien - die Regeln zu unseren Inhalten

Zwischen Zeile 51 und 52 hinzufügen
(get-Item $newImagePath).CreationTime = (Get-Item $_).CreationTime
Gruß @colinardo
raffnix
raffnix 25.07.2023 aktualisiert um 13:29:13 Uhr
Goto Top
Zitat von @colinardo:

Na das ist ja mal eine nette Anfrage 😐.
Diskussionsrichtlinien - die Regeln zu unseren Inhalten

Zwischen Zeile 51 und 52 hinzufügen
(get-Item $newImagePath).CreationTime = (Get-Item $_).CreationTime
Gruß @colinardo

Hallo Colinardo,

Sorry dafür. War trotzdem sehr lieb und Nett, das du darauf geantwortet hast. Ich gelobe Besserung´.

Beste Grüße
@raffnix
markushi
markushi 08.11.2023 um 19:43:57 Uhr
Goto Top
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:
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
colinardo
colinardo 08.11.2023 aktualisiert um 23:19:29 Uhr
Goto Top
Zitat von @markushi:
Was mir noch nicht klar ist, wodurch die Erhaltung des Seitenverhältnisses angegeben wird?

Servus Markus,
Freut mich das es dir nützliche Dienste erweist.
Das Seitenverhältnis wird immer beibehalten, es gibt keinen Parameter im Skript dafür, kann ich aber wenn gewünscht gerne noch ergänzen.

#edit# Ein neuer Parameter -aspectratio wurde hinzugefügt, und kann mit den Werten Original oder Scale versehen werden.
Default ohne Angabe des Parameters ist
, das Seitenverhältnis des Originals beizubehalten. Scale staucht oder dehnt das Bild auf die gewünschte Größe.

Grüße Uwe
markushi
markushi 09.11.2023 um 07:05:40 Uhr
Goto Top
Servus Uwe,

vielen Dank 🙏 für die Erweiterung! Damit kann ich echt was anfangen, perfekt 👌👏

Gruß - Markus
Nico1991
Nico1991 18.01.2024 um 08:33:19 Uhr
Goto Top
Hi,

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 face-smile
Nico1991
Nico1991 18.01.2024 aktualisiert um 09:36:45 Uhr
Goto Top
Ich bin ein kleines Stück weiter. Die Bilder haben Teilweise "[" und "]" im Namen. Hiermit kann die Remove-Item Funktion nicht umgehen, bzw nur mit einem Zusatz. Weiß jemand, wie es korrekt wäre?
colinardo
colinardo 18.01.2024 aktualisiert um 10:15:03 Uhr
Goto Top
Servus @Nico1991, willkommen auf Administrator.de!
Zitat von @Nico1991:
Die Bilder haben Teilweise "[" und "]" im Namen.
Ja das lag daran da das für die Shell sogenannte Glob-Zeichen sind die die Shell für eine Auswahl an Zeichen im Pfad interpretiert, man muss hier dann explizit -LiteralPath für die Pfadangaben benutzen, hatte das bei den "Remove-Item" und "Rename-Item" Befehlen in der Funktion übersehen, sorry ist jetzt oben korrigiert und es sollte nun wie gewünscht auch mit den "[]" Zeichen im Pfad/Namen funktionieren.

Grüße Uwe
Nico1991
Nico1991 18.01.2024 um 10:16:13 Uhr
Goto Top
Uwe, vielen Dank!

Es funktioniert nun wie gewünscht.
colinardo
colinardo 18.01.2024 aktualisiert um 10:18:38 Uhr
Goto Top
Immer gerne 👍. Danke auch für den Hinweis.
maxmey
maxmey 23.04.2024 um 15:09:57 Uhr
Goto Top
Hi colinardo/Uwe,

dein Skript kommt mir wie gerufen- erst mal danke dafür!
Ich würde gerne ein einzelnes Bild ändern und ersetzten, habe auch ein bisschen rum probiert, aber bekomme es leider nicht hin :/

Bei den folgenden zwei Varianten soll ich bei beiden in der konsole den Output path manuelll angeben. Geht das einfach nicht automatisiert oder bin ich zu blöd?
Resize-Image -images "C:\bild.jpg" -ReplaceOriginal -NewWidth $newWidth -NewHeight $newHeight   
Resize-Image -images "C:\bild.jpg"  -NewWidth $newWidth -NewHeight $newHeight -ReplaceOriginal  
colinardo
colinardo 23.04.2024 aktualisiert um 15:35:38 Uhr
Goto Top
Zitat von @maxmey:
Bei den folgenden zwei Varianten soll ich bei beiden in der konsole den Output path manuelll angeben. Geht das einfach nicht automatisiert oder bin ich zu blöd?
Resize-Image -images "C:\bild.jpg" -ReplaceOriginal -NewWidth $newWidth -NewHeight $newHeight   
Resize-Image -images "C:\bild.jpg"  -NewWidth $newWidth -NewHeight $newHeight -ReplaceOriginal  

Servus @maxmey, willkommen auf Administrator.de!
Doch natürlich, aber du hast vergessen den Parameter -outpath <Ausgabeordner> mit anzugeben wenn keine Bilder über die Pipeline kommen, siehe Anwendungsbeispiel Nr. 4 oben im Beitrag.

Also entweder
Resize-Image -images "C:\bild.jpg" -OutPath "C:\" -ReplaceOriginal -NewWidth $newWidth -NewHeight $newHeight  
oder alternativ auch so
Get-Item "C:\bild.jpg" | Resize-Image -ReplaceOriginal -NewWidth $newWidth -NewHeight $newHeight  

Grüße Uwe
maxmey
maxmey 23.04.2024 um 16:23:58 Uhr
Goto Top
Mein Fehler, eigene Dummheit :D
Vielen Dank!!
SysDetlef
SysDetlef 05.07.2024 um 15:37:36 Uhr
Goto Top
Hallo nochmal!

Sorry - Punkt 1 hat sich erledigt. War wohl etwas verkopft und hatte es direkt nach dem Posten bemerkt: Wenn man bei NewWitdh oder NewHeight jeweils 1920 eingibt, dann wird genau das gemacht, wie ich es beschrieben hatte.

Dann bleibt eigentlich nur die Frage:
Wie verhält es sich (falls der Vorschlag tatsächlich implementiert werden kann), wenn die lange Seite bereits 1920 Pixel lang ist - würde das Bild dennoch nochmals auf die gleiche Größe konvertiert werden oder einfach übersprungen?
Es geht darum dies regelmäßig über einen Fileserver mit vielen Bildern laufen zu lassen, bei denen eine Größe von 1920 Pixel der längsten Seite absolut ausreicht.

Vielen Dank nochmal!
Detlef
colinardo
colinardo 05.07.2024 aktualisiert um 15:40:55 Uhr
Goto Top
Servus Detlef.
Wie verhält es sich (falls der Vorschlag tatsächlich implementiert werden kann), wenn die lange Seite bereits 1920 Pixel lang ist - würde das Bild dennoch nochmals auf die gleiche Größe konvertiert werden oder einfach übersprungen?

Wenn du den Switch Parameter -DownSizeOnly verwendest wird nur angepasst wenn das Bild auch tatsächlich reduziert werden muss.

Grüße Uwe
SysDetlef
SysDetlef 10.07.2024 um 11:54:20 Uhr
Goto Top
Hallo Zusammen,
Hallo Uwe,

das Script funktioniert super bei mir - zumindest so lange ich nicht diese Zeile zwischen Zeile 51 & 52 einfüge:
(get-Item $newImagePath).CreationTime = (Get-Item $_).CreationTime
(Damit der Zeitstempel der Bilddatei bestehen bleibt)

Sobald ich die Zeile einfüge, kommt folgende Fehlermeldung:
Resize-Image : Cannot bind argument to parameter 'Path' because it is an empty string.  
At C:\Scripts\Resize-Image\Resize-Image_J_AutoBilderVerkleinerer.ps1:1 char:65
+ ... rse -file | Resize-Image -NewWidth 1920 -NewHeight 1920 -DownSizeOnly ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Resize-Image

Was mache ich falsch?
Vielen Dank nochmal und viele Grüße,
Detlef
colinardo
colinardo 10.07.2024 aktualisiert um 13:45:01 Uhr
Goto Top
Zitat von @SysDetlef:
Sobald ich die Zeile einfüge, kommt folgende Fehlermeldung:
Resize-Image : Cannot bind argument to parameter 'Path' because it is an empty string.  

Was mache ich falsch?
Zu dem Zeitpunkt ist die Variable noch leer und die Datei existiert ja auch noch nicht deswegen auch die Meldung because it is an empty string face-wink.
Wenn dann nach Zeile 82 einfügen:
(Get-Item -LiteralPath $newImagePath).CreationTime = $finfo.CreationTime
Grüße Uwe
SysDetlef
SysDetlef 12.07.2024 um 10:08:36 Uhr
Goto Top
Hallo Uwe,

vielen Dank für deine Hilfe.
Ich habe die beiden Zeilen eingefügt (die eine Zeile nach Zeile 51, die andere Zeile nach Zeile 82 [bzw nach Zeile 83, da ja eine Zeile mehr])
Wenn ich meinen Befehl so 1x ausführe, dann funktioniert es.
Get-ChildItem -Path "c:\Test" -include "*.jpg" -recurse -file | Resize-Image -NewWidth 1920 -NewHeight 1920 -DownSizeOnly -ReplaceOriginal -RotateByExifOrientation  
Beim zweiten Mal ausführen (ohne was zu ändern) kommt für jede Bild-Datei diese Fehlermeldung:
Resize-Image : Cannot bind argument to parameter 'Path' because it is an empty string.  
At C:\Scripts\Resize-Image\Resize-Image_J_AutoBilderVerkleinerer.ps1:1 char:65
+ ... rse -file | Resize-Image -NewWidth 1920 -NewHeight 1920 -DownSizeOnly ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Resize-Image

Und gibt es auch die Möglichkeit dass das Änderungsdatum UND das Erstelldatum gleich bleiben? Dann wäre das Script für mich komplett.

Ich hoffe dass ich dich damit nicht nerve und würde mich freuen, wenn du mir (nochmal) helfen könntest.

Vielen Dank vorab!
Detlef
colinardo
colinardo 12.07.2024 aktualisiert um 10:35:38 Uhr
Goto Top
Ich habe die beiden Zeilen eingefügt (die eine Zeile nach Zeile 51, die andere Zeile nach Zeile 82 [bzw nach Zeile 83, da ja eine Zeile mehr])
Eigentlich war es nur eine Zeile, aber egal.
Bevor ich mich hier jetzt fusselig rede, habe ich die Funktion um den Switch-Parameter -KeepOriginalDates erweitert der Erstell- und Änderungsdatum der Quelldateien bei den Zieldateien beibehält.

Für dein Beispiel ist dann nur der Parameter zu ergänzen
Get-ChildItem -Path "c:\Test" -include "*.jpg" -recurse -file | Resize-Image -NewWidth 1920 -NewHeight 1920 -DownSizeOnly -ReplaceOriginal -RotateByExifOrientation -KeepOrginalDates  
Damit sollte das Thema erledigt sein.

Grüße Uwe
kreuzberger
kreuzberger 09.10.2024 um 13:11:29 Uhr
Goto Top
TaCH @colinardo

vielleicht kommt die frage ja etwas „dümmlich“ an:

Wie kann ich denn diese Funktion in mein lokales System einbinden, damit Aufrufe wie dieser

Get-ChildItem -Path "c:\Test" -include "*.jpg" -recurse -file | Resize-Image -NewWidth 1920 -NewHeight 1920 -DownSizeOnly -ReplaceOriginal -RotateByExifOrientation -KeepOrginalDates    

funktionieren?

Oder geht das nur in einem vervollständigten Script, in dem die Funktion oben komplett enthalten ist und anschliessen der hier zitierte Aufruf z.b. folgt?

Grüße

Kreuzberger
colinardo
colinardo 09.10.2024 aktualisiert um 13:25:29 Uhr
Goto Top
Servus Kreuzberger,
Oder geht das nur in einem vervollständigten Script, in dem die Funktion oben komplett enthalten ist und anschliessen der hier zitierte Aufruf z.b. folgt?
Gibt es viele Möglichkeiten, entweder das also komplett ins Skript packen, oder du machst aus der Funktion ein Modul mit der Endung *.psm1 und bindest das mittels
Import-Module "<Pfad zum Modul>"  
im Kopf des Skriptes ein.
Alternativ die Funktion in die bekannten Powershell Profildateien des Users kopieren (Pfad steht in der $profile Variablen ), oder das Modul in die Modulverzeichnisse kopieren ($env:PSModulePath) dann steht es auch automatisch in jeder neuen PS-Session zur Verfügung.
https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell ...

Grüße Uwe
kreuzberger
kreuzberger 09.10.2024 um 14:01:17 Uhr
Goto Top
@colinardo

DANKE!!!!

Ich habe die komplette Funktion in eine Datei „Reize-Image.psm1“ kopiert/geschrieben. Danach habe ich
Import-Module -Path "<Pfad zum Modul>    
durchgeführt.

Zuletzt habe ich dann in der PwerShell
Get-ChildItem -Path "c:\Test" -include "*.jpg" -recurse -file | Resize-Image -NewWidth 1440 -NewHeight 1440 -DownSizeOnly -ReplaceOriginal -RotateByExifOrientation -KeepOrginalDates      
ausgeführt (angepasst an meine Pfade natürlich).

Das hat super funktioniert. Somit Steht diese Funktion also immer auf diesem Host zur verfügung!?!?

Gäbe es denn - ich ich weiss, es ist fast ausverschämt - einen Tip, wie man im Images-Ordner die Originale belässt und die verkleinerten Images mit neuem Namen absichert?

Beispiel:
aus DSC_5623.JPG
wird DSC_5623_1440.JPG oder DSC_5623_klein.JPG oder /Unterordner/DSC_5623.JPG

Kreuzberger
colinardo
colinardo 09.10.2024 aktualisiert um 14:09:42 Uhr
Goto Top
Zitat von @kreuzberger:
Das hat super funktioniert. Somit Steht diese Funktion also immer auf diesem Host zur verfügung!?!?
Nein, nur in der aktuellen Session in der du Import-Module ausgeführt hast. Für die dauerhafte Einbindung, siehe meine Anmerkungen zu den Modulpfaden oben.

Gäbe es denn - ich ich weiss, es ist fast ausverschämt - einen Tip, wie man im Images-Ordner die Originale belässt und die verkleinerten Images mit neuem Namen absichert?

Beispiel:
aus DSC_5623.JPG
wird DSC_5623_1440.JPG oder DSC_5623_klein.JPG oder /Unterordner/DSC_5623.JPG

Steht doch schon oben in den Beispielen 🤔.
kreuzberger
kreuzberger 09.10.2024 um 14:10:55 Uhr
Goto Top
auweia, sorry