From af07b6e681bf101a69485c737a63ca75dbe3c821 Mon Sep 17 00:00:00 2001 From: ttldtor Date: Tue, 30 Sep 2025 21:43:27 +0300 Subject: [PATCH] Add color manipulation example and build configuration - Introduced a comprehensive color manipulation example (`colormanip.cpp`) illustrating various use cases of the `bits` library. - Added `ORG_TTLDTOR_BITS_BUILD_EXAMPLES` option to build examples. - Updated CMake configuration to include the `examples` directory. - Adjusted `.gitignore` for documentation output folders. - Minor `Doxyfile` cleanup. --- .gitignore | 6 +- CMakeLists.txt | 5 + README.md | 336 +++++++++++++++++++++++++++++++++++++++- docs/Doxyfile | 1 - examples/CMakeLists.txt | 13 ++ examples/colormanip.cpp | 321 ++++++++++++++++++++++++++++++++++++++ include/bits/bits.hpp | 30 +++- 7 files changed, 705 insertions(+), 7 deletions(-) create mode 100644 examples/CMakeLists.txt create mode 100644 examples/colormanip.cpp diff --git a/.gitignore b/.gitignore index 00d4051..7ed86ef 100644 --- a/.gitignore +++ b/.gitignore @@ -34,11 +34,13 @@ *.out *.app +*.log + build/ cmake-build-*/ .idea/ -/doc/html/ -/doc/latex/ +/docs/html/ +/docs/latex/ .PVS-Studio/ *.PVS-Studio.* diff --git a/CMakeLists.txt b/CMakeLists.txt index 0095c0a..86c5a50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,4 +39,9 @@ option(ORG_TTLDTOR_BITS_BUILD_UNIT_TESTS "Build tests" ${ORG_TTLDTOR_BITS_IS_ROO if (ORG_TTLDTOR_BITS_BUILD_UNIT_TESTS) enable_testing() add_subdirectory(tests) +endif() + +option(ORG_TTLDTOR_BITS_BUILD_EXAMPLES "Build examples" ${ORG_TTLDTOR_BITS_IS_ROOT_PROJECT}) +if (ORG_TTLDTOR_BITS_BUILD_EXAMPLES) + add_subdirectory(examples) endif() \ No newline at end of file diff --git a/README.md b/README.md index 7d31979..40e85f9 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,338 @@ int main(int argc, char** argv) { } ``` -## [Benchmarks](./Benchmarks.md) \ No newline at end of file +## [Benchmarks](./Benchmarks.md) + +### A possibly complete, but probably not very useful example of using this library. +
+ +Color Manipulation Example + +
+ +```c++ +// Copyright (c) 2025 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +/** + * @file colormanip.cpp + * @brief Example demonstrating color manipulation using the `bits` library + * + * This example shows how to use the `bits` library for: + * - Packing color components into a single integer + * - Unpacking color components from an integer + * - Manipulating individual color channels + * - Converting between different color formats + */ + +#include +#include +#include +#include + +using namespace org::ttldtor::bits; + +/** + * @brief Represents an RGBA color with individual components + */ +struct Color { + std::uint8_t red; ///< Red channel (0-255) + std::uint8_t green; ///< Green channel (0-255) + std::uint8_t blue; ///< Blue channel (0-255) + std::uint8_t alpha; ///< Alpha channel (0-255, 0=transparent, 255=opaque) + + /** + * @brief Packs color components into a 32-bit ARGB value + * @return 32-bit integer in ARGB format `(Alpha << 24 | Red << 16 | Green << 8 | Blue)` + * + *
+   * Layout: [AAAAAAAA][RRRRRRRR][GGGGGGGG][BBBBBBBB]
+   *    bits    24-31    16-23      8-15       0-7
+   * 
+ */ + [[nodiscard]] std::uint32_t pack() const { + std::uint32_t result = 0; + + // Shift alpha to bits 24-31 and OR with the result + result = orOp(result, shl(static_cast(alpha), 24)); + + // Shift red to bits 16-23 and OR with the result + result = orOp(result, shl(static_cast(red), 16)); + + // Shift green to bits 8-15 and OR with the result + result = orOp(result, shl(static_cast(green), 8)); + + // Blue occupies bits 0-7, no shift needed + result = orOp(result, static_cast(blue)); + + return result; + } + + /** + * @brief Unpacks a 32-bit ARGB value into color components + * @param packed 32-bit integer in ARGB format + * @return Color struct with unpacked components + */ + [[nodiscard]] static Color unpack(std::uint32_t packed) { + Color color{}; + + // Extract alpha from bits 24-31 + color.alpha = static_cast(shr(packed, 24)); + + // Extract red from bits 16-23 + color.red = static_cast(shr(packed, 16)); + + // Extract green from bits 8-15 + color.green = static_cast(shr(packed, 8)); + + // Extract blue from bits 0-7 (no shift needed, just mask) + color.blue = static_cast(packed); + + return color; + } + + /** + * @brief Modifies the alpha channel of a packed color + * @param packed Original packed color value + * @param alpha New alpha value (0-255) + * @return New packed color with an updated alpha channel + */ + [[nodiscard]] static std::uint32_t setAlpha(std::uint32_t packed, std::uint8_t alpha) { + // Clear the alpha channel (bits 24-31) + packed = resetBits(packed, 0xFF000000u); + + // Set a new alpha value + return setBits(packed, shl(static_cast(alpha), 24)); + } + + /** + * @brief Modifies the red channel of a packed color + * @param packed Original packed color value + * @param red New red value (0-255) + * @return New packed color with an updated red channel + */ + [[nodiscard]] static std::uint32_t setRed(std::uint32_t packed, std::uint8_t red) { + // Clear the red channel (bits 16-23) + packed = resetBits(packed, 0x00FF0000u); + + // Set a new red value + return setBits(packed, shl(static_cast(red), 16)); + } + + /** + * @brief Modifies the green channel of a packed color + * @param packed Original packed color value + * @param green New green value (0-255) + * @return New packed color with an updated green channel + */ + [[nodiscard]] static std::uint32_t setGreen(std::uint32_t packed, std::uint8_t green) { + // Clear the green channel (bits 8-15) + packed = resetBits(packed, 0x0000FF00u); + + // Set a new green value + return setBits(packed, shl(static_cast(green), 8)); + } + + /** + * @brief Modifies the blue channel of a packed color + * @param packed Original packed color value + * @param blue New blue value (0-255) + * @return New packed color with an updated blue channel + */ + [[nodiscard]] static std::uint32_t setBlue(std::uint32_t packed, std::uint8_t blue) { + // Clear the blue channel (bits 0-7) + packed = resetBits(packed, 0x000000FFu); + + // Set a new blue value + return setBits(packed, static_cast(blue)); + } + + /** + * @brief Converts an ARGB format to RGBA format + * @param argb Color in ARGB format (Alpha << 24 | Red << 16 | Green << 8 | Blue) + * @return Color in RGBA format (Red << 24 | Green << 16 | Blue << 8 | Alpha) + */ + [[nodiscard]] static std::uint32_t argbToRgba(std::uint32_t argb) { + // Extract individual channels + const auto alpha = static_cast(shr(argb, 24)); + const auto red = static_cast(shr(argb, 16)); + const auto green = static_cast(shr(argb, 8)); + const auto blue = static_cast(argb); + + // Repack in RGBA format + std::uint32_t rgba = 0; + rgba = orOp(rgba, shl(static_cast(red), 24)); + rgba = orOp(rgba, shl(static_cast(green), 16)); + rgba = orOp(rgba, shl(static_cast(blue), 8)); + rgba = orOp(rgba, static_cast(alpha)); + + return rgba; + } + + /** + * @brief Blends two colors using alpha blending + * @param foreground Foreground color (with alpha) + * @param background Background color + * @return Blended color + * + * Formula: `result = foreground * alpha + background * (1 - alpha)` + */ + [[nodiscard]] static Color blend(const Color& foreground, const Color& background) { + // Convert alpha from 0-255 to 0.0-1.0 range + const float alpha = static_cast(foreground.alpha) / 255.0f; + const float invAlpha = 1.0f - alpha; + + Color result{}; + result.red = static_cast(static_cast(foreground.red) * alpha + + static_cast(background.red) * invAlpha); + result.green = static_cast(static_cast(foreground.green) * alpha + + static_cast(background.green) * invAlpha); + result.blue = static_cast(static_cast(foreground.blue) * alpha + + static_cast(background.blue) * invAlpha); + result.alpha = 255; // Result is fully opaque + + return result; + } + + /** + * @brief Checks if the color has an alpha channel (not fully opaque) + * @param packed Packed color value + * @return true if alpha < 255 + */ + [[nodiscard]] static bool hasTransparency(std::uint32_t packed) { + // Extract the alpha channel and check if it's less than 255 + const auto alpha = static_cast(shr(packed, 24)); + + return alpha < 255; + } + + /** + * @brief Inverts the color (excluding an alpha channel) + * @param packed Original color + * @return Inverted color + */ + [[nodiscard]] static std::uint32_t invert(std::uint32_t packed) { + // XOR with 0x00FFFFFF to invert RGB channels, leaving alpha unchanged + return xorOp(packed, 0x00FFFFFFu); + } + + /** + * @brief Prints color information + */ + void print() const { + std::cout << "RGBA(" << static_cast(red) << ", " << static_cast(green) << ", " << static_cast(blue) + << ", " << static_cast(alpha) << ")"; + } +}; + +int main() { + std::cout << "=== Color Manipulation Example ===" << std::endl; + std::cout << std::hex << std::uppercase << std::setfill('0'); + + // Example 1: Pack and unpack color + 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; + + // Example 2: Modify individual channels + 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; + + // Example 3: Format conversion + std::cout << "\n--- Example 3: ARGB to RGBA ---" << std::endl; + std::uint32_t argb = 0xC8FF8040u; // A=200, R=255, G=128, B=64 + 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; + + // Example 4: Color blending + std::cout << "\n--- Example 4: Alpha Blending ---" << std::endl; + Color foreground{255, 0, 0, 128}; // Semi-transparent red + Color background{0, 0, 255, 255}; // Opaque blue + + 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; + + // Example 5: Transparency check + 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; + + // Example 6: Color inversion + 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; + + // Example 7: Grayscale conversion + 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; + + // Convert to grayscale using weighted average + constexpr auto gray = + static_cast(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; +} +``` +
+ + diff --git a/docs/Doxyfile b/docs/Doxyfile index c569d0b..4a0abc0 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -62,7 +62,6 @@ FILE_PATTERNS = *.c \ *.qsf \ *.ice RECURSIVE = YES -EXCLUDE_PATTERNS = */isolated/* USE_MDFILE_AS_MAINPAGE = ../README.md REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..575a65f --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) 2025 ttldtor. +# SPDX-License-Identifier: BSL-1.0 + +add_executable(colormanip + colormanip.cpp +) + +set_target_properties(colormanip PROPERTIES + CXX_STANDARD 20 + CXX_EXTENSIONS OFF +) + +target_link_libraries(colormanip PRIVATE bits::bits) diff --git a/examples/colormanip.cpp b/examples/colormanip.cpp new file mode 100644 index 0000000..fa5cfe3 --- /dev/null +++ b/examples/colormanip.cpp @@ -0,0 +1,321 @@ +// Copyright (c) 2025 ttldtor. +// SPDX-License-Identifier: BSL-1.0 + +/** + * @file colormanip.cpp + * @brief Example demonstrating color manipulation using the `bits` library + * + * This example shows how to use the `bits` library for: + * - Packing color components into a single integer + * - Unpacking color components from an integer + * - Manipulating individual color channels + * - Converting between different color formats + */ + +#include +#include +#include +#include + +using namespace org::ttldtor::bits; + +/** + * @brief Represents an RGBA color with individual components + */ +struct Color { + std::uint8_t red; ///< Red channel (0-255) + std::uint8_t green; ///< Green channel (0-255) + std::uint8_t blue; ///< Blue channel (0-255) + std::uint8_t alpha; ///< Alpha channel (0-255, 0=transparent, 255=opaque) + + /** + * @brief Packs color components into a 32-bit ARGB value + * @return 32-bit integer in ARGB format `(Alpha << 24 | Red << 16 | Green << 8 | Blue)` + * + *
+   * Layout: [AAAAAAAA][RRRRRRRR][GGGGGGGG][BBBBBBBB]
+   *    bits    24-31    16-23      8-15       0-7
+   * 
+ */ + [[nodiscard]] std::uint32_t pack() const { + std::uint32_t result = 0; + + // Shift alpha to bits 24-31 and OR with the result + result = orOp(result, shl(static_cast(alpha), 24)); + + // Shift red to bits 16-23 and OR with the result + result = orOp(result, shl(static_cast(red), 16)); + + // Shift green to bits 8-15 and OR with the result + result = orOp(result, shl(static_cast(green), 8)); + + // Blue occupies bits 0-7, no shift needed + result = orOp(result, static_cast(blue)); + + return result; + } + + /** + * @brief Unpacks a 32-bit ARGB value into color components + * @param packed 32-bit integer in ARGB format + * @return Color struct with unpacked components + */ + [[nodiscard]] static Color unpack(std::uint32_t packed) { + Color color{}; + + // Extract alpha from bits 24-31 + color.alpha = static_cast(shr(packed, 24)); + + // Extract red from bits 16-23 + color.red = static_cast(shr(packed, 16)); + + // Extract green from bits 8-15 + color.green = static_cast(shr(packed, 8)); + + // Extract blue from bits 0-7 (no shift needed, just mask) + color.blue = static_cast(packed); + + return color; + } + + /** + * @brief Modifies the alpha channel of a packed color + * @param packed Original packed color value + * @param alpha New alpha value (0-255) + * @return New packed color with an updated alpha channel + */ + [[nodiscard]] static std::uint32_t setAlpha(std::uint32_t packed, std::uint8_t alpha) { + // Clear the alpha channel (bits 24-31) + packed = resetBits(packed, 0xFF000000u); + + // Set a new alpha value + return setBits(packed, shl(static_cast(alpha), 24)); + } + + /** + * @brief Modifies the red channel of a packed color + * @param packed Original packed color value + * @param red New red value (0-255) + * @return New packed color with an updated red channel + */ + [[nodiscard]] static std::uint32_t setRed(std::uint32_t packed, std::uint8_t red) { + // Clear the red channel (bits 16-23) + packed = resetBits(packed, 0x00FF0000u); + + // Set a new red value + return setBits(packed, shl(static_cast(red), 16)); + } + + /** + * @brief Modifies the green channel of a packed color + * @param packed Original packed color value + * @param green New green value (0-255) + * @return New packed color with an updated green channel + */ + [[nodiscard]] static std::uint32_t setGreen(std::uint32_t packed, std::uint8_t green) { + // Clear the green channel (bits 8-15) + packed = resetBits(packed, 0x0000FF00u); + + // Set a new green value + return setBits(packed, shl(static_cast(green), 8)); + } + + /** + * @brief Modifies the blue channel of a packed color + * @param packed Original packed color value + * @param blue New blue value (0-255) + * @return New packed color with an updated blue channel + */ + [[nodiscard]] static std::uint32_t setBlue(std::uint32_t packed, std::uint8_t blue) { + // Clear the blue channel (bits 0-7) + packed = resetBits(packed, 0x000000FFu); + + // Set a new blue value + return setBits(packed, static_cast(blue)); + } + + /** + * @brief Converts an ARGB format to RGBA format + * @param argb Color in ARGB format (Alpha << 24 | Red << 16 | Green << 8 | Blue) + * @return Color in RGBA format (Red << 24 | Green << 16 | Blue << 8 | Alpha) + */ + [[nodiscard]] static std::uint32_t argbToRgba(std::uint32_t argb) { + // Extract individual channels + const auto alpha = static_cast(shr(argb, 24)); + const auto red = static_cast(shr(argb, 16)); + const auto green = static_cast(shr(argb, 8)); + const auto blue = static_cast(argb); + + // Repack in RGBA format + std::uint32_t rgba = 0; + rgba = orOp(rgba, shl(static_cast(red), 24)); + rgba = orOp(rgba, shl(static_cast(green), 16)); + rgba = orOp(rgba, shl(static_cast(blue), 8)); + rgba = orOp(rgba, static_cast(alpha)); + + return rgba; + } + + /** + * @brief Blends two colors using alpha blending + * @param foreground Foreground color (with alpha) + * @param background Background color + * @return Blended color + * + * Formula: `result = foreground * alpha + background * (1 - alpha)` + */ + [[nodiscard]] static Color blend(const Color& foreground, const Color& background) { + // Convert alpha from 0-255 to 0.0-1.0 range + const float alpha = static_cast(foreground.alpha) / 255.0f; + const float invAlpha = 1.0f - alpha; + + Color result{}; + result.red = static_cast(static_cast(foreground.red) * alpha + + static_cast(background.red) * invAlpha); + result.green = static_cast(static_cast(foreground.green) * alpha + + static_cast(background.green) * invAlpha); + result.blue = static_cast(static_cast(foreground.blue) * alpha + + static_cast(background.blue) * invAlpha); + result.alpha = 255; // Result is fully opaque + + return result; + } + + /** + * @brief Checks if the color has an alpha channel (not fully opaque) + * @param packed Packed color value + * @return true if alpha < 255 + */ + [[nodiscard]] static bool hasTransparency(std::uint32_t packed) { + // Extract the alpha channel and check if it's less than 255 + const auto alpha = static_cast(shr(packed, 24)); + + return alpha < 255; + } + + /** + * @brief Inverts the color (excluding an alpha channel) + * @param packed Original color + * @return Inverted color + */ + [[nodiscard]] static std::uint32_t invert(std::uint32_t packed) { + // XOR with 0x00FFFFFF to invert RGB channels, leaving alpha unchanged + return xorOp(packed, 0x00FFFFFFu); + } + + /** + * @brief Prints color information + */ + void print() const { + std::cout << "RGBA(" << static_cast(red) << ", " << static_cast(green) << ", " << static_cast(blue) + << ", " << static_cast(alpha) << ")"; + } +}; + +int main() { + std::cout << "=== Color Manipulation Example ===" << std::endl; + std::cout << std::hex << std::uppercase << std::setfill('0'); + + // Example 1: Pack and unpack color + 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; + + // Example 2: Modify individual channels + 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; + + // Example 3: Format conversion + std::cout << "\n--- Example 3: ARGB to RGBA ---" << std::endl; + std::uint32_t argb = 0xC8FF8040u; // A=200, R=255, G=128, B=64 + 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; + + // Example 4: Color blending + std::cout << "\n--- Example 4: Alpha Blending ---" << std::endl; + Color foreground{255, 0, 0, 128}; // Semi-transparent red + Color background{0, 0, 255, 255}; // Opaque blue + + 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; + + // Example 5: Transparency check + 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; + + // Example 6: Color inversion + 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; + + // Example 7: Grayscale conversion + 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; + + // Convert to grayscale using weighted average + constexpr auto gray = + static_cast(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; +} \ No newline at end of file diff --git a/include/bits/bits.hpp b/include/bits/bits.hpp index 6adee0e..235bd57 100644 --- a/include/bits/bits.hpp +++ b/include/bits/bits.hpp @@ -14,9 +14,9 @@ #include /** - * @defgroup bits - * @{ + * @defgroup bits Library for bit manipulation. */ +/**@{*/ namespace org::ttldtor::bits { @@ -33,12 +33,14 @@ struct MaxImpl { } // namespace detail /** + * @ingroup bits * Returns max type by size (first is better) */ template using Max = detail::MaxImpl::Type; /** + * @ingroup bits * Performs a right arithmetic bit shift operation (`>>` in Java, C, etc.). The sign bit is extended to preserve the * signedness of the number. * @@ -57,6 +59,7 @@ template constexpr ValueType sar(ValueType value, ShiftType shift) noexcept; /** + * @ingroup bits * Performs a left arithmetic bit shift operation (`sal`, `<<` in Java, C, etc.). The `shift` is unsigned. * * The result of the shift will be of the same type as the `value` being shifted. @@ -82,6 +85,7 @@ constexpr ValueType leftArithmeticShift(ValueType value, UnsignedShiftType shift } /** + * @ingroup bits * Performs a left arithmetic bit shift operation (`sal`, `<<` in Java, C, etc.). The `shift` is signed. * * The result of the shift will be of the same type as the `value` being shifted. @@ -117,6 +121,7 @@ constexpr ValueType leftArithmeticShift(ValueType value, SignedShiftType shift) } /** + * @ingroup bits * Performs a left arithmetic bit shift operation (`<<` in Java, C, etc.). * * The result of the shift will be of the same type as the `value` being shifted. @@ -136,6 +141,7 @@ constexpr ValueType sal(ValueType value, ShiftType shift) noexcept { } /** + * @ingroup bits * Performs a right arithmetic bit shift operation (`sar`, `>>` in Java, C, etc.). The `shift` is unsigned. * The sign bit is extended to preserve the signedness of the number. * @@ -162,6 +168,7 @@ constexpr ValueType rightArithmeticShift(ValueType value, UnsignedShiftType shif } /** + * @ingroup bits * Performs a right arithmetic bit shift operation (`sar`, `>>` in Java, C, etc.). The `shift` is signed. * The sign bit is extended to preserve the signedness of the number. * @@ -198,6 +205,7 @@ constexpr ValueType rightArithmeticShift(ValueType value, SignedShiftType shift) } /** + * @ingroup bits * Performs a right arithmetic bit shift operation (`>>` in Java, C, etc.). The sign bit is extended to preserve the * signedness of the number. * @@ -218,6 +226,7 @@ constexpr ValueType sar(ValueType value, ShiftType shift) noexcept { } /** + * @ingroup bits * Performs a right logical bit shift operation (`>>>` in Java). Fills the left bits by zero. * * The result of the shift will be of the same type as the `value` being shifted. @@ -235,6 +244,7 @@ template constexpr ValueType shr(ValueType value, ShiftType shift) noexcept; /** + * @ingroup bits * Performs a left logical bit shift operation (`shl`, `<<<`). The `shift` is unsigned. * * The result of the shift will be of the same type as the `value` being shifted. @@ -254,6 +264,7 @@ constexpr ValueType leftLogicalShift(ValueType value, UnsignedShiftType shift) n } /** + * @ingroup bits * Performs a left logical bit shift operation (`shl`, `<<<`). The `shift` is signed. * * The result of the shift will be of the same type as the `value` being shifted. @@ -289,6 +300,7 @@ constexpr ValueType leftLogicalShift(ValueType value, SignedShiftType shift) noe } /** + * @ingroup bits * Performs a left logical bit shift operation (`shl`, `<<<`). * * The result of the shift will be of the same type as the `value` being shifted. @@ -308,6 +320,7 @@ constexpr ValueType shl(ValueType value, ShiftType shift) noexcept { } /** + * @ingroup bits * Performs a right logical bit shift operation (`shr`, `>>>` in Java). The `shift` is unsigned. Fills the left bits by * zero. * @@ -335,6 +348,7 @@ constexpr ValueType rightLogicalShift(ValueType value, UnsignedShiftType shift) } /** + * @ingroup bits * Performs a right logical bit shift operation (`shr`, `>>>` in Java). The `shift` is signed. Fills the left bits by * zero. * @@ -371,6 +385,7 @@ constexpr ValueType rightLogicalShift(ValueType value, SignedShiftType shift) no } /** + * @ingroup bits * Performs a right logical bit shift operation (`shr`, `>>>` in Java). Fills the left bits by zero. * * The result of the shift will be of the same type as the `value` being shifted. @@ -390,6 +405,7 @@ constexpr ValueType shr(ValueType value, ShiftType shift) noexcept { } /** + * @ingroup bits * Performs a bitwise AND operation between two values of possibly different types * and ensures the result is cast back to the type of the first argument. * @@ -407,6 +423,7 @@ constexpr FirstType andOp(FirstType first, SecondType second) noexcept { } /** + * @ingroup bits * Performs a bitwise OR operation between two values of possibly different types * and ensures the result is cast back to the type of the first argument. * @@ -424,6 +441,7 @@ constexpr FirstType orOp(FirstType first, SecondType second) noexcept { } /** + * @ingroup bits * Performs a bitwise XOR operation between two values of possibly different types * and ensures the result is cast back to the type of the first argument. * @@ -441,6 +459,7 @@ constexpr FirstType xorOp(FirstType first, SecondType second) noexcept { } /** + * @ingroup bits * Determines if the specified bits are set in the source value. * * @tparam T the type of arguments. @@ -454,6 +473,7 @@ constexpr bool bitsAreSet(T sourceBits, T bitMaskToCheck) { } /** + * @ingroup bits * Determines if the specified bits are set in the source value. * * @tparam SourceBitsType The type of the source bits (e.g., an integer type). @@ -476,6 +496,7 @@ constexpr bool bitsAreSet(SourceBitsType sourceBits, BitMaskType bitMaskToCheck) } /** + * @ingroup bits * Sets specific bits in the source value using a bitmask. * * @tparam T The type of arguments. @@ -489,6 +510,7 @@ constexpr T setBits(T sourceBits, T bitMaskToSet) { } /** + * @ingroup bits * Sets specific bits in the source value using a bitmask. * * @tparam SourceBitsType The type of the source bits (e.g., an integer type). @@ -512,6 +534,7 @@ constexpr SourceBitsType setBits(SourceBitsType sourceBits, BitMaskType bitMaskT } /** + * @ingroup bits * Resets (clears) specific bits in a bitmask. * * @tparam T The type of the source bits and the bitmask. Should be an integral type. @@ -525,6 +548,7 @@ constexpr T resetBits(T sourceBits, T bitMaskToReset) { } /** + * @ingroup bits * Resets (clears) specific bits in a bitmask. * * @tparam SourceBitsType The type of the source bits (e.g., an integer type). @@ -551,4 +575,4 @@ constexpr SourceBitsType resetBits(SourceBitsType sourceBits, BitMaskType bitMas } // namespace org::ttldtor::bits -/** @} */ \ No newline at end of file +/**@}*/ \ No newline at end of file