fix: Image() drops maxintval when dtype= is also given, silently truncating - #95
Merged
petercorke merged 5 commits intoAug 16, 2026
Merged
Conversation
…cating Image.__init__ applied an explicit dtype= via a raw .astype() cast before convert()-only kwargs (eg. maxintval) ever reached convert(). For an out-of-range integer downcast this truncates to the low byte instead of scaling: Image(uint16_data, dtype='uint8', maxintval=4095) on 12-bit data kept only the bottom 8 bits of each 16-bit pixel, producing a corrupted, wrapping-sawtooth image instead of a properly rescaled one. Found via RVC3-python's visodom.py, which reads 12-bit .pgm frames with exactly this dtype+maxintval combination; the resulting images looked broken even though idisp()/cv2.imshow's own 16-bit display conversion was independently verified correct -- the data was already wrong before display. Fix: when other convert()-relevant kwargs are also given alongside an explicit dtype=, defer the cast to convert() (which threads dtype+maxintval through int_image()/float_image() correctly) instead of astype()'ing early. The plain dtype-only path (no other kwargs) is untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Not up to standards ⛔🔴 Issues
|
| Category | Results |
|---|---|
| Security | 10 high |
🟢 Metrics 6 complexity · 0 duplication
Metric Results Complexity 6 Duplication 0
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Image(im, dtype=..., **other_kwargs)(eg.maxintval=,mono=, ...) applied the explicitdtype=via a raw.astype()cast before the other kwargs ever reachedconvert(). For an out-of-range integer downcast this truncates to the low byte instead of scaling.Image(uint16_12bit_data, dtype='uint8', maxintval=4095)kept only the bottom 8 bits of each pixel, producing a corrupted, sawtooth-wrapping image instead of a properly rescaled one (convert()'sint_image()already implements the correctmaxintval-aware scaling -- the constructor just never let it see the original data).visodom.py, which reads 12-bit.pgmframes with exactly thisdtype=+maxintval=combination. The resulting images looked broken;idisp()/cv2.imshow's own 16-bit display conversion was independently verified correct (empirically, via on-screen pixel readback) -- the data was already wrong before it ever reached display.Fix
When other
convert()-relevant kwargs are given alongside an explicitdtype=, defer the dtype cast toconvert()(which threadsdtype+maxintvalthroughint_image()/float_image()correctly) instead ofastype()'ing early. The common plain-dtype-only path (no other kwargs) is untouched -- verified with a dedicated regression test.Test plan
TestImageConstructorMaxintvalclass intests/test_dtype_resolution.py: downscale-with-maxintval matchesint_image()'s own scaling, result is monotonic (not byte-truncated),maxintval=Nonedefault still uses the source dtype's max,dtype=+maxintval=+mono=combined (the real-world case),dtype=alone stays an unscaled cast (regression guard),maxintval=withoutdtype=stays inert (regression guard).🤖 Generated with Claude Code