2 Punkte von GN⁺ 2023-09-05 | 1 Kommentare | Auf WhatsApp teilen
  • Wenn man Textinhalte in einer PDF ohne kommerzielle PDF-Tools ändern will, muss man komprimierte Streams entpacken, die fontbezogene Kodierung nachvollziehen und Original- sowie Ersatztext auf dieselbe Weise austauschen
  • Viele PDFs speichern den eigentlichen Dokumenttext nicht als Klartext, sondern in komprimierten Streams und in Zeichenfolgen, die wie Hexadezimalwerte aussehen; mit qpdf --qdf --object-streams=disable lässt sich das in eine Form entpacken, die einer bearbeitbaren Darstellung näherkommt
  • Textblöcke bestehen aus PDF-Befehlen wie BT, Tf, Td, Tj und ET, und Werte wie <002a004800570003003600480057> Tj sind möglicherweise keine einfachen Unicode-Codepoints
  • Wenn die PDF eine fontbezogene ToUnicode-Zuordnung enthält, kann man mit pdffonts prüfen, ob emb und uni auf yes stehen, und über Referenzen wie /ToUnicode 19 0 R die Kodierungstabelle finden
  • Wegen der Komplexität des PDF-Standards lässt sich diese Methode nicht auf alle Dateien verallgemeinern, aber bei bestimmten PDFs kann man die ursprüngliche Kodierung ermitteln und den Text per find-and-replace ersetzen

Komprimierte PDF-Textstreams entpacken

  • Öffnet man eine PDF in einem Texteditor, ist ein Teil der Struktur lesbar, der eigentliche Dokumenttext aber möglicherweise nicht sichtbar
  • Viele PDFs speichern Textdaten in komprimierter Form
  • Mit qpdf lassen sich komprimierte Textstreams zur Prüfung entpacken
    • Auf dem Mac gibt es eine Homebrew-Formel
    • Auch in Linux-Distributionen sind entsprechende Tools verfügbar
qpdf --qdf --object-streams=disable in.pdf out.pdf
  • Nach der Bearbeitung lassen sich die Streams wieder komprimieren
qpdf out-edited.pdf out-recompressed.pdf
  • Der Re-Komprimierungsbefehl erzeugte zwar einen Fehler, die resultierende PDF ließ sich in Preview aber lesen

Text innerhalb von PDF-Befehlen finden

  • Auch nach dem Entpacken bleibt der Text in PDF-Befehlsblöcken eingebettet
  • Ein grundlegender Textblock sieht etwa so aus
BT
  /Font_0 12 Tf
  288 720 Td
  <002a004800570003003600480057> Tj
ET
  • Laut PDF Reference führt dieser Block nacheinander folgende Schritte aus
    • Ein Textobjekt beginnen
    • Die verwendete Schriftart und Größe festlegen
    • Die Startposition auf der Seite festlegen
    • Die Glyphen der Zeichenfolge an dieser Position zeichnen
    • Das Textobjekt beenden

Warum der Text nicht direkt lesbar ist

  • Werte wie <002a004800570003003600480057> sehen zwar wie Hex-Strings aus, sind aber möglicherweise keine einfache Liste von Unicode-Codepoints
  • PDFs bieten viele Arten, Kodierungen anzugeben, und können benutzerdefinierte Kodierungen in der Datei enthalten
  • Solche Kodierungen lassen sich meist auf Unicode-Codepoints abbilden
  • Dieses Vorgehen setzt voraus, dass die bearbeitete PDF eine eingebettete Kodierung enthält
    • Andere Fälle werden hier nicht behandelt

Schriftarten und Unicode-Zuordnung prüfen

  • Die Textkodierung einer PDF ist mit einer bestimmten Schriftart verknüpft
  • pdffonts zeigt Informationen zu Schriftarten und Kodierung in einer PDF an
$ pdffonts sample.pdf
name                                 type              emb sub uni prob object ID
------------------------------------ ----------------- --- --- --- ---- ---------
CLDQZB+TrebuchetMS,Bold              CID TrueType      yes yes yes           9  0
YQBAIZ+TrebuchetMS                   CID TrueType      yes yes yes          10  0
  • Relevante Felder sind hier
    • emb: bedeutet, dass die Schriftart in die PDF eingebettet ist
    • uni: bedeutet, dass eine Unicode-Zuordnung vorhanden ist
  • Wenn beide Werte yes sind, besteht eine gute Chance, die nötige Zuordnung zu finden
  • Ein Font-Identifier wie /Font_0 aus dem Beispiel entspricht je nach Fall dem Schriftnamen aus der pdffonts-Ausgabe
    • Im gezeigten Fall verwies /Font_0 auf CLDQZB+TrebuchetMS,Bold

