Jump to content

  • Log In with Google      Sign In   
  • Create Account


LogLUV conversion now working


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 Chris_F   Members   -  Reputation: 1972

Like
0Likes
Like

Posted 30 December 2012 - 05:34 AM

I wrote a small program to test the conversion from HDR RGB to LogLUV. It takes a HDR image (.EXR) and then converts the floating point RGB pixel value to an 32-bit LogLUV value. It then converts it back to floating point RGB and saves the image to a new EXR file.

 

For some reason, I know not why, it is not working.

 

#include <iostream>

#include <FreeImage.h>

#include <glm/glm.hpp>


using namespace glm;


FIBITMAP* LoadImage(const char* filename)

{

    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;

    fif = FreeImage_GetFileType(filename);

    if(fif == FIF_UNKNOWN)

    {

        fif = FreeImage_GetFIFFromFilename(filename);

    }

    if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif))

    {

        return FreeImage_Load(fif, filename);

    }

    return NULL;

}


// M matrix, for encoding

const mat3 M(

    0.2209, 0.3390, 0.4184,

    0.1138, 0.6780, 0.7319,

    0.0102, 0.1130, 0.2969

);


// Inverse M matrix, for decoding

const mat3 InverseM(

    6.0014, -2.7008, -1.7996,

    -1.3320,  3.1029, -5.7721,

    0.3008, -1.0882,  5.6268

);


vec4 LogLuvEncode(vec3 vRGB)

{

    vec4 vResult;

    vec3 Xp_Y_XYZp = vRGB * M;

    Xp_Y_XYZp = glm::max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));

    vResult.x = Xp_Y_XYZp.x / Xp_Y_XYZp.z;

    vResult.y = Xp_Y_XYZp.y / Xp_Y_XYZp.z;

    float Le = 2 * glm::log2(Xp_Y_XYZp.y) + 127;

    vResult.w = glm::fract(Le);

    vResult.z = (Le - (glm::floor(vResult.w*255.0f))/255.0f)/255.0f;

    return vResult;

}


vec3 LogLuvDecode(vec4 vLogLuv)

{

    float Le = vLogLuv.z * 255 + vLogLuv.w;

    vec3 Xp_Y_XYZp;

    Xp_Y_XYZp.y = glm::exp2((Le - 127) / 2);

    Xp_Y_XYZp.z = Xp_Y_XYZp.y / vLogLuv.y;

    Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;

    vec3 vRGB = Xp_Y_XYZp * InverseM;

    return glm::max(vRGB, 0);

}


int main()

{

    FIBITMAP* dib = LoadImage("in.exr");


    int width = FreeImage_GetWidth(dib);

    int height = FreeImage_GetHeight(dib);


    FIBITMAP* dib2 = FreeImage_AllocateT(FIT_RGBF, width, height);


    for(int y = 0; y < height; y++)

    {

        FIRGBF* InputPixel = (FIRGBF*)FreeImage_GetScanLine(dib, y);

        FIRGBF* OutputPixel = (FIRGBF*)FreeImage_GetScanLine(dib2, y);


        for(int x = 0; x < width; x++)

        {

            vec3 input(InputPixel[x].red, InputPixel[x].green, InputPixel[x].blue);


            vec4 enc = LogLuvEncode(input);


            BYTE r = enc.r * 255.0;

            BYTE g = enc.g * 255.0;

            BYTE b = enc.b * 255.0;

            BYTE a = enc.a * 255.0;


            vec3 dec = LogLuvDecode(vec4(r,g,b,a) / 255.0);


            OutputPixel[x].red = dec.r;

            OutputPixel[x].green = dec.g;

            OutputPixel[x].blue = dec.b;

        }

    }


    FreeImage_Save(FIF_EXR, dib2, "out.exr");

}

 

This doesn't work.

 

#include <iostream>

#include <FreeImage.h>

#include <glm/glm.hpp>


using namespace glm;


FIBITMAP* LoadImage(const char* filename)

