Add custom implementation of half float

This commit is contained in:
2025-03-06 15:35:12 +01:00
parent 7b70b6cce5
commit 05b0aa9a2f
3 changed files with 90 additions and 8 deletions
+1
View File
@@ -54,6 +54,7 @@ set(TENMON_SRC
statusbar.cpp statusbar.h statusbar.cpp statusbar.h
stfslider.cpp stfslider.h stfslider.cpp stfslider.h
stretchtoolbar.cpp stretchtoolbar.h stretchtoolbar.cpp stretchtoolbar.h
tfloat16.h
) )
qt_add_resources(TENMON_SRC resources/resources.qrc) qt_add_resources(TENMON_SRC resources/resources.qrc)
+28 -8
View File
@@ -1,6 +1,7 @@
#include "rawimage.h" #include "rawimage.h"
#include <cstring> #include <cstring>
#include <lcms2.h> #include <lcms2.h>
#include <algorithm>
#ifndef NO_QT #ifndef NO_QT
#include <QDebug> #include <QDebug>
#include <QElapsedTimer> #include <QElapsedTimer>
@@ -8,9 +9,16 @@
#include <QColorSpace> #include <QColorSpace>
using F16 = qfloat16; using F16 = qfloat16;
#else #else
#include <algorithm> #define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <float.h>
#ifdef FLT16_MAX
using F16 = _Float16; using F16 = _Float16;
#endif #else
#include "tfloat16.h"
using F16 = TFloat16;// this is only for MXE
#endif // FLT16_MAX
#endif // NO_QT
int THUMB_SIZE = 128; int THUMB_SIZE = 128;
int THUMB_SIZE_BORDER = 138; int THUMB_SIZE_BORDER = 138;
@@ -464,13 +472,25 @@ void RawImage::convertToThumbnail()
if(m_channels == 1) if(m_channels == 1)
{ {
out[idx] = out[idx + 1] = out[idx + 2] = (F16)(in[idx2] * scale); if(scale == 1.0f)
out[idx] = out[idx + 1] = out[idx + 2] = (F16)(in[idx2]);
else
out[idx] = out[idx + 1] = out[idx + 2] = (F16)(in[idx2] * scale);
} }
else else
{ {
out[idx] = (F16)(in[idx2] * scale); if(scale == 1.0f)
out[idx + 1] = (F16)(in[idx2 + 1] * scale); {
out[idx + 2] = (F16)(in[idx2 + 2] * scale); out[idx] = (F16)(in[idx2]);
out[idx + 1] = (F16)(in[idx2 + 1]);
out[idx + 2] = (F16)(in[idx2 + 2]);
}
else
{
out[idx] = (F16)(in[idx2] * scale);
out[idx + 1] = (F16)(in[idx2 + 1] * scale);
out[idx + 2] = (F16)(in[idx2 + 2] * scale);
}
} }
out[idx + 3] = (F16)1.0f; out[idx + 3] = (F16)1.0f;
} }
@@ -546,9 +566,9 @@ void convertType2(size_t size, const T *src, U *dst)
if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>)) if constexpr(std::is_integral_v<T> && (std::is_floating_point_v<U> || std::is_same_v<U, F16>))
{ {
U scale = (U)(1.0 / (double)std::numeric_limits<T>::max()); float scale = (float)(1.0 / (double)std::numeric_limits<T>::max());
for(size_t i = 0; i < size; i++) for(size_t i = 0; i < size; i++)
dst[i] = (U)src[i] * scale; dst[i] = (U)(src[i] * scale);
} }
} }
+61
View File
@@ -0,0 +1,61 @@
#ifndef TFLOAT16_H
#define TFLOAT16_H
// crude implementation of float16 for platforms that do not support _Float16
#include <stdint.h>
class TFloat16
{
uint16_t b16;
public:
TFloat16(){ b16 = 0; }
explicit inline TFloat16(float f)
{
uint32_t i = *reinterpret_cast<uint32_t*>(&f);
uint32_t sign = (i >> 16) & 0x8000;
uint32_t exp = (i >> 23) & 0xff;
uint32_t mantisa = (i & 0x7fffff) >> 13;
b16 = 0;
if(exp < 111)
{
// do nothing it map to 0
}
else if(exp == 111)
{
b16 |= sign;
b16 |= mantisa;
}
else if(exp > 142)
{
b16 = 0x7c00;// inf
b16 |= sign;
}
else
{
b16 |= sign;
b16 |= (exp - 112) << 10;
b16 |= mantisa;
}
}
friend TFloat16 operator*(TFloat16 a, TFloat16 b)
{
return TFloat16(static_cast<float>(a) * static_cast<float>(b));
}
operator float() const
{
uint32_t i = 0;
uint32_t sign = b16 & 0x8000;
uint32_t exp = (b16 & 0x7c00) >> 10;
if(b16)
{
i |= sign << 16;
i |= (exp + 112) << 23;
i |= (b16 & 0x3ff) << 13;
}
return *reinterpret_cast<float*>(&i);
}
};
#endif // TFLOAT16_H