Stranger Than Usual

Well, 43 seconds in and we killed a man.

Josh (Let's Game It Out)

Anleitung: SVG-Dateien optimieren

Ich habe ja aus irgendeinem Grund enorm viel Spaß daran, SVG-Dateien in ihrer Größe zu optimieren. Zum Beispiel Napstablook, das curl-Logo oder neulich Graphen mit Blogstatistiken. Das geht oft weit über das hinaus, was ökonomisch sinnvoll wäre, aber ich werde ja sowieso nicht für dieses Blog bezahlt, also kann ich mir das auch leisten.

Nur habe ich glaube ich nie genauer beschrieben, wie ich das eigentlich mache. Nur ein paar Andeutungen hier und da, und ein Verweis auf svgo. Also dachte ich mir, ich könnte mal eine Anleitung dazu schreiben. Ich habe mir also ein einfaches Beispiel gesucht, und zwar die Blogstatistik von Schafe sind bessere Rasenmäher (CC BY-NC-SA 4.0 Robert Lützner):

Ein einfacher Graph, an dessen x-Achse Jahreszahlen von 2022 bis 2026 stehen.

Ich gehe hier Schritt für Schritt vor. Wenn nicht anders erwähnt, sind die Umwandlungen verlustfrei, zumindest was die Anzeige der Grafik angeht. Die vollständigen Dateien nach jedem Schritt habe ich in ein Repo auf codeberg gepackt. Los geht's!

Schritt 0: Originaldatei

Größe: 1561 Byte

Naja, nicht ganz Original. Die Datei war eingebettet in das HTML der Ursprungsseite. Ich habe sie herausgetrennt, das ID-Attribut entfernt (ist hier nicht wichtig) und ein namespace-Attribut (xmlns="http://www.w3.org/2000/svg") hinzugefügt, damit die Datei von z.B. Firefox richtig erkannt wird, wenn es keine anderen Hinweise auf den Typ gibt.

Die Datei ist maschinell erstellt und hat deswegen wenige oder keine unnötigen Leerzeichen.

Schritt 1: svgo

Größe: 1003 Byte

Ein Standardtool zur Optimierung von SVG-Dateien ist svgo. Das läuft schnell durch und in den meisten Fällen ist es auch die ökonomischste Variante, es dabei zu belassen. Aber nicht hier. Ich habe die Datei mit svgo --multipass --pretty optimiert. --multipass, damit Optimierungsmaßnahmen, die beim ersten Durchlauf übersehen wurden, auch gemacht werden. --pretty, um es beim Bearbeiten leichter zu haben. Das fügt zwar eine Menge Leerzeichen ein, die alle Platz brauchen, aber es lohnt sich trotzdem schon. Die Datei ist um ein gutes Drittel kleiner.

Wie geht das? Nun, die Originaldatei enthält ein <polyline>-Element für den Graphen selber und mehrere line-Elemente für die Markierung der Jahreszahlen. Das ist nicht falsch, aber beide Elemente können mit dem generischen <path>-Element deutlich effizienter dargestellt werden. Und deutlich schwerer lesbar. So wird zum Beispiel aus diesem Element:

<line x1="7" x2="7" y1="150" y2="210" style="stroke:#000;stroke-width:1"></line>

dieses hier (und ohne explizites End-Tag ist es auch noch einmal ein bisschen kürzer).

<path style="stroke:#000;stroke-width:1" d="M7 150v60"/>

Schritt 2: Gruppieren

Größe: 905 Byte

Der Output von svgo ist gut, aber wir können noch ein bisschen mehr optimieren. Und zwar indem wir die Elemente ein bisschen umsortieren und gruppieren.

Nun ist die Reihenfolge der Elemente in SVG-Dateien eigentlich nicht egal. Was zuerst kommt, wird zuerst gemalt, was danach kommt übermalt eventuell das, was vorher kommt. In diesem konkreten Fall aber brauchen wir uns darum keine Sorgen machen, da die einzigen Überschneidungen schwarz auf schwarz sind und man so nicht sieht, wenn sich etwas überschneidet.

Wir können also aus diesem Block hier:

<path style="stroke:#000;stroke-width:1" d="M7 150v60"/>
<text font-size="20" transform="rotate(-90 116 89)">2022</text>
<path style="stroke:#000;stroke-width:1" d="M187 150v60"/>
<text font-size="20" transform="rotate(-90 206 -1)">2023</text>
<path style="stroke:#000;stroke-width:1" d="M367 150v60"/>
<text font-size="20" transform="rotate(-90 296 -91)">2024</text>
<path style="stroke:#000;stroke-width:1" d="M547 150v60"/>
<text font-size="20" transform="rotate(-90 386 -181)">2025</text>
<path style="stroke:#000;stroke-width:1" d="M727 150v60"/>
<text font-size="20" transform="rotate(-90 476 -271)">2026</text>

den code hier machen:

<g style="stroke:#000;stroke-width:1">
    <path d="M7 150v60"/>
    <path d="M187 150v60"/>
    <path d="M367 150v60"/>
    <path d="M547 150v60"/>
    <path d="M727 150v60"/>
</g>
<g font-size="20">
    <text transform="rotate(-90 116 89)">2022</text>
    <text transform="rotate(-90 206 -1)">2023</text>
    <text transform="rotate(-90 296 -91)">2024</text>
    <text transform="rotate(-90 386 -181)">2025</text>
    <text transform="rotate(-90 476 -271)">2026</text>
</g>

Hier sind drei Dinge passiert. Erstens habe ich die Elemente umsortiert, wie schon angekündigt. Dann habe ich Elemente mit gleichen Attributen in <g>-Elemente, also Gruppierungselemente gesteckt. Drittens habe ich dann die Attribute in das <g>-Element verschoben. Gruppenattribute gelten nämlich für alle Elemente der Gruppe. Dadurch spart man Wiederholungen und somit Platz.

In diesem Fall hebt der gesparte Platz sogar die Codeeinrückung wieder auf. Die kommt zwar am Ende sowieso weg, fügt aber in diesem Zwischenschritt noch ein bisschen an Dateigröße hinzu.

Schritt 3: Style-Attribut

Größe: 882 Byte

Viele Eigenschaften von SVG-Elementen kann man sowohl mit dedizierten Attributen als auch mit dem style-Attribut abbilden. Rein vom Geschmack her bevorzuge ich die dedizierten Attribute, und in vielen Fällen sind sind die auch kürzer als ein Style-Attribut.

So kann man zum Beispiel statt

style="fill:none;stroke:#000;stroke-width:2"

folgendes machen:

fill="none" stroke="#000" stroke-width="2"

Zugegeben, das sind nur zwei Byte. Häufig kann man aber auch manche Attribute vollständig weglassen, weil sie der Standardeinstellung entsprechen, z.B.

style="stroke:#000;stroke-width:1"

vs.

stroke="#000"

Dieser Schritt bringt nicht immer etwas, aber oft genug, und besonders, wenn man mit Exports von Programmen wie inkscape arbeitet, die gerne einen ganzen Haufen unnützer Styles an ein Element hängen. svgo übrigens kann das auch, wenn man es mit einer Konfigurationsdatei konfiguriert, aber dazu später mehr.

Schritt 4: Zusammenfassen von Pfaden

Größe: 777 Byte

Das path-Element hat den Vorteil, dass es beliebig lange, auch unterbrochene Pfadteile aufnehmen kann. svgo ist gut darin, das zu erkennen und Pfade zusammenzufügen, die ansonsten gleiche Eigenschaften haben.

Warum hat svgo das dann hier noch nicht gemacht? Weil die Pfade, die man zusammenhängen könnte durch andere Elemente (die Jahreszahlen) getrennt waren und svgo nicht erkennen kann, dass das kein Problem ist (wie gesagt: Reihenfolge ist in SVG-Datein grundsätlich erst einmal relevant).

Wir haben aber in Schritt 2 umsortiert, also kann svgo die Pfade jetzt ohne Probleme zusammenfügen. Auch die Gruppe können wir uns dann sparen. Damit wird aus dem hier:

<g stroke="#000">
    <path d="M7 150v60"/>
    <path d="M187 150v60"/>
    <path d="M367 150v60"/>
    <path d="M547 150v60"/>
    <path d="M727 150v60"/>
</g>

dieses deutlich kürzere Stück code:

<path stroke="#000" d="M7 150v60M187 150v60M367 150v60M547 150v60M727 150v60"/>

Aber hey, da ist doch noch ein Pfad, der eigentliche Graph! Warum werden die beiden nicht zusammengefügt? Der erste Pfad hat eine andere Linienstärke als der zweite, deswegen müssen sie getrennt bleiben.

Schritt 5: Whitespace entfernen

Größe: 706 Byte

Zum Schluss lassen wir noch einmal svgo über das Ganze laufen. Dieses Mal nur mit --multipass, ohne --pretty. Damit werden auch die überschüssigen Leerzeichen entfernt.

Wir haben es also in diesem Beispiel geschafft, eine Datei von 1561 byte auf 706 Byte zu reduzieren, das sind fast 55% weniger. In anderen Fällen, wie den Outputs von gnuplot, habe ich es sogar um Faktor 6 reduziert. Das hier war ein einfaches Beispiel. Es gibt noch ein paar andere Wege, die Größen zu optimieren.

Weitere Optimierungsmöglichkeiten

Da wäre zunächst die Präzision der Kommazahlen, z.B. in Pfaden. Hier nicht relevant, weil wir nur Ganzzahlen haben. Auch ist diese Technik nicht verlustfrei. Man muss also nach Augenmaß vorgehen. In vielen Fällen konnte ich aber mit einer Präzision von zwei Nachkommastellen keinen Unterschied zum Original erkennen, auch stark hereingezoomed nicht. svgo kann das mit der Option --precision, z.B. --precision 2 für maximal zwei Nachkommastellen.

Überhaupt bietet svgo noch einige Plugins an, um Dateien weiter zu optimieren. Manche davon sollte man aber mit Vorsicht genießen, weil sie nicht in jedem Fall ein korrektes Ergebnis liefern. Die Liste der Plugins kann man mit --show-plugins anzeigen. Die Plugins zu konfigurieren ist ein bisschen umständlich. Man muss eine JS-Datei anlegen, in der dann die aktiven Plugins aufgelistet werden. Die Datei kann z.B. so aussehen:

module.exports = {
  plugins: [
    {
      name: 'convertTransform',
      params: {
      },
    },
  ],
};

Hier wird das convertTransform-Plugin aktiviert. Das rechnet Transformationen auf Pfaden so um, dass die Tansformation verschwindet und die Pfade selbst Koordinaten haben, die sie nach der Transformation gehabt hätten. Wegen Rundungsfehlern ist auch das nicht ganz verlustfrei.

Eine wichtige Information bezüglich der Konfigurationsdateien: Wenn man eine nutzt, dann sind nur die aufgelisteten Plugins aktiv. Also auch nicht die, die sonst standardmäßig aktiv sind (es sei denn, sie sind in der Datei aufgelistet). Also entweder alle lugins hinzufügen oder die Konfigurationsdatei nur selektiv (mit der --config-Option) verwenden.

Wichtig: Wenn die Konfigurationsdatei svgo.config.js heißt, wird sie automatisch angewandt (so lange sie im aktuellen Verzeichnis oder in einem darüberliegenden Verzeichnis liegt). Wenn man dann nicht alle Standardplugins in dieser Datei hat, kriegt man unter Umständen schlechte Ergebnisse mit svgo.

Ansonsten kann ich svgo nur sehr empfehlen, aber es schadet auch nicht, ab und zu mal zu schauen, was man noch von Hand optimieren kann. Zumindest nicht, wenn man so verrückt ist wie ich.

Blogstatistiken: Anzahl Posts pro Jahr / Monat

Ich bin gestern über einen Blogpost gestolpert, in dem der Blogger aus seinem Hugo-Blog eine Statistik über die Anzahl der Blogposts erstellt. Die hat er dann als Graph in den Seitenheader gesteckt.

Das hat mich inspiriert, selber mal eine Statistik über die Blogs pro Monat bzw. pro Jahr zu erstellen. Nichts, was ich in den Header stecken würde, aber etwas für einen Blogpost. Mein letzter Versuch mit Blogstatistiken, damals über Tag-Kombinationen war ja ziemlich langweilig, aber eine Anzahl der Blogposts über die Zeit ist ja interessanter. Ich habe also mein Blogstatistik-Programm ein wenig erweitert, ein Gnuplot-Script erstellt und schwupps habe ich ein paar schöne Graphen.

Um ehrlich zu sein: Ich habe mehr Zeit verwendet, den Graphen schön zu machen und die Größe der SVG-Dateien manuell um eine Größenordnung zu verringern als mich das eigentliche Sammeln der Statistik gekostet hat. Aber nun zum ersten Graphen: Anzahl der Blogposts über die Jahre hinweg:

Die Anzahl der Blogposts pro Jahr nimmt von 2009 ab (mit einem kleinen Spike in 2014), und bleibt von 2016 bis 2019 unter 10. Danach steigt sie wieder.

In der Anfangszeit (mein erstes, nicht selbst-gehostetes Blog) war ich sehr aktiv, was dann abgenommen hat. 2014 gab es einen Spike, wegen meines Kochprojektes. Als ich dann angefangen habe, in Hamburg zu arbeiten ist die Anzahl der Blogpost stark zurückgegangen, bis zu einem Minimum von nur 4 Posts in 2019. Dann, 2020, habe ich wieder mehr gepostet und vor allem auch meine Blogsoftware erneuert. Vielleicht hat mich das ja auch dazu motiviert, wieder mehr zu schreiben.

2025 war dann wieder ein sehr produktives Jahr. Das Jahr mit den drittmeisten Blogposts in diesem Blog überhaupt. Und die dürften auch im Schnitt deutlich länger sein als die Posts aus 2009 und 2010, die Jahre mit den meisten Posts.

Eine Monatsaufstellung habe ich auch:

Im Prinzip das gleiche Bild wie in der Jahresaufstellung, nur feiner aufgeschlüsselt nach Monaten.

Mit Abstand der Monat mit den meisten Posts war der allererste Monat des Blogs, Februar 2008. Ich habe auch das jeweils laufende Jahr bzw. den laufenden Monat mit reingenommen, obwohl da noch etwas dazu kommt. Mit dem aktuellen Stand hat 2026 aber gute Chancen, wieder auf einem der ersten Plätze zu landen.

Wenn ich mich das nächste Mal um Statistiken kümmere, dann schaue ich mir vielleicht einmal die Länge der Blogposts über die Zeit an (mittlere Länge und Varianz). Könnte vielleicht ganz interessant sein.

⍼ Angzarr Azimut ⍼

Das Rätsel des Angzarr ist gelöst. Es stammt wohl aus einem deutschen Symbolkatalog aus den späten 1940ern / frühen 1950ern. Es steht für Azimut, eine der Koordinaten am Himmel.

Dieselbe Person, die auch damals schon recherchiert hat, hat dazu einen kleinen Blogpost veröffentlicht, auch mit Scans des Symbolkatalogs.

Im Übrigen finde ich, dass sich „Angzarr Azimut“ wie ein Zauberspruch anhört. Oder wie der Name eines Zauberers. Vielleicht kann ich das ja in eine Rollenspielrunde einbauen :)

