Skip to main content

Mein virtuelles Bücherregal

Ein Bild sagt mehr als 1000 Listeneinträge

Ich habe vor einigen Jahren beschlossen, mir wenn es irgendwie geht, keine Bücher mehr anzuschaffen. Dabei geht es mir nicht darum, das ich nichts mehr lesen möchte, im Gegenteil, sondern um diese riesige raumverschlingende Menge an Papier in den Regalen, die man bei jedem Umzug einmal ein- und dann auch wieder auspacken muss. EBooks sind also OK und seither meine bevorzugte Art Bücher zu lesen.

So hat sich im Laufe der Zeit so einiges an Lesestoff angesammelt. Ich habe mir das ein oder andere Humble Bundle gekauft, mir die Klassiker aus der Gutenberg Sammlung in meine Sammlung geladen, jede Menge verbilligte Altauflagen von Grundlagenwissen gehortet, und neben der Sammlung aller verfügbaren Datenschleudern habe ich auch noch jede Menge Scans von interessanten Artikeln aufgehoben, als ich diese entsorgt habe. Im Laufe der Zeit sind so gut 1000 "Werke" zusammengekommen.

Wer wie ich mit Linux arbeitet wir zur Verwaltung wahrscheinlich ganz natürlich zu Calibre greifen., Damit kann ich die Bücher zwischen meinem PC und den Readern hin und her kopieren, Metadaten hinzufügen und auch direkt die Bücher lesen. Dabei bewege ich mich im Wesentlichen die ganze Zeit in einer langen Liste von Büchern. Und ich verliere ständig den Überblick.

Wie viel einfacher wäre jetzt ein Bücherregal

Oft hatte ich beim suchen in dieser Liste den Gedanken, wie viel intuitiver dieses Suchen ging als ich früher vor meinem Bücherregal stand. Ich wusste genau, das meine Fantasy Ecke dort begann, wo die neongrüne Ausgabe des Herrn der Ringe im Regal leuchtete, und die Programmierbücher standen auf Hüfthöhe und gruppierten sich rund um den dicken "C von A bis Z" Wälzer. Optisch markante Bücher bildeten eine Art mentales Gerüst in dem sich das Hirn sehr schnell orientieren kann. Das Auge ist immer noch der breitbandigste Eingangskanal des Menschen. Lange Listen nutzen diese Eigenschaft nur sehr unzureichend aus.

Also habe ich nach einem Plugin für Calibre gesucht um mir meine Sammlung als eine Art Bücherregal darstellen zu lassen, und zu meinem eigenen Erstaunen nicht gefunden.

Als sich kurz drauf meine Partnerin für ein Wochenende zu Hause verbarrikadierte, um letzte Hand an ihre Masterarbeit zu legen, hab ich das auch für einen kleinen Coders-Retreat getan, um an einer Umsetzung zu arbeiten. Das Ergebnis war dann kurz darauf schon sehr zufriedenstellend:

SVG als Mittel der Wahl

SVG also Scalable Vector Graphics, hatte für mich als Mittel der Wahl einige Vorteile

  • Es kann mit jedem Browser angezeigt werden, was bedeutet ich brauche die grafische Darstellung nur erzeugen, und muss mich nicht selbst um die Anzeige kümmern
  • Ich kann direkt in die Grafik Links einbauen, die dann vom Browser verarbeitet werden. Dadurch wird für jede Art von eBook (epub, mobi, pdf) genau der Betrachter aufgerufen, den das Betriebssystem dafür vorsieht. Auch darum muss ich mich nicht kümmern. Ich klicke auf das Buch, und es öffnet sich im Reader.
  • Die Grafik ist, wie der Name schon nahelegt skalierbar, ich kann also näher an das Regal zoomen, und sehe dann auch tatsächlich mehr Details.

Interessante Probleme bei der Umsetzung

Umgesetzt habe ich das ganze mit Python, der komplette Code liegt auf meinem Codeberg.

Unterschiedliche Grössen und Farben

Wenn ich in mein Bücherregal schaue (ich habe noch ca 1,5 Meter davon) dann fällt mir zum Beispiel direkt die Death Note Serie auf. Die Bücher sind alle kleiner als die anderen, und sie haben den gleichen Buchrücken. Etwas ähnliches wollte ich für meine virtuellen Bücher auch tun.

Gelöst habe ich das vorerst dadurch, dass ich je nach Verlag den Büchern eine einheitliche Farbe und Größe gebe. Das mache ich auf die simpelste Weise, die mir einfiel:

