Merge pull request #3406 from Nazime/negativeindex

Add negative index to PixelAccess
This commit is contained in:
Hugo 2018-10-27 23:27:15 +03:00 committed by GitHub
commit e12aa375ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 90 additions and 3 deletions

View File

@ -64,6 +64,43 @@ class TestImagePutPixel(AccessTest):
self.assert_image_equal(im1, im2)
def test_sanity_negative_index(self):
im1 = hopper()
im2 = Image.new(im1.mode, im1.size, 0)
width, height = im1.size
self.assertEqual(im1.getpixel((0, 0)), im1.getpixel((-width, -height)))
self.assertEqual(im1.getpixel((-1, -1)),
im1.getpixel((width-1, height-1)))
for y in range(-1, -im1.size[1]-1, -1):
for x in range(-1, -im1.size[0]-1, -1):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
self.assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
im2.readonly = 1
for y in range(-1, -im1.size[1]-1, -1):
for x in range(-1, -im1.size[0]-1, -1):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
self.assertFalse(im2.readonly)
self.assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
pix1 = im1.load()
pix2 = im2.load()
for y in range(-1, -im1.size[1]-1, -1):
for x in range(-1, -im1.size[0]-1, -1):
pix2[x, y] = pix1[x, y]
self.assert_image_equal(im1, im2)
class TestImageGetPixel(AccessTest):
@staticmethod
@ -85,23 +122,43 @@ class TestImageGetPixel(AccessTest):
im.getpixel((0, 0)), c,
"put/getpixel roundtrip failed for mode %s, color %s" % (mode, c))
# check putpixel negative index
im.putpixel((-1, -1), c)
self.assertEqual(
im.getpixel((-1, -1)), c,
"put/getpixel roundtrip negative index failed"
" for mode %s, color %s" % (mode, c))
# Check 0
im = Image.new(mode, (0, 0), None)
with self.assertRaises(IndexError):
im.putpixel((0, 0), c)
with self.assertRaises(IndexError):
im.getpixel((0, 0))
# Check 0 negative index
with self.assertRaises(IndexError):
im.putpixel((-1, -1), c)
with self.assertRaises(IndexError):
im.getpixel((-1, -1))
# check initial color
im = Image.new(mode, (1, 1), c)
self.assertEqual(
im.getpixel((0, 0)), c,
"initial color failed for mode %s, color %s " % (mode, c))
# check initial color negative index
self.assertEqual(
im.getpixel((-1, -1)), c,
"initial color failed with negative index"
"for mode %s, color %s " % (mode, c))
# Check 0
im = Image.new(mode, (0, 0), c)
with self.assertRaises(IndexError):
im.getpixel((0, 0))
# Check 0 negative index
with self.assertRaises(IndexError):
im.getpixel((-1, -1))
def test_basic(self):
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F",

View File

@ -74,7 +74,12 @@ class PyAccess(object):
"""
if self.readonly:
raise ValueError('Attempt to putpixel a read only image')
(x, y) = self.check_xy(xy)
(x, y) = xy
if x < 0:
x = self.xsize + x
if y < 0:
y = self.ysize + y
(x, y) = self.check_xy((x, y))
return self.set_pixel(x, y, color)
def __getitem__(self, xy):
@ -88,8 +93,12 @@ class PyAccess(object):
:returns: a pixel value for single band images, a tuple of
pixel values for multiband images.
"""
(x, y) = self.check_xy(xy)
(x, y) = xy
if x < 0:
x = self.xsize + x
if y < 0:
y = self.ysize + y
(x, y) = self.check_xy((x, y))
return self.get_pixel(x, y)
putpixel = __setitem__

View File

@ -472,6 +472,13 @@ getpixel(Imaging im, ImagingAccess access, int x, int y)
FLOAT32 f;
} pixel;
if (x < 0) {
x = im->xsize + x;
}
if (y < 0) {
y = im->ysize + y;
}
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
PyErr_SetString(PyExc_IndexError, outside_image);
return NULL;
@ -1649,6 +1656,13 @@ _putpixel(ImagingObject* self, PyObject* args)
im = self->image;
if (x < 0) {
x = im->xsize + x;
}
if (y < 0) {
y = im->ysize + y;
}
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
PyErr_SetString(PyExc_IndexError, outside_image);
return NULL;
@ -3014,6 +3028,13 @@ pixel_access_setitem(PixelAccessObject *self, PyObject *xy, PyObject *color)
if (_getxy(xy, &x, &y))
return -1;
if (x < 0) {
x = im->xsize + x;
}
if (y < 0) {
y = im->ysize + y;
}
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
PyErr_SetString(PyExc_IndexError, outside_image);
return -1;