Eigentlich sollte ich das [hierhin] posten, aber mein Narzissmus befiehlt mir, zu diesem Thema gleich wieder einen eigenen Thread zu eröffnen.
Des öfteren werde ich gefragt - auch im VA IRC schon, glaub' ich zumindest - wofür man eigentlich eine Kommandozeile braucht, wenn man alles auf der GUI machen kann. Oftmals habe ich trotz Erfahrung nicht gleich ein passendes Beispiel bei der Hand, und kann dann nur Dinge wie "Für Systemautomation" sagen, worunter sich sowieso keiner was vorstellen kann. Aber gestern gab' es grade eines, und daher poste ich das Mal hier rein.
Hintergrund: Ich lese Manga, also Comics, wovon einige auch als Webcomics ausgelegt sind, die man sich so runterladen kann (und manchmal dankenswerterweise auch darf). Üblicherweise schmeiß' ich die durchnummerierten Bilder einfach in eine Comicbook Datei (.cbz, dafür reicht ZIP), dann können das alle gängigen Comicbook Readerprogramme auf Windows, macOS, Linux, Android, iOS usw. lesen und im besten Fall optisch ein bisserl so darstellen, als hätte man wirklich ein offenes Heft mit zwei Seiten und Falz vor sich auf dem Schirm (Pixel Shader Galore).
Alles easy. Dafür braucht man i.d.R. nichts extra, außer man hat einen Titel mit wirklich vielen .jpg oder .png Files. Aber ein Webcomic hat mich da vor ein kleines kosmetisches Problem gestellt, hier'n Beispiel:
Im Eve Online Slang würde man dazu "fucking vertical" sagen. Teilweise sind die Strips noch viel "höher" als dieser.
Ein Überblick - die Strips sehen zum größten Teil so aus:
Vertikal! - Was in Eve Online cool sein mag, ist beim Lesen von Manga-/Comic-Strips auf Breitbildschirmen etwas sperrig
Das paßt mir so überhaupt nicht, weil selbst bei zwei Seiten nebeneinander geht davon mehr als der halbe Bildschirm ungenutzt flöten, bei 16:10 schon, bei 16:9 sowieso. Rendert der Reader auch noch einen virtuellen Falz rein, ist noch mehr weg, weil die Strips keinen umgebenden weißen Rand haben, wie meist üblich. Man kann dann reinzoomen, aber dann muß man halt vertikal scrollen. Oder man hat halt zwei dünne Bänder runter und links und rechts dicke schwarze Flächen => Wäh. War mir schon wieder Mal nicht gut genug.
Anzahl der Einzelbilder in dem Fall: Mit 2.541 nicht so wenige, verteilt über 125 Kapitelordner, pro Kapitel nummeriert von 001.jpg .. nnn.jpg.
Meine Idee: Per Schleife drüber, die Bilder linear durchnummerieren, dann in 5er Gruppen zusammenfassen, und 5 Einzelbilder jeweils zu einem geblockten Bild zusammenstoppeln, und so neu abspeichern. Sollte von der Bildgröße ziemlich perfekt zu 16:10 passen.
Ich habe nicht die mindeste Ahnung, wie man so etwas z.B. unter Windows mit einem GUI Programm anstellt, selbst per Corelscript in meinem Photopaint ist das denke ich zu anspruchsvoll. Vielleicht kann Photoshop oder sonst ein Programm von Adobe sowas? Wär spannend zu wissen. Ich jedenfalls reiß' erst Mal die Shell auf, hier unter Linux mit der Bash (Powershell-Äquivalent wäre interessant! Da kenn ich mich leider nix aus).
Erst Mal der Versuch sämtliche Strips über alle Kapitel durchlaufend zu nummerieren, damit man besser damit arbeiten kann, erst Mal Dryrun (hier zusammengekürzt für weniger Textmüll):
$ k=0; for i in *; do for j in $i/*; do k=$((k+1)); echo Chapter: $i. Strip per chapter: $j. New, global strip number: $k; done; done; unset k;
000/001.jpg
Chapter: 000. Strip per chapter: 000/001.jpg. New, global strip number: 1
000/002.jpg
Chapter: 000. Strip per chapter: 000/002.jpg. New, global strip number: 2
001/001.jpg
Chapter: 001. Strip per chapter: 001/001.jpg. New, global strip number: 3
001/002.jpg
Chapter: 001. Strip per chapter: 001/002.jpg. New, global strip number: 4
Mh, das funktioniert schon Mal. Kapitel 000, Strip 002 wird zu Bild 2, Kapitel 001 Strip 001 wird zu Bild 3 usw.. Also machen wir statt dem echo ein copy, um die ganzen Bilder durchnummeriert in einem Zielordner zu haben, noch ein One-Liner:
$ k=0; for i in *; do for j in $i/*; do k=$((k+1)); cp $j ../output/$k.jpg; done; done; unset k;
Besser lesbar so:
k=0;
for i in *; do # Durchlaufe alle Ordner im aktuellen Verzeichnis
for j in $i/*; # Durchlaufe alle Dateien im Subordner $i
do k=$((k+1)); # Erhöhe globalen Bildzähler um 1
cp $j ../output/$k.jpg # Kopiere lokale Dateien mit neuer globaler Nummerierung nach ../output/
done;
done;
unset k
Resultat, der Unterordner ../output/ ist jetzt mit 1.jpg bis 2541.jpg befüllt. Soweit so gut. Als nächstes ein Versuch den Batzen in dem Ordner per Modulo (Rest einer Division) in 5er Gruppen zusammenzufassen, hier Mal über die ersten 30 Bilder:
$ j=0; for ((i=5; i<=30; i++)); do if [ $((i % 5)) = 0 ]; then j=$((j+1)); printf "Grouped file $j: "; echo $(eval echo {$((i-4))..$i}.jpg); fi; done; unset j;
Grouped file 1: 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg
Grouped file 2: 6.jpg 7.jpg 8.jpg 9.jpg 10.jpg
Grouped file 3: 11.jpg 12.jpg 13.jpg 14.jpg 15.jpg
Grouped file 4: 16.jpg 17.jpg 18.jpg 19.jpg 20.jpg
Grouped file 5: 21.jpg 22.jpg 23.jpg 24.jpg 25.jpg
Grouped file 6: 26.jpg 27.jpg 28.jpg 29.jpg 30.jpg
Na wer sagt's denn! Damit kann man schon Mal weiterarbeiten. Wieder in lesbarerer Darstellung mit Kommentaren:
j=0;
for ((i=5; i<=30; i++)); do # Zähle von 5 bis 30
if [ $((i % 5)) = 0 ]; then # Wenn Zähler teilbar durch 5..
j=$((j+1)) # Erhöhe 5er Gruppenzähler um 1
printf "Grouped file $j: " # Ausgabe der Gruppennummer
echo $(eval echo {$((i-4))..$i}.jpg) # Ausgabe einer Bildnummer und der 4 vorangehenden Bilder (=Gruppe)
fi;
done;
unset j;
Jetzt geht's an's eingemachte. Dateien von A nach B kopieren ist ja schön und gut, aber ich will ja Bilder zusammenfügen. Dafür gibt's auf unixoiden Systemen dankenswerterweise die ImageMagick Bibliotheken plus zugehöriger Kommandozeilentools (Auch für Windows zu bekommen). Das beste für's Zusammenstückeln dürfte wohl der ImageMagick Befehl "montage" sein (sagen zumindest irgendwelche Internetmenschen), also habe ich das erstmals ausprobiert. Kurz Doku lesen und auf geht's mit folgenden Parametern:
- -tile 5x1: Füge Bilder in 5 Spalten in einer Zeile zusammen
- -background '#111111': Hintergrundfarbe, sehr dunkles grau, fast schwarz (für die Ränder)
- -geometry +10+10: Ränder zwischen den Bildern, 10 Pixel um jedes Einzelbild
Geschrieben werden die Daten in einen neuen Ordner ../concat/. Soweit so gut, schicken wir das Trumm los:
$ j=0; for ((i=5; i<=11; i++)); do if [ $((i % 5)) = 0 ]; then j=$((j+1)); montage $(eval echo {$i..$((i-4))}.jpg) -quality 95 -tile 5x1 -background '#111111' -geometry +10+10 ../concat/$(printf "%04d" $j).jpg; fi; done; unset j;
Der fügt die ersten 5 Bilder zusammen, und speichert das unter ../concat/0001.jpg, dann die nächsten 5 unter ../concat/0002.jpg und so weiter, bis (in meinem Fall) ../concat/0508.jpg. Eigentlich hätten dreistellige Dateinamen gereicht, najo. Übrigens habe ich auch Mal versucht alle 508 Prozesse komplett parallel loszuschicken, anstatt auf nur einem Kern zu rechnen. Aber das war dann doch etwas zuviel, mußte den Rechner resetten. Die Bilder werden übrigens "verkehrt" gestoppelt, sodaß man von rechts nach links lesen muß; Das ist Absicht, weil es sich um ein ursprünglich japanisches Medium handelt.
Hier wieder besser lesbar und kommentiert, der Teil:
j=0
for ((i=5; i<=2541; i++)); do # Zähle von 5 bis 2541 (Weil wir die Bilder vom aktuellen rückzählend lesen)
if [ $((i % 5)) = 0 ]; then # Wenn Zähler teilbar durch 5
j=$((j+1)) # Erhöhe 5er Gruppenzähler um 1
# Füge die aktuelle 5er Gruppe aus 5 Einzelbildern horizontal mit Abstand 10 links und 10 rechts zusammen, und speichere 4-stellig nummeriert ab:
montage $(eval echo {$i..$((i-4))}.jpg) -quality 95 -tile 5x1 -background '#111111' -geometry +10+10 ../concat/$(printf "%04d" $j).jpg
fi;
done;
unset j
Also bei Nutzung von nur einem Kern hat er schon ein bißchen gebraucht, um die 2.540 Einzelbilder zu 508 Gruppenbilder zusammenzufügen und als JPEGs zusammenzuspeichern. Auf einem i7 980X hat das 2 Minuten und 34 Sekunden gedauert. Es "schlau" zu parallelisieren war mir zu aufwendig. "Scheiß der Hund drauf", wie meine Oma zu sagen pflegt.
Das Ergebnis im Überblick (Das ist eine recht kleine Bilddatei, daher nicht als Thumbnail):
Sieht aus, als ob's halbwegs richtig wär...
Noch zwei Stichproben (Hier wäre PNG wohl auch die bessere Wahl gewesen, das werde ich noch versuchen, aber was soll's erst Mal für's Erste):
Mh jo, ich denke das ist einigermaßen brauchbar, so kann man das in ein Comicbook-Format speichern, und angenehmer lesen
Jetzt könnte man natürlich argumentieren, daß dieser Anwendungsfall nur eine dumme kleine Spielerei ist, und das wäre schon auch nicht so ganz falsch. Aber da spielt man halt Mal 20 Minuten auf'm Terminal herum, und hat über 2.500 Bilddateien automatisch durchverarbeitet - manuell wäre das ein Alptraum gewesen. Und klar - derartige Automatismen lassen sich auch für richtige Arbeit mannigfaltiger Natur nutzen, und können einem das Leben ungemein erleichtern.
Und z.B. dafür braucht man dann die Kommandozeile - also ich zumindest.
Den Thread stelle ich einfach Mal so her, wenn ich auf die Frage "wofür braucht man ein Terminal" Mal wieder keine schnelle Antwort parat habe.
Mich würde jetzt wirklich interessieren, wie ein Windows Benutzer ohne Kommandozeilenerfahrung mit dem Fall hier umgehen würde. Vielleicht gibt's die GUI Werkzeuge für gerade diese Anwendung ja eh schon, und ich kenne sie nur nicht... Bin da nicht gaaanz so bewandert.