mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-12 18:26:17 +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)
|
||||
|
||||
|
||||
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):
|
||||
"""Unsharp mask filter.
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ from . import Image
|
|||
from ._util import isStringType
|
||||
import operator
|
||||
import functools
|
||||
import warnings
|
||||
|
||||
|
||||
#
|
||||
|
@ -437,6 +438,13 @@ def solarize(image, threshold=128):
|
|||
def gaussian_blur(im, radius=None):
|
||||
""" 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:
|
||||
radius = 5.0
|
||||
|
||||
|
@ -444,12 +452,30 @@ def gaussian_blur(im, radius=None):
|
|||
|
||||
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):
|
||||
""" 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:
|
||||
radius = 5.0
|
||||
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)
|
||||
|
||||
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):
|
||||
|
@ -478,6 +515,13 @@ def box_blur(image, radius):
|
|||
in each direction, i.e. 9 pixels in total.
|
||||
: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()
|
||||
|
||||
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):
|
||||
|
||||
def test_imageops_box_blur(self):
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from helper import unittest, PillowTestCase, hopper
|
||||
|
||||
from PIL import Image
|
||||
from PIL import ImageFilter
|
||||
from PIL import Image, ImageFilter
|
||||
|
||||
|
||||
class TestImageFilter(PillowTestCase):
|
||||
|
@ -9,10 +8,11 @@ class TestImageFilter(PillowTestCase):
|
|||
def test_sanity(self):
|
||||
|
||||
def filter(filter):
|
||||
im = hopper("L")
|
||||
out = im.filter(filter)
|
||||
self.assertEqual(out.mode, im.mode)
|
||||
self.assertEqual(out.size, im.size)
|
||||
for mode in ["L", "RGB", "CMYK"]:
|
||||
im = hopper(mode)
|
||||
out = im.filter(filter)
|
||||
self.assertEqual(out.mode, im.mode)
|
||||
self.assertEqual(out.size, im.size)
|
||||
|
||||
filter(ImageFilter.BLUR)
|
||||
filter(ImageFilter.CONTOUR)
|
||||
|
@ -28,9 +28,9 @@ class TestImageFilter(PillowTestCase):
|
|||
filter(ImageFilter.MedianFilter)
|
||||
filter(ImageFilter.MinFilter)
|
||||
filter(ImageFilter.ModeFilter)
|
||||
filter(ImageFilter.Kernel((3, 3), list(range(9))))
|
||||
filter(ImageFilter.GaussianBlur)
|
||||
filter(ImageFilter.GaussianBlur(5))
|
||||
filter(ImageFilter.BoxBlur(5))
|
||||
filter(ImageFilter.UnsharpMask)
|
||||
filter(ImageFilter.UnsharpMask(10))
|
||||
|
||||
|
|
|
@ -12,15 +12,25 @@ class TestImageOpsUsm(PillowTestCase):
|
|||
|
||||
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.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.size, (128, 128))
|
||||
# i.save("usm.bmp")
|
||||
|
||||
def test_filter_api(self):
|
||||
|
||||
|
@ -36,38 +46,38 @@ class TestImageOpsUsm(PillowTestCase):
|
|||
|
||||
def test_usm_formats(self):
|
||||
|
||||
usm = ImageOps.unsharp_mask
|
||||
self.assertRaises(ValueError, usm, im.convert("1"))
|
||||
usm(im.convert("L"))
|
||||
self.assertRaises(ValueError, usm, im.convert("I"))
|
||||
self.assertRaises(ValueError, usm, im.convert("F"))
|
||||
usm(im.convert("RGB"))
|
||||
usm(im.convert("RGBA"))
|
||||
usm(im.convert("CMYK"))
|
||||
self.assertRaises(ValueError, usm, im.convert("YCbCr"))
|
||||
usm = ImageFilter.UnsharpMask
|
||||
self.assertRaises(ValueError, im.convert("1").filter, usm)
|
||||
im.convert("L").filter(usm)
|
||||
self.assertRaises(ValueError, im.convert("I").filter, usm)
|
||||
self.assertRaises(ValueError, im.convert("F").filter, usm)
|
||||
im.convert("RGB").filter(usm)
|
||||
im.convert("RGBA").filter(usm)
|
||||
im.convert("CMYK").filter(usm)
|
||||
self.assertRaises(ValueError, im.convert("YCbCr").filter, usm)
|
||||
|
||||
def test_blur_formats(self):
|
||||
|
||||
blur = ImageOps.gaussian_blur
|
||||
self.assertRaises(ValueError, blur, im.convert("1"))
|
||||
blur = ImageFilter.GaussianBlur
|
||||
self.assertRaises(ValueError, im.convert("1").filter, blur)
|
||||
blur(im.convert("L"))
|
||||
self.assertRaises(ValueError, blur, im.convert("I"))
|
||||
self.assertRaises(ValueError, blur, im.convert("F"))
|
||||
blur(im.convert("RGB"))
|
||||
blur(im.convert("RGBA"))
|
||||
blur(im.convert("CMYK"))
|
||||
self.assertRaises(ValueError, blur, im.convert("YCbCr"))
|
||||
self.assertRaises(ValueError, im.convert("I").filter, blur)
|
||||
self.assertRaises(ValueError, im.convert("F").filter, blur)
|
||||
im.convert("RGB").filter(blur)
|
||||
im.convert("RGBA").filter(blur)
|
||||
im.convert("CMYK").filter(blur)
|
||||
self.assertRaises(ValueError, im.convert("YCbCr").filter, blur)
|
||||
|
||||
def test_usm_accuracy(self):
|
||||
|
||||
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.
|
||||
self.assertEqual(i.tobytes(), src.tobytes())
|
||||
|
||||
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.
|
||||
# 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),
|
||||
|
|
|
@ -38,6 +38,7 @@ image enhancement filters:
|
|||
* **SHARPEN**
|
||||
|
||||
.. autoclass:: PIL.ImageFilter.GaussianBlur
|
||||
.. autoclass:: PIL.ImageFilter.BoxBlur
|
||||
.. autoclass:: PIL.ImageFilter.UnsharpMask
|
||||
.. autoclass:: PIL.ImageFilter.Kernel
|
||||
.. autoclass:: PIL.ImageFilter.RankFilter
|
||||
|
|
|
@ -4,13 +4,19 @@
|
|||
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,
|
||||
``image.getchannel("A")`` will return alpha channel as separate image.
|
||||
``getchannel`` should work up to 6 times faster than ``image.split()[0]``
|
||||
in previous Pillow versions.
|
||||
|
||||
|
||||
Box Blur
|
||||
========
|
||||
|
||||
New filter :py:class:`PIL.ImageFilter.BoxBlur` is added.
|
||||
|
||||
|
||||
Partial Resampling
|
||||
==================
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user