Recover an alpha channel from the same image rendered twice, once on pure white and once on pure black. Useful for getting transparency out of image models that only emit flat RGB.
npm install
node index.js on_white.png on_black.png output.pngdifferenceMatte(white, black) is the whole thing: two raw 8-bit RGBA buffers
in, one RGBA buffer out. extractAlpha() wraps it in PNG reading and writing.
Compositing is C = a*F + (1 - a)*B, so the same pixel over white and over
black gives Cw - Cb = (1 - a)*255. Alpha is whatever is left over, and the
foreground colour follows from either image once alpha is known.
Adapted from Julien De Luca's write-up, with three fixes:
- Alpha comes from the signed mean of the channel differences, not their Euclidean distance. Distance is unsigned, so noise on an opaque pixel only ever pushes alpha down — solid areas come out faintly transparent, and a channel darker on white than on black moves alpha the wrong way.
- Colour is recovered from both images rather than the black one alone. Identical on clean input, but roughly a third less variance on noisy input, where dividing by a small alpha amplifies whatever noise is present.
- Input sizes are compared as dimensions, not byte counts. 100x200 and 200x100 are the same number of bytes, so the blog's check passes and one image gets matted against the other transposed.
Assumes the backgrounds really are #000000 and #ffffff and that the two
images are pixel-aligned.