Der ToUnicode-Zuordnungstabelle folgen

  • Nachdem man den vollständigen Namen der im Text verwendeten Schriftart gefunden hat, sucht man in der PDF intern nach diesem Namen
  • An einer bestimmten Stelle kann man dann auf eine Referenz wie diese stoßen
/ToUnicode 19 0 R
  • Dieser Wert verweist auf die Objekt-ID der Kodierungstabelle
  • Anschließend ließ sich die entsprechende Tabelle durch die Suche nach 19 0 obj finden

Text mithilfe der Kodierungstabelle ersetzen

  • Der zentrale Teil der Zuordnungstabelle kann etwa so aussehen
38 beginbfrange^M
<0036><0036><0053>^M
<0057><0057><0074>^M
<0044><0044><0061>^M
<0048><0048><0065>^M
<0050><0050><006D>^M
...
  • Dieses Beispiel ordnet Bereiche benutzerdefinierter Kodierungspunkte Unicode-Punkten zu
    • Hier besteht jeder Bereich nur aus einem einzelnen Zeichen
    • 0036 wird auf den Unicode-Punkt 0053 abgebildet
  • Falls das Tabellenformat anders aussieht, hilft das Tutorial zu ToUnicode-Mapping-Dateien
  • Für die automatische Umwandlung wurde die Tabelle in Python in ein Dictionary überführt und eine einfache Kodier-/Dekodierfunktion geschrieben
  • Der abschließende Ablauf für den Austausch ist folgender
    • Den benutzerdefinierten Kodierungswert des zu ersetzenden Originaltexts ermitteln
    • Den Ersatztext auf dieselbe Weise benutzerdefiniert kodieren
    • In der PDF per find-and-replace den alten Wert durch den neuen ersetzen