{

    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;

    fif = FreeImage_GetFileType(filename);

    if(fif == FIF_UNKNOWN)

    {

        fif = FreeImage_GetFIFFromFilename(filename);

    }

    if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif))

    {

        return FreeImage_Load(fif, filename);

    }

    return NULL;

}


// M matrix, for encoding

const mat3 M(

    0.2209, 0.3390, 0.4184,

    0.1138, 0.6780, 0.7319,

    0.0102, 0.1130, 0.2969

);


// Inverse M matrix, for decoding

const mat3 InverseM(

    6.0014, -2.7008, -1.7996,

    -1.3320,  3.1029, -5.7721,

    0.3008, -1.0882,  5.6268

);


vec4 LogLuvEncode(vec3 vRGB)

{

    vec4 vResult;

    vec3 Xp_Y_XYZp = vRGB * M;

    Xp_Y_XYZp = glm::max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));

    vResult.x = Xp_Y_XYZp.x / Xp_Y_XYZp.z;

    vResult.y = Xp_Y_XYZp.y / Xp_Y_XYZp.z;

    float Le = 2 * glm::log2(Xp_Y_XYZp.y) + 127;

    vResult.w = glm::fract(Le);

    vResult.z = (Le - (glm::floor(vResult.w*255.0f))/255.0f)/255.0f;

    return vResult;

}


vec3 LogLuvDecode(vec4 vLogLuv)

{

    float Le = vLogLuv.z * 255 + vLogLuv.w;

    vec3 Xp_Y_XYZp;

    Xp_Y_XYZp.y = glm::exp2((Le - 127) / 2);

    Xp_Y_XYZp.z = Xp_Y_XYZp.y / vLogLuv.y;

    Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;

    vec3 vRGB = Xp_Y_XYZp * InverseM;

    return glm::max(vRGB, 0);

}


int main()

{

    FIBITMAP* dib = LoadImage("in.exr");


    int width = FreeImage_GetWidth(dib);

    int height = FreeImage_GetHeight(dib);


    FIBITMAP* dib2 = FreeImage_AllocateT(FIT_RGBF, width, height);


    for(int y = 0; y < height; y++)

    {

        FIRGBF* InputPixel = (FIRGBF*)FreeImage_GetScanLine(dib, y);

        FIRGBF* OutputPixel = (FIRGBF*)FreeImage_GetScanLine(dib2, y);


        for(int x = 0; x < width; x++)

        {

            vec3 input(InputPixel[x].red, InputPixel[x].green, InputPixel[x].blue);


            vec4 enc = LogLuvEncode(input);


            vec3 dec = LogLuvDecode(enc);


            OutputPixel[x].red = dec.r;

            OutputPixel[x].green = dec.g;

            OutputPixel[x].blue = dec.b;

        }

    }


    FreeImage_Save(FIF_EXR, dib2, "out.exr");

}

 

However, this does.


Edited by Chris_F, 30 December 2012 - 05:39 AM.


Sponsor:

#2 Chris_F   Members   -  Reputation: 1972

Like
0Likes
Like

Posted 30 December 2012 - 06:32 AM

I don't get it. The algorithm I'm using can be seen all over the Internet. http://realtimecollisiondetection.net/blog/?p=15

 

But when I test the LogLuvEncode function with values { 1.0, 1.0, 1.0 } I get back { 2.32873, 3.62699, 0.504747, 0.215164 }.

 

Why are the values not in the range [0, 1]?



#3 Marcel Stockli   Members   -  Reputation: 167

Like
1Likes
Like

Posted 02 January 2013 - 04:22 PM

Did you checked the matrix order? (row major, column major). Your matrix constructor should have the same order than the HLSL Matrix constructor because the code you are usin, originally was HLSL. The same with the vector-matrix multiplication.



#4 Chris_F   Members   -  Reputation: 1972

Like
0Likes
Like

Posted 02 January 2013 - 08:54 PM

Thanks, that was the problem. This isn't the first time matrix order has done this to me. rolleyes.gif



#5 Marcel Stockli   Members   -  Reputation: 167

Like
0Likes
Like

Posted 03 January 2013 - 12:40 PM

No problem! Cool you fixed it, that kind of errors are very annoying.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS