Prevent masking Image reduce method

This commit is contained in:
Andrew Murray 2020-03-24 19:19:46 +11:00
parent 64e7d72ee8
commit ff6ca4159a
4 changed files with 38 additions and 6 deletions

View File

@ -127,10 +127,19 @@ def test_prog_res_rt():
def test_reduce():
with Image.open("Tests/images/test-card-lossless.jp2") as im:
assert callable(im.reduce)
im.reduce = 2
assert im.reduce == 2
im.load()
assert im.size == (160, 120)
try:
im.thumbnail((40, 40))
except ValueError as e:
assert str(e) == "box can't exceed original image size"
def test_layers_type(tmp_path):
outfile = str(tmp_path / "temp_layers.jp2")

View File

@ -3,6 +3,9 @@ from PIL import Image, ImageMath, ImageMode
from .helper import convert_to_comparable
codecs = dir(Image.core)
# There are several internal implementations
remarkable_factors = [
# special implementations
@ -247,3 +250,11 @@ def test_mode_F():
for factor in remarkable_factors:
compare_reduce_with_reference(im, factor, 0, 0)
compare_reduce_with_box(im, factor)
@pytest.mark.skipif(
"jpeg2k_decoder" not in codecs, reason="JPEG 2000 support not available"
)
def test_jpeg2k():
with Image.open("Tests/images/test-card-lossless.jp2") as im:
assert im.reduce(2).size == (320, 240)

View File

@ -1866,7 +1866,11 @@ class Image:
factor_y = int((box[3] - box[1]) / size[1] / reducing_gap) or 1
if factor_x > 1 or factor_y > 1:
reduce_box = self._get_safe_box(size, resample, box)
self = self.reduce((factor_x, factor_y), box=reduce_box)
factor = (factor_x, factor_y)
if callable(self.reduce):
self = self.reduce(factor, box=reduce_box)
else:
self = Image.reduce(self, factor, box=reduce_box)
box = (
(box[0] - reduce_box[0]) / factor_x,
(box[1] - reduce_box[1]) / factor_y,

View File

@ -176,7 +176,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
if self.size is None or self.mode is None:
raise SyntaxError("unable to determine size/mode")
self.reduce = 0
self._reduce = 0
self.layers = 0
fd = -1
@ -200,13 +200,21 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
"jpeg2k",
(0, 0) + self.size,
0,
(self.codec, self.reduce, self.layers, fd, length),
(self.codec, self._reduce, self.layers, fd, length),
)
]
@property
def reduce(self):
return self._reduce or super().reduce
@reduce.setter
def reduce(self, value):
self._reduce = value
def load(self):
if self.reduce:
power = 1 << self.reduce
if self._reduce:
power = 1 << self._reduce
adjust = power >> 1
self._size = (
int((self.size[0] + adjust) / power),
@ -216,7 +224,7 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
if self.tile:
# Update the reduce and layers settings
t = self.tile[0]
t3 = (t[3][0], self.reduce, self.layers, t[3][3], t[3][4])
t3 = (t[3][0], self._reduce, self.layers, t[3][3], t[3][4])
self.tile = [(t[0], (0, 0) + self.size, t[2], t3)]
return ImageFile.ImageFile.load(self)