Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2f22d04
docs: plan and spec for moving PCS adjustments into CIccPcsXform
maxderhak Aug 26, 2026
d4e1f2d
docs: apply pre-flight scan rulings to the PCS adjustment plan
maxderhak Aug 26, 2026
955000e
test: characterize PCS adjustment behavior before moving it
maxderhak Aug 26, 2026
dd1920c
test: fix vacuous relative-intent control in PCS adjustment character…
maxderhak Aug 26, 2026
e2357c8
fix: build a leading-edge CIccPcsXform when the xform needs a PCS adjust
maxderhak Aug 26, 2026
2ec4e63
feat: add per-side virtual PCS adjust predicates answerable at Begin …
maxderhak Aug 26, 2026
ae5bbc5
fix: add CIccXformNamedColor PCS-adjust predicate overrides, out of line
maxderhak Aug 26, 2026
af2c273
test: cover the spectral-PCS term in CIccXformNamedColor's predicates
maxderhak Aug 26, 2026
1693b4d
test: replace unreachable spectral-PCS fixture with a real test double
maxderhak Aug 26, 2026
eb04612
refactor: CIccPcsXform performs PCS adjustments at chain edges too
maxderhak Aug 26, 2026
eeec06d
docs: add spectral-PCS precondition to Task 5 of the PCS adjustment plan
maxderhak Aug 26, 2026
85eb2d3
fix: correct the ConnectLast() domain comment and add leading-edge co…
maxderhak Aug 26, 2026
f41275d
test: pin the live spectral-PCS in-xform adjustment
maxderhak Aug 26, 2026
851869b
test: pin XYZ-PCS behaviour after the clip retirement; document place…
maxderhak Aug 26, 2026
aaa11ee
docs: record BPC black-point deltas from the PCS adjustment move
maxderhak Aug 26, 2026
6bb880f
docs: fix BPC delta measurement to use a fixture proven live
maxderhak Aug 26, 2026
8109adf
docs: remove irreproducible external probe from BPC delta record
maxderhak Aug 26, 2026
8a89677
docs: full sweep and corrected contract matrix for the PCS adjustment…
maxderhak Aug 26, 2026
45bbc76
docs+fix: address final review findings on the PCS-adjust-in-PcsXform…
maxderhak Aug 26, 2026
2af4dcc
docs: spec the spectral PCS white-point conversion
maxderhak Aug 26, 2026
e680d1c
fix(cmm): convert spectral PCS between relative and absolute via the …
maxderhak Aug 26, 2026
8d11da5
docs: resumption record for the PCS adjustment refactor
maxderhak Aug 26, 2026
60bae1b
fix(cmm): cache spectral-port predicates and correct review-round com…
maxderhak Aug 26, 2026
a1f40fc
fix(cmm): refresh named-color spectral-port cache on setter, not just…
maxderhak Aug 26, 2026
c36831d
fix(cmm): centralise the PCS-port cache refresh into one helper
maxderhak Aug 26, 2026
b352d7c
docs: discharge Task 5's spectral precondition
maxderhak Aug 26, 2026
85b7b85
refactor: retire the in-xform PCS adjustment path
maxderhak Aug 26, 2026
185ac61
test+docs: pin a reachable non-PCS port the Task 5 deletion changes
maxderhak Aug 27, 2026
c93486b
docs: record the MCS gap in the canonical PCS adjustment design note
maxderhak Aug 27, 2026
25e4c5d
docs: update the resumption record - all tasks complete, three decisi…
maxderhak Aug 27, 2026
35b838b
refactor: delete AdjustPCS()/CheckSrcAbs()/CheckDstAbs() and m_AbsLab
maxderhak Aug 27, 2026
a98afba
docs+fix: address review round 2 on the AdjustPCS/CheckSrcAbs deletion
maxderhak Aug 27, 2026
3abdd3d
docs: record the helper deletion in the resumption record
maxderhak Aug 27, 2026
b1b9ed3
ci: remove fixed JSON profile count
xsscx Aug 27, 2026
75d839f
ci: remove fixed Windows profile count
xsscx Aug 27, 2026
ee8670f
chore: use the ICC copyright + BSD 3-Clause header on the new regress…
maxderhak Aug 27, 2026
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
1,806 changes: 1,806 additions & 0 deletions .github/ci/regression/pcs-adjust-placement.cpp

Large diffs are not rendered by default.

