globalCompositeOperation=”darker”が使えないブラウザ用の自前JS実装改良版

function darker(src, dst, globalAlpha)
{  
    var w,h;
   
    if(src.width > dst.width)
    {
        w = src.width;
    }
    else
    {
        w = dst.width;
    }
   
    if(src.height > dst.height)
    {
        h = src.height;
    }
    else
    {
        h = dst.height;
    }

    var ctx1 = src.getContext("2d");
    var canvas = document.createElement("canvas");
    canvas.setAttribute("width", w);
    canvas.setAttribute("height", h);
    ctx2 = canvas.getContext("2d");
    ctx2.drawImage(src, 0, 0);

    var canvas2 = document.createElement("canvas");
    canvas2.setAttribute("width", w);
    canvas2.setAttribute("height", h);
    ctx3 = canvas2.getContext("2d");
    ctx3.drawImage(dst, 0, 0);

    var result = ctx2.getImageData(0, 0, w, h);
    var blend  = ctx3.getImageData(0, 0, w, h);
    var alpha;

    for(var data = result.data, blend = blend.data, i = 0 ; i < data.length ; i+=4)
    {
        if(typeof globalAlpha !== "undefined") gA = globalAlpha * 1;
        else gA = 1;
       
        alpha = blend[i+3] * gA;
        alpha = alpha / 255;

        if(data[i] == 0 && data[i+1] == 0 && data[i+2] == 0 && data[i+3] == 0)
        {
            data[i] = blend[i], data[i+1] = blend[i+1], data[i+2] = blend[i+2], data[i+3] = alpha * 255;
        }
        else
        {
            data[i] = ((data[i]) * (1 - alpha) + -blend[i] * (alpha));
            data[i+1] = ((data[i+1]) * (1 - alpha) + -blend[i+1] * (alpha));
            data[i+2] = ((data[i+2]) * (1 - alpha) + -blend[i+2] * (alpha));
            data[i+3] = 255;
        }
    }
   
    ctx1.putImageData(result, 0, 0);
   
    return src;
}

背景色が白以外の場合に動作がおかしかったのと、
globalAlphaへの対応を追加。
いろいろ計算式をいじっていてこれで動いたけど、
なぜこの計算式なのかは不明。
ChromeとSafariの実装にあわせたからこの式になったけど、
Firefoxと同じ結果になる式のほうが論理的に正しいのかもしれない。

コメントをどうぞ