简体   繁体   中英

Qt ( C++ ) Convert between 32 bit float and QRgba

I am attempting to port the code shown in this post ( How do I convert a vec4 rgba value to a float? ) to Qt ( C++ ). I've pasted the entire code below. My results are not quite exact. Any ideas as to what I am doing wrong?

Results:

Input:  -10.01
Sign:  1  F:  10  Sign:  1  Exponent:  130  Mantissa:  1.25
Red:  193  Green:  32  Blue:  0  Alpha:  0
Result:  -10.0151 

Input:  -1
Sign:  1  F:  1  Sign:  1  Exponent:  127  Mantissa:  1
Red:  191  Green:  128  Blue:  0  Alpha:  0
Result:  -1.00195 

Input:  5.3
Sign:  0  F:  5  Sign:  0  Exponent:  129  Mantissa:  1.25
Red:  64  Green:  160  Blue:  0  Alpha:  0
Result:  5.0116 

Code:

#include <QCoreApplication>
#include <math.h>
#include <QColor>
#include <QDebug>

float step(float edge, float x) {
    if ( x < edge ) {
        return 0.0;
    }
    else {
        return 1.0;
    }
}

QColor encode32(float f) {

    //float e = 5.0;
    qDebug() << "Input: " << f;
    float F = abs(f);
    float Sign = step(0.0,-f);
    float Exponent = floor(log2(F));
    float Mantissa = F/exp2(Exponent);
    if(Mantissa < 1)
        Exponent -= 1;
    Exponent +=  127;
    qDebug() << "Sign: " << Sign << " F: " << F << " Sign: " << Sign << " Exponent: " << Exponent << " Mantissa: " << Mantissa;
    float red = 128.0 * Sign  + floor(Exponent*exp2(-1.0));
    float green = 128.0 * fmod(Exponent,2.0) + fmod(floor(Mantissa*128.0),128.0);
    float blue = floor(fmod(floor(Mantissa*exp2(23.0 -8.0)),exp2(8.0)));
    float alpha = floor(exp2(23.0)*fmod(Mantissa,exp2(-15.0)));
    qDebug() << "Red: " << red << " Green: " << green << " Blue: " << blue << " Alpha: " << alpha;
    QColor rgba;
    rgba.setRed(red);
    rgba.setGreen(green);
    rgba.setBlue(blue);
    rgba.setAlpha(alpha);
    return rgba;

}

float decode32 (QColor rgba) {

    float red = rgba.redF() * 255.0;
    float green = rgba.greenF() * 255.0;
    float blue = rgba.blackF() * 255.0;
    float alpha = rgba.alphaF() * 255.0;

    float Sign = 1.0 - step(128.0,red)*2.0;
    float Exponent = 2.0 * fmod(red,128.0) + step(128.0,green) - 127.0;
    float Mantissa = fmod(green,128.0)*65536.0 + blue*256.0 + alpha + float(0x800000);
    float Result =  Sign * exp2(Exponent-23.0f) * Mantissa;
    return Result;
}

int main(int argc, char *argv[])
{

    QCoreApplication a(argc, argv);


    {
        float result;
        QColor rgba = encode32(-10.01);
        result = decode32(rgba);
        qDebug() << "Result: " << result << "\n";
    }

    {
        float result;
        QColor rgba = encode32(-1.0);
        result = decode32(rgba);
        qDebug() << "Result: " << result << "\n";
    }

    {
        float result;
        QColor rgba = encode32(5.3);
        result = decode32(rgba);
        qDebug() << "Result: " << result << "\n";
    }

    return a.exec();

}

It is not possible, at least not with that method. A float has 32 bits of data, but it has to represent things like NaN and infinity. So, you effectively have fewer than 32 bits to attempt to store your rgba value, but it needs a full 32 bits (8 bits each for red, green, blue, alpha). It can't be done, not unless you cast the memory to an int which defeats the purpose.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM