#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_CONVERTPIXEL_H
#error This file is intended to be included through ConvertPixel.h
#endif
namespace Nuclex { namespace Pixels { namespace PixelFormats {
// ------------------------------------------------------------------------------------------- //
/// Converts between two different integer-based pixel formats
/// Pixel format used by the input pixel
/// Pixel format used by the output pixel
/// Pixel that will be converted to the output pixel format
/// A pixel in the output pixel format that's equivalent to the input pixel
template<
PixelFormat TSourcePixelFormat, PixelFormat TTargetPixelFormat,
typename std::enable_if_t<
(TSourcePixelFormat != TTargetPixelFormat) &&
(!IsFloatFormat) &&
(!IsFloatFormat)
> * = nullptr
>
NUCLEX_PIXELS_ALWAYS_INLINE void ConvertPixel(
const PixelTypeFromFormat *sourcePixel,
PixelTypeFromFormat *targetPixel
) {
typedef LargerPixelType IntermediatePixelType;
static_assert(
(!IsSignedFormat) && (!IsSignedFormat) &&
u8"Signed pixel formats not implemented yet, results will be wrong"
);
(void)sourcePixel; // MSVC fantasizes a constellation where no channels exist
(void)targetPixel; // then warns that these two parameters aren't used...
// Convert the red channel and assign it to the target pixel
if constexpr(NeedConvertChannel1) {
*targetPixel = static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel1::BitCount,
PixelFormats::PixelFormatDescription::Channel1::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel1::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel1::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel1::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel1::BitCount
>
);
}
// Convert the green channel and assign it to the target pixel
if constexpr(NeedConvertChannel2) {
if constexpr(NeedConvertChannel1) {
*targetPixel |= static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel2::BitCount,
PixelFormats::PixelFormatDescription::Channel2::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel2::BitCount
>
);
} else {
*targetPixel = static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel2::BitCount,
PixelFormats::PixelFormatDescription::Channel2::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel2::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel2::BitCount
>
);
}
}
// Convert the blue channel and assign it to the target pixel
if constexpr(NeedConvertChannel3) {
if constexpr(
NeedConvertChannel1 ||
NeedConvertChannel2
) {
*targetPixel |= static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel3::BitCount,
PixelFormats::PixelFormatDescription::Channel3::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel3::BitCount
>
);
} else {
*targetPixel = static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel3::BitCount,
PixelFormats::PixelFormatDescription::Channel3::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel3::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel3::BitCount
>
);
}
}
// Convert the alpha channel and assign it to the target pixel
if constexpr(NeedConvertChannel4) {
if constexpr(
NeedConvertChannel1 ||
NeedConvertChannel2 ||
NeedConvertChannel3
) {
*targetPixel |= static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel4::BitCount,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>
);
} else {
*targetPixel = static_cast>(
PixelFormats::UnsignedBitAdjuster<
PixelFormats::PixelFormatDescription::Channel4::BitCount,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>::template Adjust<
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex
>(
static_cast(*sourcePixel)
) & BitMask<
IntermediatePixelType,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>
);
}
} else if constexpr(HasAlphaChannel) {
if constexpr(
NeedConvertChannel1 ||
NeedConvertChannel2 ||
NeedConvertChannel3
) {
*targetPixel |= BitMask<
PixelTypeFromFormat,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>;
} else {
*targetPixel = BitMask<
PixelTypeFromFormat,
PixelFormats::PixelFormatDescription::Channel4::LowestBitIndex,
PixelFormats::PixelFormatDescription::Channel4::BitCount
>;
}
}
}
// ------------------------------------------------------------------------------------------- //
}}} // namespace Nuclex::Pixels::PixelFormats