20 changes: 12 additions & 8 deletions .github/ci/regression/v2-legacy-pcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@
// - CIccCmm::Begin() (IccCmm.cpp:9214 and :9285) splices a CIccPcsXform onto a
// legacy transform's PCS edge when UseLegacyPCS() is set. This is the leg
// that produces the rescale seen at the output, and the one group 3 covers.
// - CIccXform::AdjustPCS() picks Lab2ToXyz/XyzToLab2 over LabToXyz/XyzToLab.
// It runs here (v2 + perceptual sets m_bAdjustPCS), but it converts
// - Wherever a colorimetric PCS adjustment applies (v2 + perceptual sets
// m_bAdjustPCS), CIccPcsXform's Connect()/ConnectFirst()/ConnectLast()
// push pushLab2ToXyz()/pushXyzToLab2() instead of pushLabToXyz()/
// pushXyzToLab() when UseLegacyPCS() is set (IccCmm.cpp, e.g. the
// pushLab2ToXyz()/pushLabToXyz() choices in Connect()). But it converts
// Lab -> XYZ -> Lab with the *same* encoding on both sides, so changing both
// sides together cancels out and is not visible at the output at all. Only a
// one-sided change is, and group 3 does catch that. Measured, against a
// deliberately broken library: predicate forced false -> 5 assertions fail;
// AdjustPCS input leg only -> 4 fail; both AdjustPCS legs together -> passes,
// correctly, because the encodings cancel.
// the input leg's encoding choice alone -> 4 fail; both legs together ->
// passes, correctly, because the encodings cancel.
//
// Nothing in CI reached any of that. A clean checkout's Testing corpus -- the 80
// tracked profiles plus the 130 CreateAllProfiles.sh generates, 210 in all -- is
Expand Down Expand Up @@ -223,8 +226,9 @@ void legacyEncodingMath()
}
}

// The pair is used in both directions inside a single AdjustPCS call, so a
// one-sided change would corrupt every v2 transform rather than fail loudly.
// The pair is used in both directions inside a single legacy-PCS
// conversion, so a one-sided change would corrupt every v2 transform
// rather than fail loudly.
CIccPCSUtil::Lab4ToLab2(back, lab4);
for (int c = 0; c < 3; c++) {
if (std::fabs((double)back[c] - (double)probe[i][c]) > 1e-6) {
Expand All @@ -233,8 +237,8 @@ void legacyEncodingMath()
}
}

// The full legacy leg of AdjustPCS: Lab2 -> XYZ -> Lab2 must be an identity
// to within float noise, exactly as the v4 leg is.
// The full legacy leg of the PCS adjustment: Lab2 -> XYZ -> Lab2 must be
// an identity to within float noise, exactly as the v4 leg is.
icFloatNumber xyz[3], roundTrip[3];
CIccPCSUtil::Lab2ToXyz(xyz, probe[i], true);
CIccPCSUtil::XyzToLab2(roundTrip, xyz, true);
Expand Down
5 changes: 2 additions & 3 deletions .github/workflows/ci-json-roundtrip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,9 @@ jobs:
ICCDEV_TEST_OUTDIR="$BUILD_JSON/Testing/ctest-output/ci-json-create-profiles" \
bash CreateAllProfiles.sh 2>&1 | tee "$CREATE_LOG"

# 130 before #1883; the Testing/V2 section now adds five v2 fixtures.
profile_parse_count="$(grep -c 'Profile parsed and saved correctly' "$CREATE_LOG" || true)"
if [ "$profile_parse_count" -ne 135 ]; then
echo "[FAIL] Expected 135 generated profiles, got ${profile_parse_count}"
if [ "$profile_parse_count" -eq 0 ]; then
echo "[FAIL] Test-profile generation completed without producing a profile"
exit 1
fi
Comment thread
xsscx marked this conversation as resolved.
echo "[OK] Generated ${profile_parse_count} test profiles"
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ shares one source of truth. Update rules here, not in the mirrors.
| MCP subprocess debug | `.github/prompts/debug-mcp-subprocess.prompt.md` |
| Python/Cython debug | `.github/prompts/debug-python-bindings.prompt.md` |
| Documentation maintenance | `docs/documentation-maintenance.md` |
| PCS adjustment placement (`CIccPcsXform` refactor) | `docs/pcs-adjustment-placement.md` |

## CFL Harness Scope

Expand Down
62 changes: 54 additions & 8 deletions Build/Cmake/Testing/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4879,6 +4879,58 @@ function(iccdev_add_v2_legacy_pcs_test)
endif()
endfunction()