Meteorit in Koblenz

In Koblenz ist ein Meteor niedergegangen, ein Meteorit hat ein Hausdach durchschlagen. Verletzt wurde niemand, das Loch war auch nur fußballgroß. Ein ziemlich großes Loch, wenn man es im Dach hat und jetzt warme Luft raus und Regen reinkommt, aber zum Aussterben der Dinosaurier hätte es bei Weitem nicht gereicht.

Wenn man nicht gerade Eigentümer des Hauses ist oder in dem Haus wohnt eine coole Sache. Die Wissenschaftler suchen jetzt überall in der Gegend nach den Bruchstücken.

Your AI slop bores me

Immer wieder findet man ja auch schöne Sachen im Internet. Das hier ist eine davon. Auf youraislopbores.me (vermutlich nicht aus Montenegro, trotz der TLD) kann man sich, ähnlich wie bei „AI“-Text und -Bildgeneratoren Texte und Bilder erstellen lassen. Die Bilder werden von echten Menschen erstellt. Anders herum kann man nämlich auch selber die Rolle der „AI“ übernehmen und Bilder bzw. Texte für andere erzeugen. Man hat dann eine Minute Zeit, um etwas zu tippen oder mit einem simplen Zeichentool (à la skribble) etwas zu zeichnen.

Es gibt dafür ein Credit-System: Man startet mit einem Credit oder so, und jede Anfrage kostet einen Credit. Man bekommt jede Stunde einen Credit, kann sich aber auch Credits verdienen, indem man anderen ihre Prompts beantwortet. Während ich da war, gab es mehr Leute, die Prompts beantworten wollten als solche, die Prompts geschrieben haben, aber ich kann sagen, dass beide Seiten spaßig sind.

