Converting F images to I turns large values, inf and NaN into -2147483648
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
Research direction
The bug is the unchecked cast i = f; in the f2i function in src/libImaging/Convert.c; clip32() in src/libImaging/Filter.c shows the existing range guard to follow. Reproduce with the Python snippet in the issue, then confirm the F to I results. Done when values above the INT32 range clip to 2147483647, -inf clips to -2147483648, NaN becomes 0, and the round trip returns 2147483647.
Written by the indexing model from the issue text.
Description
What did you do?
Converted a float (F) image with large or non-finite values to I, for example a float TIFF or a NumPy result with inf or NaN pixels, or an I image that went through F for processing:
import numpy as np
from PIL import Image
im = Image.fromarray(np.array([[1.5, 70000, 3e9, np.inf, -np.inf, np.nan]], np.float32), "F")
print("I", np.asarray(im.convert("I")).tolist())
print("L", np.asarray(im.convert("L")).tolist())
print(Image.new("I", (1, 1), 2**31 - 1).convert("F").convert("I").getpixel((0, 0)))
What did you expect to happen?
Values outside the I range clipped to it, the way F to L and F to I;16 clip to theirs, and the round trip to keep 2147483647:
I [[1, 70000, 2147483647, 2147483647, -2147483648, 0]]
L [[1, 255, 255, 255, 0, 0]]
2147483647
What actually happened?
Every value above the INT32 range, inf and NaN become -2147483648, the most negative value:
I [[1, 70000, -2147483648, -2147483648, -2147483648, -2147483648]]
L [[1, 255, 255, 255, 0, 0]]
-2147483648
The round trip fails because 2147483647 isn't representable as a float32 and rounds up to 2147483648.0, which is just past the INT32 range.
f2i in Convert.c casts with i = f; and no range check. Converting an out-of-range float or NaN to an integer is undefined behavior in C (-fsanitize=float-cast-overflow reports it), and the result depends on the CPU: x86 gives INT_MIN, while ARM saturates and gives INT32_MAX for large values and 0 for NaN. clip32() in Filter.c already guards the same overflow to INT_MIN.
I can open a PR that clips to the INT32 range in f2i and maps NaN to 0.
What are your OS, Python and Pillow versions?
- OS: Ubuntu 26.04 (WSL2), x86-64
- Python: 3.12.13
- Pillow: 13.0.0
- Dominant language
- Python
- Stars
- 14k
- Forks
- 2.6k
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 182
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python-pillow/Pillow
-
XPM values line with more than one space between numbers raises ValueErrorPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
python-pillow/Pillow#10429 ·
Maintainers usually reply within 1 day
-
Sun raster files with RLE encoding and odd-width rows decode shiftedPossibly taken @PerryLink claimed this 4 days ago. Open🤖-assisted
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
python-pillow/Pillow#10370 · 3 comments ·
Maintainers usually reply within 1 day
-
Warn that pre-applying arabic_reshaper + python-bidi corrupts text on a Raqm buildPossibly taken @Syamjith-NK claimed this 68 days ago. OpenDocumentation Font Rendering PNG Third Party Framework
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
python-pillow/Pillow#9907 · 2 comments ·
Maintainers usually reply within 1 day
-
Image.putpixel incorrectly labels supported arguments in type annotationsPossibly taken @radarhere claimed this 196 days ago. OpenPNG
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
python-pillow/Pillow#9584 · 1 comment ·
Maintainers usually reply within 1 day
-
`ImageDraw.arc()` segfaults on a tuple subclass whose `__len__` is too largePossibly taken @Parsiffall1 claimed this 7 days ago. Open
Difficulty 4/5 1-2 days Newbie friendliness 58/100
python-pillow/Pillow#10358 · 2 comments ·
Maintainers usually reply within 1 day
All issues in python-pillow/Pillow
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
its-me-prash/vwgroup-connect-ha#2019 ·
Maintainers usually reply within 1 day
-
bug good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
KonstantinStarovoytov/kitden#21 ·
Maintainers usually reply within 1 day
-
RefactorOpen
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
ehmatthes/gh-profiler#166 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
smart-on-fhir/smart-fetch#73 ·
-
good first issue help wanted
Difficulty 1/5 1-3 hours Newbie friendliness 85/100
RizgarOzan/playcal#13 ·