# Characterization tests for PCS adjustment placement. Builds its own v2/v4
# CMYK fixtures in memory -- Testing/**/*.icc is gitignored and generated, so a
# tracked profile is not available on a fresh clone. Links IccProfLib alone.
function(iccdev_add_pcs_adjust_placement_test)
if(NOT TARGET "${TARGET_LIB_ICCPROFLIB}")
return()
endif()

iccdev_add_regression_executable(iccPcsAdjustPlacementTest
"${ICCDEV_REPO_ROOT}/.github/ci/regression/pcs-adjust-placement.cpp"
)
target_compile_features(iccPcsAdjustPlacementTest PRIVATE cxx_std_17)
target_include_directories(iccPcsAdjustPlacementTest PRIVATE
"${ICCDEV_REPO_ROOT}/IccProfLib"
)
target_link_libraries(iccPcsAdjustPlacementTest PRIVATE ${TARGET_LIB_ICCPROFLIB})
add_dependencies(check iccPcsAdjustPlacementTest)

if(WIN32)
add_test(
NAME iccdev.pcs-adjust-placement
COMMAND "$<TARGET_FILE:iccPcsAdjustPlacementTest>"
)
else()
add_test(
NAME iccdev.pcs-adjust-placement
COMMAND
Comment thread
xsscx marked this conversation as resolved.
"${CMAKE_COMMAND}" -E env
${ICCDEV_TEST_ENV}
"$<TARGET_FILE:iccPcsAdjustPlacementTest>"
)
endif()
set_tests_properties(iccdev.pcs-adjust-placement PROPERTIES
WORKING_DIRECTORY "${ICCDEV_REPO_ROOT}"
TIMEOUT 60
LABELS "iccdev;iccprofLib;pcs;cmm;regression"
)
if(WIN32)
set(_pcs_adjust_placement_windows_env_mods
"PATH=path_list_prepend:$<TARGET_FILE_DIR:iccPcsAdjustPlacementTest>"
"PATH=path_list_prepend:$<TARGET_FILE_DIR:${TARGET_LIB_ICCPROFLIB}>"
)
foreach(_runtime_path IN LISTS ICCDEV_WINDOWS_RUNTIME_PATHS)
list(APPEND _pcs_adjust_placement_windows_env_mods
"PATH=path_list_prepend:${_runtime_path}")
endforeach()
set_tests_properties(iccdev.pcs-adjust-placement PROPERTIES
ENVIRONMENT_MODIFICATION "${_pcs_adjust_placement_windows_env_mods}"
)
endif()
endfunction()

# #1883, second half: pin the tracked v2 XML fixtures themselves. Testing/**/*.icc
# is gitignored, so Testing/V2/*.xml is the tracked artifact and the profile is
# generated from it by CreateAllProfiles.sh. Each case asserts the fixture still
Expand Down Expand Up @@ -6062,14 +6114,6 @@ if(WIN32)
300
"iccdev;windows;setup;profiles"
"${ICCDEV_TESTING_DIR}/CreateAllProfiles.bat"
# Validate the disposable Windows Testing tree by artifact count. The
# batch file echoes commands through cmd.exe, and tool stdout can be lost
# in that layer even when profiles are generated successfully.
# 135 since Testing/V2/v2GrayTRC{,Lab}.xml were added: they are the only
# sources in the tree that produce a CIccXformMonochrome, one per PCS
# encoding. Bump this with any change to the number of profiles
# CreateAllProfiles.bat generates.
EXPECTED_GENERATED_PROFILE_COUNT 135
)
set_tests_properties(iccdev.windows-create-profiles PROPERTIES
FIXTURES_SETUP iccdev_profiles
Expand Down Expand Up @@ -6269,6 +6313,7 @@ if(WIN32)
iccdev_add_json_fixednum_size_cap_test()
iccdev_add_json_srng_uf32_test()
iccdev_add_v2_legacy_pcs_test()
iccdev_add_pcs_adjust_placement_test()
iccdev_add_v2_xml_fixtures_test()
iccdev_add_datetime_parse_test()
iccdev_add_encoding_surround_test()
Expand Down Expand Up @@ -6626,6 +6671,7 @@ iccdev_add_json_writer_move_test()
iccdev_add_json_fixednum_size_cap_test()
iccdev_add_json_srng_uf32_test()
iccdev_add_v2_legacy_pcs_test()
iccdev_add_pcs_adjust_placement_test()
iccdev_add_v2_xml_fixtures_test()
iccdev_add_datetime_parse_test()
iccdev_add_encoding_surround_test()
Expand Down
Loading
Loading