In the vein of suggestions made by Martin Brown, David Eather, et al a while back, this is idea for a lossy compressor/decompressor designed to compress 10 bits of greyscale image data down to 8 in a semi-logarithmic way.
To avoid taking a square root on the output side the lossy "decompressor", such as it is, is two iterations of a modified Newton's method to compute the inverse.
Since the compression function is nearly linear when its input is small-valued using the 8 bit compressed value as the starting guess for the inverse helps prevent Newton from hunting over across the discontinuity in the input function, on the wrong side of the Y axis
#include
//family of curves of the form x = int( 0.5+k*y*(A + By)/(A + Cy))
constexpr auto compress(uint16_t y) -> uint8_t { //tweak "k" to taste to avoid overflow return 0.5 + 0.997 * y * (4096 + y) / (4096 + 32 * y); }
auto decompress(uint8_t x) -> uint16_t { auto f_y = [x](uint16_t y) { return compress(y) - x; };
auto f_y_prime = [](uint16_t y) { return (16351.2 + 7.984 * y + 0.0311875 * y * y) / ((128 + y) * (128 + y)); };
const uint16_t y_init = x;
auto y = y_init - f_y(y_init) / f_y_prime(y_init); y = y - f_y(y) / f_y_prime(0.5*(y + y_init)); auto y_prime = y - f_y(y) / f_y_prime(y); return y - f_y(y) / f_y_prime(0.5*(y + y_prime)); }