What is the best way to change the color/hue of an image on canvas?

吃可爱长大的小学妹 提交于 2020-01-03 04:46:28

问题


I tried googling for an answer, but I never was able to find a plain answer, or why the answer works. So I would like to know, what is the code that one would use to change the color of an image on canvas? For example, lets say I want to change things to #ff0000. If a pixel is #000000, it should stay that way. If a pixel us #ffffff, it should become #ff0000. Here is my text object constructor:

Text = function(x, y, str, s, c){
        var img = new Image();
        img.src = "font.png";
        var alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", "!", "?"]
        this.text = str.toLowerCase();
        this.x = x;
        this.y = y;
        this.type = "text";
        this.rows = 1;
        this.height = this.rows * 10;
        this.width = this.text.length * 8;
        this.draw = function(){
            for (var i = 0; i < this.text.length; i++)
            {
                scene.ctx.drawImage(img, (alphabet.indexOf(this.text[i]) % 16) * 8, Library.newMath.roundZero(alphabet.indexOf(this.text[i]) / 16) * 10, 8, 10, this.x + i * 8 + (scene.xOffset * !this.fixed), this.y + 0 + (scene.yOffset * !this.fixed), 8, 10);
            }           
        }
        Shape.prototype.constructor.call(this, x, y);
    }

回答1:


markE gave you the whole keys to achieve what you want in comments but here it is applied to your case :

You stated that your image consists of only one solid color, white.
(here I will consider transparent has not a color, but in other contexts it is)
To change this color, you may use the ctx.globalCompositeOperation('source-atop') parameter, which will draw the new shapes "only where it overlaps the existing canvas content." This means that you can first draw your letter shape, then fill a rectangle over it, and only the colored letter shape will be drawn.

var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
  canvas.width = this.width;
  canvas.height = this.height;
  ctx.fillStyle = 'red';
  ctx.drawImage(this, 0, 0);
  ctx.globalCompositeOperation = 'source-atop';
  ctx.fillRect(0, 0, canvas.width, canvas.height)
    // reset to default
  ctx.globalCompositeOperation = 'source-over';
}
img.src = "http://i.stack.imgur.com/9RQXh.png";
<canvas id="canvas"></canvas>

Or you can do it the other way : first draw the colored rect, set the globalCompositeOperation to "destination-atop" and then draw your letter.

var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = function() {
  canvas.width = this.width;
  canvas.height = this.height;
  ctx.fillStyle = 'red';
  ctx.fillRect(0, 0, canvas.width, canvas.height)
  ctx.globalCompositeOperation = 'destination-atop';
  ctx.drawImage(this, 0, 0);
  // reset to default
  ctx.globalCompositeOperation = 'source-over';
}
img.src = "http://i.stack.imgur.com/9RQXh.png";
<canvas id="canvas"></canvas>

Now, to implement it in your code, you can save the colored letters set in your Text object and draw it instead of the original image :

Text = function(x, y, str, s, c){
    var img = new Image();
    // save a pointer to our object so we can use it in the onload event
    var that = this;
    // here implement the coloring part
    img.onload = function(){
      that.img = document.createElement('canvas');
      that.img.width = this.width;
      that.img.height = this.height;
      var ctx = that.img.getContext('2d');
      // set the color to the wanted one
      ctx.fillStyle = c;
      ctx.fillRect(0, 0, canvas.width, canvas.height)
      ctx.globalCompositeOperation = 'destination-atop';
      ctx.drawImage(this, 0, 0);
      }
    img.src = "font.png";
    var alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ".", "!", "?"]
    this.text = str.toLowerCase();
    this.x = x;
    this.y = y;
    this.type = "text";
    this.rows = 1;
    this.height = this.rows * 10;
    this.width = this.text.length * 8;
    this.draw = function(){
        for (var i = 0; i < this.text.length; i++)
        {
            // here use the canvas we created
            scene.ctx.drawImage(this.img, (alphabet.indexOf(this.text[i]) % 16) * 8, Library.newMath.roundZero(alphabet.indexOf(this.text[i]) / 16) * 10, 8, 10, this.x + i * 8 + (scene.xOffset * !this.fixed), this.y + 0 + (scene.yOffset * !this.fixed), 8, 10);
        }           
    }
    Shape.prototype.constructor.call(this, x, y);
}


来源:https://stackoverflow.com/questions/33135691/what-is-the-best-way-to-change-the-color-hue-of-an-image-on-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!