Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,17 @@ if(COLORCPP_BUILD_EXAMPLES)

add_executable(harmony_example harmony_example.cpp)
target_link_libraries(harmony_example colorcpp::colorcpp)


add_executable(adobe_rgb_example adobe_rgb_example.cpp)
target_link_libraries(adobe_rgb_example colorcpp::colorcpp)

add_executable(chromatic_adaptation_example chromatic_adaptation_example.cpp)
target_link_libraries(chromatic_adaptation_example colorcpp::colorcpp)

add_executable(prophoto_rgb_example prophoto_rgb_example.cpp)
target_link_libraries(prophoto_rgb_example colorcpp::colorcpp)

add_executable(rec2020_example rec2020_example.cpp)
target_link_libraries(rec2020_example colorcpp::colorcpp)

endif()
75 changes: 75 additions & 0 deletions examples/adobe_rgb_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* @file adobe_rgb_example.cpp
* @brief Demonstrates Adobe RGB (A98-RGB) wide-gamut color space usage.
*
* Build: cmake -DCOLORCPP_BUILD_EXAMPLES=ON && make adobe_rgb_example
*/

#include <colorcpp/colorcpp.hpp>
#include <iostream>

using namespace colorcpp;
using namespace colorcpp::io::ansi;

int main() {
std::cout << "=== Adobe RGB (A98-RGB) Wide-Gamut Color Space ===\n\n";

// 1. Construct Adobe RGB colors
std::cout << "1. Construction\n";
core::adobe_rgbf_t pure_red(1.0f, 0.0f, 0.0f);
core::adobe_rgbf_t pure_green(0.0f, 1.0f, 0.0f);
core::adobe_rgbf_t pure_blue(0.0f, 0.0f, 1.0f);
std::cout << " Red: " << pure_red << "\n";
std::cout << " Green: " << pure_green << "\n";
std::cout << " Blue: " << pure_blue << "\n\n";

// 2. Convert sRGB → Adobe RGB → sRGB (show gamut differences)
std::cout << "2. sRGB ↔ Adobe RGB round-trip\n";
core::rgbf_t srgb_green(0.0f, 1.0f, 0.0f);
auto adobe_green = conversion::color_cast<core::adobe_rgbf_t>(srgb_green);
auto back_to_srgb = conversion::color_cast<core::rgbf_t>(adobe_green);
std::cout << " sRGB green: " << srgb_green << "\n";
std::cout << " → Adobe RGB: " << adobe_green << "\n";
std::cout << " → back to sRGB: " << back_to_srgb << "\n\n";

// 3. Gamma encoding: show linear values
std::cout << "3. Gamma encoding (Adobe RGB → Linear Adobe RGB)\n";
auto linear_adobe = conversion::color_cast<core::linear_adobe_rgbf_t>(adobe_green);
std::cout << " Adobe RGB (gamma): " << adobe_green << "\n";
std::cout << " Linear Adobe RGB: " << linear_adobe << "\n";
std::cout << " (Pure gamma 2.2 — mid-tones are darker in linear)\n\n";

// 4. Cross-space chain: Adobe RGB → Display P3 → Rec.2020 → OKLab
std::cout << "4. Cross-space chain: Adobe RGB → Display P3 → Rec.2020 → OKLab\n";
core::adobe_rgbf_t test_color(0.7f, 0.2f, 0.4f);
auto dp3 = conversion::color_cast<core::display_p3f_t>(test_color);
auto r2020 = conversion::color_cast<core::rec2020_rgbf_t>(dp3);
auto oklab = conversion::color_cast<core::oklab_t>(r2020);
std::cout << " Input (Adobe RGB): " << test_color << "\n";
std::cout << " → Display P3: " << dp3 << "\n";
std::cout << " → Rec.2020: " << r2020 << "\n";
std::cout << " → OKLab: " << oklab << "\n\n";

// 5. CSS parsing
std::cout << "5. CSS color(a98-rgb ...) parsing\n";
auto css = colorcpp::io::css::parse_css_color<core::adobe_rgbaf_t>("color(a98-rgb 0.64 0.33 0.21)");
if (css) {
std::cout << " Parsed: " << *css << "\n";
std::cout << " CSS string: "
<< colorcpp::io::css::to_css_color_string(conversion::color_cast<core::rgbaf_t>(*css)) << "\n";
}
std::cout << "\n";

// 6. ANSI swatch
std::cout << "6. Color swatches\n";
std::cout << " Adobe Red ";
print_swatch(std::cout, conversion::color_cast<core::rgb8_t>(core::adobe_rgbf_t{0.64f, 0.1f, 0.1f}));
std::cout << "\n Adobe Green";
print_swatch(std::cout, conversion::color_cast<core::rgb8_t>(core::adobe_rgbf_t{0.1f, 0.64f, 0.1f}));
std::cout << "\n Adobe Blue ";
print_swatch(std::cout, conversion::color_cast<core::rgb8_t>(core::adobe_rgbf_t{0.1f, 0.1f, 0.64f}));
std::cout << "\n";

std::cout << "Done.\n";
return 0;
}
2 changes: 1 addition & 1 deletion examples/ansi_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* @brief Example: ANSI terminal color utilities for debugging and visualization.
*/

