Technik

Viele Bilder bei TinyPNG komprimieren – mit Powershell

Das Maskottchen von TinyPNG

Ja schon wieder ein Powershellscript. Ich bringe zur Zeit einige Internetseiten auf Vordermann und will dort optimal komprimierte Bilder hochladen. Am besten komprimiert werden Bilder auf tinypng.com aber ich wollte nicht immer auf die Internseite müssen. Darum habe ich ein Powershell Script geschrieben, das die API verwendet.

Man kann auf TinyPNG (oder TinyJPG) gehen und oben bei Developer API eine Emailadresse angeben. Dann kriegt man einen Link mit einem API Schlüssel zugeschickt, den man hierfür braucht.

Mit meinem Script kann man beliebig viele Jpg oder Png Bilder in einem Ordner haben. Dort kopiert man das Powershellscript hin, führt es aus und alle Bilder werden zuerst zu tinypng hochgeladen und dann die komprimierten Versionen heruntergeladen. Als nichtzahlender Kunde darf man so bis zu 500 Bilder im Monat komprimieren – für mich mehr als genug! Danach kostet ein Bild 0,009USD. Als normaler Blogger dürfte man aber nie so viel brauchen.

Das Maskottchen oben habe ich von der TinyPNG Website direkt per Screenshot geklaut und mit dem guten alten Paint zugeschnitten und abgespeichert. Man kann natürlich davon ausgehen, dass Paint nicht optimal abspeichert, daher habe ich das Bild direkt mit meinem Script komprimiert.

Das Bild ist um mehr als die Hälfte kleiner geworden!

Wenn du eigentlich nur das Tool nutzen willst und dich gar nicht interessiert wie es programmiert ist, dann kannst du es auch hier herunterladen.

Zum Script:

$user = "api"
$pass = "[dein API Key]"
$pair = "${user}:${pass}"

$bytes = [System.Text.Encoding]::ASCII.GetBytes($pair)
$base64 = [System.Convert]::ToBase64String($bytes)

$basicAuthValue = "Basic $base64"

$headers = @{ Authorization = $basicAuthValue }

$regex = '"url":".*"'

gci * -Include *.png, *.jpg | select -ExpandProperty name | %{
    $return = Invoke-WebRequest -uri "https://api.tinify.com/shrink" -Headers $headers -InFile $_ -Method Post
    $url = Select-string -InputObject $return.Content -Pattern $regex -AllMatches | %{$_.Matches.Value.Replace('"url":"','').Replace('"','')}
    $output = "tinyfi" + $_
    md -force tinyfi
    Invoke-WebRequest -Uri $url -OutFile $output
}

Ich will auch wieder erklären was hier passiert.

Der ganze obere Teil ist nur zum Authentifizieren. Das ist ein bisschen blöd mit Powershell. Linuxbenutzer mit curl können da einfach –user schreiben. Mit Powershell muss man den Header leider selbst zusammenbauen. Den Teil kopiere ich aber auch einfach immer wieder (es ist der gleiche wie in meinem DynDNS mit Powershell Script).

gci: ist kurz für get-child-item und in Powershell das, was in Linux ls ist. Mit gci * sage ich, dass ich alle Dateien in einem Ordner aufgelistet haben will. Ich schränke das aber noch mit dem Parameter -Include ein. Der erlaubt mir mehr als ein Muster zu nehmen und so kann ich nach den zwei Endungen filtern die ich haben möchte. Gäbe es nur eine Mögliche Endung hätte z.b. gci *.jpg gereicht.

|: verkettet Befehle. Es wird die Ausgabe des vorigen Befehls in den neuen Befehl weitergeleitet.

select: ist ganz interessant. Das Ergebnis von gci * ist eine Tabelle und mit select kann man diese SQL artig weiterverarbeiten. Für die Ausgabe wäre gci * | select name optimal, allerdings will ich mit den Daten ja noch weiterarbeiten. Daher verwende ich den Parameter -ExpandProperty. Damit schneide ich letzendlich die Kopfzeile von der Tabelle weg.

