From 8f7f527732e30a4b35250bb5696bd55418d69f67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Du=C5=A1an=20Poizl?= Date: Tue, 29 Oct 2024 19:42:36 +0100 Subject: [PATCH] Add RawImage::convertToType() --- rawimage.cpp | 129 +++++++++++++++++++++++++++++++++++++-------------- rawimage.h | 1 + 2 files changed, 96 insertions(+), 34 deletions(-) diff --git a/rawimage.cpp b/rawimage.cpp index 3695a4d..c36b669 100644 --- a/rawimage.cpp +++ b/rawimage.cpp @@ -435,45 +435,106 @@ void RawImage::convertToThumbnail() void RawImage::convertToGLFormat() { - size_t s = size() * m_ch; - if(m_type == UINT32) - { - m_origWidth = m_width; - m_origHeight = m_height; - m_original = std::move(m_pixels); - allocate(m_width, m_height, m_channels, FLOAT32); - m_origType = UINT32; - float *dst = reinterpret_cast(m_pixels.get()); - uint32_t *src = reinterpret_cast(m_original.get()); + if(m_type == UINT32 || m_type == FLOAT64) + convertToType(FLOAT32); + else if(OpenGLES && m_type == UINT16) + convertToType(FLOAT16); +} - for(size_t i = 0; i < s; i++) - dst[i] = src[i] / (float)UINT32_MAX; - } - else if(m_type == FLOAT64) +template +void convertType2(uint32_t size, const T *src, U *dst) +{ + if constexpr((std::is_floating_point_v || std::is_same_v) && (std::is_floating_point_v || std::is_same_v)) { - m_origWidth = m_width; - m_origHeight = m_height; - m_original = std::move(m_pixels); - allocate(m_width, m_height, m_channels, FLOAT32); - m_origType = FLOAT64; - float *dst = reinterpret_cast(m_pixels.get()); - double *src = reinterpret_cast(m_original.get()); - - for(size_t i = 0; i < s; i++) + for(uint32_t i = 0; i < size; i++) dst[i] = src[i]; } - else if(OpenGLES && m_type == UINT16) - { - m_origWidth = m_width; - m_origHeight = m_height; - m_original = std::move(m_pixels); - allocate(m_width, m_height, m_channels, FLOAT16); - m_origType = UINT16; - F16 *dst = reinterpret_cast(m_pixels.get()); - uint16_t *src = reinterpret_cast(m_original.get()); - for(size_t i = 0; i < s; i++) - dst[i] = (F16)(src[i] / (float)UINT16_MAX); + if constexpr(std::is_integral_v && std::is_integral_v) + { + if constexpr(sizeof(T) > sizeof(U)) + for(uint32_t i = 0; i < size; i++) + dst[i] = src[i] >> ((sizeof(T) - sizeof(U)) * 8); + else + for(uint32_t i = 0; i < size; i++) + dst[i] = static_cast(src[i]) << ((sizeof(U) - sizeof(T)) * 8); + } + + if constexpr((std::is_floating_point_v || std::is_same_v) && std::is_integral_v) + { + U max = std::numeric_limits::max(); + T scale = (T)(max); + for(uint32_t i = 0; i < size; i++) + dst[i] = src[i] * scale; + } + + if constexpr(std::is_integral_v && (std::is_floating_point_v || std::is_same_v)) + { + U scale = 1.0 / std::numeric_limits::max(); + for(uint32_t i = 0; i < size; i++) + dst[i] = (U)src[i] * scale; + } +} + +template +void convertType(uint32_t size, RawImage::DataType dstType, const T *src, void *dst) +{ + switch(dstType) + { + case RawImage::UINT8: + convertType2(size, src, static_cast(dst)); + break; + case RawImage::UINT16: + convertType2(size, src, static_cast(dst)); + break; + case RawImage::UINT32: + convertType2(size, src, static_cast(dst)); + break; + case RawImage::FLOAT16: + convertType2(size, src, static_cast(dst)); + break; + case RawImage::FLOAT32: + convertType2(size, src, static_cast(dst)); + break; + case RawImage::FLOAT64: + convertType2(size, src, static_cast(dst)); + break; + } +} + +void RawImage::convertToType(DataType type) +{ + if(type == m_type) + return; + + m_origWidth = m_width; + m_origHeight = m_height; + m_original = std::move(m_pixels); + DataType origType = m_type; + allocate(m_width, m_height, m_channels, type); + m_origType = origType; + + uint32_t s = size() * m_ch; + switch(m_origType) + { + case UINT8: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; + case UINT16: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; + case UINT32: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; + case FLOAT16: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; + case FLOAT32: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; + case FLOAT64: + convertType(s, type, reinterpret_cast(m_original.get()), m_pixels.get()); + break; } } diff --git a/rawimage.h b/rawimage.h index 26c10dd..c565025 100644 --- a/rawimage.h +++ b/rawimage.h @@ -103,6 +103,7 @@ public: void setPlanar(); void convertToThumbnail(); void convertToGLFormat(); + void convertToType(RawImage::DataType type); float thumbAspect() const; bool pixel(int x, int y, double &r, double &g, double &b) const; void resize(uint32_t w, uint32_t h);