#include <cstdint>
#include <iomanip>
#include <iostream>
using namespace org::ttldtor::bits;
struct Color {
std::uint8_t red;
std::uint8_t green;
std::uint8_t blue;
std::uint8_t alpha;
[[nodiscard]] std::uint32_t pack() const {
std::uint32_t result = 0;
result =
orOp(result,
shl(
static_cast<std::uint32_t
>(alpha), 24));
result =
orOp(result,
shl(
static_cast<std::uint32_t
>(red), 16));
result =
orOp(result,
shl(
static_cast<std::uint32_t
>(green), 8));
result =
orOp(result,
static_cast<std::uint32_t
>(blue));
return result;
}
[[nodiscard]] static Color unpack(std::uint32_t packed) {
Color color{};
color.alpha =
static_cast<std::uint8_t
>(
shr(packed, 24));
color.red =
static_cast<std::uint8_t
>(
shr(packed, 16));
color.green =
static_cast<std::uint8_t
>(
shr(packed, 8));
color.blue = static_cast<std::uint8_t>(packed);
return color;
}
[[nodiscard]] static std::uint32_t setAlpha(std::uint32_t packed, std::uint8_t alpha) {
return setBits(packed,
shl(
static_cast<std::uint32_t
>(alpha), 24));
}
[[nodiscard]] static std::uint32_t setRed(std::uint32_t packed, std::uint8_t red) {
return setBits(packed,
shl(
static_cast<std::uint32_t
>(red), 16));
}
[[nodiscard]] static std::uint32_t setGreen(std::uint32_t packed, std::uint8_t green) {
return setBits(packed,
shl(
static_cast<std::uint32_t
>(green), 8));
}
[[nodiscard]] static std::uint32_t setBlue(std::uint32_t packed, std::uint8_t blue) {
return setBits(packed,
static_cast<std::uint32_t
>(blue));
}
[[nodiscard]] static std::uint32_t argbToRgba(std::uint32_t argb) {
const auto alpha =
static_cast<std::uint8_t
>(
shr(argb, 24));
const auto red =
static_cast<std::uint8_t
>(
shr(argb, 16));
const auto green =
static_cast<std::uint8_t
>(
shr(argb, 8));
const auto blue = static_cast<std::uint8_t>(argb);
std::uint32_t rgba = 0;
rgba =
orOp(rgba,
shl(
static_cast<std::uint32_t
>(red), 24));
rgba =
orOp(rgba,
shl(
static_cast<std::uint32_t
>(green), 16));
rgba =
orOp(rgba,
shl(
static_cast<std::uint32_t
>(blue), 8));
rgba =
orOp(rgba,
static_cast<std::uint32_t
>(alpha));
return rgba;
}
[[nodiscard]] static Color blend(const Color& foreground, const Color& background) {
const float alpha = static_cast<float>(foreground.alpha) / 255.0f;
const float invAlpha = 1.0f - alpha;
Color result{};
result.red = static_cast<std::uint8_t>(static_cast<float>(foreground.red) * alpha +
static_cast<float>(background.red) * invAlpha);
result.green = static_cast<std::uint8_t>(static_cast<float>(foreground.green) * alpha +
static_cast<float>(background.green) * invAlpha);
result.blue = static_cast<std::uint8_t>(static_cast<float>(foreground.blue) * alpha +
static_cast<float>(background.blue) * invAlpha);
result.alpha = 255;
return result;
}
[[nodiscard]] static bool hasTransparency(std::uint32_t packed) {
const auto alpha =
static_cast<std::uint8_t
>(
shr(packed, 24));
return alpha < 255;
}
[[nodiscard]] static std::uint32_t invert(std::uint32_t packed) {
return xorOp(packed, 0x00FFFFFFu);
}
void print() const {
std::cout << "RGBA(" << static_cast<int>(red) << ", " << static_cast<int>(green) << ", " << static_cast<int>(blue)
<< ", " << static_cast<int>(alpha) << ")";
}
};
int main() {
std::cout << "=== Color Manipulation Example ===" << std::endl;
std::cout << std::hex << std::uppercase << std::setfill('0');
std::cout << "\n--- Example 1: Pack and Unpack ---" << std::endl;
Color color1{255, 128, 64, 200};
std::cout << "Original color: ";
color1.print();
std::cout << std::endl;
std::uint32_t packed = color1.pack();
std::cout << "Packed (ARGB): 0x" << std::setw(8) << packed << std::endl;
Color unpacked = Color::unpack(packed);
std::cout << "Unpacked color: ";
unpacked.print();
std::cout << std::endl;
std::cout << "\n--- Example 2: Modify Channels ---" << std::endl;
std::uint32_t color2 = Color{100, 150, 200, 255}.pack();
std::cout << "Original: 0x" << std::setw(8) << color2 << " -> ";
Color::unpack(color2).print();
std::cout << std::endl;
color2 = Color::setRed(color2, 255);
std::cout << "After setRed(255): 0x" << std::setw(8) << color2 << " -> ";
Color::unpack(color2).print();
std::cout << std::endl;
color2 = Color::setAlpha(color2, 128);
std::cout << "After setAlpha(128): 0x" << std::setw(8) << color2 << " -> ";
Color::unpack(color2).print();
std::cout << std::endl;
std::cout << "\n--- Example 3: ARGB to RGBA ---" << std::endl;
std::uint32_t argb = 0xC8FF8040u;
std::cout << "ARGB: 0x" << std::setw(8) << argb << std::endl;
std::uint32_t rgba = Color::argbToRgba(argb);
std::cout << "RGBA: 0x" << std::setw(8) << rgba << std::endl;
std::cout << "\n--- Example 4: Alpha Blending ---" << std::endl;
Color foreground{255, 0, 0, 128};
Color background{0, 0, 255, 255};
std::cout << "Foreground: ";
foreground.print();
std::cout << std::endl;
std::cout << "Background: ";
background.print();
std::cout << std::endl;
Color blended = Color::blend(foreground, background);
std::cout << "Blended: ";
blended.print();
std::cout << std::endl;
std::cout << "\n--- Example 5: Transparency Check ---" << std::endl;
const std::uint32_t opaqueColor = Color{255, 255, 255, 255}.pack();
const std::uint32_t transparentColor = Color{255, 255, 255, 200}.pack();
std::cout << "Opaque color (0x" << std::setw(8) << opaqueColor
<< ") has transparency: " << (Color::hasTransparency(opaqueColor) ? "YES" : "NO") << std::endl;
std::cout << "Transparent color (0x" << std::setw(8) << transparentColor
<< ") has transparency: " << (Color::hasTransparency(transparentColor) ? "YES" : "NO") << std::endl;
std::cout << "\n--- Example 6: Color Inversion ---" << std::endl;
constexpr Color original{255, 128, 64, 255};
std::cout << "Original: 0x" << std::setw(8) << original.pack() << " -> ";
original.print();
std::cout << std::endl;
const std::uint32_t inverted = Color::invert(original.pack());
std::cout << "Inverted: 0x" << std::setw(8) << inverted << " -> ";
Color::unpack(inverted).print();
std::cout << std::endl;
std::cout << "\n--- Example 7: Grayscale Conversion ---" << std::endl;
constexpr Color colorful{200, 100, 50, 255};
std::cout << "Colorful: ";
colorful.print();
std::cout << std::endl;
constexpr auto gray =
static_cast<std::uint8_t>(0.299f * colorful.red + 0.587f * colorful.green + 0.114f * colorful.blue);
constexpr Color grayscale{gray, gray, gray, colorful.alpha};
std::cout << "Grayscale: ";
grayscale.print();
std::cout << std::endl;
return 0;
}
constexpr T setBits(T sourceBits, T bitMaskToSet)
Sets specific bits in the source value using a bitmask.
Definition bits.hpp:508
constexpr ValueType shr(ValueType value, ShiftType shift) noexcept
Performs a right logical bit shift operation (>>> in Java).
Definition bits.hpp:403
constexpr T resetBits(T sourceBits, T bitMaskToReset)
Resets (clears) specific bits in a bitmask.
Definition bits.hpp:546
constexpr FirstType orOp(FirstType first, SecondType second) noexcept
Performs a bitwise OR operation between two values of possibly different types and ensures the result...
Definition bits.hpp:437
constexpr FirstType xorOp(FirstType first, SecondType second) noexcept
Performs a bitwise XOR operation between two values of possibly different types and ensures the resul...
Definition bits.hpp:455