diff --git a/.changeset/hex-alpha-full-precision.md b/.changeset/hex-alpha-full-precision.md new file mode 100644 index 00000000..d31caacd --- /dev/null +++ b/.changeset/hex-alpha-full-precision.md @@ -0,0 +1,5 @@ +--- +"chroma-js": patch +--- + +Preserve full alpha precision when parsing `#rrggbbaa` / `#rgba` hex colors. `hex2rgb` rounded the alpha channel to two decimals, so 136 of 256 alpha bytes did not round-trip (for example `chroma('#ff000088').hex()` returned `#ff000087`). Alpha is now parsed exactly as `aa / 255`, matching the RGB channels and CSS Color 4. diff --git a/src/io/hex/hex2rgb.js b/src/io/hex/hex2rgb.js index e1f43b4b..02974503 100644 --- a/src/io/hex/hex2rgb.js +++ b/src/io/hex/hex2rgb.js @@ -42,7 +42,7 @@ const hex2rgb = (hex) => { const r = (u >> 24) & 0xff; const g = (u >> 16) & 0xff; const b = (u >> 8) & 0xff; - const a = Math.round(((u & 0xff) / 0xff) * 100) / 100; + const a = (u & 0xff) / 0xff; return [r, g, b, a]; } diff --git a/test/alpha.test.js b/test/alpha.test.js index e398de80..f5621e18 100644 --- a/test/alpha.test.js +++ b/test/alpha.test.js @@ -35,8 +35,8 @@ describe('Tests for the alpha channel', () => { it('parsing hex rgba colors', () => { const color = chroma('#ff00004d'); expect(color.name()).toBe('red'); - expect(color.alpha()).toBe(0.3); - expect(color.rgba()).toEqual([255, 0, 0, 0.3]); + expect(color.alpha()).toBe(0x4d / 255); + expect(color.rgba()).toEqual([255, 0, 0, 0x4d / 255]); }); it('parsing rgba colors', () => { diff --git a/test/contrast.test.js b/test/contrast.test.js index 51ec8be0..776b7169 100644 --- a/test/contrast.test.js +++ b/test/contrast.test.js @@ -43,10 +43,8 @@ describe('Testing contrast ratio with APCA', () => { }); it('contrast with alpha', () => { - // todo: there's a slight difference to the values shown in the APCA demo - // when computing contrast between colors with alpha - expect(+contrastAPCA('#00000044', 'white').toFixed(1)).toBe(37.3); // 36.7 - expect(+contrastAPCA('#ffffffc0', 'black').toFixed(1)).toBe(-68); // -68.6 + expect(+contrastAPCA('#00000044', 'white').toFixed(1)).toBe(36.7); + expect(+contrastAPCA('#ffffffc0', 'black').toFixed(1)).toBe(-68.6); }); it('inverse contrast', () => { diff --git a/test/io/hex2rgb.test.js b/test/io/hex2rgb.test.js index c93cea9d..1c931d1f 100644 --- a/test/io/hex2rgb.test.js +++ b/test/io/hex2rgb.test.js @@ -116,29 +116,29 @@ describe('Testing HEX2RGB color conversions', () => { ], 'parse different #rrggbbaa HEX colors': [ [0, 0, 0, 0], - [255, 255, 255, 0.5], - [255, 0, 0, 0.25], - [0, 255, 0, 0.75], + [255, 255, 255, 128 / 255], + [255, 0, 0, 64 / 255], + [0, 255, 0, 192 / 255], [255, 0, 255, 1] ], 'parse different rrggbbaa HEX colors without #': [ [0, 0, 0, 0], - [255, 255, 255, 0.5], - [255, 0, 0, 0.25], - [0, 255, 0, 0.75], + [255, 255, 255, 128 / 255], + [255, 0, 0, 64 / 255], + [0, 255, 0, 192 / 255], [255, 0, 255, 1] ], 'parse different #rgba HEX colors': [ [0, 0, 0, 0], - [255, 255, 255, 0.53], - [255, 0, 0, 0.27], + [255, 255, 255, 136 / 255], + [255, 0, 0, 68 / 255], [0, 255, 0, 0.8], [255, 0, 255, 1] ], 'parse different rgba HEX colors without #': [ [0, 0, 0, 0], - [255, 255, 255, 0.53], - [255, 0, 0, 0.27], + [255, 255, 255, 136 / 255], + [255, 0, 0, 68 / 255], [0, 255, 0, 0.8], [255, 0, 255, 1] ]