Reputation: 60
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();
}
Upvotes: 0
Views: 940
Reputation: 2530
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.
Upvotes: 1