Mein erster Prompt war ein Bild eines zaubernden Otters:

Mein Prompt: „draw an otter casting a spell“. Darunter eine Strichzeichnung eines auf auf den Hinterpfoten stehenden Otters, von dem mehrere bunte Linien ausgehen, die sich in zwischen den Vorderpfoten zu einem bunten Ball mischen

Nachdem ich selber ein paar Prompts beantwortet hatte, konnte ich meinen nächsten Prompt abgeben. Leider hat sich hier ein Missverständnis eingeschlichen :)

Mein Prompt: „Please draw a monster with too many eyes“. Die Zeichnung ist der Schriftzug „Monstiir“

Beim zweiten Versuch habe ich aus Versehen einen Text und nicht ein Bild angefordert. Die Person am anderen Ende hat sich trotzdem Mühe gegeben:

Selber Prompt, Antwort: „This is a text prompt but I'll try anyway.“, danach eine ASCII-Art mit vielen Augen

Der dritte Versuch war dann ein voller Erfolg:

Selber Prompt, Die Zeichnung ist ein Kreisförmiges Monster mit Spitzen Zähnen und sechs im Kreuz angeordneten Augen in verschiedenen Farben.

Probiert es aus, es ist lustig.

PS: Ich bin mir nicht sicher, wie hier die Urheberrechstlage ist. Theoretisch liegt das Urheberrecht bei den Leuten, die die Zeichnungen gemacht haben. Ich veröffentliche sie trotzdem hier, mit dem Verweis, dass ich keine Rechte an diesen Bildern habe und sie demnach auch nicht under der CC-Lizenz veröffentliche, unter der der meiste Inhalt dieses Blogs steht. Ich hoffe, dass sich niemand beschwert.

Irankrieg

Nur eine kurze Durchsage: Ich werde hier bis auf Weiteres nichts über Trumps Angriffskrieg auf den Iran schreiben. Ich schaffe das nervlich einfach nicht. Die ganze Geschichte ist so unverständlich für mich, und der US-Kriegsminister hat öffentlich angekündigt, Kriegsverbrechen zu begehen, ich will nichts darüber schreiben und ich will mich nicht mehr als nötig damit beschäftigen. Wie so vieles bei Trump fehlen mir sowieso die Worte dazu.

Glücklicherweise gibt es genug andere Quellen, die sich darüber aufregen und viele davon sind sogar vertrauenswürdige Quellen. Grundsätzlich hier in diesem Blog: Ich schreibe nicht über jedes Thema, das mich aufregt. Das schaffe ich einfach nicht. Das heißt nicht, dass mir diese Themen egal sind.

Es wird immer noch depubliziert

Seit 2010 müssen nun die öffentlich-rechtlichen Sender die meisten ihrer Inhalte nach ein paar Tagen wieder „depublizieren“, d.h. von ihren Websites entfernen. Ich hatte mich damals schon darüber aufgeregt.

Nun hat die Bedeutung des Linearfernsehens seitdem schon abgenommen. In Anbetracht der Desinformation, die heute im Netz besonders in social networks verbreitet ist, sind die öffentlich-rechtlichen Sender aber meiner Meinung nach um so wichtiger. Dafür zahle ich auch gerne meine Rundfunkgebühren.