hex = hashlib.md5(self.publisher.encode('utf-8')).hexdigest()
h = int(int("0x" + str(hex)[-2:], 16)/2)
col = "#" + str(hex)[-6:]
pubcol = "#" + str(hex)[-8:-2]
hex = hashlib.md5(self.series.encode('utf-8')).hexdigest()
sercol = "#" + str(hex)[-8:-2]

link = SVG.SubElement(svg, "a",
                      href=self.formats[0],
                      type="application/epub+zip")

linktitle = SVG.SubElement(link, "title")
linktitle.text = self.title

book = SVG.SubElement(link, "rect",
                      fill=col,
                      stroke="black",
                      x=str(position),
                      y=str(bottom-192-h),
                      width=str(self.shelfspace()),
                      height=str(192+h))
book.set("stroke-width", "0.5")

publisher = SVG.SubElement(link, "rect",
                           fill=pubcol,
                           stroke="black",
                           x=str(position),
                           y=str(bottom-16),
                           width=str(self.shelfspace()),
                           height=str(16))
publisher.set("stroke-width", "0.5")

Ich generiere mir einfach aus dem Verlagsnamen einen md5 Hash (hier kommt es nicht auf cryptographische Sicherheit an) und benutze z.B. das letzte Byte davon um die Höhe zu berechnen, oder nehme die letzten 3 Bytes als Farbwert für den Buchrücken. Ähnliches mache ich dann mit einem kleinen Viereck am oberen Buchrand, um Serien unterscheiden zu können

Unterschiedliche Buchdicke

Eine weitere optische Besonderheit, die einem das auffinden von Büchern im Regal leicht machen ist die unterschiedliche Dicke der Bücher. Mein erster naiver Ansatz war zu sagen, dass mein dickstes Buch im Regal einfach 10 cm dick sein soll, und alle anderen entsprechend der Seitenzahl proportional dünner. Das ging jedoch ziemlich schief. Mein dickstes Buch hat etwa 4100 Seiten, meine dünnsten Bücher haben nur 2 - 5 Seiten. abgesehen davon das diese Scans von Artikeln dann im Regal kaum sichtbar wären, wäre es außerdem noch unmöglich ihren Rücken zu beschriften.

Dazu muss ein Buch bei mir mindestens 10mm dick sein. Ich habe den Büchern also quasi einen Einband verpasst der diese Mindestdicke hat, und nach einer Methode gesucht, wie die Dicke bei dünnen Büchern sehr schnell ansteigt, mit zunehmender Seitenanzahl dann aber immer langsamer wächst, bis schließlich 90mm erreicht sind. Plus Einband liege ich dann wieder bei 10cm heraus kam folgendes:

def shelfspace(self):
    return sqrt(1-(1-(self.seiten / Book.maxPages) ** 2)) * 90 + 10

Da sich das nicht auf Anhieb erschließt ist hier meine Skizze dazu:

nil

Wie man unten rechts sieht hatte ich kurz darüber nachgedacht das über Sinus und Kosinus zu machen, aber als ich den Radius eingezeichnet hatte, wurde deutlich, dass ich es hier mit einem rechtwinkligen Dreieck zu tun habe, und da geht immer a²+b²=c². Wenn man sich den Kreisbogen ansieht, und die Seitenanzahl von links nach rechts stetig steigt, dann sieht man wie die Dicke anfangs nahezu senkrecht zunimmt um dann immer langsamer auf die maximale Dicke zu klettern. Während es einen großen Unterschied macht, ob ein Buch 50 oder 150 Seiten hat, so ist es nahezu belanglos, ob es 1900 oder 2000 Seiten hat. Am Ende liegt es bei 90 Millimetern plus 10 Millimetern für den Einband.

Was ich noch tun möchte

Derzeit in Arbeit ist es die Bücher thematisch zu sortieren. Dazu brauche ich zunächst mal eine thematische Reihenfolge, und dazu müssen alle Bücher verschlagwortet werden. Bei 1000 Büchern nimmt das eine ganze Zeit in Anspruch, dann werde ich die Schlagworte inhaltlich gruppieren, und beim füllen darauf achten das in der passenden Reihenfolge zu tun. An die Regale kommen dann kleine Schildchen auf denen Steht welche Themen wo beginnen. Grosse Themen bekommen auch ein Schild an den Kopf des Regals ähnlich wie in einer Buchhandlung.

Die Buchrücken sollen realistischer werden, in dem Sinne, das sie das Cover ein wenig nachahmen. Ich möchte aus dem linken Rand des Covers (ein paar Pixel breit) einen Streifen erzeugen, der dann als Rücken genutzt wird.

Ein paar grafische Gimmicks, wie schräg angelehnte Bücher oder kleine Bücherstapel verschaffen bestimmt auch mehr Orientierung.

2020-04-13