8

Is it possible to use a image with a shape as a mask for a whole canvas or images within the canvas?

I want to place images in a canvas with a mask over the images, and then save it as a new image.

Jaap
  • 159
  • 1
  • 4
  • 9
  • yes, if there is really some transparent area on the mask image you could easily use `drawImage()` to draw the image on top of the canvas. The transparent part will let the underlying image/canvas shine through. – devnull69 Oct 01 '12 at 13:02
  • That's not what i mean, i want the shape to clip the image, so that the rest of the image becomes transparent. – Jaap Oct 01 '12 at 13:11

2 Answers2

18

You can use a black and white image as a mask using 'source-in' globalCompositeOperation. First you draw your mask image to the canvas, then you change the globalCompositeOperation to 'source-in', finally you draw your final image.

Your final image will only be draw where it overlay the mask.

var ctx = document.getElementById('c').getContext('2d');

ctx.drawImage(YOUR_MASK, 0, 0);
ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(YOUR_IMAGE, 0 , 0); 

More info on global composite operations

Pierre
  • 1,274
  • 1
  • 9
  • 14
  • it partly works, when i add more pictures to the canvas it fails. How can i set the mask properly, so when i load more images it still uses the mask? – Jaap Oct 02 '12 at 12:05
  • Set the globalCompositeOperation back to what it was originally after drawing (most likely "source-over"). – Alex Beals Nov 25 '15 at 23:15
  • 1
    @Pierre, this does *not* work for a "Black and White" image (as in black=transparent, white=opaque). Using "source-in" like this only works with masks containing varying levels of alpha, regardless of what the color is, black, white, blue, etc. Please see the spec and correct your answer: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalCompositeOperation – Codesmith Dec 27 '21 at 18:47
1

In addition to Pierre's answer you can also use a black and white image as a mask source for your image by copying its data into a CanvasPixelArray like:

var
dimensions = {width: XXX, height: XXX}, //your dimensions
imageObj = document.getElementById('#image'), //select image for RGB
maskObj = document.getElementById('#mask'), //select B/W-mask
image = imageObj.getImageData(0, 0, dimensions.width, dimensions.height),
alphaData = maskObj.getImageData(0, 0, dimensions.width, dimensions.height).data; //this is a canvas pixel array

for (var i = 3, len = image.data.length; i < len; i = i + 4) {

    image.data[i] =  alphaData[i-1]; //copies blue channel of BW mask into A channel of the image

}

//displayCtx is the 2d drawing context of your canvas
displayCtx.putImageData(image, 0, 0, 0, 0, dimensions.width, dimensions.height);
m90
  • 11,434
  • 13
  • 62
  • 112