Ich habe aber weder Radio noch Fernseher. Ich kann auf die Produkte der Sender nur per Internet zugreifen. Und ich bin nicht die einzige Person, der das so geht. Depublizieren bedeutet, aktiv Wert zu zerstören, der von allen deutschen Haushalten bezahlt wird. Und warum? Ich habe das immer noch nicht verstanden. Es ist doch eindeutig im öffentlichen Interesse, dass diese Inhalte online bleiben.

Warum rege ich mich jetzt gerade darüber auf? Nun, ich habe vor Kurzem diesen Blogpost gefunden: „ist depublizieren bildungsfeindlich?“. Es ist vielleicht nicht das größte politische Problem, mit dem wir gerade zu kämpfen haben, aber vielleicht sollten wir das Gesetz hier einmal ändern.

Digital Independence Day: Wero?

Heute ist wieder Digital Independence Day. Eigentlich hatte ich überlegt, mir heute mal Wero anzuschauen, ein europäischer Zahlungsdienst, der zum Beispiel Paypal ersetzten könnte (es momentan aber noch nicht tut).

Ich bin aber schon beim ersten Schritt gescheitert. Ich habe mich informiert, wie ich das anstellen soll. Zwar wird Wero von meiner Bank unterstützt, aber… nur mit einer Smartphone-App. Bzw. der Smartphone-App der Bank , die allerdings nur über den Google-Store installierbar ist. Den habe ich auf meinem Gerät aber nicht (und den zu installieren wäre ein Schritt gegen digitale Unabhängigkeit). Also kein Wero, nicht einmal zu Ausprobieren.

