javascript 将图像/精灵中的特定颜色替换为另一种颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16228048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 03:48:00  来源:igfitidea点击:

Replace a specific color by another in an image/sprite

javascripthtmlcanvas

提问by Alexandre Hitchcox

I am trying to make a game with HTML5's canvas. I have some sprites, I am able to load them well, and they work fine, but some of the parts of the image are specifically #ff0000and I would like to be able to replace it by some other color, a custom user defined color.

我正在尝试使用 HTML5 的画布制作游戏。我有一些精灵,我能够很好地加载它们,并且它们工作正常,但是图像的某些部分是专门的#ff0000,我希望能够用其他颜色(自定义用户定义的颜色)替换它。

I don't really have a lead on this, I sort of saw image filters, but I didn't really find any examples suited for my usage, and don't have the brains to think it up on my own, trust me, I've tried.

我真的没有这方面的领导,我看到了一些图像过滤器,但我没有真正找到任何适合我使用的例子,也没有大脑自己思考,相信我,我试过了。

Any help, lead, or whatsoever will be greatly appreciated.

任何帮助、领导或任何帮助将不胜感激。

回答by markE

You can use canvas' getImageData to replace any color with any other color.

您可以使用画布的 getImageData 将任何颜色替换为任何其他颜色。

// pull the entire image into an array of pixel data
var imageData = context.getImageData(0, 0, w, h);

// examine every pixel, 
// change any old rgb to the new-rgb
for (var i=0;i<imageData.data.length;i+=4)
  {
      // is this pixel the old rgb?
      if(imageData.data[i]==oldRed &&
         imageData.data[i+1]==oldGreen &&
         imageData.data[i+2]==oldBlue
      ){
          // change to your new rgb
          imageData.data[i]=newRed;
          imageData.data[i+1]=newGreen;
          imageData.data[i+2]=newBlue;
      }
  }
// put the altered data back on the canvas  
context.putImageData(imageData,0,0);

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/4apAS/

这是代码和小提琴:http: //jsfiddle.net/m1erickson/4apAS/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; padding:20px; }
    img{border:1px solid red;}
</style>

<script>
$(function(){


    // this just makes an image we can test with
    // it's just an image of a red rectangle
    var temp=document.createElement("canvas");
    var tempctx=temp.getContext("2d");
    tempctx.fillStyle="red";
    tempctx.strokeStyle="blue";
    tempctx.lineWidth=5;
    tempctx.rect(20,20,75,50);
    tempctx.fill();
    var image0=document.getElementById("image0");
    image0.src=temp.toDataURL();

    var image=new Image();
    image.onload=function(){
        // call function to replace red with green
        recolorImage(image,255,0,0,0,255,0);
    }
    image.src= image0.src;


    function recolorImage(img,oldRed,oldGreen,oldBlue,newRed,newGreen,newBlue){

        var c = document.createElement('canvas');
        var ctx=c.getContext("2d");
        var w = img.width;
        var h = img.height;

        c.width = w;
        c.height = h;

        // draw the image on the temporary canvas
        ctx.drawImage(img, 0, 0, w, h);

        // pull the entire image into an array of pixel data
        var imageData = ctx.getImageData(0, 0, w, h);

        // examine every pixel, 
        // change any old rgb to the new-rgb
        for (var i=0;i<imageData.data.length;i+=4)
          {
              // is this pixel the old rgb?
              if(imageData.data[i]==oldRed &&
                 imageData.data[i+1]==oldGreen &&
                 imageData.data[i+2]==oldBlue
              ){
                  // change to your new rgb
                  imageData.data[i]=newRed;
                  imageData.data[i+1]=newGreen;
                  imageData.data[i+2]=newBlue;
              }
          }
        // put the altered data back on the canvas  
        ctx.putImageData(imageData,0,0);
        // put the re-colored image back on the image
        var img1=document.getElementById("image1");
        img1.src = c.toDataURL('image/png');

    }

}); // end $(function(){});
</script>

</head>

<body>
    <p>Original Image</p>
    <img id="image0" width=200 height=200><br/>
    <p>Red recolored Green Image</p>
    <img id="image1" width=200 height=200>
</body>
</html>

回答by Jarrod

You can use globalCompositeOperation = "source-in"

您可以使用 globalCompositeOperation = "source-in"

For example, the following draws the image to a (new) canvas, and sets the colour.

例如,以下将图像绘制到(新)画布上,并设置颜色。

    ctx.save();

    // Draw mask to buffer
    ctx.clearRect(0, 0, this.width, this.height);
    ctx.drawImage(your_image, 0, 0, this.width, this.height, 0, 0, this.width, this.height);

    // Draw the color only where the mask exists (using source-in)
    ctx.fillStyle = [your color]; // 
    ctx.globalCompositeOperation = "source-in";
    ctx.fillRect(0, 0, this.width, this.height);

    ctx.restore();

I use this exact technique to set the text colour of my bitmap fonts.

我使用这种精确的技术来设置位图字体的文本颜色。