How to tint an image in HTML5

2019-08-03 02:47发布

问题:

I want to tint an Image but instead of subtracting colors from the origin, I want to add them. Is there a quick way to do this in HTML5 with javascript?

回答1:

Yes there are two simple ways you can use.

Method 1 - Composite mode

The composite mode lighter is in reality an additive mode.

You can activate it with a single line of code (online demo here):

ctx.globalCompositeOperation = 'lighter';

The next thing drawn will add to what is in the background which gives you this result if you painted half the image with a sepia toned rectangle.

Method 2 - manual manipulation of buffer

The other way is to manipulate the buffer itself with a few steps - this is basically the the exact same as the lighter mode but done the "low level" way.

This of course, as basis, gives you a multitude of other possibilities with manipulating the image data (multiplication, subtract, negate, solarize, convolutions etc.):

/// get the pixel data for current content
buffer = ctx.getImageData(0, 0, wh, h);

/// the color for addition
c = {r:0, g: 127, b: 200};

/// loop through pixel array (RGBA = 4 bytes)
for(; i < len; i += 4) {
    data[i]     = data[i]     + c.r;  /// add R
    data[i + 1] = data[i + 1] + c.g;  /// add G
    data[i + 2] = data[i + 2] + c.b;  /// add B
}

/// we're done, put back the new data to canvas
ctx.putImageData(buffer, 0, 0);

Which results in this:

Not that hard! Please notice that we don't need to clamp the values as this array buffer type will do this for us (the array the canvas is using is of type Uint8ClampedArray).

Here is an online demo for this approach.

Conclusion

Of course, the composite mode is more (actual) low-level and performs therefor better than iterating the buffer using JavaScript.

But you can use the second method for things composite mode does not support (e.g. it had a darken mode initially - this is however removed from the specs. The xor mode works only on alpha bits, not the actual pixels and so forth).

In addition - if you're not particularly after additive mode you can always draw next shape on top either by setting its color's alpha value to 0.5, or use globalAlpha to set alpha value for any next draw in cases where you have an image drawn on top. This will tint the content and behave as a multiply mode (with a reduction at the end).