Add custom implementation of half float
This commit is contained in:
@@ -54,6 +54,7 @@ set(TENMON_SRC
|
||||
statusbar.cpp statusbar.h
|
||||
stfslider.cpp stfslider.h
|
||||
stretchtoolbar.cpp stretchtoolbar.h
|
||||
tfloat16.h
|
||||
)
|
||||
|
||||
qt_add_resources(TENMON_SRC resources/resources.qrc)
|
||||
|
||||
+28
-8
@@ -1,6 +1,7 @@
|
||||
#include "rawimage.h"
|
||||
#include <cstring>
|
||||
#include <lcms2.h>
|
||||
#include <algorithm>
|
||||
#ifndef NO_QT
|
||||
#include <QDebug>
|
||||
#include <QElapsedTimer>
|
||||
@@ -8,9 +9,16 @@
|
||||
#include <QColorSpace>
|
||||
using F16 = qfloat16;
|
||||
#else
|
||||
#include <algorithm>
|
||||
#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#include <float.h>
|
||||
#ifdef FLT16_MAX
|
||||
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_BORDER = 138;
|
||||
@@ -464,13 +472,25 @@ void RawImage::convertToThumbnail()
|
||||
|
||||
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
|
||||
{
|
||||
out[idx] = (F16)(in[idx2] * scale);
|
||||
out[idx + 1] = (F16)(in[idx2 + 1] * scale);
|
||||
out[idx + 2] = (F16)(in[idx2 + 2] * scale);
|
||||
if(scale == 1.0f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -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>))
|
||||
{
|
||||
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++)
|
||||
dst[i] = (U)src[i] * scale;
|
||||
dst[i] = (U)(src[i] * scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+61
@@ -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
|
||||
Reference in New Issue
Block a user