From fb2a184eedf8a4caa0fa3f1369661a0f9aab5486 Mon Sep 17 00:00:00 2001 From: Hamza Date: Wed, 1 Jul 2020 00:48:38 +0500 Subject: [PATCH 1/7] ImageOps autocontrast cutoff updated --- src/PIL/ImageOps.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index e4e0840b8..24f6a3b6b 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -88,12 +88,18 @@ def autocontrast(image, cutoff=0, ignore=None): h[ix] = 0 if cutoff: # cut off pixels from both ends of the histogram + if isinstance(cutoff, int): + cutoff = (cutoff, cutoff) + elif isinstance(cutoff, tuple): + pass + else: + raise ValueError("the cutoff can only be a integer or tuple") # get number of pixels n = 0 for ix in range(256): n = n + h[ix] # remove cutoff% pixels from the low end - cut = n * cutoff // 100 + cut = n * cutoff[0] // 100 for lo in range(256): if cut > h[lo]: cut = cut - h[lo] @@ -104,7 +110,7 @@ def autocontrast(image, cutoff=0, ignore=None): if cut <= 0: break # remove cutoff% samples from the hi end - cut = n * cutoff // 100 + cut = n * cutoff[1] // 100 for hi in range(255, -1, -1): if cut > h[hi]: cut = cut - h[hi] From b768cc09d74294cf20600910560483b185d0512d Mon Sep 17 00:00:00 2001 From: Hamza Date: Wed, 1 Jul 2020 04:01:06 +0500 Subject: [PATCH 2/7] added test --- Tests/test_imageops.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index 3d0afba9c..170ad6b3d 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -300,3 +300,9 @@ def test_exif_transpose(): "Tests/images/hopper_orientation_" + str(i) + ext ) as orientation_im: check(orientation_im) + +def test_autocontrast_cutoff(): + # Test the cutoff argument of autocontrast + with Image.open("Tests/images/bw_gradient.png") as img: + assert ImageOps.autocontrast(img, cutoff=10).getdata() == ImageOps.autocontrast(img, cutoff=(10,10)).getdata() + assert ImageOps.autocontrast(img, cutoff=10).getdata() != ImageOps.autocontrast(img, cutoff=(1,10)).getdata() \ No newline at end of file From cbf4f328c7664e3690bbe2eb9136721730b14f46 Mon Sep 17 00:00:00 2001 From: Hamza Date: Wed, 1 Jul 2020 04:20:19 +0500 Subject: [PATCH 3/7] fixed tests --- Tests/test_imageops.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index 170ad6b3d..ec6a55e0e 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -304,5 +304,5 @@ def test_exif_transpose(): def test_autocontrast_cutoff(): # Test the cutoff argument of autocontrast with Image.open("Tests/images/bw_gradient.png") as img: - assert ImageOps.autocontrast(img, cutoff=10).getdata() == ImageOps.autocontrast(img, cutoff=(10,10)).getdata() - assert ImageOps.autocontrast(img, cutoff=10).getdata() != ImageOps.autocontrast(img, cutoff=(1,10)).getdata() \ No newline at end of file + assert ImageOps.autocontrast(img, cutoff=10).histogram() == ImageOps.autocontrast(img, cutoff=(10,10)).histogram() + assert ImageOps.autocontrast(img, cutoff=10).histogram() != ImageOps.autocontrast(img, cutoff=(1,10)).histogram() \ No newline at end of file From 16e804b8924c516bf18287f250685220e01aea9c Mon Sep 17 00:00:00 2001 From: Hamza Date: Wed, 1 Jul 2020 04:37:17 +0500 Subject: [PATCH 4/7] linting fixed --- Tests/test_imageops.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index ec6a55e0e..9938aff28 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -301,8 +301,15 @@ def test_exif_transpose(): ) as orientation_im: check(orientation_im) + def test_autocontrast_cutoff(): # Test the cutoff argument of autocontrast with Image.open("Tests/images/bw_gradient.png") as img: - assert ImageOps.autocontrast(img, cutoff=10).histogram() == ImageOps.autocontrast(img, cutoff=(10,10)).histogram() - assert ImageOps.autocontrast(img, cutoff=10).histogram() != ImageOps.autocontrast(img, cutoff=(1,10)).histogram() \ No newline at end of file + assert ( + ImageOps.autocontrast(img, cutoff=10).histogram() + == ImageOps.autocontrast(img, cutoff=(10, 10)).histogram() + ) + assert ( + ImageOps.autocontrast(img, cutoff=10).histogram() + != ImageOps.autocontrast(img, cutoff=(1, 10)).histogram() + ) From 27c40910d83a028fde18b9da84e6031443a96c12 Mon Sep 17 00:00:00 2001 From: Hamza <52637755+millionhz@users.noreply.github.com> Date: Wed, 1 Jul 2020 19:01:53 +0500 Subject: [PATCH 5/7] Update src/PIL/ImageOps.py Yup you are absolutely correct; it does the job in fewer lines of code too. Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com> --- src/PIL/ImageOps.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 24f6a3b6b..008ec0238 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -88,12 +88,8 @@ def autocontrast(image, cutoff=0, ignore=None): h[ix] = 0 if cutoff: # cut off pixels from both ends of the histogram - if isinstance(cutoff, int): + if not isinstance(cutoff, tuple): cutoff = (cutoff, cutoff) - elif isinstance(cutoff, tuple): - pass - else: - raise ValueError("the cutoff can only be a integer or tuple") # get number of pixels n = 0 for ix in range(256): From 7d49c8f38cc5325bd87701b54086a3f9c499b7ac Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 2 Jul 2020 19:14:24 +1000 Subject: [PATCH 6/7] Updated documentation --- src/PIL/ImageOps.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageOps.py b/src/PIL/ImageOps.py index 008ec0238..157da0b52 100644 --- a/src/PIL/ImageOps.py +++ b/src/PIL/ImageOps.py @@ -70,7 +70,9 @@ def autocontrast(image, cutoff=0, ignore=None): becomes white (255). :param image: The image to process. - :param cutoff: How many percent to cut off from the histogram. + :param cutoff: The percent to cut off from the histogram on the low and + high ends. Either a tuple of (low, high), or a single + number for both. :param ignore: The background pixel value (use None for no background). :return: An image. """ @@ -105,7 +107,7 @@ def autocontrast(image, cutoff=0, ignore=None): cut = 0 if cut <= 0: break - # remove cutoff% samples from the hi end + # remove cutoff% samples from the high end cut = n * cutoff[1] // 100 for hi in range(255, -1, -1): if cut > h[hi]: From 4b5eab4c1762910c3d80b10ec8b7dc1eb6a7939f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 2 Jul 2020 19:01:56 +1000 Subject: [PATCH 7/7] Simplified code --- Tests/test_imageops.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Tests/test_imageops.py b/Tests/test_imageops.py index 9938aff28..864df447e 100644 --- a/Tests/test_imageops.py +++ b/Tests/test_imageops.py @@ -305,11 +305,9 @@ def test_exif_transpose(): def test_autocontrast_cutoff(): # Test the cutoff argument of autocontrast with Image.open("Tests/images/bw_gradient.png") as img: - assert ( - ImageOps.autocontrast(img, cutoff=10).histogram() - == ImageOps.autocontrast(img, cutoff=(10, 10)).histogram() - ) - assert ( - ImageOps.autocontrast(img, cutoff=10).histogram() - != ImageOps.autocontrast(img, cutoff=(1, 10)).histogram() - ) + + def autocontrast(cutoff): + return ImageOps.autocontrast(img, cutoff).histogram() + + assert autocontrast(10) == autocontrast((10, 10)) + assert autocontrast(10) != autocontrast((1, 10))