Skip to content

Conversation

@Marcelo-MConti
Copy link

What does this PR do?

This PR adds a new image operation to PIL.ImageOps that applies a
primary-color dithering filter (RGB only).

The filter:

  • Thresholds RGB channels to primary colors (0 or 255)
  • Applies a simple dithering strategy to preserve local contrast
  • Returns a new image, leaving the input unchanged

Why is this useful?

Primary-color dithering can be useful for:

  • Educational purposes (image processing fundamentals)
  • Artistic and stylized image transformations
  • Low-color or hardware-constrained displays

What is included?

  • New function: ImageOps.dither_primary
  • Unit tests covering basic behavior and output properties
  • Documentation added to the ImageOps module

Notes

  • The function expects an RGB image
  • The implementation follows existing ImageOps conventions

Before Filter

mario

After Filter

composition

@Marcelo-MConti Marcelo-MConti deleted the feature-filter-composition branch December 12, 2025 22:28
@Marcelo-MConti Marcelo-MConti restored the feature-filter-composition branch December 12, 2025 22:31
@radarhere
Copy link
Member

I've created Marcelo-MConti#1 to fix the lint failures.

@radarhere
Copy link
Member

I've created Marcelo-MConti#2 with an idea - process the image by band, instead of all bands at once. I find it is a bit faster, and neater.

@Marcelo-MConti
Copy link
Author

Marcelo-MConti commented Dec 18, 2025

Thanks so much for your help!

return 255 if quadrant in (0, 3) else 0
if value > 32:
return 255 if quadrant == 1 else 0
return 0
Copy link
Member

Choose a reason for hiding this comment

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

Did you want to explain a bit where this logic comes from? Why value > 233, why quadrant in (0, 3), etc.?

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.

2 participants