#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 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_GRAPHICS_HELPERS_PIXELFORMATCONVERTER_H #error This file must be included through PixelFormatConverter.h #endif namespace Nuclex { namespace Graphics { namespace Rasterization { // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint8_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::uint16_t combined = static_cast( static_cast(pixel >> 8) ) + static_cast(pixel & 0xFF); return static_cast( (combined + (combined >> 7)) * ((combined >> 15) ^ 1) ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint16_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { return pixel; } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint16_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); std::uint16_t combined = static_cast(red) + green; red *= (static_cast(red) >> 7) ^ 1; green *= (static_cast(green) >> 7) ^ 1; combined *= (combined >> 15) ^ 1; return static_cast( (static_cast(red & 0x7C) << 9) | (static_cast(green & 0x7E) << 4) | (combined >> 3) ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint16_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); std::uint16_t combined = static_cast(red) + green; red *= (static_cast(red) >> 7) ^ 1; green *= (static_cast(green) >> 7) ^ 1; combined *= (combined >> 15) ^ 1; return static_cast( (static_cast(combined & 0x78) << 9) | (static_cast(green & 0x78) << 5) | (red) | // No mask since we're ORing alpha to max anyway 0x000F ); // TODO: I think this is generating RGB, not BGR } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint32_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); std::uint16_t combined = static_cast(red) + green; red *= (static_cast(red) >> 7) ^ 1; green *= (static_cast(green) >> 7) ^ 1; combined *= (combined >> 15) ^ 1; return static_cast( (static_cast(red & 0x7F) << 25) | (static_cast(red & 0x40) << 18) | (static_cast(green & 0x7F) << 17) | (static_cast(green & 0x40) << 10) | (combined << 9) | (combined << 2) | 0x000000FF ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint32_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::uint16_t combined = static_cast( static_cast(pixel >> 8) ) + static_cast(pixel & 0xFF); combined /= 2; return static_cast( (static_cast(pixel) << 16) | (static_cast(combined & 0x00FF) << 8) | 0x0000007F ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { // static_assert(false, "Compressed pixel formats need to be handled separately"); }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { // static_assert(false, "Compressed pixel formats need to be handled separately"); }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { // static_assert(false, "Compressed pixel formats need to be handled separately"); }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint8_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType) { return 0xFF; } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint16_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); std::uint16_t combined = static_cast(red) + green; combined = (combined + (combined >> 7)) * ((combined >> 15) ^ 1); return ((combined << 8) | (combined)); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint32_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); red *= ((red >> 8) ^ 1); green *= ((green >> 8) ^ 1); return ( (static_cast(red) << 25) | (static_cast(red) << 18) | (static_cast(red & 0xE0) << 11) | (static_cast(green) << 9) | (static_cast(green) << 2) | (green >> 5) ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint32_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { // TODO: This is broken std::uint16_t red = Half::FromNormalizedByte(static_cast(pixel >> 8)); std::uint16_t green = Half::FromNormalizedByte(static_cast(pixel & 0xFF)); return ( (static_cast(red) << 16) | green ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint32_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int16_t combined = static_cast( static_cast(pixel >> 8) ) + static_cast(pixel & 0xFF); std::int8_t negative = (static_cast(combined) >> 15); std::int8_t positive = negative ^ 1; std::uint32_t result; *reinterpret_cast(&result) = ( ((static_cast(combined) / 254.0f) * positive) + ((static_cast(combined) / 256.0f) * negative) ); return result; } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter< PixelFormat::R8_G8_Signed, PixelFormat::Modern_R16_G16_B16_A16_Unsigned > { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint64_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { std::int8_t red = static_cast(pixel >> 8); std::int8_t green = static_cast(pixel & 0xFF); std::uint16_t combined = static_cast(red) + green; red *= ((red >> 8) ^ 1); green *= ((green >> 8) ^ 1); combined *= ((combined >> 15) ^ 1); return ( (static_cast(red) << 57) | (static_cast(red) << 50) | (static_cast(red & 0xE0) << 43) | (static_cast(green) << 41) | (static_cast(green) << 34) | (static_cast(green & 0xE0) << 27) | (static_cast(combined) << 24) | (static_cast(combined) << 17) | (static_cast(combined) << 10) | 0x000000000000FFFF ); } }; // ------------------------------------------------------------------------------------------- // /// Converts pixels from one pixel format to another template<> class PixelFormatConverter< PixelFormat::R8_G8_Signed, PixelFormat::Modern_R16_G16_B16_A16_Float > { /// Data type used by the input pixel format public: typedef std::uint16_t InputType; /// Data type used by the output pixel format public: typedef std::uint64_t OutputType; /// /// Converts a pixel from the input pixel format into the output pixel format /// /// Pixel that will be converted /// The pixel in the output pixel format public: static OutputType ConvertPixel(InputType pixel) { // TODO: This is broken std::uint16_t red = Half::FromNormalizedByte(static_cast(pixel >> 8)); std::uint16_t green = Half::FromNormalizedByte(static_cast(pixel & 0xFF)); std::uint32_t combined = red + green; // TODO: We can't add floats this way return ( (static_cast(red) << 48) | (static_cast(green) << 32) | (static_cast(combined) << 15) | static_cast(Half::One) ); } }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Rasterization