/* ========================================================================= mRGBE (miniRGBE): reduced RGBE encoding of normalised RGB floats plus associated integer payload data. By default, this encoding consists of: - three signed 5-bit mantissas for each RGB colour channel, - a common 5-bit exponent, - and an associated 12-bit integer datum. However, this allocation can be modified within a 32-bit envelope if more precision is required by modifying mRGBE_MANTBITS, mRGBE_EXPBITS and mRGBE_DATABITS. The encoded float RGB tuples are assumed to lie in the range [-1, 1], with values in the interval [-mRGBE_MIN, mRGBE_MIN] clamped to 0, since these cannot be resolved. The encoded values are therefore normalised against a given normalisation factor (e.g. absolute maximum) in order to maximise the useful range. Roland Schregle (roland.schregle@{hslu.ch, gmail.com}) (c) Lucerne University of Applied Sciences and Arts, supported by the Swiss National Science Foundation (SNSF #179067, "Light Fields for Spatio-Temporal Glare Assessment") ========================================================================= $Id$ */ #ifndef _mRGBE_H #define _mRGBE_H #include /* Mantissa / exponent / payload data bits and their encoding ranges. NOTE: binary shifts can overflow if the number of bits is increased; in this case shifts must either be promoted to 64 bits (possibly at the expense of portability), or replaced by much slower pow(2, ..) */ #define mRGBE_MANTBITS 5 #define mRGBE_EXPBITS 5 #define mRGBE_DATABITS 12 /* Rounding amplitude for encoding NOTE: unit test indicates this actually _increases_ RMSE! */ #define mRGBE_ROUND 0 /* Jitter amplitude for decoding */ #define mRGBE_JITTER 0.5 /* Jitter encoded zeros (this may not always be desirable, depending on * the application */ /* #define mRGBE_ZEROJITTER */ /* Signed maximum for mantissa */ #define mRGBE_MANTMAX (1L << (mRGBE_MANTBITS - 1)) /* Absolute overflow limit for mantissa (sign flips if exceeded) */ #define mRGBE_MANTOVF ((mRGBE_MANTMAX << 1) - 1) #define mRGBE_MIN (1.0 / (1L << (1 << mRGBE_EXPBITS))) #define mRGBE_MAX 1.0 #define mRGBE_RANGE (mRGBE_MAX - mRGBE_MIN) #define mRGBE_DATAMAX ((1U << mRGBE_DATABITS) - 1) typedef union { struct { /* (mini)RGBE representation consisting of a 4-bit mantissa + sign * per RGB, a common 5-bit exponent, and a 12-bit payload data */ unsigned red: mRGBE_MANTBITS, grn: mRGBE_MANTBITS, blu: mRGBE_MANTBITS, exp: mRGBE_EXPBITS, dat: mRGBE_DATABITS; }; uint32_t all; } mRGBE; /* State for mRGBE encoding to offset and normalise floats in order to * optimally utilise the encoding range */ typedef struct { double min [3], max [3], norm [3]; } mRGBERange; mRGBERange *mRGBEinit (mRGBERange *range, double rgbMin [3], double rgbMax [3] ); /* Initialise range state for mRGBEencode()/mRGBEdecode() with * the specified float input ranges [rgbMin, rgbMax] in _absolute_ values * per colour channel. This sets the offset and normalisation for the * encoding. */ mRGBE mRGBEencode (double rgb [3], const mRGBERange *range, unsigned data); /* Encode signed float RGB tuple to mRGBE along with payload data. The * supplied range state must be previously initialised with mRGBEinit(). * A warning is issued if rgb lies outside the initialised range. */ unsigned mRGBEdecode (mRGBE mrgbe, const mRGBERange *range, double rgb [3]); /* Decode mRGBE, returning signed float RGB tuple in array rgb. The * associated payload data is decoded as return value. The supplied * range state must be previously initialised with mRGBEinit(). */ #endif