#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