Skip to content

Instantly share code, notes, and snippets.

@DavidAntliff
Created December 19, 2017 02:26
Show Gist options
  • Save DavidAntliff/70e61ba7ab3908f2edb1b0f234ff5037 to your computer and use it in GitHub Desktop.
Save DavidAntliff/70e61ba7ab3908f2edb1b0f234ff5037 to your computer and use it in GitHub Desktop.
Encode 32bit float into three 8bit RGBA channels
#!/usr/bin/env python
# Store 32-bit floating point number within three 8bit channels of a 32-bit RGBA pixel.
# Only suitable for normalised input values in the range [0.0, 1.0).
#
# Refer: https://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
import numpy as np
def frac(x):
return x - np.floor(x)
def encode(v):
enc = np.float32((1.0, 256.0, 256.0**2, 256.0**3)) * v
enc = frac(enc)
enc -= (enc[1], enc[2], enc[3], enc[3]) * np.float32((1/256.0, 1/256.0, 1/256.0, 0.0))
return enc
def decode(rgba):
return np.dot(rgba, np.float32((1.0, 1/256.0, 1/(256.0**2), 1/(256.0**3))))
if __name__ == "__main__":
max_diff = 0.0
for x in np.linspace(0.0, 1.0, 1000, endpoint=False):
enc = encode(x)
enc8 = np.uint8(enc * 256.0)
dec8 = enc8 / 256.0
dec = decode(dec8)
max_diff = np.maximum(max_diff, x - dec)
print(f"{x}: {x - dec}")
print(f"Max diff {max_diff}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment