phoboslab / qoi

The “Quite OK Image Format” for fast, lossless image compression

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add a high-dynamic range support?

MaGetzUb opened this issue · comments

So add a high-dynamic range support by using the idea from radiance image format. Store the exponent in the alpha channel, and the floating point significands into the r, g and b channels. Naturally the HDR image would be therefore just RGB. The HDR images are useful in 3D graphics, especially with IBL (image based lighting.)

Technically nothing has to be changed in QOI format itself, except maybe add some sort of implication to the header that the image is HDR type, like QOI_FORMAT_RGBE (E stand for exponent, and implies high dynamic range). Only thing that is needed is RGB32F -> RGBE8 preprocessing and RGBE8 -> RGB32F post processing steps after the data is stored / loaded. I'm not sure how this sort of data storing will effect the compression rates, but there's only one way to find out.

Pseudo code for RGB32F to RGBE8 processing:

void RGB32F_RGBE8(const RGB32F* pixel, RGBE8* result) {

      float maximum = float_max(pixel->red, float_max(pixel->green, pixel->blue));

      if(maximum < 1-e32f) {
           result->red = result->green = result->blue = result->exponent = 0;
      } else {

           int32_t expo;
           float mantissa = frexpf(maximum, &exponent) * 256.0f / maximum;
           pixel->red = (uint8_t)(pixel->red * mantissa);
           pixel->green = (uint8_t)(pixel->green * mantissa);
           pixel->blue = (uint8_t)(pixel->blue * mantissa);
           result->exponent = (128 + expo);
      }

} 

And pseudocode for the same other way around:

void RGBE8_RGB32F(const RGBE8* pixel, RGB32F* result) {

    int32_t exponent = pixel->exponent - 128;
    
    float multiplier = powf(2.f, exponent);
    
    result->red = ((float)pixel->red) * multiplier / 256.0f);
    result->green = ((float)pixel->green) * multiplier / 256.0f);
    result->blue = ((float)pixel->blue) * multiplier / 256.0f);
    
}

That's how radiance / .hdr images basically do the conversion.

QOI's compression scheme relies on an alpha value that stays mostly constant. Wouldn't this then result in terrible compression?