1 Kommentare

 
GN⁺ 2023-09-05
Hacker-News-Kommentare
  • Die PDF-Spezifikation ist ziemlich rau. Mein derzeit liebstes Trivia-Wissen ist, dass sie beim Rendern überlappender Elemente alle Layer-Blend-Modi von Photoshop unterstützt.
    Mein zweitliebstes ist, dass nachträglich angehängte Inhalte frühere Inhalte ändern können, sodass man forensisch alle unterschiedlichen Versionen untersuchen muss, die in einer Datei repräsentiert sind.
    Es ist auch ein Beispiel für die Sinnlosigkeit von DRM. Die Spezifikation enthält passwortbasierte Verschlüsselung, kann getrennte „Owner“- und „User“-Passwörter haben und hat auch Bitfelder wie „Drucken verboten“ und „Textkopieren verboten“. Aber um ein Dokument zu lesen, muss es letztlich entschlüsselt werden; wenn man also ein verschlüsseltes PDF mit dem „User“-Passwort in einem nicht konformen Tool öffnet und als unverschlüsselte Version speichert, erhält man ein bearbeitbares Äquivalent.
    [1] Abschnitt „More than just transparency“ von https://blog.adobe.com/en/publish/2022/01/31/20-years-of-tra...
    [2] https://blog.didierstevens.com/2008/05/07/solving-a-little-p...
    [3] Seite 61 von https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
    [4] Zum Beispiel ein Skript, das die pypdf-Bibliothek verwendet

    • Im Kontext, dass es ursprünglich ein proprietäres Format war, nicht allgemein für alle offengelegt wurde und in einer Zeit entstand, in der Verschlüsselung durch Exportgesetze stark kontrolliert wurde, war solche Security through Obscurity sehr verbreitet.
      Eines der damals bekannten Cracking-Tutorials entfernte das DRM des offiziellen Readers, indem es die Funktion patchte, die Berechtigungen prüft.
    • Anleitung: https://www.cyberciti.biz/faq/removing-password-from-pdf-on-...
    • Sind die unterstützten Blend-Modi nicht einfach Porter-Duff-Compositing-Modi? Das mag übertrieben wirken, passt aber sehr gut zu dem, was andere Rendering-Pipelines bieten, und hilft ziemlich dabei, den Aufwand beim Erzeugen von PDFs zu reduzieren.
    • Wenn man sich in das Berechtigungsfeld vertieft, landet man in einem Kaninchenbau: Man entdeckt, wie manche PDF-Ersteller die Spezifikation nicht einhalten, und welche Workarounds PDF-Reader oder Bibliotheken jeweils haben oder nicht haben.
    • Fairerweise: Wenn man das Kopieren von Text verhindern will, ist es am einfachsten, das ToUnicode-Mapping der Schriftart wegzulassen. Dann wird es für Leute zur Handarbeit, es selbst wiederherzustellen.
  • Dieses Thema kommt regelmäßig wieder auf; die meisten halten PDF für ein schwer zu knackendes Binärformat, tatsächlich ist es das aber nicht.
    PDF ist ein Objektgraph aus unterschiedlichen Typen, und die Typen selbst sind in der offiziellen Spezifikation gut beschrieben. Ich habe die schmerzhafte Neigung, sie zum Spaß zu lesen.
    Was ich immer empfehle, ist wie der Autor das PDF in eine Version ohne komprimierte Daten umzuwandeln. Mein bevorzugtes Tool ist mutool; mit mutool clean -d in.pdf out.pdf geht das. Wenn man danach darin herumstöbert, ist man überrascht, wie viel man nachvollziehen kann.
    Im Artikel fehlt der Schritt, sich das Page-Objekt anzusehen und die Ressourcen zu prüfen. Dort werden die im Content-Stream verwendeten Schriftnamen mit den tatsächlichen Unterobjekten verknüpft.
    Ein weiterer wichtiger fehlender Punkt ist, dass die meisten Schriftarten als Subsets in PDFs eingebettet sind. Nur die benötigten Glyphen bleiben in der Schrift erhalten. Re-Encoding scheint normalerweise hier zu passieren, und ToUnicode wird beibehalten, um Textkopieren oder PDF-Suche zu ermöglichen. Für Nutzer ist das ein nettes Extra, und meiner Erfahrung nach ist es meistens vorhanden und korrekt.

    • Wenn man das „zum Spaß liest“, ist man eher Masochist als Sadist. Wenn man an der Spezifikation mitgeschrieben oder andere dazu gebracht hätte, sie zu lesen, wäre man wohl Sadist.
    • Es ist schade, dass Adobe ein so schwer handhabbares Format entworfen hat, dass Leute überrascht sind, wenn jemand etwas hinbekommt, das eigentlich eine grundlegende Aufgabe sein sollte.
      Schon die Designphilosophie, ein Nur-Lese-Format schaffen zu wollen, war von Anfang an falsch. Es ist doch offensichtlich, welche Funktion die Leute als Erstes verlangen werden.
    • Wenn man Freude daran hat, Schmerz zu empfinden, ist man Masochist; wenn man gern anderen Schmerz zufügt, ist man Sadist. Da es eher so wirkt, als würdest du Leuten helfen wollen, passt Ersteres besser. Den mutool-Tipp weiß ich zu schätzen.
    • Für das Parsen von PDFs verlasse ich mich stark auf Amazon Textract.
      Ich frage mich, ob es weitere Erkenntnisse dazu gibt, wie man das ohne Cloud-Anbieter nativ gut hinbekommt. Besonders bei Tabellen.
  • So geht’s:
    Mit pdf2ps a.pdf in PostScript a.ps umwandeln
    Mit vim a.ps das PostScript direkt bearbeiten
    Mit ps2pdf a.ps wieder in PDF umwandeln
    Komplexe PDFs mit eingebettetem JavaScript oder Animationen funktionieren nach diesem Roundtrip manchmal nicht mehr richtig. Bei gewöhnlichen Dokumenten klappt es aber ziemlich gut. Wasserzeichen entfernen sowie Wörter und Zahlen ändern geht einfach; Abstände anzupassen ist schwieriger. Natürlich muss man sich mit PostScript einigermaßen auskennen

    • Bei einem früheren Arbeitgeber, einem Postverarbeitungsunternehmen, haben wir einen Teil der Druckvorbereitung ungefähr so gemacht. Normalerweise erstellten wir Druckdokumente mit richtigen Tools, aber gelegentlich meinten Kunden, sie wüssten es besser, und schickten PDFs; meistens bedeutete das mehr Handarbeit und ein höheres Fehlerrisiko
      Selbst wenn die Ausgabe stimmte, mussten Seiten neu sortiert, Barcodes für die Verarbeitung durch Kuvertier-/Postmaschinen und für die Postsortierung angebracht sowie Berichte erzeugt werden. Üblicherweise haben wir mit Perl und anderen Tools Text von den Seiten abgegriffen, um Adressen zu erhalten; mit PS war das im Allgemeinen viel einfacher als mit PDF, aber es gab auch sehr fragile Fälle, etwa wenn „sichere“ PDFs keine korrekten Glyph-Mappings hatten
      Im schlimmsten Fall schickte der Kunde einzelne Dokument-PDFs, und wenn man diese zusammenführte, explodierte in der Ausgabe die Zahl der Subset-Fonts, füllte den Druckerspeicher und brachte ihn zum Absturz. Als ich den Job aufgab, gab es meines Wissens immer noch kein nützliches Tool, das Subset-Fonts, die aus derselben Originalschrift stammten, vereinheitlichen und zusammenführen konnte. Das müsste eigentlich möglich sein und wäre sehr nützlich gewesen, aber mir fehlten Zeit und Wissen, um es mir anzusehen
    • Wenn man JavaScript und Animationen in PDFs einbetten kann, was hindert einen dann daran, darin ein Frontend zu bauen? Ich frage mich, wo die Grenzen dessen liegen, was man mit PDF machen kann
      Ehrlich gesagt wirkt es so, als würden von der Komplexität von PDF nur Malware-Autoren profitieren
  • Ein wichtiger Punkt scheint zu fehlen. Am Ende eines PDFs gibt es eine Tabelle, die Byte-Offsets der verschiedenen Objekte in der Datei speichert, die sogenannte Cross-Reference-Tabelle
    Wenn man die Datei bearbeitet, ändern sich diese Offsets normalerweise, und die Datei geht kaputt. Im Artikel ging es offenbar nur darum, eine Zahl durch eine andere zu ersetzen, sodass sich die Position vielleicht nicht geändert hat
    Im Allgemeinen muss man aber bei Einfügungen, Löschungen oder Änderungen in der Mitte der Datei die xref-Tabelle neu berechnen; daher ist es viel einfacher, eine Bibliothek zu verwenden, statt direkt im Texteditor zu arbeiten

    • Genau deshalb decodiert man mit qpdf und encodiert später wieder. Dann übernimmt qpdf diesen Teil
      qpdf rekonstruiert die ursprüngliche PDF-Struktur und scheint zu versuchen, auch die Objektnummern beizubehalten, aber die Offsets werden komplett neu berechnet
    • Ich halte das für den seltsamsten Teil der PDF-Spezifikation. Binäres und Text sind vermischt, und Byte-Offsets werden als Text angegeben
      Falls die Autoren irgendwann darüber sprechen, würde ich gern lesen, warum das Format so geworden ist. Es wirkt, als sei es anfangs als vollständig textbasiertes Format gedacht gewesen und man habe später entschieden, dass Binärdaten effizienter sind. Allerdings passt die Anforderung, dass xref-Tabelleneinträge eine feste Länge haben müssen, etwas merkwürdig zu dieser Annahme
    • Meiner Erfahrung nach ist es am einfachsten, die xref-Tabelle einfach kaputtzumachen und sie dann mit etwas wie mutool clean reparieren zu lassen. Da sie vollständig aus dem Inhalt abgeleitet werden kann, ist das sicher
    • Das ist dem Bearbeiten kompilierter Binärdateien ziemlich ähnlich
      Solange man die Länge beibehält, kann man Binärdateien nach Belieben ändern
      Eine Software, die ich früher verwendete, authentifizierte sich beim Server, aber die gesamte Verarbeitung fand auf dem Client statt. Der Client führte direkt SQL auf dem Server aus, und der Server prüfte nur, ob dieser Client die Zahl der gekauften Lizenzen überschritt
      Man konnte sie durch einen Disassembler jagen, die Prüfungsstelle finden, sie direkt durch ein JMP ersetzen und den verbleibenden Platz mit NOPs auffüllen
  • Bei der Verwendung des --qdf-Modus von qpdf scheint ein wichtiger Schritt zu fehlen. Nach dem Bearbeiten muss man die Datei durch das Dienstprogramm fix-pdf laufen lassen, damit alle Objekt-Offsets neu berechnet und die Cross-Reference-Tabelle am Dateiende neu aufgebaut werden. Ausnahme: Man hat nur an Ort und Stelle geändert, ohne Bytes hinzuzufügen oder zu entfernen
    Die Top 3 der interessanten PDF-Fakten sind diese

    1. PDF-Dokumente sind normalerweise 8-Bit-Binärdateien, aber mit dem ASCII85-Filter kann man gültige UTF-8-Klartext-PDFs erstellen, sogar inklusive Bildern
    2. PDF erlaubt eine enorme Menge bizarrer Funktionen: 3D-Objekte, JavaScript, Videos in eingebetteten Flash-Objekten, unsichtbare Kommentare und mehr. PDF/A ist eine wesentlich vernünftigere und sicherere Teilmenge
    3. Die PDF-Spezifikation erlaubt es, Widgets, zum Beispiel Formularsteuerelemente, als Rich Text zu schreiben, der eine Teilmenge von XHTML und CSS ist. Diese Funktion wird außerhalb des offiziellen Adobe Reader allerdings nur sehr selten unterstützt
      [0] Beispiel: https://lab6.com/2
    • Nach dem Bearbeiten reicht es, die Datei wie weiter oben beschrieben ohne Parameter durch qpdf laufen zu lassen. Dann werden die Daten neu komprimiert und die xref-Tabelle neu erstellt. Ein weiteres Tool ist nicht nötig
  • Wenn du deine PDF-Reise fortsetzen und mehr lernen möchtest, kannst du diese kürzlich zusammengestellte Dateisezierungs-Dokumentation lesen:
    https://pdfsyntax.dev/introduction_pdf_syntax.html

  • Was Leute bei PDFs oft übersehen: In gewisser Hinsicht sind sie eher ein Bildformat als ein Word-Dokument. Bei der Dokumentbearbeitung entsprechen Word-Dokumente, PDFs und Bilder ungefähr DAW-Projekten, MIDI und MP3 in der Musik, oder Java-Quellcode, JVM-Bytecode und reinem x86-Maschinencode in der Software
    Der Hauptzweck einer PDF-Datei ist es, vollkommen eindeutig festzulegen, was angezeigt oder gedruckt werden soll – mit deutlich weniger Bytes als ein echtes Bild. Sie nutzt aus, dass der Dokumentautor die Muster in der Dokumentstruktur kennt, und komprimiert bei richtiger Darstellung viel besser als ein echter Bildkompressionsalgorithmus. Wenn man zum Beispiel Zugriff auf die eigentliche Schriftart hat, ist es besser zu sagen: „Setze diese Zeichen an diese Koordinaten mit diesem Abstand“, statt jedes Auftreten eines Buchstabens als Teil eines Bildes abzulegen und darauf zu hoffen, dass der Kompressionsalgorithmus die Wiederholungen schon reduziert. Welches Zeichen zu welchem Wort gehört oder sogar welcher Unicode-Codepoint welchem Font-Glyphen entspricht, ist im Grunde nicht wichtig, wenn das einzige Ziel darin besteht, ein Dokumentbild effizient zu übertragen
    Bei einem editierbaren Dokument ist neben der Darstellung die semantische Struktur des Inhalts viel wichtiger. Es spielt eine Rolle, ob ein bestimmter Abstand im Text mehrere Leerzeichen sind, die nächste Spalte einer Tabelle oder eine merkwürdige Seitenanordnung wegen eines Bildes. Es ist auch wichtig, ob der Text unten auf jeder Seite vom Autor mehrfach eingefügt wurde oder ob er einmal eingegeben und als Fußzeile eingerichtet wurde. Wenn ein neuer Absatz hinzugefügt wird und sich dadurch das Seitenlayout ändern muss, ist es wichtig zu wissen, dass der letzte Absatz dieser Seite eine Fußnote ist und nicht auf die nächste Seite rutschen darf. Wenn eine Abschnittsüberschrift auf eine andere Seite wandert, muss sich das Inhaltsverzeichnis automatisch aktualisieren; es darf nicht bloß manuell eingegebener Text des Autors sein
    Aus Sicht eines Druckers oder Bildschirms ist all das egal. Er druckt oder zeigt einfach an, was ihm angewiesen wurde. In PDF müssen Fußnoten, Abschnittsüberschriften, Fußzeilen und Inhaltsverzeichnisse nichts Besonderes sein; sie können auch einfach bedeutungslos formatierter Text sein. Deshalb kann es nie zu 100 % korrekt werden, wenn man PDF für Zwecke verwendet, die nicht Anzeige oder Druck sind. Natürlich gibt es Bemühungen, das auszugleichen, und PDF-Erzeugungsprogramme können beliebige Metadaten einfügen, aber verpflichtend ist das nicht
    Das ist vielleicht nicht das mentale Modell, das die PDF-Autoren im Sinn hatten, aber es ist eine nützliche Perspektive, um zu verstehen, warum PDF so aufgebaut ist

    • Das ursprüngliche Ziel von PDF war es, eine portable druckgetreue Kopie zu erstellen. Echtes WYSIWYG. Eine PDF-Datei sollte gleich aussehen, egal ob man sie an einen Laserdrucker, eine Linotype-Maschine oder einen Bildschirm schickte
      Auf einem PostScript-Drucker sah die Ausgabe exakt gleich aus, und mit Type-1-Schriften sogar noch besser
  • Wer das tun will, verfehlt den Kern von PDF. PDF ist ein Seitenbeschreibungsformat und beschreibt daher nicht die Dokumentstruktur, sondern nur die sichtbaren Spuren auf der Seite
    Man sollte nicht versuchen, das PDF zu bearbeiten, sondern das Originaldokument, aus dem das PDF erzeugt wurde

    • Wenn Leute aufhören, mir PDFs zu schicken, die ich bearbeiten soll, höre ich auch auf, PDFs zu bearbeiten
      Irgendwie ist es „unprofessionell“ geworden, einfach das Dokument zu schicken, das zum Bearbeiten gedacht ist, und so landen wir am Ende in genau dieser Situation
    • PDF unterstützt auch Funktionen, um Informationen zur logischen Dokumentstruktur einzuschließen. Das nennt sich Tagged PDF
      Es ist optional, wird aber für Barrierefreiheit empfohlen. Ein Beispiel ist PDF/UA. Siehe dazu Kapitel 14.7–14.8 in [1]
      [1] https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandard...
    • An dieser Stelle ist „das sollte man nicht tun“ nicht besonders hilfreich. In der Realität gibt es sehr viele Situationen, in denen man auf die eine oder andere Weise zur PDF-Bearbeitung aufgefordert wird
    • Eine Schwierigkeit besteht darin, Korrekturen zu markieren, die wieder ins Originaldokument zurückfließen müssen. Man bekommt vom Setzer einen Korrekturabzug und muss markieren, was er ändern soll
      Den PDF-Text kann man nicht direkt ändern, denn der Setzer würde diese Änderung nicht sehen. Die Markup-Werkzeuge von Acrobat sind nicht schrecklich, aber sie reichen nicht an die Zeiten von Papier und rotem Bleistift heran. Es sei denn, man benutzt Acrobats „pencil“-Werkzeug. Ich wünschte, dieser Teil würde verbessert
    • Wenn es ein „Seitenbeschreibungsformat“ ist und nicht die Dokumentstruktur, sondern nur das Erscheinungsbild auf der Seite beschreibt, hätte man es dann nicht Page Description Format statt Portable Document Format nennen sollen?
  • Vor 20 Jahren habe ich bei einer Zeitung als Druckplatten-Verantwortlicher gearbeitet. Wir hatten zwei Kodak-„Drucker“ für Platten im Wert von je einer Million Dollar, wobei „Drucker“ nicht wirklich stimmt. Wenn ich mich richtig erinnere, wurde die Emulsion auf der Platte mit UV-Licht belichtet und dann in einem chemischen Bad herausgelöst
    Die Kodak-Geräte fielen häufig aus, und mein Chef öffnete dann direkt PostScript- oder EPS-Dateien, um Header oder fehlerhafte Stellen zu korrigieren, die die Layoutsoftware geschickt hatte. Danach lief es wieder. Nebenbei: Unsere riesige deutsche Offset-Rotationsmaschine lief unter Linux
    Mein Chef hieß, glaube ich, Bill. Ein guter Mensch, der mich mit 17 zu einem Sigur-Rós-Konzert mitgenommen hat. Jetzt sind es gleich zwei Geschichten, die nichts mit PDF zu tun haben

  • Guter Artikel. In den letzten etwa fünf Jahren habe ich beim Bau von DocSpring [1] viel in der PDF-Spezifikation gelesen, und trotzdem fühlt es sich an, als hätte ich nur an der Oberfläche gekratzt. qpdf ist ein hervorragendes Tool, und ein weiteres meiner Lieblingswerkzeuge ist RUPS [2], mit dem man tief in die PDF-Struktur eintauchen kann
    [1] https://docspring.com
    [2] https://github.com/itext/i7j-rups