#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_PIXELS_PIXELFORMATS_UNSIGNEDBITADJUST_H #define NUCLEX_PIXELS_PIXELFORMATS_UNSIGNEDBITADJUST_H #include "Nuclex/Pixels/Config.h" #include "BitShift.h" #include // for std::size_t namespace Nuclex { namespace Pixels { namespace PixelFormats { // ------------------------------------------------------------------------------------------- // /// Adjust a color channel's number of bits /// Bit count of the origin color channel /// Bit count the color channel will be converted to /// /// /// Adjusting the number of bits in a color channel is not an entirely trivial /// problem. Consider the following: /// /// /// std::size_t eightBit = (fourBit << 4); /// /// /// This kind of expansion would cap the expanded value's maximum intensity /// ot 0xF0 (240 instead of 255). Alternative methods like multiplying instead /// of bit-shifting or even converting to float will be slow. This class /// offers a few verified methods that produce the correct result fast. /// /// /// IMPORTANT: For the output, garbage bits before and after the correct result /// can be generated. If the result does not happen to be exactly the size of /// a type, an extra AND operation with a bit mask of the output range is needed. /// /// template class UnsignedBitAdjuster; // ------------------------------------------------------------------------------------------- // /// Keeps the number of bits the same /// The number of bits both channels have template class UnsignedBitAdjuster { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 5 template<> class UnsignedBitAdjuster<4, 5> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 6 template<> class UnsignedBitAdjuster<4, 6> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 8 template<> class UnsignedBitAdjuster<4, 8> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 10 template<> class UnsignedBitAdjuster<4, 10> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 16 template<> class UnsignedBitAdjuster<4, 16> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { TPixel originalTwice = BitShift<-4>(original) | original; return ( BitShift(originalTwice) | BitShift(originalTwice) ); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 5 to 4 template<> class UnsignedBitAdjuster<5, 4> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 6 template<> class UnsignedBitAdjuster<5, 6> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 8 template<> class UnsignedBitAdjuster<5, 8> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 10 template<> class UnsignedBitAdjuster<5, 10> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 16 template<> class UnsignedBitAdjuster<5, 16> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { TPixel originalTwice = BitShift<-5>(original) | original; return ( BitShift(originalTwice) | BitShift(originalTwice) ); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 6 to 4 template<> class UnsignedBitAdjuster<6, 4> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 6 to 5 template<> class UnsignedBitAdjuster<6, 5> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 8 template<> class UnsignedBitAdjuster<6, 8> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 10 template<> class UnsignedBitAdjuster<6, 10> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 16 template<> class UnsignedBitAdjuster<6, 16> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 4 template<> class UnsignedBitAdjuster<8, 4> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 5 template<> class UnsignedBitAdjuster<8, 5> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 6 template<> class UnsignedBitAdjuster<8, 6> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 8 to 10 template<> class UnsignedBitAdjuster<8, 10> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 8 to 16 template<> class UnsignedBitAdjuster<8, 16> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// /// Position of the bits in the result relative to the input value /// /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 4 template<> class UnsignedBitAdjuster<10, 4> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 5 template<> class UnsignedBitAdjuster<10, 5> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 6 template<> class UnsignedBitAdjuster<10, 6> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 8 template<> class UnsignedBitAdjuster<10, 8> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 10 to 16 template<> class UnsignedBitAdjuster<10, 16> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return ( BitShift(original) | BitShift(original) ); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 4 template<> class UnsignedBitAdjuster<16, 4> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 5 template<> class UnsignedBitAdjuster<16, 5> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 6 template<> class UnsignedBitAdjuster<16, 6> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 8 template<> class UnsignedBitAdjuster<16, 8> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 10 template<> class UnsignedBitAdjuster<16, 10> { /// Widens or narrows a color channel's bits /// Lowest bit in the source channel /// Lowest bit in the target channel /// Type used to store the pixel /// Original color value that will be adjusted /// The adjusted color value public: template NUCLEX_PIXELS_ALWAYS_INLINE static constexpr TPixel Adjust(TPixel original) { return BitShift(original); } }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Pixels::PixelFormats #endif // NUCLEX_PIXELS_PIXELFORMATS_UNSIGNEDBITADJUST_H