#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 a pixel between two different floating point-based 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
) {
(void)sourcePixel; // MSVC fantasizes a constellation where no channels exist
(void)targetPixel; // then warns that these two parameters aren't used...
// Convert the red color channel, if one is present
if constexpr(NeedConvertChannel1) {
static_assert(
((PixelFormatDescription::Channel1::LowestBitIndex % 8) == 0) &&
u8"Source floating point channel bits start at a byte boundary"
);
static_assert(
((PixelFormatDescription::Channel1::LowestBitIndex % 8) == 0) &&
u8"Target floating point channel bits start at a byte boundary"
);
typedef ChannelFloatType<
PixelFormatDescription::Channel1::BitCount
> SourceFloatType;
const SourceFloatType *source = reinterpret_cast(
reinterpret_cast(sourcePixel) +
(PixelFormatDescription::Channel1::LowestBitIndex / 8)
);
typedef ChannelFloatType<
PixelFormatDescription::Channel1::BitCount
> TargetFloatType;
TargetFloatType *target = reinterpret_cast(
reinterpret_cast(targetPixel) +
(PixelFormatDescription::Channel1::LowestBitIndex / 8)
);
*target = static_cast(*source);
}
// Convert the green color channel, if one is present
if constexpr(NeedConvertChannel2) {
static_assert(
((PixelFormatDescription::Channel2::LowestBitIndex % 8) == 0) &&
u8"Source floating point channel bits start at a byte boundary"
);
static_assert(
((PixelFormatDescription::Channel2::LowestBitIndex % 8) == 0) &&
u8"Target floating point channel bits start at a byte boundary"
);
typedef ChannelFloatType<
PixelFormatDescription::Channel2::BitCount
> SourceFloatType;
const SourceFloatType *source = reinterpret_cast(
reinterpret_cast(sourcePixel) +
(PixelFormatDescription::Channel2::LowestBitIndex / 8)
);
typedef ChannelFloatType<
PixelFormatDescription::Channel2::BitCount
> TargetFloatType;
TargetFloatType *target = reinterpret_cast(
reinterpret_cast(targetPixel) +
(PixelFormatDescription::Channel2::LowestBitIndex / 8)
);
*target = static_cast(*source);
}
// Convert the blue color channel, if one is present
if constexpr(NeedConvertChannel3) {
static_assert(
((PixelFormatDescription::Channel3::LowestBitIndex % 8) == 0) &&
u8"Source floating point channel bits start at a byte boundary"
);
static_assert(
((PixelFormatDescription::Channel3::LowestBitIndex % 8) == 0) &&
u8"Target floating point channel bits start at a byte boundary"
);
typedef ChannelFloatType<
PixelFormatDescription::Channel3::BitCount
> SourceFloatType;
const SourceFloatType *source = reinterpret_cast(
reinterpret_cast(sourcePixel) +
(PixelFormatDescription::Channel3::LowestBitIndex / 8)
);
typedef ChannelFloatType<
PixelFormatDescription::Channel3::BitCount
> TargetFloatType;
TargetFloatType *target = reinterpret_cast(
reinterpret_cast(targetPixel) +
(PixelFormatDescription::Channel3::LowestBitIndex / 8)
);
*target = static_cast(*source);
}
// Convert the alpha channel, if one is present
if constexpr(NeedConvertChannel4) {
static_assert(
((PixelFormatDescription::Channel4::LowestBitIndex % 8) == 0) &&
u8"Source floating point channel bits start at a byte boundary"
);
static_assert(
((PixelFormatDescription::Channel4::LowestBitIndex % 8) == 0) &&
u8"Target floating point channel bits start at a byte boundary"
);
typedef ChannelFloatType<
PixelFormatDescription::Channel4::BitCount
> SourceFloatType;
const SourceFloatType *source = reinterpret_cast(
reinterpret_cast(sourcePixel) +
(PixelFormatDescription::Channel4::LowestBitIndex / 8)
);
typedef ChannelFloatType<
PixelFormatDescription::Channel4::BitCount
> TargetFloatType;
TargetFloatType *target = reinterpret_cast(
reinterpret_cast(targetPixel) +
(PixelFormatDescription::Channel4::LowestBitIndex / 8)
);
*target = static_cast(*source);
} else if constexpr(HasAlphaChannel) {
typedef ChannelFloatType<
PixelFormatDescription::Channel4::BitCount
> TargetFloatType;
TargetFloatType *target = reinterpret_cast(
reinterpret_cast(targetPixel) +
(PixelFormatDescription::Channel4::LowestBitIndex / 8)
);
*target = static_cast(1);
}
}
// ------------------------------------------------------------------------------------------- //
}}} // namespace Nuclex::Pixels::PixelFormats