mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-06-06 14:13:15 +03:00
Merge pull request #3406 from Nazime/negativeindex
Add negative index to PixelAccess
This commit is contained in:
commit
e12aa375ec
|
@ -64,6 +64,43 @@ class TestImagePutPixel(AccessTest):
|
||||||
|
|
||||||
self.assert_image_equal(im1, im2)
|
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):
|
class TestImageGetPixel(AccessTest):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -85,23 +122,43 @@ class TestImageGetPixel(AccessTest):
|
||||||
im.getpixel((0, 0)), c,
|
im.getpixel((0, 0)), c,
|
||||||
"put/getpixel roundtrip failed for mode %s, color %s" % (mode, 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
|
# Check 0
|
||||||
im = Image.new(mode, (0, 0), None)
|
im = Image.new(mode, (0, 0), None)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
im.putpixel((0, 0), c)
|
im.putpixel((0, 0), c)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
im.getpixel((0, 0))
|
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
|
# check initial color
|
||||||
im = Image.new(mode, (1, 1), c)
|
im = Image.new(mode, (1, 1), c)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
im.getpixel((0, 0)), c,
|
im.getpixel((0, 0)), c,
|
||||||
"initial color failed for mode %s, color %s " % (mode, 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
|
# Check 0
|
||||||
im = Image.new(mode, (0, 0), c)
|
im = Image.new(mode, (0, 0), c)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
im.getpixel((0, 0))
|
im.getpixel((0, 0))
|
||||||
|
# Check 0 negative index
|
||||||
|
with self.assertRaises(IndexError):
|
||||||
|
im.getpixel((-1, -1))
|
||||||
|
|
||||||
def test_basic(self):
|
def test_basic(self):
|
||||||
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F",
|
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F",
|
||||||
|
|
|
@ -74,7 +74,12 @@ class PyAccess(object):
|
||||||
"""
|
"""
|
||||||
if self.readonly:
|
if self.readonly:
|
||||||
raise ValueError('Attempt to putpixel a read only image')
|
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)
|
return self.set_pixel(x, y, color)
|
||||||
|
|
||||||
def __getitem__(self, xy):
|
def __getitem__(self, xy):
|
||||||
|
@ -88,8 +93,12 @@ class PyAccess(object):
|
||||||
:returns: a pixel value for single band images, a tuple of
|
:returns: a pixel value for single band images, a tuple of
|
||||||
pixel values for multiband images.
|
pixel values for multiband images.
|
||||||
"""
|
"""
|
||||||
|
(x, y) = xy
|
||||||
(x, y) = self.check_xy(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)
|
return self.get_pixel(x, y)
|
||||||
|
|
||||||
putpixel = __setitem__
|
putpixel = __setitem__
|
||||||
|
|
|
@ -472,6 +472,13 @@ getpixel(Imaging im, ImagingAccess access, int x, int y)
|
||||||
FLOAT32 f;
|
FLOAT32 f;
|
||||||
} pixel;
|
} 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) {
|
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1649,6 +1656,13 @@ _putpixel(ImagingObject* self, PyObject* args)
|
||||||
|
|
||||||
im = self->image;
|
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) {
|
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3014,6 +3028,13 @@ pixel_access_setitem(PixelAccessObject *self, PyObject *xy, PyObject *color)
|
||||||
if (_getxy(xy, &x, &y))
|
if (_getxy(xy, &x, &y))
|
||||||
return -1;
|
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) {
|
if (x < 0 || x >= im->xsize || y < 0 || y >= im->ysize) {
|
||||||
PyErr_SetString(PyExc_IndexError, outside_image);
|
PyErr_SetString(PyExc_IndexError, outside_image);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user