diff --git a/Lib/colorsys.py b/Lib/colorsys.py index e97f91718a3a30..13981b5706335b 100644 --- a/Lib/colorsys.py +++ b/Lib/colorsys.py @@ -83,7 +83,12 @@ def rgb_to_hls(r, g, b): if l <= 0.5: s = rangec / sumc else: - s = rangec / (2.0-maxc-minc) # Not always 2.0-sumc: gh-106498. + # Fix for gh-106498: avoid division by zero when very close to white + denominator = 2.0 - maxc - minc + if abs(denominator) < 1e-10: # Very close to zero + s = 0.0 + else: + s = rangec / denominator rc = (maxc-r) / rangec gc = (maxc-g) / rangec bc = (maxc-b) / rangec @@ -145,7 +150,9 @@ def rgb_to_hsv(r, g, b): def hsv_to_rgb(h, s, v): if s == 0.0: return v, v, v - i = int(h*6.0) # XXX assume int() truncates! + # Ensure h is in [0, 1) range for proper calculation + h = h % 1.0 + i = int(h*6.0) # This will truncate towards zero, which is correct f = (h*6.0) - i p = v*(1.0 - s) q = v*(1.0 - s*f) diff --git a/Lib/test/test_colorsys.py b/Lib/test/test_colorsys.py index 74d76294b0b4d4..1733cdd3bcc1ee 100644 --- a/Lib/test/test_colorsys.py +++ b/Lib/test/test_colorsys.py @@ -106,5 +106,27 @@ def test_yiq_values(self): self.assertTripleEqual(yiq, colorsys.rgb_to_yiq(*rgb)) self.assertTripleEqual(rgb, colorsys.yiq_to_rgb(*yiq)) + def test_hsv_hue_wrapping(self): + """Test that HSV hue values outside [0,1) are handled correctly.""" + # Test with hue values outside the normal range + test_cases = [ + (1.0, 1.0, 1.0), # hue = 1.0 (should wrap to 0.0) + (1.5, 1.0, 1.0), # hue = 1.5 (should wrap to 0.5) + (2.0, 1.0, 1.0), # hue = 2.0 (should wrap to 0.0) + (-0.5, 1.0, 1.0), # hue = -0.5 (should wrap to 0.5) + ] + + for h, s, v in test_cases: + # Convert to RGB and back to HSV + rgb = colorsys.hsv_to_rgb(h, s, v) + h_out, s_out, v_out = colorsys.rgb_to_hsv(*rgb) + + # The output hue should be in [0, 1) range + self.assertGreaterEqual(h_out, 0.0) + self.assertLess(h_out, 1.0) + + # The round-trip should preserve the color (within tolerance) + self.assertTripleEqual(rgb, colorsys.hsv_to_rgb(h_out, s_out, v_out)) + if __name__ == "__main__": unittest.main()