Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reuse decoding, sampling, and forward OKLCH conversion when async palette graphics request both a palette and semantic swatches with the automatic or CPU quantizer.
Background
A cache miss in
AsyncPaletteGraphicLoadercurrently extracts a palette and then callsswatches, which repeats the image pipeline with at least 16 colors. With the default 10-color palette, the two quantizations are necessary to preserve their different results, but preprocessing the same source twice is redundant.Solution
Add an internal paired extraction path with request-local prepared pixels. It preserves both quantizations at K and max(K, 16), including when K is already 16 or greater. The loader uses the pair and retains its cancellation check before caching or publishing success.
Custom and Metal quantizers keep the existing two-call path. Public API signatures, filtering, fallback, source color-space selection, and the first palette's timing boundary are preserved. A second extraction failure still produces a successful palette with nil swatches. The internal cancellation method returns the canceled task so tests can await completion deterministically.
Related Issue
N/A.
Verification
swift package resolveswift build -c debugswift test --filter PaletteKitTests --filter PaletteKitInsightsTests— 67 tests passed.swift test -c release --filter SharedExtractionTests— 8 tests passed.xcodebuild test -scheme PaletteKit-Package -only-testing:PaletteKitTests -only-testing:PaletteKitInsightsTests -destination 'id=5F0334CA-5AD2-47FE-B837-F802AFFB20FD'— 164 tests passed on iOS 26.5 Simulator (155 core and 9 Insights).SharedExtractionBenchmarks/testSeparatePaletteAndSwatchesandtestSharedPaletteAndSwatches, three process runs each with order alternated.git diff --checkCompatibility and Impact
Additional Context
Release benchmark: a reused 1024×1024 deterministic noise CGImage, K=10, OKLCH, CPU, default downsampling. The same full output checksum consumes both results; input generation is outside measurement. Fifteen clock samples per path from three process runs:
This is 46.4% lower latency for this Mac fixture, not an iPhone or all-image improvement claim. Both paths are measured from this branch; a separate base-versus-head standalone API control uses three JPEG fixtures, gradient, noise, and transparent fallback, with
collectTimings: trueand 45 samples per input. Ordered output signatures match, and median changes range from -0.5% to +1.1%; these measurements do not establish zero overhead or peak-memory equivalence.The benchmark target also provides
testStandalonePalette. This branch is based directly onmainand is independent of the LUT and MMCQ cache PRs.Checklist