#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_BITADJUST_H #define NUCLEX_PIXELS_PIXELFORMATS_BITADJUST_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 BitAdjuster; // ------------------------------------------------------------------------------------------- // /// Keeps the number of bits the same /// The number of bits both channels have template class BitAdjuster { /// Widens or narrows a color channel's bits /// 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 original; } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 5 template<> class BitAdjuster<4, 5> { /// Widens or narrows a color channel's bits /// 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<-1>(original) | BitShift<3>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 6 template<> class BitAdjuster<4, 6> { /// Widens or narrows a color channel's bits /// 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<-2>(original) | BitShift<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 8 template<> class BitAdjuster<4, 8> { /// Widens or narrows a color channel's bits /// 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 original | BitShift<-4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 10 template<> class BitAdjuster<4, 10> { /// Widens or narrows a color channel's bits /// 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<-6>(original) | BitShift<-2>(original) | BitShift<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 4 to 16 template<> class BitAdjuster<4, 16> { /// Widens or narrows a color channel's bits /// 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 temp = original | BitShift<-4>(original); return temp | BitShift<-8>(temp); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 5 to 4 template<> class BitAdjuster<5, 4> { /// Widens or narrows a color channel's bits /// 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<1>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 6 template<> class BitAdjuster<5, 6> { /// Widens or narrows a color channel's bits /// 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<-1>(original) | BitShift<4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 8 template<> class BitAdjuster<5, 8> { /// Widens or narrows a color channel's bits /// 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<-3>(original) | BitShift<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 10 template<> class BitAdjuster<5, 10> { /// Widens or narrows a color channel's bits /// 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 original | BitShift<-5>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 5 to 16 template<> class BitAdjuster<5, 16> { /// Widens or narrows a color channel's bits /// 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 temp = original | BitShift<-5>(original); return BitShift<-6>(temp) | BitShift<4>(temp); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 6 to 4 template<> class BitAdjuster<6, 4> { /// Widens or narrows a color channel's bits /// 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<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 6 to 5 template<> class BitAdjuster<6, 5> { /// Widens or narrows a color channel's bits /// 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<1>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 8 template<> class BitAdjuster<6, 8> { /// Widens or narrows a color channel's bits /// 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<-2>(original) | BitShift<4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 10 template<> class BitAdjuster<6, 10> { /// Widens or narrows a color channel's bits /// 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<-4>(original) | BitShift<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 6 to 16 template<> class BitAdjuster<6, 16> { /// Widens or narrows a color channel's bits /// 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<-10>(original) | BitShift<-4>(original) | BitShift<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 4 template<> class BitAdjuster<8, 4> { /// Widens or narrows a color channel's bits /// 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<4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 5 template<> class BitAdjuster<8, 5> { /// Widens or narrows a color channel's bits /// 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<3>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 8 to 6 template<> class BitAdjuster<8, 6> { /// Widens or narrows a color channel's bits /// 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<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 8 to 10 template<> class BitAdjuster<8, 10> { /// Widens or narrows a color channel's bits /// 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<-2>(original) | BitShift<6>(original); } }; // ------------------------------------------------------------------------------------------- // #if defined(WHY_DONT_YOU_COMPILE_DAMMIT) /// Expands a color channel's number of bits from 8 to 16 template<> class BitAdjuster<8, 16> { /// Widens or narrows a color channel's bits /// 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) ); } }; #else /// Expands a color channel's number of bits from 8 to 16 template<> class BitAdjuster<8, 16> { /// Widens or narrows a color channel's bits /// 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 original | BitShift<-8>(original); } }; #endif // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 4 template<> class BitAdjuster<10, 4> { /// Widens or narrows a color channel's bits /// 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<6>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 5 template<> class BitAdjuster<10, 5> { /// Widens or narrows a color channel's bits /// 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<5>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 6 template<> class BitAdjuster<10, 6> { /// Widens or narrows a color channel's bits /// 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<4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 10 to 8 template<> class BitAdjuster<10, 8> { /// Widens or narrows a color channel's bits /// 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<2>(original); } }; // ------------------------------------------------------------------------------------------- // /// Expands a color channel's number of bits from 10 to 16 template<> class BitAdjuster<10, 16> { /// Widens or narrows a color channel's bits /// 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<-6>(original) | BitShift<4>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 4 template<> class BitAdjuster<16, 4> { /// Widens or narrows a color channel's bits /// 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<12>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 5 template<> class BitAdjuster<16, 5> { /// Widens or narrows a color channel's bits /// 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<11>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 6 template<> class BitAdjuster<16, 6> { /// Widens or narrows a color channel's bits /// 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<10>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 8 template<> class BitAdjuster<16, 8> { /// Widens or narrows a color channel's bits /// 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<8>(original); } }; // ------------------------------------------------------------------------------------------- // /// Narrows a color channel's number of bits from 16 to 10 template<> class BitAdjuster<16, 10> { /// Widens or narrows a color channel's bits /// 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<6>(original); } }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Pixels::PixelFormats #endif // NUCLEX_PIXELS_PIXELFORMATS_BITADJUST_H