HTML5 Canvas,替换在某些机器上不能工作的图像中的颜色

HTML5 Canvas, replacing colors in an image not working on some machines

本文关键字:工作 不能 图像 颜色 机器 Canvas 替换 HTML5      更新时间:2023-09-26

我有一个2d RTS HTML5/Javascript游戏。我使用图像来显示玩家的单位和建筑。我提供了图像,然后使用脚本将图像中的某些颜色替换为其他颜色,以获得具有不同颜色的图像的不同版本(所以玩家1的士兵有一把红色的剑,玩家2的士兵有一把蓝色的剑,等等……)。问题是,对于大约20%的用户来说,这种替换功能不起作用,他们看到的所有单元都是相同的(默认)颜色。我现在想知道为什么会这样。下面是我用来替换颜色的函数:

// returns a image with some colors replaced, specified by search and replace, which are arrays of color arrays ([[255, 255, 255], [...], ...], )
ImageTransformer.replaceColors = function(img, search, replace)
{
    var canv = document.createElement('canvas');
    canv.height = img.height;
    canv.width = img.width
    var ctx = canv.getContext('2d');
    ctx.drawImage(img, 0, 0);
    var imgData = ctx.getImageData(0, 0, canv.width, canv.height);
    for(var i = 0; i < imgData.data.length; i += 4)
        for(var k = 0; k < search.length; k++)
            if(imgData.data[i] == search[k][0] && imgData.data[i + 1] == search[k][1] && imgData.data[i + 2] == search[k][2])
            {
                imgData.data[i] = replace[k][0];
                imgData.data[i + 1] = replace[k][1];
                imgData.data[i + 2] = replace[k][2];
            }
    ctx.putImageData(imgData, 0, 0);
    return canv;
}

浏览器在绘制图像之前可能会或可能不会对图像应用gamma,目的是要有更自然的颜色(…)。
我敢打赌,这是浏览器应用的伽马欺骗你的算法。

您可以使用颜色距离,并决定阈值来决定是否切换,而不是测试严格的相等性:

var imgData = ctx.getImageData(0, 0, canv.width, canv.height);
var data = imgData.data, length = imgData.data.length ;
    for(var k = 0; k < search.length; k++) {
       var thisCol = search[k];
       for(var i = 0; i < length; i += 4) {
            var colDist = Math.abs(data[i] - thisCol[0] ) 
                          + Math.abs(data[i+1] - thisCol[1] ) 
                            + Math.abs(data[i+2] - thisCol[2] );
            if( colDist < 5 )
           {
              data[i] = thisCol[0];
              data[i + 1] = thisCol[1];
              data[i + 2] = thisCol[2];
           }
     }
}
ctx.putImageData(imgData, 0, 0);
return canv; 

(这里我用r,g,b;正如@ mark建议的,你可以选择其他的,欧几里得是这样的:

        var colDist = sq(data[i] - thisCol[0] ) 
                      + sq(data[i+1] - thisCol[1] ) 
                        + sq(data[i+2] - thisCol[2] );
       // notice this is the squared euclidian distance.
       // whith function sq(x) { return x*x }

测试几个图片/距离,看看哪个合适。

测试几个阈值也。
div)。