Canvas JavaScript

Compositing Images

This JavaScript program demonstrates the difference between putImageData() and drawImage(). The function putImageData() write over the pixels entirely, while drawImage() composites the pixel data over the context according to the alpha value.

CompositingImages.html

<!DOCTYPE html>
<html>
  <head>
    <title>XoaX.net's Javascript</title>
    <script type="text/javascript" src="CompositingImages.js"></script>
  </head>
  <body onload="Initialize()">
    <canvas id="idCanvas" width="640" height ="640" style="background-color: #F0F0F0;"></canvas>
  </body>
</html>

CompositingImages.js

function Initialize() {
	const qCanvas = document.getElementById("idCanvas");
	const qContext2D = qCanvas.getContext("2d");
	const qImageElement = new Image();
	
	qContext2D.strokeStyle = "red";
	qContext2D.lineWidth = "100";
	qContext2D.beginPath();
	qContext2D.moveTo(0, 200);
	qContext2D.lineTo(640, 400);
	qContext2D.stroke();
	
	PutVersusDrawComposite(qContext2D);
}

async function PutVersusDrawComposite(qContext) {
	// An image with transparency
	var qImageData = qContext.createImageData(100, 100);
	// Change the actual pixel data. There are 4 channels per pixel rgba.
	// The array begins in the upper-left corner and pixels 
	for (var i = 0; i < qImageData.data.length; i += 4) {
		// The pixel (x, y) in the coordinate ranges [-50, 50] is at ((i % 400)/4 - 50, floor(i/400) - 50)
		var x = (i % 400)/4 - 50;
		var y = Math.floor(i/400) - 50;
		// The y-coordinate is upside-down, but it doesn't matter because I am drawing a circle
		if (x*x + y*y <= 2500) {
			qImageData.data[i] = 200;
			qImageData.data[i+1] = 200;
			qImageData.data[i+2] = 200;
			qImageData.data[i+3] = 128; // Half transparency
		} else {
			qImageData.data[i] = 0;
			qImageData.data[i+1] = 0;
			qImageData.data[i+2] = 0;
			qImageData.data[i+3] = 0; // Totally transparent
		}
	}
	// Use the image data to draw the circle several times.
	// This does not composite
	qContext.putImageData(qImageData, 100, 200);
	qContext.putImageData(qImageData, 100, 230);
	qContext.putImageData(qImageData, 100, 260);
	
	// This composites the image over the rest of what has been drawn
	const qBitmap = await createImageBitmap(qImageData);
	qContext.drawImage(qBitmap, 300, 200);
	qContext.drawImage(qBitmap, 300, 230);
	qContext.drawImage(qBitmap, 300, 260);
}
 

Output

 
 

© 2007–2025 XoaX.net LLC. All rights reserved.