RgbToHex emitted a single hex digit for channel values below 0x10 because strconv.FormatInt produces the minimal representation. This broke the fixed-width hex format, the round-trip with HexToRgb, and the hex2basicMap fast path in Rgb2basic. Format each channel with %02x, matching RgbTo256.
2.1 KiB
fix(convert): zero-pad each channel in RgbToHex
Problem
RgbToHex (and its alias Rgb2hex) does not zero-pad channel values below
0x10, so a single hex digit is emitted for those channels:
color.RgbToHex([]int{1, 2, 3}) // "123" , want "010203"
color.RgbToHex([]int{0, 0, 0}) // "000" , want "000000"
color.RgbToHex([]int{10, 11, 12}) // "0a0b0c" -> actually "abc"
This breaks two contracts:
-
The round-trip with
HexToRgbis no longer an identity for colors with any channel below 16:color.RgbToHex(color.HexToRgb("010203")) // "123", not "010203" -
Rgb2basiclooks a color up inhex2basicMap, whose keys are all fixed-width 6-digit hex strings (e.g. "000000"). BecauseRgbToHex(0,0,0)returns "000", pure black never matches the fast-path map and silently falls through to the approximateRgbToAnsi.
The sibling converter RgbTo256 already builds its hex key with
fmt.Sprintf("%02x%02x%02x", ...), so this is an inconsistency within the same
file.
Root cause
convert.go, RgbToHex:
for _, v := range rgb {
hexNodes = append(hexNodes, strconv.FormatInt(int64(v), 16))
}
strconv.FormatInt(_, 16) produces the minimal representation, i.e. one digit
for values 0-15.
Fix
Format each channel as a fixed two-digit hex value:
hexNodes = append(hexNodes, fmt.Sprintf("%02x", v))
fmt is already imported in the file. Existing values >= 16 are unchanged.
Test
Extended TestRgbToHex in utils_test.go with small-channel cases
({0,0,0}, {1,2,3}, {10,11,12}) and an explicit
RgbToHex(HexToRgb(hex)) == hex round-trip check.
- Gate:
go test ./-> ok (PASS) go vet ./...-> exit 0go build ./...-> exit 0
Counterfactual: reverting RgbToHex to strconv.FormatInt(int64(v), 16) makes
the new test fail with expect: "abc" vs actual: "0a0b0c".
Note: gofmt -l convert.go reports the file, but this is pre-existing (a doc
comment near line 866, unrelated to this change and present on the base commit).
The changed region is gofmt-clean, so unrelated lines were intentionally left
untouched.