mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-27 09:44:31 +03:00
Merge pull request #2735 from uploadcare/deprecate-some-ops
Deprecate ImageOps undocumented functions
This commit is contained in:
commit
9f787f6e3d
|
@ -160,6 +160,26 @@ class GaussianBlur(MultibandFilter):
|
||||||
return image.gaussian_blur(self.radius)
|
return image.gaussian_blur(self.radius)
|
||||||
|
|
||||||
|
|
||||||
|
class BoxBlur(MultibandFilter):
|
||||||
|
"""Blurs the image by setting each pixel to the average value of the pixels
|
||||||
|
in a square box extending radius pixels in each direction.
|
||||||
|
Supports float radius of arbitrary size. Uses an optimized implementation
|
||||||
|
which runs in linear time relative to the size of the image
|
||||||
|
for any radius value.
|
||||||
|
|
||||||
|
:param radius: Size of the box in one direction. Radius 0 does not blur,
|
||||||
|
returns an identical image. Radius 1 takes 1 pixel
|
||||||
|
in each direction, i.e. 9 pixels in total.
|
||||||
|
"""
|
||||||
|
name = "BoxBlur"
|
||||||
|
|
||||||
|
def __init__(self, radius):
|
||||||
|
self.radius = radius
|
||||||
|
|
||||||
|
def filter(self, image):
|
||||||
|
return image.box_blur(self.radius)
|
||||||
|
|
||||||
|
|
||||||
class UnsharpMask(MultibandFilter):
|
class UnsharpMask(MultibandFilter):
|
||||||
"""Unsharp mask filter.
|
"""Unsharp mask filter.
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ from . import Image
|
||||||
from ._util import isStringType
|
from ._util import isStringType
|
||||||
import operator
|
import operator
|
||||||
import functools
|
import functools
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -437,6 +438,13 @@ def solarize(image, threshold=128):
|
||||||
def gaussian_blur(im, radius=None):
|
def gaussian_blur(im, radius=None):
|
||||||
""" PIL_usm.gblur(im, [radius])"""
|
""" PIL_usm.gblur(im, [radius])"""
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
'PIL.ImageOps.gaussian_blur is deprecated. '
|
||||||
|
'Use PIL.ImageFilter.GaussianBlur instead. '
|
||||||
|
'This function will be removed in a future version.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
if radius is None:
|
if radius is None:
|
||||||
radius = 5.0
|
radius = 5.0
|
||||||
|
|
||||||
|
@ -444,12 +452,30 @@ def gaussian_blur(im, radius=None):
|
||||||
|
|
||||||
return im.im.gaussian_blur(radius)
|
return im.im.gaussian_blur(radius)
|
||||||
|
|
||||||
gblur = gaussian_blur
|
|
||||||
|
def gblur(im, radius=None):
|
||||||
|
""" PIL_usm.gblur(im, [radius])"""
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
'PIL.ImageOps.gblur is deprecated. '
|
||||||
|
'Use PIL.ImageFilter.GaussianBlur instead. '
|
||||||
|
'This function will be removed in a future version.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
return gaussian_blur(im, radius)
|
||||||
|
|
||||||
|
|
||||||
def unsharp_mask(im, radius=None, percent=None, threshold=None):
|
def unsharp_mask(im, radius=None, percent=None, threshold=None):
|
||||||
""" PIL_usm.usm(im, [radius, percent, threshold])"""
|
""" PIL_usm.usm(im, [radius, percent, threshold])"""
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
'PIL.ImageOps.unsharp_mask is deprecated. '
|
||||||
|
'Use PIL.ImageFilter.UnsharpMask instead. '
|
||||||
|
'This function will be removed in a future version.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
if radius is None:
|
if radius is None:
|
||||||
radius = 5.0
|
radius = 5.0
|
||||||
if percent is None:
|
if percent is None:
|
||||||
|
@ -461,7 +487,18 @@ def unsharp_mask(im, radius=None, percent=None, threshold=None):
|
||||||
|
|
||||||
return im.im.unsharp_mask(radius, percent, threshold)
|
return im.im.unsharp_mask(radius, percent, threshold)
|
||||||
|
|
||||||
usm = unsharp_mask
|
|
||||||
|
def usm(im, radius=None, percent=None, threshold=None):
|
||||||
|
""" PIL_usm.usm(im, [radius, percent, threshold])"""
|
||||||
|
|
||||||
|
warnings.warn(
|
||||||
|
'PIL.ImageOps.usm is deprecated. '
|
||||||
|
'Use PIL.ImageFilter.UnsharpMask instead. '
|
||||||
|
'This function will be removed in a future version.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
|
return unsharp_mask(im, radius, percent, threshold)
|
||||||
|
|
||||||
|
|
||||||
def box_blur(image, radius):
|
def box_blur(image, radius):
|
||||||
|
@ -478,6 +515,13 @@ def box_blur(image, radius):
|
||||||
in each direction, i.e. 9 pixels in total.
|
in each direction, i.e. 9 pixels in total.
|
||||||
:return: An image.
|
:return: An image.
|
||||||
"""
|
"""
|
||||||
|
warnings.warn(
|
||||||
|
'PIL.ImageOps.box_blur is deprecated. '
|
||||||
|
'Use PIL.ImageFilter.BoxBlur instead. '
|
||||||
|
'This function will be removed in a future version.',
|
||||||
|
DeprecationWarning
|
||||||
|
)
|
||||||
|
|
||||||
image.load()
|
image.load()
|
||||||
|
|
||||||
return image._new(image.im.box_blur(radius))
|
return image._new(image.im.box_blur(radius))
|
||||||
|
|
|
@ -13,20 +13,6 @@ sample.putdata(sum([
|
||||||
], []))
|
], []))
|
||||||
|
|
||||||
|
|
||||||
class ImageMock(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.im = self
|
|
||||||
|
|
||||||
def load(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _new(self, im):
|
|
||||||
return im
|
|
||||||
|
|
||||||
def box_blur(self, radius, n):
|
|
||||||
return radius, n
|
|
||||||
|
|
||||||
|
|
||||||
class TestBoxBlurApi(PillowTestCase):
|
class TestBoxBlurApi(PillowTestCase):
|
||||||
|
|
||||||
def test_imageops_box_blur(self):
|
def test_imageops_box_blur(self):
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from helper import unittest, PillowTestCase, hopper
|
from helper import unittest, PillowTestCase, hopper
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image, ImageFilter
|
||||||
from PIL import ImageFilter
|
|
||||||
|
|
||||||
|
|
||||||
class TestImageFilter(PillowTestCase):
|
class TestImageFilter(PillowTestCase):
|
||||||
|
@ -9,7 +8,8 @@ class TestImageFilter(PillowTestCase):
|
||||||
def test_sanity(self):
|
def test_sanity(self):
|
||||||
|
|
||||||
def filter(filter):
|
def filter(filter):
|
||||||
im = hopper("L")
|
for mode in ["L", "RGB", "CMYK"]:
|
||||||
|
im = hopper(mode)
|
||||||
out = im.filter(filter)
|
out = im.filter(filter)
|
||||||
self.assertEqual(out.mode, im.mode)
|
self.assertEqual(out.mode, im.mode)
|
||||||
self.assertEqual(out.size, im.size)
|
self.assertEqual(out.size, im.size)
|
||||||
|
@ -28,9 +28,9 @@ class TestImageFilter(PillowTestCase):
|
||||||
filter(ImageFilter.MedianFilter)
|
filter(ImageFilter.MedianFilter)
|
||||||
filter(ImageFilter.MinFilter)
|
filter(ImageFilter.MinFilter)
|
||||||
filter(ImageFilter.ModeFilter)
|
filter(ImageFilter.ModeFilter)
|
||||||
filter(ImageFilter.Kernel((3, 3), list(range(9))))
|
|
||||||
filter(ImageFilter.GaussianBlur)
|
filter(ImageFilter.GaussianBlur)
|
||||||
filter(ImageFilter.GaussianBlur(5))
|
filter(ImageFilter.GaussianBlur(5))
|
||||||
|
filter(ImageFilter.BoxBlur(5))
|
||||||
filter(ImageFilter.UnsharpMask)
|
filter(ImageFilter.UnsharpMask)
|
||||||
filter(ImageFilter.UnsharpMask(10))
|
filter(ImageFilter.UnsharpMask(10))
|
||||||
|
|
||||||
|
|
|
@ -12,15 +12,25 @@ class TestImageOpsUsm(PillowTestCase):
|
||||||
|
|
||||||
def test_ops_api(self):
|
def test_ops_api(self):
|
||||||
|
|
||||||
i = ImageOps.gaussian_blur(im, 2.0)
|
i = self.assert_warning(DeprecationWarning,
|
||||||
|
ImageOps.gaussian_blur, im, 2.0)
|
||||||
self.assertEqual(i.mode, "RGB")
|
self.assertEqual(i.mode, "RGB")
|
||||||
self.assertEqual(i.size, (128, 128))
|
self.assertEqual(i.size, (128, 128))
|
||||||
# i.save("blur.bmp")
|
|
||||||
|
|
||||||
i = ImageOps.unsharp_mask(im, 2.0, 125, 8)
|
i = self.assert_warning(DeprecationWarning,
|
||||||
|
ImageOps.gblur, im, 2.0)
|
||||||
|
self.assertEqual(i.mode, "RGB")
|
||||||
|
self.assertEqual(i.size, (128, 128))
|
||||||
|
|
||||||
|
i = self.assert_warning(DeprecationWarning,
|
||||||
|
ImageOps.unsharp_mask, im, 2.0, 125, 8)
|
||||||
|
self.assertEqual(i.mode, "RGB")
|
||||||
|
self.assertEqual(i.size, (128, 128))
|
||||||
|
|
||||||
|
i = self.assert_warning(DeprecationWarning,
|
||||||
|
ImageOps.usm, im, 2.0, 125, 8)
|
||||||
self.assertEqual(i.mode, "RGB")
|
self.assertEqual(i.mode, "RGB")
|
||||||
self.assertEqual(i.size, (128, 128))
|
self.assertEqual(i.size, (128, 128))
|
||||||
# i.save("usm.bmp")
|
|
||||||
|
|
||||||
def test_filter_api(self):
|
def test_filter_api(self):
|
||||||
|
|
||||||
|
@ -36,38 +46,38 @@ class TestImageOpsUsm(PillowTestCase):
|
||||||
|
|
||||||
def test_usm_formats(self):
|
def test_usm_formats(self):
|
||||||
|
|
||||||
usm = ImageOps.unsharp_mask
|
usm = ImageFilter.UnsharpMask
|
||||||
self.assertRaises(ValueError, usm, im.convert("1"))
|
self.assertRaises(ValueError, im.convert("1").filter, usm)
|
||||||
usm(im.convert("L"))
|
im.convert("L").filter(usm)
|
||||||
self.assertRaises(ValueError, usm, im.convert("I"))
|
self.assertRaises(ValueError, im.convert("I").filter, usm)
|
||||||
self.assertRaises(ValueError, usm, im.convert("F"))
|
self.assertRaises(ValueError, im.convert("F").filter, usm)
|
||||||
usm(im.convert("RGB"))
|
im.convert("RGB").filter(usm)
|
||||||
usm(im.convert("RGBA"))
|
im.convert("RGBA").filter(usm)
|
||||||
usm(im.convert("CMYK"))
|
im.convert("CMYK").filter(usm)
|
||||||
self.assertRaises(ValueError, usm, im.convert("YCbCr"))
|
self.assertRaises(ValueError, im.convert("YCbCr").filter, usm)
|
||||||
|
|
||||||
def test_blur_formats(self):
|
def test_blur_formats(self):
|
||||||
|
|
||||||
blur = ImageOps.gaussian_blur
|
blur = ImageFilter.GaussianBlur
|
||||||
self.assertRaises(ValueError, blur, im.convert("1"))
|
self.assertRaises(ValueError, im.convert("1").filter, blur)
|
||||||
blur(im.convert("L"))
|
blur(im.convert("L"))
|
||||||
self.assertRaises(ValueError, blur, im.convert("I"))
|
self.assertRaises(ValueError, im.convert("I").filter, blur)
|
||||||
self.assertRaises(ValueError, blur, im.convert("F"))
|
self.assertRaises(ValueError, im.convert("F").filter, blur)
|
||||||
blur(im.convert("RGB"))
|
im.convert("RGB").filter(blur)
|
||||||
blur(im.convert("RGBA"))
|
im.convert("RGBA").filter(blur)
|
||||||
blur(im.convert("CMYK"))
|
im.convert("CMYK").filter(blur)
|
||||||
self.assertRaises(ValueError, blur, im.convert("YCbCr"))
|
self.assertRaises(ValueError, im.convert("YCbCr").filter, blur)
|
||||||
|
|
||||||
def test_usm_accuracy(self):
|
def test_usm_accuracy(self):
|
||||||
|
|
||||||
src = snakes.convert('RGB')
|
src = snakes.convert('RGB')
|
||||||
i = src._new(ImageOps.unsharp_mask(src, 5, 1024, 0))
|
i = src.filter(ImageFilter.UnsharpMask(5, 1024, 0))
|
||||||
# Image should not be changed because it have only 0 and 255 levels.
|
# Image should not be changed because it have only 0 and 255 levels.
|
||||||
self.assertEqual(i.tobytes(), src.tobytes())
|
self.assertEqual(i.tobytes(), src.tobytes())
|
||||||
|
|
||||||
def test_blur_accuracy(self):
|
def test_blur_accuracy(self):
|
||||||
|
|
||||||
i = snakes._new(ImageOps.gaussian_blur(snakes, .4))
|
i = snakes.filter(ImageFilter.GaussianBlur(.4))
|
||||||
# These pixels surrounded with pixels with 255 intensity.
|
# These pixels surrounded with pixels with 255 intensity.
|
||||||
# They must be very close to 255.
|
# They must be very close to 255.
|
||||||
for x, y, c in [(1, 0, 1), (2, 0, 1), (7, 8, 1), (8, 8, 1), (2, 9, 1),
|
for x, y, c in [(1, 0, 1), (2, 0, 1), (7, 8, 1), (8, 8, 1), (2, 9, 1),
|
||||||
|
|
|
@ -38,6 +38,7 @@ image enhancement filters:
|
||||||
* **SHARPEN**
|
* **SHARPEN**
|
||||||
|
|
||||||
.. autoclass:: PIL.ImageFilter.GaussianBlur
|
.. autoclass:: PIL.ImageFilter.GaussianBlur
|
||||||
|
.. autoclass:: PIL.ImageFilter.BoxBlur
|
||||||
.. autoclass:: PIL.ImageFilter.UnsharpMask
|
.. autoclass:: PIL.ImageFilter.UnsharpMask
|
||||||
.. autoclass:: PIL.ImageFilter.Kernel
|
.. autoclass:: PIL.ImageFilter.Kernel
|
||||||
.. autoclass:: PIL.ImageFilter.RankFilter
|
.. autoclass:: PIL.ImageFilter.RankFilter
|
||||||
|
|
|
@ -4,13 +4,19 @@
|
||||||
Get One Channel From Image
|
Get One Channel From Image
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
New method :py:meth:`PIL.Image.Image.getchannel` added.
|
New method :py:meth:`PIL.Image.Image.getchannel` is added.
|
||||||
It returns single channel by index or name. For example,
|
It returns single channel by index or name. For example,
|
||||||
``image.getchannel("A")`` will return alpha channel as separate image.
|
``image.getchannel("A")`` will return alpha channel as separate image.
|
||||||
``getchannel`` should work up to 6 times faster than ``image.split()[0]``
|
``getchannel`` should work up to 6 times faster than ``image.split()[0]``
|
||||||
in previous Pillow versions.
|
in previous Pillow versions.
|
||||||
|
|
||||||
|
|
||||||
|
Box Blur
|
||||||
|
========
|
||||||
|
|
||||||
|
New filter :py:class:`PIL.ImageFilter.BoxBlur` is added.
|
||||||
|
|
||||||
|
|
||||||
Partial Resampling
|
Partial Resampling
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user