Home > Mobile >  Invert alpha value of a canvas image
Invert alpha value of a canvas image

Time:11-03

What is the best way to invert the alpha channel of a canvas' content?

I have seen solutions such as enter image description here

I would like to produce this image where the RGB channels are unchanged:

enter image description here

Note that there are a range of alpha values in the original and final images.

CodePudding user response:

We can use globalCompositeOperation to invert the color with alpha.

  1. Source image with radial gradient.

  2. Result image with inverted alpha.

  3. Checking the result: drawing result image on top of yellow background

const src_canvas = document.querySelector('canvas#source');
const src_ctx = src_canvas.getContext('2d');

const result_canvas = document.querySelector('canvas#result');
const result_ctx = result_canvas.getContext('2d');

const check_canvas = document.querySelector('canvas#check');
const check_ctx = check_canvas.getContext('2d');

const w = src_canvas.width = result_canvas.width = check_canvas.width = 180;
const h = src_canvas.height = result_canvas.height = check_canvas.height = 180;

const gradient = src_ctx.createRadialGradient(w/2,h/2,0, w/2,h/2,w/3);
gradient.addColorStop(0, 'rgba(0,0,0,1)');
gradient.addColorStop(1, 'rgba(0,0,0,0)');

src_ctx.fillStyle = gradient;
src_ctx.fillRect(0,0,w,h);

result_ctx.drawImage(src_canvas,0,0);
result_ctx.globalCompositeOperation = 'source-out';
result_ctx.fillRect(0,0,w,h); // uses default fillStyle = 'black'

check_ctx.fillStyle = 'yellow'; // to check if the figure isn't fully opaque
check_ctx.fillRect(0,0,w,h);

check_ctx.drawImage(result_canvas,0,0);
<canvas id="source"></canvas>
<canvas id="result"></canvas>
<canvas id="check"></canvas>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

It works only if the base color of gradient (your transparent image) and the color for fillStyle after applying globalCompositeOperation="source-out" is the same. If you have different colors in your transparent image - it wouldn't work.

I have black as base color of transparent image rgba(0,0,0,...) and black color as default for filling when result_ctx.fillRect(0,0,w,h). If, for example, base color of source image would be red ('rgba(255,0,0,...)') then we had to explicitly define it before fillRect() -> result_ctx.fillStyle = 'red' ('rgb(255,0,0)');

CodePudding user response:

If you want to invert the entire canvas (which is equivalent to your example in the question), apply a CSS filter to it:

canvas { filter: invert(); }

If your real case is different than your example in that inverting the alpha channel of each pixel is different than inverting the entire canvas, then the only way to invert each pixel is to go pixel by pixel as the post that you linked to covers.

  • Related