So it happened today that I was forced to use a library in C++ which stores RGB8 colors in float. I personally think it is a really bad design decision but I had to deal with that.
Simple function like the following one doesn’t work:
1 2 3 4 5 |
float getRGB(uchar r, uchar g, uchar b) { return (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b)); } |
The problem is that the uint32_t is implicitly converted to float and the binary layout is lost.
After a quick google search I had arrived at this:
1 2 3 4 5 6 |
float getRGB(uchar r, uchar g, uchar b) { uint32_t rgb = (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b)); return *reinterpret_cast<float*>(&rgb); } |
It works correctly and maybe it is an idiomatic way to achieve this but to me it seems a bit hacky. After a while I had recalled unions and decided to use the following code:
1 2 3 4 5 6 7 8 9 10 |
float getRGB(uchar r, uchar g, uchar b) { union { uint32_t colorUInt32; float colorFloat; } rgb; rgb.colorUInt32 = static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | static_cast<uint32_t>(b); return rgb.colorFloat; } |
It is a bit longer but to me it seems much more readable. Also my inner geek is satisfied that I’ve used union and it actually made sense (: