Skip to content

Conversation

radarhere
Copy link
Member

Originally mentioned in #9261 (comment)

class ImagingCore:
def __getitem__(self, index: int) -> float: ...

is incorrect.

>>> from PIL import Image
>>> im = Image.new("RGB", (1, 1))
>>> im.im[0]
(0, 0, 0)
>>> im = Image.new("F", (1, 1))
>>> im.im[0]
0.0

In our code,

Pillow/src/_imaging.c

Lines 3847 to 3851 in 5122c83

static PyTypeObject Imaging_Type = {
PyVarObject_HEAD_INIT(NULL, 0).tp_name = "ImagingCore",
.tp_basicsize = sizeof(ImagingObject),
.tp_dealloc = (destructor)_dealloc,
.tp_as_sequence = &image_as_sequence,

calls

Pillow/src/_imaging.c

Lines 3835 to 3839 in 5122c83

static PySequenceMethods image_as_sequence = {
(lenfunc)image_length, /*sq_length*/
(binaryfunc)NULL, /*sq_concat*/
(ssizeargfunc)NULL, /*sq_repeat*/
(ssizeargfunc)image_item, /*sq_item*/

calls

Pillow/src/_imaging.c

Lines 3821 to 3832 in 5122c83

image_item(ImagingObject *self, Py_ssize_t i) {
int x, y;
Imaging im = self->image;
if (im->xsize > 0) {
x = i % im->xsize;
y = i / im->xsize;
} else {
x = y = 0; /* leave it to getpixel to raise an exception */
}
return getpixel(im, self->access, x, y);

calls

Pillow/src/_imaging.c

Lines 504 to 555 in 5122c83

getpixel(Imaging im, ImagingAccess access, int x, int y) {
union {
UINT8 b[4];
UINT16 h;
INT32 i;
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;
}
access->get_pixel(im, x, y, &pixel);
switch (im->type) {
case IMAGING_TYPE_UINT8:
switch (im->bands) {
case 1:
return PyLong_FromLong(pixel.b[0]);
case 2:
return Py_BuildValue("BB", pixel.b[0], pixel.b[1]);
case 3:
return Py_BuildValue("BBB", pixel.b[0], pixel.b[1], pixel.b[2]);
case 4:
return Py_BuildValue(
"BBBB", pixel.b[0], pixel.b[1], pixel.b[2], pixel.b[3]
);
}
break;
case IMAGING_TYPE_INT32:
return PyLong_FromLong(pixel.i);
case IMAGING_TYPE_FLOAT32:
return PyFloat_FromDouble(pixel.f);
case IMAGING_TYPE_SPECIAL:
if (im->bands == 1) {
return PyLong_FromLong(pixel.h);
} else {
return Py_BuildValue("BBB", pixel.b[0], pixel.b[1], pixel.b[2]);
}
break;
}
/* unknown type */
Py_RETURN_NONE;

You can see that float, a tuple of int, or None might be returned.

This matches another existing return type.

Pillow/src/PIL/Image.py

Lines 1631 to 1633 in 5122c83

def getpixel(
self, xy: tuple[int, int] | list[int]
) -> float | tuple[int, ...] | None:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant