#87 BlendMode.MULTIPLY / BlendMode.FILTER

open
nobody
None
1
2014-08-19
2013-02-06
Anonymous
No

Current BlendMode.MULIPLY (yes, u named it so ^^) should be renamed to BlendMode.Filter, a new BlendMode.MULTIPLY should be implemented… read on:


There is a problem with BlendMode – you just have 2 of them.
Reason: When you want something blended into solid-color (incl. blackness), your fine with BlendMode.BLEND. If you want it colorized, your fine with BlendMode.MULIPLY, which is (almost xD) correctly named in programmers perspective but not in perspective of colors! There, it should be named BlendMode.FILTER or something like that, because it just filters out color-components.

BlendMode.MULTIPLY should be something like:

Get each color-component from the original color (as, as, gs, bs), get each color-component of the to-multiply color (am, rm, gm, bm), multiply it that way into the destination color:

A = max(1, as * 2 * am)
R = max(1, rs * 2 * rm)
G = max(1, gs * 2 * gm)
B = max(1, bs * 2 * bm)

by doing this, you get the original color by multiplying it with neutral color (#8888), you get the same color, but darker, by multiplying with dark alpha-neutral gray (#4448), you get the same color, but lighter, by multiplying with light alpha-neutral gray (#ccc8), you stay color-neutral but change alpha-blending by multiplying with neutral color with another alphamode and so on.

So you can REALLY multiply in any direction just by giving a Color.

One Implementation may look like this:


if (fWipeAlpha || clrPaint != 0xFF000000)
{
// we buffer channels to increase performance
double dbRed = ((double)(clrPaint & 0xFF)) / 127;
double dbGreen = ((double)((clrPaint >>> 8) & 0xFF)) / 127;
double dbBlue = ((double)((clrPaint >>> 16) & 0xFF)) / 127;

for (int i = 0; i < destImage.getHeight(); i++)
{
    int [] rgb = destImage.getRGB (0, i, destImage.getWidth(),
            1, null, 0, destImage.getWidth ()*4);
    for (int j = 0; j < rgb.length; j++)
    {
        int pixel = rgb[j];
        int alpha = (pixel >>> 24) & 0xFF;

    if (fWipeAlpha)
        {
            // wipe 75% transparency for better image
            if (alpha < 0x40)
                alpha = 0;
            else
                alpha = 255;
        }
        if (clrPaint != 0xFF000000)
        {
            int red   = (int)((double)(pixel & 0xFF) * dbRed);
            int green = (int)((double)(((pixel >> 8) & 0xFF))
                * dbGreen);
            int blue  = (int)((double)(((pixel >> 16) & 0xFF))
                * dbBlue);
            red   = (red   <= 0xFF) ? red   : 0xFF;
            green = (green <= 0xFF) ? green : 0xFF;
            blue  = (blue  <= 0xFF) ? blue  : 0xFF;
            pixel = (blue << 16)|(green << 8) | red;    
        }
        else
            pixel &= 0x00FFFFFF;
            rgb [j] = (alpha << 24) | pixel;
        }
        destImage.setRGB (0, i, destImage.getWidth (), 1, rgb, 0,
            destImage.getWidth ()*4);
    }
}

}

Discussion


  • Anonymous
    2013-02-06

    Oh, in case someone wants to give credits: anonymous = rhavin – at - shadowtec dot de