#include <colorcpp/colorcpp.hpp>
#include <array>
#include <colorcpp/colorcpp.hpp>
#include <iostream>

using namespace colorcpp;
Expand Down
3 changes: 2 additions & 1 deletion examples/blend_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
#include <iomanip>
#include <iostream>

// implementation note: examples reflect the current encoded rgbaf_t working-space path described in docs/reference/blend.rst
// implementation note: examples reflect the current encoded rgbaf_t working-space path described in
// docs/reference/blend.rst

using namespace colorcpp;
using namespace colorcpp::operations::conversion;
Expand Down
72 changes: 72 additions & 0 deletions examples/chromatic_adaptation_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* @file chromatic_adaptation_example.cpp
* @brief Demonstrates chromatic adaptation (white point conversion).
*
* Build: cmake -DCOLORCPP_BUILD_EXAMPLES=ON && make chromatic_adaptation_example
*/

#include <colorcpp/colorcpp.hpp>
#include <iostream>

using namespace colorcpp;

int main() {
std::cout << "=== Chromatic Adaptation (White Point Conversion) ===\n\n";

using namespace algorithms::chromatic_adaptation;

// 1. White point constants
std::cout << "1. Standard white points (CIE XYZ, Y=1)\n";
std::cout << " D65 (noon daylight): " << WHITEPOINT_D65 << "\n";
std::cout << " D50 (horizon daylight): " << WHITEPOINT_D50 << "\n";
std::cout << " A (tungsten): " << WHITEPOINT_A << "\n";
std::cout << " D55 (mid-day): " << WHITEPOINT_D55 << "\n\n";

// 2. Bradford D65 → D50 adaptation
std::cout << "2. Bradford adaptation: D65 → D50\n";
core::xyz_t color_d65(0.5f, 0.4f, 0.3f);
auto color_d50 = bradford_adapt(color_d65, WHITEPOINT_D65, WHITEPOINT_D50);
std::cout << " Color under D65: " << color_d65 << "\n";
std::cout << " → under D50: " << color_d50 << "\n\n";

// 3. Round-trip verification
std::cout << "3. Round-trip: D65 → D50 → D65\n";
auto back_to_d65 = bradford_adapt(color_d50, WHITEPOINT_D50, WHITEPOINT_D65);
std::cout << " Original: " << color_d65 << "\n";
std::cout << " After D65→D50→D65: " << back_to_d65 << "\n";
std::cout << " (Should match original within floating-point precision)\n\n";

// 4. Tungsten (A) simulation — warm color shift
std::cout << "4. Daylight → Tungsten (D65 → A) — warm shift\n";
core::rgbf_t white(1.0f, 1.0f, 1.0f);
auto warm_white = bradford_adapt(white, WHITEPOINT_D65, WHITEPOINT_A);
std::cout << " White under D65: " << white << "\n";
std::cout << " → under Tungsten A: " << warm_white << "\n";
std::cout << " (Expect warm/yellowish shift)\n\n";

// 5. Von Kries comparison
std::cout << "5. Bradford vs Von Kries (D65 → A)\n";
core::xyz_t test(0.3f, 0.5f, 0.2f);
auto brad = bradford_adapt(test, WHITEPOINT_D65, WHITEPOINT_A);
auto vk = von_kries_adapt(test, WHITEPOINT_D65, WHITEPOINT_A);
std::cout << " Original: " << test << "\n";
std::cout << " Bradford(D65→A): " << brad << "\n";
std::cout << " Von Kries(D65→A): " << vk << "\n";
std::cout << " (Bradford is more perceptually accurate)\n\n";

// 6. ANSI swatches
std::cout << "6. Visual comparison\n";
auto white_d65_rgb = conversion::color_cast<core::rgb8_t>(core::rgbf_t{1.0f, 1.0f, 1.0f});
std::cout << " D65 white ";
colorcpp::io::ansi::print_swatch(std::cout, white_d65_rgb);
std::cout << "\n";

auto tungsten_rgb = conversion::color_cast<core::rgb8_t>(
bradford_adapt(core::rgbf_t{1.0f, 1.0f, 1.0f}, WHITEPOINT_D65, WHITEPOINT_A));
std::cout << " Tungsten A ";
colorcpp::io::ansi::print_swatch(std::cout, tungsten_rgb);
std::cout << "\n\n";

std::cout << "Done.\n";
return 0;
}
4 changes: 2 additions & 2 deletions examples/compare_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ int main() {
<< compare::perceptual_equal_de2000(ui_rgb, converted_rgb, 0.05f) << '\n';
rgbaf_t alpha_a{0.5f, 0.25f, 0.75f, 1.0f};
rgbaf_t alpha_b{0.5f, 0.25f, 0.75f, 0.1f};
std::cout << " perceptual_equal(rgba alpha differs, 0.001): " << compare::perceptual_equal(alpha_a, alpha_b, 0.001f)
<< '\n';
std::cout << " perceptual_equal(rgba alpha differs, 0.001): "
<< compare::perceptual_equal(alpha_a, alpha_b, 0.001f) << '\n';
std::cout << " exact_equal(rgba alpha differs): " << compare::exact_equal(alpha_a, alpha_b) << '\n';
std::cout << " note: perceptual compare converts through CIELAB, so alpha is currently ignored\n";

Expand Down
70 changes: 70 additions & 0 deletions examples/prophoto_rgb_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* @file prophoto_rgb_example.cpp
* @brief Demonstrates ProPhoto RGB (ROMM RGB) wide-gamut color space usage.
*
* Build: cmake -DCOLORCPP_BUILD_EXAMPLES=ON && make prophoto_rgb_example
*/

#include <colorcpp/colorcpp.hpp>
#include <iostream>

using namespace colorcpp;

int main() {
std::cout << "=== ProPhoto RGB (ROMM RGB) Wide-Gamut Color Space ===\n\n";

// 1. Construct ProPhoto RGB colors
std::cout << "1. Construction\n";
core::prophoto_rgbf_t red(0.8f, 0.1f, 0.1f);
core::prophoto_rgbf_t green(0.1f, 0.8f, 0.1f);
core::prophoto_rgbf_t blue(0.1f, 0.1f, 0.8f);
std::cout << " Red: " << red << "\n";
std::cout << " Green: " << green << "\n";
std::cout << " Blue: " << blue << "\n\n";

// 2. sRGB → ProPhoto → sRGB (gamut expansion)
std::cout << "2. sRGB ↔ ProPhoto RGB round-trip\n";
core::rgbf_t srgb_red(1.0f, 0.0f, 0.0f);
auto pprgb = conversion::color_cast<core::prophoto_rgbf_t>(srgb_red);
auto back = conversion::color_cast<core::rgbf_t>(pprgb);
std::cout << " sRGB red: " << srgb_red << "\n";
std::cout << " → ProPhoto RGB: " << pprgb << "\n";
std::cout << " → back to sRGB: " << back << "\n\n";

// 3. D50 white point / chromatic adaptation
std::cout << "3. Chromatic adaptation (D50 ↔ D65)\n";
core::xyz_t white_d65 = algorithms::chromatic_adaptation::WHITEPOINT_D65;
core::xyz_t white_d50 = algorithms::chromatic_adaptation::WHITEPOINT_D50;
std::cout << " D65 white: " << white_d65 << "\n";
std::cout << " D50 white: " << white_d50 << "\n";
auto d65_to_d50 = algorithms::chromatic_adaptation::bradford_adapt(white_d65, white_d65, white_d50);
std::cout << " Bradford(D65→D50): " << d65_to_d50 << "\n\n";

// 4. Gamut check
std::cout << "4. Gamut membership\n";
core::rgbf_t in_gamut(0.5f, 0.5f, 0.5f);
std::cout << " Gray 0.5 in ProPhoto? " << std::boolalpha << algorithms::gamut::is_in_prophoto_gamut(in_gamut)
<< "\n";
// ProPhoto is huge — most sRGB colors are well inside it
std::cout << " sRGB red in ProPhoto? " << algorithms::gamut::is_in_prophoto_gamut(srgb_red) << "\n\n";

// 5. CSS parsing
std::cout << "5. CSS color(prophoto-rgb ...) parsing\n";
auto css = colorcpp::io::css::parse_css_color<core::prophoto_rgbaf_t>("color(prophoto-rgb 0.5 0.3 0.7 / 0.9)");
if (css) {
std::cout << " Parsed: " << *css << "\n";
std::cout << " CSS string: "
<< colorcpp::io::css::to_css_color_string(conversion::color_cast<core::rgbaf_t>(*css)) << "\n";
}
std::cout << "\n";

// 6. Gamma encoding
std::cout << "6. Gamma encoding (Gamma 1.8 with linear segment)\n";
auto linear_pp = conversion::color_cast<core::linear_prophoto_rgbf_t>(core::prophoto_rgbf_t{0.5f, 0.5f, 0.5f});
std::cout << " ProPhoto (gamma): " << core::prophoto_rgbf_t{0.5f, 0.5f, 0.5f} << "\n";
std::cout << " Linear ProPhoto: " << linear_pp << "\n";
std::cout << " (Gamma 1.8 is gentler than sRGB's ~2.2)\n\n";

std::cout << "Done.\n";
return 0;
}
75 changes: 75 additions & 0 deletions examples/rec2020_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* @file rec2020_example.cpp
* @brief Demonstrates Rec.2020 (BT.2020) wide-gamut color space usage.
*
* Build: cmake -DCOLORCPP_BUILD_EXAMPLES=ON && make rec2020_example
*/

#include <colorcpp/colorcpp.hpp>
#include <iostream>

using namespace colorcpp;

int main() {
std::cout << "=== Rec.2020 (BT.2020) Wide-Gamut Color Space ===\n\n";

// 1. Construct Rec.2020 colors
std::cout << "1. Construction\n";
core::rec2020_rgbf_t red(0.8f, 0.1f, 0.1f);
core::rec2020_rgbf_t green(0.1f, 0.8f, 0.1f);
core::rec2020_rgbf_t blue(0.1f, 0.1f, 0.8f);
std::cout << " Red: " << red << "\n";
std::cout << " Green: " << green << "\n";
std::cout << " Blue: " << blue << "\n\n";

// 2. Gamut hierarchy: sRGB ⊂ Display P3 ⊂ Adobe RGB ⊂ Rec.2020 ⊂ ProPhoto
std::cout << "2. Gamut hierarchy comparison\n";
core::rgbf_t test_color(0.0f, 1.0f, 0.0f); // sRGB pure green

auto dp3 = conversion::color_cast<core::display_p3f_t>(test_color);
auto argb = conversion::color_cast<core::adobe_rgbf_t>(test_color);
auto r2020 = conversion::color_cast<core::rec2020_rgbf_t>(test_color);
auto pprgb = conversion::color_cast<core::prophoto_rgbf_t>(test_color);

std::cout << " sRGB green:\n";
std::cout << " -> Display P3: " << dp3 << "\n";
std::cout << " -> Adobe RGB: " << argb << "\n";
std::cout << " -> Rec.2020: " << r2020 << "\n";
std::cout << " -> ProPhoto: " << pprgb << "\n";
std::cout << " (Notice how the same sRGB green maps to different values\n";
std::cout << " in each space due to different primaries)\n\n";

// 3. Round-trip fidelity
std::cout << "3. Rec.2020 round-trip fidelity\n";
core::rec2020_rgbf_t orig(0.5f, 0.3f, 0.7f);
auto via_srgb = conversion::color_cast<core::rec2020_rgbf_t>(conversion::color_cast<core::rgbf_t>(orig));
std::cout << " Original: " << orig << "\n";
std::cout << " Via sRGB: " << via_srgb << "\n\n";

// 4. Transfer function
std::cout << "4. BT.709-style piecewise transfer function\n";
core::rec2020_rgbf_t mid(0.5f, 0.5f, 0.5f);
auto linear = conversion::color_cast<core::linear_rec2020_rgbf_t>(mid);
std::cout << " Rec.2020 (gamma): " << mid << "\n";
std::cout << " Linear Rec.2020: " << linear << "\n";
std::cout << " (alpha=1.0993, beta=0.0181 -- slightly different from sRGB)\n\n";

// 5. CSS parsing
std::cout << "5. CSS color(rec2020 ...) parsing\n";
using namespace colorcpp::io::css;
auto css = parse_css_color<core::rec2020_rgbaf_t>("color(rec2020 0.64 0.33 0.21)");
if (css) {
std::cout << " Parsed: " << *css << "\n";
std::cout << " CSS string (sRGB fallback): " << to_css_color_string(conversion::color_cast<core::rgbaf_t>(*css))
<< "\n";
}
std::cout << "\n";

// 6. Rec.2020 is widely used in UHD/HDR
std::cout << "6. Rec.2020 fact\n";
std::cout << " Rec.2020 covers ~75% of CIE 1931 visible gamut.\n";
std::cout << " It is the standard color space for 4K/8K UHDTV.\n\n";

std::cout << "Done.\n";
return 0;
}
5 changes: 3 additions & 2 deletions include/colorcpp/algorithms/algorithms.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @file algorithms.hpp
* @brief Aggregates color algorithms: accessibility, color temperature, delta E, gamut mapping, gradient, harmony,
* vision simulation.
* @brief Aggregates color algorithms: accessibility, chromatic adaptation, color temperature, delta E, gamut mapping,
* gradient, harmony, vision simulation.
*
* @par Color difference
* - @ref delta_e::delta_e_76 / @ref delta_e::delta_e_94 / @ref delta_e::delta_e_2000: **CIELAB D65** metrics.
Expand All @@ -12,6 +12,7 @@
#pragma once

#include <colorcpp/algorithms/accessibility.hpp>
#include <colorcpp/algorithms/chromatic_adaptation.hpp>
#include <colorcpp/algorithms/color_temperature.hpp>
#include <colorcpp/algorithms/delta_e.hpp>
#include <colorcpp/algorithms/gamut.hpp>
Expand Down
Loading
Loading