The BitBlt
blending rule Form blendAlphaScaled
(34
) doesn't blend the colors 0x00000000
(source; fully transparent) and 0xFFFFFFFF
(destination; white) correctly. The output is 0xFEFEFEFE
(slightly transparent white), whereas it should be 0xFFFFFFFF
(fully opaque white).
I think the problem lies in the implementation of BitBltSimulation>>#alphaBlendScaled:with:
. When calculating the summand containing the destinationWord
, a right bit shift by 8
is performed to normalize the result after multiplying with unAlpha
(semantically a division by 256
). However, unAlpha
is in the range 0x00
- 0xFF
and thus a division by 0xFF = 255
should be used instead. I think that the other bit shifts by 8
in the function are ok, as they are only used to extract or compose certain bytes and not to (semantically) divide a value by 256
.
This problem causes the described behavior, because the following computation is performed in each channel:
((0xFF * 0xFF) >> 8) + 0x00 = 0xFE01 >> 8 = 0xFE
A division by 0xFF
produces the expected result:
((0xFF * 0xFF) / 0xFF) + 0x00 = 0xFE01 / 0xFF = 0xFF
Code to reproduce:
| src dst |
src := (Form extent: 1 @ 1 depth: 1)
colorAt: 0 @ 0 put: Color black; "transparency is applied with the fillColor:"
yourself.
dst := (Form extent: 1 @ 1 depth: 32)
colorAt: 0 @ 0 put: Color white; "16rFFFFFFFF"
yourself.
dst
copyBits: (0 @ 0 corner: 1 @ 1)
from: src
at: 0 @ 0
clippingBox: (0 @ 0 corner: 1 @ 1)
rule: Form blendAlphaScaled
fillColor: Color transparent. "16r00000000"
(dst pixelValueAt: 0 @ 0) hex "16rFEFEFEFE"
Notes:
+
, *
and >>
to increase performance. A quick search on the internet shows some possible alternatives.Form
s. I think this is due to alphaSourceBlendBits32
being called in this case, which is optimized for edge cases with full or zero transparency and handles those correctly (it doesn't call alphaBlendScaledwith
).—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.