Reference
Transparency Explained
Alpha channels, straight vs premultiplied, and why the difference matters in Photoshop.
What is an alpha channel?
Every pixel in an RGBA image has four values: Red, Green, Blue, and Alpha. The alpha channel records how opaque the pixel is. Alpha = 255 means fully opaque (solid); Alpha = 0 means fully transparent (invisible); values between 0 and 255 create partial transparency — used for soft edges, anti-aliasing, and blending.
Straight alpha (correct)
In straight alpha (also called unassociated alpha), the RGB values represent the actual colour of the pixel, independent of its opacity. A red pixel that is 50% transparent has R=255, G=0, B=0, A=128. At alpha=0, the RGB values still contain the pixel's original colour — they're just not visible.
This is the correct format for professional tools like Photoshop, Figma, Affinity, and InDesign.
Premultiplied alpha (problematic)
In premultiplied alpha (associated alpha), the RGB values have been multiplied by the alpha value. That same red pixel at 50% transparency becomes R=128, G=0, B=0, A=128. At alpha=0, all RGB values are zero — the colour is destroyed.
When Photoshop opens a premultiplied file, those zeroed pixels appear black, causing the infamous “black background in Photoshop” problem.
Why does premultiplied alpha exist?
GPU hardware historically worked with premultiplied alpha internally because it simplifies certain blending operations. The HTML Canvas API returns premultiplied data. Many browser-based tools export premultiplied alpha by mistake because they naively pass canvas data to the PNG encoder without converting back to straight alpha.
How to test your file
Open the PNG in Photoshop. If you see a checkerboard behind your subject, it's straight alpha — correct. If you see black, it's premultiplied alpha — incorrect. You can also use our transparency checker tool.
NSS and straight alpha
NSS keeps the image buffer and the mask buffer completely separate throughout the pipeline. At export time, each pixel is written as R=original_R, G=original_G, B=original_B, A=Math.round(mask*255) — never premultiplied. Every export is verified with an automated integrity check before download.