How are colorschemes represented in OS X Terminal.app Settings Files?

I'm interested in moving color values I've created for OS X Terminal to applications on other platforms, such as Linux. I'm familiar with the usual methods of representing color values like RGB, HSB, L*A*B, HEX, etc. However, the <data> strings used in Terminal settings files are unlike other methods used to define colors. I'd like help understanding this XML <data> type in relation to other color values.

As an example, I used OS X's built-in Color Picker to manually change Terminal's default ANSI scheme with HSB values from Ethan Schoonover's excellent Solarized. I then saved those settings in an XML .plist called Solarized Dark xterm-256color.terminal (The contents of that file may be found here.)

I arbitrarily chose brblack from that file as a single color value for comparison:

    <key>ANSIBrightBlackColor</key>
    <data>
    YnBsaXN0MDDUAQIDBAUGFRZYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
    AAGGoKMHCA9VJG51bGzTCQoLDA0OVU5TUkdCXE5TQ29sb3JTcGFjZVYkY2xhc3NOMCAw
    LjE2NDUgMC4yMQAQAoAC0hAREhNaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yohIU
    WE5TT2JqZWN0XxAPTlNLZXllZEFyY2hpdmVy0RcYVHJvb3SAAQgRGiMtMjc7QUhOW2Jx
    c3V6hY6WmaK0t7wAAAAAAAABAQAAAAAAAAAZAAAAAAAAAAAAAAAAAAAAvg==
    </data>

This looks much different (and more complex) than the simple HSB value 193 100 21 taken from Schoonover's table:

    SOLARIZED HEX     16/8 TERMCOL  XTERM/HEX   L*A*B      RGB         HSB
    --------- ------- ---- -------  ----------- ---------- ----------- -----------
    base03    #002b36  8/4 brblack  234 #1c1c1c 15 -12 -12   0  43  54 193 100  21
    ...

Why does the simple value 193 100 21 get converted into a data string 5 lines long? What other information is contained in that string? Finally, and most importantly, how can I convert such a string into simple standard color values that I can use on other platforms?


bplist means binary property list, which can be converted to XML with plutil -convert xml1. Inside each plist for a color is another data key for the fractional RGB values.

/usr/libexec/PlistBuddy -x -c 'Print "Window Settings":"My Theme"' ~/Library/Preferences/com.apple.Terminal.plist|tr -d '\n\t'|grep -o '[^>]*</key><data>[^<]*'|while read l;do echo ${l%%<*} $(base64 -D<<<${l##*>}|plutil -convert xml1 - -o -|awk '/<data>/{getline;print}'|tr -d '\t'|base64 -D);done

The output looks like this:

ANSIBlueColor 0.4769933663 0.4769933663 0.9314516129
ANSICyanColor 0.2666655827 0.8165705831 0.8588709677
ANSIGreenColor 0.428833897 0.8508064516 0.490967087
ANSIMagentaColor 0.9072580645 0.4499707336 0.9072580645
ANSIRedColor 0.9072580645 0.508503512 0.508503512
ANSIYellowColor 0.9072580645 0.9072580645 0.3914379553
CursorColor 0.9998760223 0.999984026 0.999786377
SelectionColor 0.3899414837 0.4639441073 0.5917825699
TextBoldColor 0.9441435337 0.4102420509 0.427282244
TextColor 1 0.99997437 0.9999912977

You're looking at base64 encoded serialized data.

Base64 + serialized original:

 YnBsaXN0MDDUAQIDBAUGFRZYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3AS
AAGGoKMHCA9VJG51bGzTCQoLDA0OVU5TUkdCXE5TQ29sb3JTcGFjZVYkY2xhc3NOMCAw
LjE2NDUgMC4yMQAQAoAC0hAREhNaJGNsYXNzbmFtZVgkY2xhc3Nlc1dOU0NvbG9yohIU
WE5TT2JqZWN0XxAPTlNLZXllZEFyY2hpdmVy0RcYVHJvb3SAAQgRGiMtMjc7QUhOW2Jx
c3V6hY6WmaK0t7wAAAAAAAABAQAAAAAAAAAZAAAAAAAAAAAAAAAAAAAAvg==

Using something like http://www.base64decode.org/, you can see the decoded version:

bplist00X$versionX$objectsY$archiverT$topU$null    
UNSRGB\NSColorSpaceV$classN0 0.1645 0.21Z$classnameX$classesWNSColorXNSObject_NSKeyedArchiverTroot#-27;AHN[bqsuz

At this point, the interesting part is: NSKeyedArchiver which is the built-in serialization engine in Objective-C, which of course, OSX apps are written in.

As for the question behind your question, of how to convert between this and other standard representations of color: The answer is unfortunately, not easily or reliably.

It's clear that you know how to take an HSB value and generate the encoded data. If you wanted to take the time to reverse engineer how the archiving happens, you'd be able to do it. Not sure what your familiarity with the objective c language is, but you could probably make a simple program that converts between the two. Essentially, probably not worth your time.