Bug in BitmapData.draw() function (openfl next and legacy)

In order to create some “hole” into a picture, I tried to draw a transparent square over a colored one using BitmapData.draw() and the BlendMode.ALPHA (or BlendMode.ERASE) blending mode
However, this only seems to work when targetting flash but is bugged when targeting windows (and probably others cpp targets), both with openfl legacy and openfl next…

Consider the following sample test code:

import openfl.Assets;
import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.display.BlendMode;
import openfl.display.Graphics;
import openfl.display.Shape;
import openfl.display.Sprite;
import openfl.text.TextField;
import openfl.text.TextFormat;
import openfl.text.TextFormatAlign;

class Main extends Sprite {
    public function new () {
        super ();
        //Create a blue background square so we can check transparency
        var bg:BitmapData = new BitmapData(200, 200, true, 0xFF0000FF); // A bitmapdata with a default red background 
        var background:Bitmap = new Bitmap(bg);
        //Create a bitmapdata with some transparent "windows" in it
        var bm:BitmapData = new BitmapData(100, 100, true, 0xFFFF0000); // A bitmapdata with a default red background 
        //Draw the transparent windows over it
        var hs:Shape = new Shape();
        var g:Graphics = hs.graphics;
        g.lineStyle(0, 0x000000);
        g.beginFill(0x000000, 0);
        var bitmap:Bitmap = new Bitmap(bm);

you should see this (which is what you get on flash)

But here is what you get on windows (openfl legacy and openfl next)

So is it possible to fix this both on openfl next but also openfl legacy (because I use legacy for some projects which still have issues with next for now)?

Also, you can see in this example another bug. The line of the square “window” is supposed to have a thickness of 0, meaning it shouldn’t be visible. This is the case on flash but actually not on cpp targets… (even if it can be masked by setting an alpha of 0 in the linestyle() function to make it transparent. So it is not really anoying. But this is still a bug so might be cool to fix it too (probably just have to add a test to test if thickness is 0 and to prevent line from drawing if this is the case) :wink: )

This is not a direct answer to your question, as I don’t know the state of BlendModes. But as a workaround you can use copyChannel to simulate the same effect:

var hole = new BitmapData(bm.width, bm.height, true, 0xff0000ff);
bm.copyChannel(hole, hole.rect, new Point(), BitmapDataChannel.BLUE, BitmapDataChannel.ALPHA);

Basically, in another bitmapData, you draw your holes in blue, and then override the alpha channel of your target bitmap with that blue channel.

Yes thanks. I end up with a similar solution using iteration over pixels of my hole shape and copying them to my bm bitmapdata if they are transparent…
I looked more in detail into the BitmapData class and it I was quite surprised to see that actually no BlendMode at all are implemented for cpp and js/html targets. The BlendMode actually will only work for flash targets for now. I think a warning should be add in the functions having BlendMode parametter to tell that this is not implemented for anything else than flash yet…
For cpp and neko targets, that use cairo, I think most of the blendmodes can be implemented by just mapping them into the correct cairo operator though http://cairographics.org/operators/ (So it should just be a matter of adding some cairo.operator = CairoOperator.X to the draw() function with X depending on the BlendMode parametter) even if not all beldmodes might have cairo operator counterpart (but most will)…

1 Year later, BlendModes are still not supported in BitmapData.draw() function. Is there any plan to support them in the future? Else would be good to simply delete this parametter from the draw function…

1 Like

up. would appreciate to get an answer on this…