After trying around, the only thing I could see was that you're 100% right. Multiplication by 255 results in a subtraction of 1 -- every time. In the end, I downloaded the pygame source code, and the answer is right there, in surface.h
:
#define BLEND_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
dR = (dR && sR) ? (dR * sR) >> 8 : 0; \
dG = (dG && sG) ? (dG * sG) >> 8 : 0; \
dB = (dB && sB) ? (dB * sB) >> 8 : 0;
Pygame implements multiply blending as
new_val = old_dest * old_source / 256
and not, which would be the correct way, as
new_val = old_dest * old_source / 255
This is probably done for optimization purposes -- a bit shift is a lot faster than a division. As the ratio 255 / 256
is very close to one, the only difference this makes is an "off by one": The value you get is the expected value minus one -- except if you expected zero, in which case the result is correct.
So, you have these possibilities:
- Ignore it, because the off-by-one doesn't matter for most purposes.
- Add
1
to all result values. Closest to the expected result, except you lose the zero. - If overall correctness is not important, but you need
255 * 255 == 255
(you know what I mean), ORing1
instead of adding suffices, and is faster.
Note that if you don't choose answer 1, for performance reasons you'll probably have to write a C extension instead of using Python directly.