Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw error on incorrect type in Image.putpixel #4876

Closed
ghost opened this issue Aug 19, 2020 · 4 comments · Fixed by #4882
Closed

Throw error on incorrect type in Image.putpixel #4876

ghost opened this issue Aug 19, 2020 · 4 comments · Fixed by #4882

Comments

@ghost
Copy link

ghost commented Aug 19, 2020

This text is pasted from my PR, #4875

For Image objects with mode L (greyscale), when running img.putpixel, if the argument xy is not a tuple with types (int, int), the code raises a rather cryptic error:

SystemError: new style getargs format but argument is not a tuple

Again, if the argument is a tuple, but not with the types (int, int), this error will come up, which is likely to confuse many people. I propose adding an if statement in the putpixel function to catch this case, and then to throw a clearer error message:

Expected argument xy to be a tuple (int, int) but got { xy }

Where xy is replaced by whatever acutal value of xy caused the error.

See the Pull Request.


  • Related: #2802
  • I got the idea to submit this pull request after reading this answer on StackOverflow
@radarhere
Copy link
Member

Hi. I'm not seeing this on my machine. Could you provide code so that we have an exact example, and let us know what version of Pillow you are using?

import PIL
print(PIL.__version__)

from PIL import Image
im = Image.new("L", (1, 1))
im.putpixel("test", 0)

gives me

7.2.0
Traceback (most recent call last):
  File "example.py", line 6, in <module>
    im.putpixel("test", 0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/Image.py", line 1744, in putpixel
    return self.im.putpixel(xy, value)
TypeError: argument 1 must be sequence of length 2, not 4

Trying with a tuple instead,

import PIL
print(PIL.__version__)

from PIL import Image
im = Image.new("L", (1, 1))
im.putpixel(("test", "test"), 0)

I get

7.2.0
Traceback (most recent call last):
  File "example.py", line 6, in <module>
    im.putpixel(("test", "test"), 0)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/Image.py", line 1744, in putpixel
    return self.im.putpixel(xy, value)
TypeError: an integer is required (got type str)

@nulano
Copy link
Contributor

nulano commented Aug 19, 2020

Based on the SO answer, I found I can reproduce the given error message with im.putpixel((0, 0), "hi"). Looking at the code, the error is most likely coming from the line below, which should probably check the parameter is a tuple first. Is this the error you are trying to fix? If so, this should probably be done at the C level.

if (!PyArg_ParseTuple(color, "Lii|i", &r, &g, &b, &a)) {

@ghost
Copy link
Author

ghost commented Aug 19, 2020

@radarhere, I got the error because I was mapping my data from (0,1) to (0,255), and so the output values were floats. So, when I ran:

for y in range(height):
  for x in range(width):
    img.putpixel((x,y), map_[x,y])

My map_[x,y] was a float, causing the error.

@nulano, I proposed catching the error in the Python code, because that's what I know, but yes, it might make more sense to correct it in the C code. If that's the case, someone else can add the fix, because my C knowledge is limited.

@nulano
Copy link
Contributor

nulano commented Aug 19, 2020

I have created PR #4882 to fix this in C.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants