mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-11-10 19:56:47 +03:00
Make Image.crop an immediate operation, not lazy. Fixes #1077
This commit is contained in:
parent
2178da8ec2
commit
95b50bf611
53
PIL/Image.py
53
PIL/Image.py
|
@ -1020,10 +1020,7 @@ class Image(object):
|
|||
4-tuple defining the left, upper, right, and lower pixel
|
||||
coordinate.
|
||||
|
||||
This is a lazy operation. Changes to the source image may or
|
||||
may not be reflected in the cropped image. To break the
|
||||
connection, call the :py:meth:`~PIL.Image.Image.load` method on
|
||||
the cropped copy.
|
||||
Note: Prior to Pillow 3.4.0, this was a lazy operation.
|
||||
|
||||
:param box: The crop rectangle, as a (left, upper, right, lower)-tuple.
|
||||
:rtype: :py:class:`~PIL.Image.Image`
|
||||
|
@ -1034,8 +1031,15 @@ class Image(object):
|
|||
if box is None:
|
||||
return self.copy()
|
||||
|
||||
# lazy operation
|
||||
return _ImageCrop(self, box)
|
||||
x0, y0, x1, y1 = map(int, map(round, box))
|
||||
|
||||
if x1 < x0:
|
||||
x1 = x0
|
||||
if y1 < y0:
|
||||
y1 = y0
|
||||
|
||||
return self._new(self.im.crop(( x0, y0, x1, y1)))
|
||||
|
||||
|
||||
def draft(self, mode, size):
|
||||
"""
|
||||
|
@ -1954,43 +1958,6 @@ class Image(object):
|
|||
return ImageQt.toqpixmap(self)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Lazy operations
|
||||
|
||||
class _ImageCrop(Image):
|
||||
|
||||
def __init__(self, im, box):
|
||||
|
||||
Image.__init__(self)
|
||||
|
||||
# Round to nearest integer, runs int(round(x)) when unpacking
|
||||
x0, y0, x1, y1 = map(int, map(round, box))
|
||||
|
||||
if x1 < x0:
|
||||
x1 = x0
|
||||
if y1 < y0:
|
||||
y1 = y0
|
||||
|
||||
self.mode = im.mode
|
||||
self.size = x1-x0, y1-y0
|
||||
|
||||
self.__crop = x0, y0, x1, y1
|
||||
|
||||
self.im = im.im
|
||||
|
||||
def load(self):
|
||||
|
||||
# lazy evaluation!
|
||||
if self.__crop:
|
||||
self.im = self.im.crop(self.__crop)
|
||||
self.__crop = None
|
||||
|
||||
if self.im:
|
||||
return self.im.pixel_access(self.readonly)
|
||||
|
||||
# FIXME: future versions should optimize crop/paste
|
||||
# sequences!
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# Abstract handlers.
|
||||
|
|
|
@ -66,6 +66,24 @@ class TestImageCrop(PillowTestCase):
|
|||
# Assert
|
||||
self.assertEqual(cropped.size, (3, 5))
|
||||
|
||||
def test_crop_crash(self):
|
||||
#Image.crop crashes prepatch with an access violation
|
||||
#apparently a use after free on windows, see
|
||||
#https://github.com/python-pillow/Pillow/issues/1077
|
||||
|
||||
test_img = 'Tests/images/bmp/g/pal8-0.bmp'
|
||||
extents = (1,1,10,10)
|
||||
#works prepatch
|
||||
img = Image.open(test_img)
|
||||
img2 = img.crop(extents)
|
||||
img2.load()
|
||||
|
||||
# fail prepatch
|
||||
img = Image.open(test_img)
|
||||
img = img.crop(extents)
|
||||
img.load()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
Loading…
Reference in New Issue
Block a user