| % {: die schicke kurze Variante für “Nimm jede einzelne Zeile von oben und mache mit ihr alles, was im Block bis zum Ende der geschweiften Klammer (})steht”

$return: Eine Variable, in der ich die Übergabe vom nächsten Befehl speichere, damit ich später damit weiterarbeiten kann.

Invoke-WebRequest: der curl von Powershell. Ich gebe mit -uri an, wo der Service liegt. -Headers beinhaltet den Authkram von weiter oben, auf den ich nicht eingehe, den wir aber brauchen.

-InFile $_: InFile heißt, dass eine Datei beim WebRequest mitgesendet wird. In diesem Fall ist der Pfad zur Datei in der Variable $_ und diese beinhaltet die Zeile, in der wir gerade wegen der %-Schleife sind. -Method Post ist die Übermittlungsart, die die API braucht.

$url: wieder eine Hilfsvariable. Das $return-Objekt beinhaltet alle möglichen Informationen, unter anderem unter welcher Url wir unser komprimiertes Bild finden. Die Wollen wir rausbekommen.

Select-String: Damit können wir einen Text durchsuchen. -InObject ermöglicht uns, in unserem eben erstellten $return zu suchen. -Pattern kann Regex beinhalten. Unser Regex hier ist weiter oben definiert.

“url”:”.*”: Bedeutet der Text den wir suchen sieht so aus: “url”:”[irgendwas]”

%{$_.Matches.Value.Replace: Wir schneiden vom Treffer alles ab bisauf die url selbst.

$output = “tinyfi” + $_: Hier basteln wir den Dateipfad für die neue Datei zusammen. Der Ordner “tinyfi” mit Dateinamen $_ (darin ist immer noch der Originalname aus der %-Schleife abgelegt).

md -force tinyfi: md erstellt ein Verzeichnis und -force verhindert in dem Fall nur den Fehler der kommt, wenn das Verzeichnis schon existiert. Beim Schreiben hier fällt mir dabei auf, dass es wenig elegant ist den md Befehl an dieser Stelle zu haben, weil das Progamm so versucht bei jedem Durchlauf den Ordner anzulegen und es natürlich reichen würde, wenn man das nur am Anfang einmal macht. Das ist nun deine Hausaufgabe!

Am Ende ist noch einmal ein Invoke-WebRequest, mit der Url, die wir weiter oben gebastelt haben und mit dem Pfad, den wir gebastelt haben. Das Ganze läuft in der %-Schleife für jeden Dateinamen in dem Ordner und am Ende hast du einen Ordner tinyfi, in dem alle deine Bilder liegen aber optimal komprimiert.

Womit komprimiert ihr eure Bilder?
Habt ihr schon mal die Powershell benutzt, um lästige Aufgaben zu vereinfachen?

Wust

Share
Published by
Wust

Recent Posts

Condor Map Mover

Kürzlich hatte ich beschrieben, wie man Condor Maps auf SD Karte verschieben kann. Jetzt habe…

5 Jahren ago

Mein La Reunion Video

Ich habe jetzt mein Video zur meiner Reise nach La Reunion auf Youtube gestellt. Das…

5 Jahren ago

Condor2 Landscapes Spielemodul erstellen

Mein Condor Spielmodul Gelegentlich spiele ich ganze gerne den Segelflugsimulator Condor 2 dabei hat mich…

5 Jahren ago

Dragonball Crawler in Node.js mit und ohne Puppeteer und Powershell

Ich hatte gerade Lust mal wieder alle Folgen von Dragonball zu gucken. Leider gibt es…

5 Jahren ago

Die aktuelle DHV Info lesen

Auf der Website vom DHV kann man normalerweise Kostenlos die DHV Info lesen. Das ist…

6 Jahren ago

Meine Hardware

Ich bin für manche so etwas wie ein digitaler Nomade, ich arbeite mit meinem Laptop…

6 Jahren ago