Merge pull request #4320 from uploadcare/rgb2l-rounding-error

Fix rounding error on RGB to L conversion
This commit is contained in:
Andrew Murray 2020-01-01 20:09:34 +11:00 committed by GitHub
commit 4203845a24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 21 additions and 18 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 B

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 498 B

View File

@ -7,9 +7,9 @@ class TestImageEntropy(PillowTestCase):
return hopper(mode).entropy()
self.assertAlmostEqual(entropy("1"), 0.9138803254693582)
self.assertAlmostEqual(entropy("L"), 7.06650513081286)
self.assertAlmostEqual(entropy("I"), 7.06650513081286)
self.assertAlmostEqual(entropy("F"), 7.06650513081286)
self.assertAlmostEqual(entropy("L"), 7.063008716585465)
self.assertAlmostEqual(entropy("I"), 7.063008716585465)
self.assertAlmostEqual(entropy("F"), 7.063008716585465)
self.assertAlmostEqual(entropy("P"), 5.0530452472519745)
self.assertAlmostEqual(entropy("RGB"), 8.821286587714319)
self.assertAlmostEqual(entropy("RGBA"), 7.42724306524488)

View File

@ -20,9 +20,9 @@ class TestImageGetData(PillowTestCase):
return data[0], len(data), len(list(data))
self.assertEqual(getdata("1"), (0, 960, 960))
self.assertEqual(getdata("L"), (16, 960, 960))
self.assertEqual(getdata("I"), (16, 960, 960))
self.assertEqual(getdata("F"), (16.0, 960, 960))
self.assertEqual(getdata("L"), (17, 960, 960))
self.assertEqual(getdata("I"), (17, 960, 960))
self.assertEqual(getdata("F"), (17.0, 960, 960))
self.assertEqual(getdata("RGB"), ((11, 13, 52), 960, 960))
self.assertEqual(getdata("RGBA"), ((11, 13, 52, 255), 960, 960))
self.assertEqual(getdata("CMYK"), ((244, 242, 203, 0), 960, 960))

View File

@ -9,14 +9,14 @@ class TestImageGetExtrema(PillowTestCase):
return hopper(mode).getextrema()
self.assertEqual(extrema("1"), (0, 255))
self.assertEqual(extrema("L"), (0, 255))
self.assertEqual(extrema("I"), (0, 255))
self.assertEqual(extrema("F"), (0, 255))
self.assertEqual(extrema("L"), (1, 255))
self.assertEqual(extrema("I"), (1, 255))
self.assertEqual(extrema("F"), (1, 255))
self.assertEqual(extrema("P"), (0, 225)) # fixed palette
self.assertEqual(extrema("RGB"), ((0, 255), (0, 255), (0, 255)))
self.assertEqual(extrema("RGBA"), ((0, 255), (0, 255), (0, 255), (255, 255)))
self.assertEqual(extrema("CMYK"), ((0, 255), (0, 255), (0, 255), (0, 0)))
self.assertEqual(extrema("I;16"), (0, 255))
self.assertEqual(extrema("I;16"), (1, 255))
def test_true_16(self):
with Image.open("Tests/images/16_bit_noise.tif") as im:

View File

@ -8,9 +8,9 @@ class TestImageHistogram(PillowTestCase):
return len(h), min(h), max(h)
self.assertEqual(histogram("1"), (256, 0, 10994))
self.assertEqual(histogram("L"), (256, 0, 638))
self.assertEqual(histogram("I"), (256, 0, 638))
self.assertEqual(histogram("F"), (256, 0, 638))
self.assertEqual(histogram("L"), (256, 0, 662))
self.assertEqual(histogram("I"), (256, 0, 662))
self.assertEqual(histogram("F"), (256, 0, 662))
self.assertEqual(histogram("P"), (256, 0, 1871))
self.assertEqual(histogram("RGB"), (768, 4, 675))
self.assertEqual(histogram("RGBA"), (1024, 0, 16384))

View File

@ -165,14 +165,14 @@ class TestImageColor(PillowTestCase):
self.assertEqual(0, ImageColor.getcolor("black", "L"))
self.assertEqual(255, ImageColor.getcolor("white", "L"))
self.assertEqual(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L"))
self.assertEqual(163, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L"))
Image.new("L", (1, 1), "white")
self.assertEqual(0, ImageColor.getcolor("black", "1"))
self.assertEqual(255, ImageColor.getcolor("white", "1"))
# The following test is wrong, but is current behavior
# The correct result should be 255 due to the mode 1
self.assertEqual(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
self.assertEqual(163, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
# Correct behavior
# self.assertEqual(
# 255, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
@ -180,5 +180,5 @@ class TestImageColor(PillowTestCase):
self.assertEqual((0, 255), ImageColor.getcolor("black", "LA"))
self.assertEqual((255, 255), ImageColor.getcolor("white", "LA"))
self.assertEqual((162, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA"))
self.assertEqual((163, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA"))
Image.new("LA", (1, 1), "white")

View File

@ -134,7 +134,9 @@ def getcolor(color, mode):
if Image.getmodebase(mode) == "L":
r, g, b = color
color = (r * 299 + g * 587 + b * 114) // 1000
# ITU-R Recommendation 601-2 for nonlinear RGB
# scaled to 24 bits to match the convert's implementation.
color = (r * 19595 + g * 38470 + b * 7471 + 0x8000) >> 16
if mode[-1] == "A":
return (color, alpha)
else:

View File

@ -44,7 +44,8 @@
#define L(rgb)\
((INT32) (rgb)[0]*299 + (INT32) (rgb)[1]*587 + (INT32) (rgb)[2]*114)
#define L24(rgb)\
((rgb)[0]*19595 + (rgb)[1]*38470 + (rgb)[2]*7471)
((rgb)[0]*19595 + (rgb)[1]*38470 + (rgb)[2]*7471 + 0x8000)
#ifndef round
double round(double x) {