Skip to content

Apply dither when converting/quantizing to an adaptive palette - #9859

Open
83Gh0st wants to merge 1 commit into
python-pillow:mainfrom
83Gh0st:fix-adaptive-palette-dithering
Open

Apply dither when converting/quantizing to an adaptive palette#9859
83Gh0st wants to merge 1 commit into
python-pillow:mainfrom
83Gh0st:fix-adaptive-palette-dithering

Conversation

@83Gh0st

@83Gh0st 83Gh0st commented Aug 9, 2026

Copy link
Copy Markdown

Fixes #5836.

dither was silently ignored whenever no reference palette was given (e.g. im.convert("P", palette=Image.Palette.ADAPTIVE, dither=...) or plain im.quantize(dither=...)), because the underlying self.im.quantize() C call has no dithering support without an explicit reference palette. This re-converts through the computed adaptive palette when dithering is explicitly requested, so dither is honored in both convert() and quantize(). Calls that don't pass dither are unaffected.

Changes proposed in this pull request:

  • Apply dithering to Image.convert(..., palette=Palette.ADAPTIVE, dither=...)
  • Apply dithering to Image.quantize(..., dither=...) when no reference palette is given
  • Add regression tests + a release note

Fixes python-pillow#5836. dither was silently ignored whenever no reference palette was given, since the underlying quantize() has no dither support without one. Now re-converts through the computed palette when dithering is explicitly requested.
Comment thread Tests/test_image_quantize.py
Comment thread src/PIL/Image.py
mode "RGB" to "P" or from "RGB" or "L" to "1".
Available methods are :data:`Dither.NONE` or :data:`Dither.FLOYDSTEINBERG`
(default).
(default). Prior to this, dithering was silently ignored when no

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(default). Prior to this, dithering was silently ignored when no
(default). Prior to 13.0.0, dithering was silently ignored when no

Reading this docstring on its own, I would have no idea what 'this' is.


assert dither.tobytes() != no_dither.tobytes()
# unspecified dither must remain backwards compatible with no dithering
assert default.tobytes() == no_dither.tobytes()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate that you're being backwards compatible, but doesn't this mean that the docstring of

Available methods are :data:Dither.NONE or :data:Dither.FLOYDSTEINBERG (default)

should be updated?

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 this pull request may close these issues.

Inconsistent use of dithering in convert and quantize

2 participants