fix: keep full alpha precision when parsing hex colors#137
Open
spokodev wants to merge 1 commit into
Open
Conversation
`parseHex` rounded the alpha channel to 2 decimals, while the rest of the
library standardized on `ALPHA_PRECISION` (3) — the constant whose own
comment notes that "2 digits after the decimal point ... wasn't accurate
enough, so the library produced colors that were perceived differently".
2 decimals can't represent every 8-bit alpha byte, so hex colors failed
to round-trip: `colord("#476d5e55").toHex()` returned `"#476d5e54"`. 155
of the 255 fractional alpha bytes drifted this way. Using
`ALPHA_PRECISION` lets every hex alpha byte round-trip exactly.
The HEX8 assertion for `#80808080` is updated from `0.5` to `0.502`
(128 / 255 = 0.50196…), the value the documented 3-digit precision yields.
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.
The problem
A HEX8 color does not survive a round-trip through colord:
This affects 155 of the 255 fractional alpha bytes.
Root cause
parseHexrounds the parsed alpha to 2 decimals:…but the rest of the library uses
ALPHA_PRECISION, which is3, and its own comment explains exactly this failure mode:roundRgba(used byrgbaToHexand every output method) already rounds alpha toALPHA_PRECISION, and object/rgb()inputs keep full precision viaclampRgba. OnlyparseHexwas left on the old hard-coded2, so a hex alpha of0x55(85 / 255 = 0.3333…) is stored as0.33, andround(0.33 * 255) = 84 = 0x54on the way back out.2 decimals simply cannot represent every 8-bit alpha byte; 3 can (verified across all 0–254 fractional bytes: 2 digits drifts 155 of them, 3 digits drifts none).
Fix
Use
ALPHA_PRECISIONinparseHex, matching the rest of the library. Every HEX8 alpha byte now round-trips exactly, and hex parsing is consistent withrgb()/object inputs.Test plan
colord(hex).toHex() === hexfor a spread of HEX8 alpha bytes (fails onmain, passes here).colord("#80808080").toRgb().ais0.502rather than0.5—128 / 255 = 0.50196…, i.e. the value the documented 3-digit precision produces (the old0.5was the 2-digit approximation this change moves away from).jest).