Я пытаюсь портировать код показанный в этом посте ( Как преобразовать значение vec4 rgba в число с плавающей точкой? ) в Qt (C ++). Я вставил весь код ниже. Мои результаты не совсем точны. Есть идеи, что я делаю не так?
Результаты:
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
Код:
#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();
}
Это невозможно, по крайней мере, не с этим методом. Float имеет 32 бита данных, но он должен представлять такие вещи, как NaN и бесконечность. Таким образом, у вас фактически есть менее 32 бит, чтобы попытаться сохранить ваше значение rgba, но для этого нужны полные 32 бита (по 8 бит для красного, зеленого, синего и альфа). Это не может быть сделано, если вы не приведете память к int, который побеждает цель.
Других решений пока нет …