How to merge two bitmaps using multiply blending?

I have a BitmapData which contains a white shape with a black outline, and some transparent pixels. I want to add a “striping” effect programmatically, where the white is replaced by coloured stripes, the black remains black, and the transparent remains transparent.

I figured that BitmapData#draw() with the MULTIPLY blend mode should get me at least part of the way there, but it doesn’t seem to have any effect. It’s as though it just uses NORMAL blend mode. Simplified, my code looks like this:

var shape: BitmapData = ...; // shape with alpha channel
var stripes: BitmapData = ...; // stripe pattern, alpha always 255
var stripedShape = new BitmapData(w, h, true);
stripedShape.draw(stripes, BlendMode.MULTIPLY);

As a workaround, I tried using getPixels() and setPixels() to manipulate the pixel data manually, but it’s too slow.

Using OpenFL 3.6.1, and this is happening on cpp and on neko. I found a couple of old bug reports, but they are all supposed to have been fixed.

Is MULTIPLY blend mode broken, or am I just doing it wrong?

Answering my own question; it looks like in OpenFL 3.6.1, the blendMode argument is completely ignored :frowning:

I also just found #1149 which suggests that it won’t be fixed in legacy, and yet it seems to have been fixed (or at least changed) in the openfl3 branch. Does anyone know if/when that will be released?

BTW, in case it’s relevant, I’m using HaxeFlixel, but passing -Dnext seems to make no difference to the output. (I know it’s picking up next because it initially failed to compile openfl.Lib.exit().) I would prefer the stability of not using next for now, though.

Meanwhile, is there a viable workaround?

For a reference for other people googling, as of 2016-09-13 blendMode is still ignored in openfl 4.1. However, there is BlendModeManager for cairo (even if not all blend modes are available). Possibly just doing this enables blend modes on cairo. No blendModeManager for canvas though.

I don’t know, whether this is a viable workaround, but it could help:

You mean just iterating over the pixels? I tried that, it’s too slow. It’s faster if I use getPixels(), manipulate the array, then use setPixels() to update the graphic, but it’s still significantly slower than just using draw() and its ilk.

You could write a shader to do that, but I’m not sure if shader support is in a state to do something like this yet.

I’m a little torn how we should handle features that obviously don’t work well in software

We use software for features such as bitmapData.draw when hardware is enabled, and use software when the GPU of a desktop is not going to support shaders well.

Any opinions on this? This would apply to blendMode, colorTransform, etc