Skip to main content
2 of 3
added 722 characters in body

I realize now that this question is analogous to asking to fit an ordered set of $2^N$ discrete points into a cube of discrete points with size $2^8 \times 2^8 \times 2^8$. The discrete points will snake around in this cube (they can't be scattered because that will make the Libschitz constant of $f:2^N \to 2^8 \times 2^8 \times 2^8$ large).

Looking at how matplotlib's HSV colormap clarified this. matplotlib's HSV cmap maps $[0,1] \to 2^8 \times 2^8 \times 2^8$, and really in implementation it maps $2^8 \to 2^8 \times 2^8 \times 2^8$ because their code uses a lookuptable with size 256. The way it maps the unit interval to RGB is like so:

enter image description here

This means on the $2^8 \times 2^8 \times 2^8$ cube we can snake a $6\times 2^8$ long line across the edges in a loop like so, starting and ending at the black dot:

enter image description here

For this particular mapping that covers 6 edges, it can store 8 bits of information 6 times. So $N\approx 10.58$ and $K = 6$. We could easily think of extending this loop to 8 faces without our path crossing, then $N=11$ and $K=8$.

And you can go further, snaking around a longer and longer line. So the relationship becomes clear:

For an injective mapping $f: 2^N \to 2^8 \times 2^8 \times 2^8$ with Lipschitz-1 bound $K$, $K$ and $N$ are not independent. If $N=8$, $K=1$ which is small, but if $N=24$, $K$ must be large. In fact as far as I understand for $N\geq 8$, $K=2^{N-8}$.

To fit a lot of bits into a colormap, your colors must change fast when you draw the colormap for the unit interval.

The HSV colormap with its 10.58 bits looks like:

enter image description here

But a colormap where Red stores the 8 most significant bits, Green the 8 middle significant bits, and Blue the 8 least significant bits, of a 24 bit fixed point number in $[0,1]$ looks like:

enter image description here

This means if you have a collection of data that you need to encode into a sequence of colors, and you expect some small noise added to each color channel before inverting back to the original data format, you will not be able to invert with to the original noiseless data with anywhere near $2^{24}$ bits precision.

Following @Will Sawin's answer, we can draw a Hilbert curve in $2^8 \times 2^8 \times 2^8$ space to make the colormap, with more subcubes leading to a longer curve. For 3 subcubes per side this looks like:

enter image description here

This image is from here where there is also code to generate these paths. I've included the colormaps for 1,2,3, and 4 subcubes per side:

enter image description here

Plotting the RGB of these paths makes the paths clearer:

enter image description here