Unbunt
Heute habe ich mehr über ICC profile gelernt, als ich eigentlich jemals wissen wollte. Alles fing damit an, dass ich darum gebeten wurde, einen hässlich-bunten PDF-Foliensatz auf druckerfreundliches schwarz-weiß zu reduzieren. Man gab mir freundlicherweise schon den Hinweis, dass OSX so etwas in der Richtung schon unterstützt, und zwar über ColorSync.

Nun liefert aber der Schwarz&Weiß filter ein ganz und gar ungewünschtes ergebnis bei dem erwähnten Foliensatz, nämlich weißen Text auf schwarzem Hintergrund. Meh. Also gehe ich der Sache nach und finde heraus was denn dieser Filter eigentlich macht: Nichts anderes, als ein icc Profil auf das Dokument anwenden. Wie es bei Top gear schon so schön heißt: "How hard can it be?(tm)"
Wat iss eijentlisch ennen ICC-Profil?
Das International Color Consortium spezifiziert das Profilformat, um Geräteübergreifend eine gleichmäßige Farbdarstellung zu ermöglichen. Kurzgefasst beschreibt ein ICC-Profil die Mathematischen operationen die auf die Farben in einem Dokument anzuwenden sind, damit es richtig dargestellt wird.
Damit kann man natürlich auch einigen Schindluder treiben, und sich „Abstrakte” Profile basteln, die irgendwas mit den Farben anstellen. So auch das mitgelieferte Schwarz&Weiß-Profil, welches im L*a*b* System Folgenden transform macht (Graphen vom ICC Profile Inspector):

Also den Luminanzkanal (Channel 0 im Bild) irgendwo in der mitte auf schwarz und weiß aufteilen. Wie komme ich jetzt also zum inversen ergebnis, also schwarzen Text auf weißen Folien? Spontan fällt mir ein, die Eingangskurve einfach umzudrehen. Und dann geht der Ärger auch schon los.
How to hack an ICC File
Es gibt keinen Editor für ICC Files. Keinen. Nada. Nichts. Gut, mit ColorSync kann man ein bisschen an den Metadaten rumspielen, mit dem Profile Inspector textfiles exportieren, aber danach nicht mehr importieren. Gnampf. Aber gut, es sind auch nur Bits und Bytes, schnell den Hexeditor (vim + xxd) und die Spezifikation (s.o.) ausgepackt, und frisch ans Werk.
Etwas verwirrung später steht folgendes in meinem XXD-File:
00000c0: 6d66 7432 0000 0000 0303 0200 0001 0000 mft2............ # [ sig ] [ rsvd ] #i#o #cRR [ e00 ] 00000d0: 0000 0000 0000 0000 0000 0000 0001 0000 ................ # [ e01 ] [ e02 ] [ e10 ] [ e11 ] 00000e0: 0000 0000 0000 0000 0000 0000 0001 0000 ................ # [ e12 ] [ e20 ] [ e21 ] [ e22 ] 00000f0: 0002 1000 0000 ffff 0000 ffff 0000 ffff ................ # #in #out [ in = 2x3x2 bytes ] 0000100: 0000 8000 8000 0000 8000 8000 0000 8000 ................ # [ clut 2^3 x 3 x 2 bytes | 3 0000110: 8000 0000 8000 8000 ff00 8000 8000 ff00 ................ # | 4 | 5 | 6 0000120: 8000 8000 ff00 8000 8000 ff00 8000 8000 ................ # | 7 | 8 ]
Die interessante Stelle dabei ist der mit „in” markierte Block. Das ist die "input Table", welche die Einganswerte bestimmt. Die Spezifikation sagt, dass die werte hier als (L,a,b) tupel, jeweils 16bit stehen. Das würde bedeuten, dass hier Lab-Anfang=(0,128,-128) und Lab-Ende=(100,-128,128) als Eckpunkte stünden. Die Praxis dagegen lehrte mich, dass es eigentlich L-Range=(0,100), a-Range=(-128,128) und b-Range(-128,128) sind. Also fix die L-Range umgedreht:
00000f0: 0002 1000 ffff 0000 0000 ffff 0000 ffff ................gespeichert und siehe da:

Das gewünschte Ergebnis. Hack complete... Das fertige File gibts wie immer rechts bei den Downloads.