// This file is part of VSTGUI. It is subject to the license terms // in the LICENSE file found in the top-level directory of this // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE #include "pixelbuffer.h" #include "vstguibase.h" //------------------------------------------------------------------------ namespace VSTGUI { namespace PixelBuffer { namespace Private { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4293) #endif //------------------------------------------------------------------------ template inline uint32_t shuffle (uint32_t input) { static constexpr auto s1 = bs1 * 8; static constexpr auto s2 = bs2 * 8; static constexpr auto s3 = bs3 * 8; static constexpr auto s4 = bs4 * 8; uint32_t b1 = (input & 0xFF000000); uint32_t b2 = (input & 0x00FF0000); uint32_t b3 = (input & 0x0000FF00); uint32_t b4 = (input & 0x000000FF); if constexpr (ByteOrder::kNativeByteOrder == ByteOrder::kLittleEndianByteOrder) { b1 = (s4 >= 0) ? b1 >> s4 : b1 << -s4; b2 = (s3 >= 0) ? b2 >> s3 : b2 << -s3; b3 = (s2 >= 0) ? b3 >> s2 : b3 << -s2; b4 = (s1 >= 0) ? b4 >> s1 : b4 << -s1; } else { b1 = (s1 >= 0) ? b1 << s1 : b1 >> -s1; b2 = (s2 >= 0) ? b2 << s2 : b2 >> -s2; b3 = (s3 >= 0) ? b3 << s3 : b3 >> -s3; b4 = (s4 >= 0) ? b4 << s4 : b4 >> -s4; } return b1 | b2 | b3 | b4; } #ifdef _MSC_VER #pragma warning(pop) #endif //------------------------------------------------------------------------ template inline void convert (uint8_t* buffer, uint32_t bytesPerRow, uint32_t width, uint32_t height) { for (auto y = 0u; y < height; ++y, buffer += bytesPerRow) { auto intPtr = reinterpret_cast (buffer); for (auto x = 0u; x < width; ++x, ++intPtr) { auto pixel = *intPtr; switch (SourceFormat) { case Format::ARGB: { switch (DestinationFormat) { case Format::ARGB: { // nothing to do break; } case Format::ABGR: { *intPtr = shuffle<-2, 0, 2, 0> (pixel); break; } case Format::BGRA: { *intPtr = shuffle<-3, -1, 1, 3> (pixel); break; } case Format::RGBA: { *intPtr = shuffle<-1, -1, -1, 3> (pixel); break; } } break; } case Format::ABGR: { switch (DestinationFormat) { case Format::ARGB: { *intPtr = shuffle<-2, 0, 2, 0> (pixel); break; } case Format::ABGR: { // nothing to do break; } case Format::BGRA: { *intPtr = shuffle<-1, -1, -1, 3> (pixel); break; } case Format::RGBA: { *intPtr = shuffle<-3, -1, 1, 3> (pixel); break; } } break; } case Format::RGBA: { switch (DestinationFormat) { case Format::ARGB: { *intPtr = shuffle<-1, -1, -1, 3> (pixel); break; } case Format::ABGR: { *intPtr = shuffle<-3, -1, 1, 3> (pixel); break; } case Format::BGRA: { *intPtr = shuffle<-2, 0, 2, 0> (pixel); break; } case Format::RGBA: { // nothing to do break; } } break; } case Format::BGRA: { switch (DestinationFormat) { case Format::ARGB: { *intPtr = shuffle<-3, -1, 1, 3> (pixel); break; } case Format::ABGR: { *intPtr = shuffle<-1, -1, -1, 3> (pixel); break; } case Format::BGRA: { // nothing to do break; } case Format::RGBA: { *intPtr = shuffle<0, -2, 0, 2> (pixel); break; } } break; } } } } } //------------------------------------------------------------------------ } // Private //------------------------------------------------------------------------ void convert (Format srcFormat, Format dstFormat, uint8_t* buffer, uint32_t bytesPerRow, uint32_t width, uint32_t height) { using namespace Private; switch (srcFormat) { case Format::ARGB: { switch (dstFormat) { case Format::ARGB: return; case Format::ABGR: { convert (buffer, bytesPerRow, width, height); break; } case Format::RGBA: { convert (buffer, bytesPerRow, width, height); break; } case Format::BGRA: { convert (buffer, bytesPerRow, width, height); break; } } break; } case Format::ABGR: { switch (dstFormat) { case Format::ARGB: { convert (buffer, bytesPerRow, width, height); break; } case Format::ABGR: return; case Format::RGBA: { convert (buffer, bytesPerRow, width, height); break; } case Format::BGRA: { convert (buffer, bytesPerRow, width, height); break; } } break; } case Format::RGBA: { switch (dstFormat) { case Format::ARGB: { convert (buffer, bytesPerRow, width, height); break; } case Format::ABGR: { convert (buffer, bytesPerRow, width, height); break; } case Format::RGBA: return; case Format::BGRA: { convert (buffer, bytesPerRow, width, height); break; } } break; } case Format::BGRA: { switch (dstFormat) { case Format::ARGB: { convert (buffer, bytesPerRow, width, height); break; } case Format::ABGR: { convert (buffer, bytesPerRow, width, height); break; } case Format::RGBA: { convert (buffer, bytesPerRow, width, height); break; } case Format::BGRA: return; } } } } //------------------------------------------------------------------------ } // PixelBuffer } // VSTGUI