diff --git a/CMakeLists.txt b/CMakeLists.txt index abec9b8..6e69fb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/rawimage.cpp b/rawimage.cpp index a35be38..36ec0f2 100644 --- a/rawimage.cpp +++ b/rawimage.cpp @@ -1,6 +1,7 @@ #include "rawimage.h" #include #include +#include #ifndef NO_QT #include #include @@ -8,9 +9,16 @@ #include using F16 = qfloat16; #else -#include +#define __STDC_WANT_IEC_60559_TYPES_EXT__ +#include +#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 && (std::is_floating_point_v || std::is_same_v)) { - U scale = (U)(1.0 / (double)std::numeric_limits::max()); + float scale = (float)(1.0 / (double)std::numeric_limits::max()); for(size_t i = 0; i < size; i++) - dst[i] = (U)src[i] * scale; + dst[i] = (U)(src[i] * scale); } } diff --git a/tfloat16.h b/tfloat16.h new file mode 100644 index 0000000..3e5237e --- /dev/null +++ b/tfloat16.h @@ -0,0 +1,61 @@ +#ifndef TFLOAT16_H +#define TFLOAT16_H + +// crude implementation of float16 for platforms that do not support _Float16 + +#include + +class TFloat16 +{ + uint16_t b16; +public: + TFloat16(){ b16 = 0; } + explicit inline TFloat16(float f) + { + uint32_t i = *reinterpret_cast(&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(a) * static_cast(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(&i); + } +}; + +#endif // TFLOAT16_H