mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 17:36:18 +03:00
Merge pull request #5350 from elejke/master
Add preserve_tone option to autocontrast
This commit is contained in:
commit
b0b4fee796
|
@ -29,6 +29,7 @@ def test_sanity():
|
|||
ImageOps.autocontrast(hopper("L"), cutoff=(2, 10))
|
||||
ImageOps.autocontrast(hopper("L"), ignore=[0, 255])
|
||||
ImageOps.autocontrast(hopper("L"), mask=hopper("L"))
|
||||
ImageOps.autocontrast(hopper("L"), preserve_tone=True)
|
||||
|
||||
ImageOps.colorize(hopper("L"), (0, 0, 0), (255, 255, 255))
|
||||
ImageOps.colorize(hopper("L"), "black", "white")
|
||||
|
@ -336,7 +337,7 @@ def test_autocontrast_mask_toy_input():
|
|||
assert ImageStat.Stat(result_nomask).median == [128]
|
||||
|
||||
|
||||
def test_auto_contrast_mask_real_input():
|
||||
def test_autocontrast_mask_real_input():
|
||||
# Test the autocontrast with a rectangular mask
|
||||
with Image.open("Tests/images/iptc.jpg") as img:
|
||||
|
||||
|
@ -362,3 +363,52 @@ def test_auto_contrast_mask_real_input():
|
|||
threshold=2,
|
||||
msg="autocontrast without mask pixel incorrect",
|
||||
)
|
||||
|
||||
|
||||
def test_autocontrast_preserve_tone():
|
||||
def autocontrast(mode, preserve_tone):
|
||||
im = hopper(mode)
|
||||
return ImageOps.autocontrast(im, preserve_tone=preserve_tone).histogram()
|
||||
|
||||
assert autocontrast("RGB", True) != autocontrast("RGB", False)
|
||||
assert autocontrast("L", True) == autocontrast("L", False)
|
||||
|
||||
|
||||
def test_autocontrast_preserve_gradient():
|
||||
gradient = Image.linear_gradient("L")
|
||||
|
||||
# test with a grayscale gradient that extends to 0,255.
|
||||
# Should be a noop.
|
||||
out = ImageOps.autocontrast(gradient, cutoff=0, preserve_tone=True)
|
||||
|
||||
assert_image_equal(gradient, out)
|
||||
|
||||
# cutoff the top and bottom
|
||||
# autocontrast should make the first and last histogram entries equal
|
||||
# and, with rounding, should be 10% of the image pixels
|
||||
out = ImageOps.autocontrast(gradient, cutoff=10, preserve_tone=True)
|
||||
hist = out.histogram()
|
||||
assert hist[0] == hist[-1]
|
||||
assert hist[-1] == 256 * round(256 * 0.10)
|
||||
|
||||
# in rgb
|
||||
img = gradient.convert("RGB")
|
||||
out = ImageOps.autocontrast(img, cutoff=0, preserve_tone=True)
|
||||
assert_image_equal(img, out)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"color", ((255, 255, 255), (127, 255, 0), (127, 127, 127), (0, 0, 0))
|
||||
)
|
||||
def test_autocontrast_preserve_one_color(color):
|
||||
img = Image.new("RGB", (10, 10), color)
|
||||
|
||||
# single color images shouldn't change
|
||||
out = ImageOps.autocontrast(img, cutoff=0, preserve_tone=True)
|
||||
assert_image_equal(img, out) # single color, no cutoff
|
||||
|
||||
# even if there is a cutoff
|
||||
out = ImageOps.autocontrast(
|
||||
img, cutoff=10, preserve_tone=True
|
||||
) # single color 10 cutoff
|
||||
assert_image_equal(img, out)
|
||||
|
|
|
@ -83,6 +83,15 @@ be specified through a keyword argument::
|
|||
|
||||
im.save("out.tif", icc_profile=...)
|
||||
|
||||
|
||||
ImageOps.autocontrast: preserve_tone
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The default behaviour of :py:meth:`~PIL.ImageOps.autocontrast` is to normalize
|
||||
separate histograms for each color channel, changing the tone of the image. The new
|
||||
``preserve_tone`` argument keeps the tone unchanged by using one luminance histogram
|
||||
for all channels.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ def _lut(image, lut):
|
|||
# actions
|
||||
|
||||
|
||||
def autocontrast(image, cutoff=0, ignore=None, mask=None):
|
||||
def autocontrast(image, cutoff=0, ignore=None, mask=None, preserve_tone=False):
|
||||
"""
|
||||
Maximize (normalize) image contrast. This function calculates a
|
||||
histogram of the input image (or mask region), removes ``cutoff`` percent of the
|
||||
|
@ -77,9 +77,17 @@ def autocontrast(image, cutoff=0, ignore=None, mask=None):
|
|||
:param mask: Histogram used in contrast operation is computed using pixels
|
||||
within the mask. If no mask is given the entire image is used
|
||||
for histogram computation.
|
||||
:param preserve_tone: Preserve image tone in Photoshop-like style autocontrast.
|
||||
|
||||
.. versionadded:: 8.2.0
|
||||
|
||||
:return: An image.
|
||||
"""
|
||||
histogram = image.histogram(mask)
|
||||
if preserve_tone:
|
||||
histogram = image.convert("L").histogram(mask)
|
||||
else:
|
||||
histogram = image.histogram(mask)
|
||||
|
||||
lut = []
|
||||
for layer in range(0, len(histogram), 256):
|
||||
h = histogram[layer : layer + 256]
|
||||
|
|
Loading…
Reference in New Issue
Block a user