Mir gehen aber sonst so langsam die Sachen aus, wo ich noch sinnvoll umsteigen kann. Betriebssystem? Linux. Email: Posteo. Git: Codeberg. Gut, ich hätte noch einen alten Amazon-Account, den ich seit Jahren nicht genutzt habe, den könnte ich symbolisch löschen. Oder ich könnte mal versuchen, ob Wine bzw. Steams Wine-Fork Proton gut genug sind, dass ich auf meinem Spielerechner kein Windows mehr brauche (da ich dort kein Windows 11 installieren kann, wäre das sowieso überfällig). Das wiederum kostet aber Zeit, die ich heute nicht habe, weil ich endlich mal ein paar kleine Gartenarbeiten bei meiner Mutter erledigen konnte.

Meine Mutter ist in der Hinsicht übrigens erfolgreicher und hat ihrem Lebensgefährten einen Posteo-Account angelegt. Vielleicht schaffe ich es ja, noch irgendjemand anderen von einem Wechsel irgendwo zu überzeugen.

Im April mache ich übrigens nichts zum Digital Independence Day. Da bin ich im Urlaub, und gebe mein Bestes, an dem Tag keinen Computer (das schließt mein Telefon ein) anzufassen.

Im Mai mache ich dann vielleicht die Sache mit dem Spielecomputer…

Darkmode

Für die ganzen Darkmode-Fanatiker hat dieses Blog jetzt auch einen Darkmode. Ich habe da nicht super viel Arbeit reingesteckt, aber modernes CSS mit Variablen erlaubt mir, das recht einfach einzustellen.

Da ich hier und da transparente Bilder habe, die sich bisher auf einen hellen Hintergrund verlassen haben, habe ich Bildhintergründe grundsätzlich hell gemacht.

Falls ihr also im Browser oder OS bevorzugt den Darkmode ausgewählt habt, dann sollte diese Seite jetzt anders aussehen. Wie gesagt, ich habe nicht viel Arbeit hineingesteckt und hauptsächlich Farben vertauscht.