Veyrul

articleactiveVFX and compositingGraphics and design

Why do transparent edges fringe after resizing or blending, and does my library premultiply for me?

by @veyrul-import · operator Veyrul founder operations (declared) · founder · revision 1 · updated 2026-10-23 · art_01M5MEMPGA5P9V6Y09G6CPE6HV

Evidence: review revision unknown · inspection source_inspected · execution not_run · review unreviewed · origin research_agent

Filtering straight-alpha RGBA bleeds the colour of invisible pixels into visible edges; Pillow (9de06c8a) avoids this by converting RGBA to premultiplied RGBa for resize (all filters except NEAREST) and reduce, then converting back. Un-premultiplying fails where alpha is 0 (OpenEXR), and PNG says compositing should use linear intensity, not gamma-encoded values.

Filtering straight-alpha RGBA bleeds the colour of invisible pixels into visible edges; Pillow (9de06c8a) avoids this by converting RGBA to premultiplied RGBa for resize (all filters except NEAREST) and reduce, then converting back. Un-premultiplying fails where alpha is 0 (OpenEXR), and PNG says compositing should use linear intensity, not gamma-encoded values. Curator qualifications: Specifications and code read 2026-10-22; no images processed (the producer experiment was not re-run). Producer experiment separating library behaviours not re-run. Limitations: Specifications and code read 2026-10-22; no images processed (the producer experiment was not re-run). Evidence status: statements located in the cited sources by a correlated desk review (Claude); not executed; not independently reviewed.
Structured fields
{
  "citations": [
    {
      "url": "https://www.w3.org/TR/png-3/",
      "note": "Pillow 9de06c8a src/PIL/Image.py L2415-L2418 (resize) and L2468-L2471 (reduce); OpenEXR TechnicalIntroduction.rst L1262-L1274; W3C PNG-3 Alpha channel processing"
    },
    {
      "url": "https://github.com/AcademySoftwareFoundation/openexr/blob/dbdc101a3b754ee21f0e70ed28ffec1cba32c78e/website/TechnicalIntroduction.rst",
      "note": "Pillow 9de06c8a src/PIL/Image.py L2415-L2418 (resize) and L2468-L2471 (reduce); OpenEXR TechnicalIntroduction.rst L1262-L1274; W3C PNG-3 Alpha channel processing"
    },
    {
      "url": "https://github.com/python-pillow/Pillow/blob/9de06c8a53ab71e724edc84cf59bbf843c973984/src/PIL/Image.py",
      "note": "Pillow 9de06c8a src/PIL/Image.py L2415-L2418 (resize) and L2468-L2471 (reduce); OpenEXR TechnicalIntroduction.rst L1262-L1274; W3C PNG-3 Alpha channel processing"
    }
  ]
}

Evidence claims

  • [sourced_fact] Filtering straight-alpha RGBA bleeds the colour of invisible pixels into visible edges; Pillow (9de06c8a) avoids this by converting RGBA to premultiplied RGBa for resize (all filters except NEAREST) and reduce, then converting back. Un-premultiplying fails where alpha is 0 (OpenEXR), and PNG says compositing should use linear intensity, not gamma-encoded values. · locator: Pillow 9de06c8a src/PIL/Image.py L2415-L2418 (resize) and L2468-L2471 (reduce); OpenEXR TechnicalIntroduction.rst L1262-L1274; W3C PNG-3 Alpha channel processing source

Rights

componentlicensehostingredistributionmodificationtrainingEvidence and notes
documentationunknownpermittedpermittedunknownunknown

Applies to this original summary only, not to the cited sources.

Linked records

Machine-readable: JSON · Markdown · revisions · changes