W3docs

Canvas Images

Learn how to draw images on an HTML canvas: get an image source, use the three forms of drawImage(), handle CORS, and avoid a tainted canvas.

One of the features of the <canvas> element is the possibility of using images. These can be used for different purposes. You can use external images in any format supported by the browser (e.g., PNG, GIF, or JPEG). As a source, you can also use the image created by other canvas elements.

This chapter builds on the Canvas introduction and Canvas drawing basics. Here you will learn how to get an image source, how to use the three forms of the drawImage() method, and how to avoid the "tainted canvas" problem when loading images from other domains.

Importing images into a canvas is a two-step process:

  1. Get a reference to another canvas element or an HTMLImageElement object as a source.
  2. Draw an image on the canvas with the drawImage() function.

As an image source, the canvas API can use any of the following data types:

Data TypeDescription
HTMLImageElementThese are images created with the Image() constructor, or any <img> element.
SVGImageElementThese are images embedded with the <image> element.
HTMLVideoElementAn HTML <video> element as an image source takes the current frame from the video and uses it as an image.
HTMLCanvasElementAs an image source, you can use another <canvas> element.

These sources together are referred to by the type CanvasImageSource.

There are many ways to get images for use on canvas.

Using images from the same page

You can get a reference to images on the same page with the canvas with one of the following:

  • The document.images collection
  • The document.getElementsByTagName() method
  • The document.getElementById() method if you know the ID of the image you want to use

For example, to grab an existing <img> element by its ID and draw it once the page has loaded:

<img id="photo" src="myImage.png" alt="My image" />
<canvas id="exampleCanvas" width="240" height="225"></canvas>
<script>
  window.onload = function () {
    const canvas = document.getElementById("exampleCanvas");
    const ctx = canvas.getContext("2d");
    const img = document.getElementById("photo");
    ctx.drawImage(img, 0, 0);
  };
</script>

Because the <img> is already in the document, the browser has usually finished loading it by the time window.onload fires, so it is safe to draw immediately.

Using images from other domains

Using the <img> element with the crossorigin="anonymous" attribute, you can request permission to load an image from another domain. If the hosting domain allows cross-domain access via CORS headers, you can use the image in your canvas without tainting it.

<img id="remote" src="https://example.com/photo.jpg" crossorigin="anonymous" alt="Remote image" />

When you set crossorigin="anonymous", the browser sends the request without credentials (cookies). The image is only allowed onto a clean canvas if the server responds with the header:

Access-Control-Allow-Origin: *

(or a value that includes your origin). If you create the image in JavaScript, set the property before the src:

const img = new Image();
img.crossOrigin = "anonymous";
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src = "https://example.com/photo.jpg";

Note If you draw a cross-origin image without proper CORS setup, the canvas becomes "tainted". A tainted canvas blocks access to its pixel data for security reasons — calling toDataURL(), toBlob(), or getImageData() will throw a SecurityError. The fix is on the server: it must send the Access-Control-Allow-Origin header. There is no way to read pixels from a tainted canvas on the client side.

Using other canvas elements

Other canvas elements can be accessed using either the document.getElementById() or document.getElementsByTagName() method.

Embedding an image via data: URL

Data URLs allow specifying an image as a Base64 encoded string of characters directly in the code. The data URL’s advantage is that the resulting image is available immediately. It is also possible to wrap all your CSS, HTML, JavaScript, and images in one file.

However, there is also a disadvantage: the image is not cached, and the encoded URL can be too long for larger images.

To use a data URL, assign it to the src of an image and draw it once it has loaded:

const img = new Image();
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src =
  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==";

The string after base64, is the encoded image. Because it is part of the script, no extra network request is made — the image is ready as soon as it is decoded.

Creating an image from scratch

You can also create a new HTMLImageElement object in your script. For this, use the Image() constructor:

Creating an image from scratch

const img = new Image();
img.onload = function () {
  ctx.drawImage(img, 0, 0);
};
img.src = "myImage.png";

The image begins loading the moment src is set, and loading is asynchronous. If you call drawImage() before the image has finished loading, nothing is drawn. To make sure drawImage() runs only after the image is ready, attach the onload event handler before setting src.

The drawImage() function

Once a reference to the source image is available, you can use the drawImage() method. It comes in three forms, each accepting more parameters than the last:

1. Position only

ctx.drawImage(image, dx, dy);

Draws the whole image at its natural size, placing its top-left corner at the point (dx, dy) on the canvas.

2. Position and size (scaling)

ctx.drawImage(image, dx, dy, dWidth, dHeight);

Draws the whole image, scaled to fit a box dWidth × dHeight pixels whose top-left corner is at (dx, dy).

3. Slicing (source rectangle to destination rectangle)

ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

Takes a rectangular slice of the source image and draws it into a destination rectangle on the canvas. This is the most flexible form — it is used for sprite sheets, cropping, and zooming.

The parameters split into two groups:

ParameterGroupMeaning
sx, sySourceTop-left corner of the slice cut from the source image.
sWidth, sHeightSourceWidth and height of that slice.
dx, dyDestinationWhere the slice is placed on the canvas.
dWidth, dHeightDestinationSize the slice is drawn at on the canvas (it is scaled if different from sWidth/sHeight).

The s* (source) values are measured in the original image's pixels; the d* (destination) values are measured in canvas pixels. The basic form, drawImage(image, dx, dy), is just the first of these three.

In the following example, we use the document.getElementById() method to get a reference to the image and then use the drawImage() function to draw it.

Example of drawing an image with the drawImage() function:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2>Image</h2>
    <img id="photo" src="/uploads/media/default/0001/01/25acddb3da54207bc6beb5838f65f022feaa81d7.jpeg" alt="Aleq" width="200" height="185" />
    <h2>Image with canvas:</h2>
    <canvas id="exampleCanvas" width="240" height="225" style="border:2px solid #cccccc;">
      Your browser doesn't support the canvas tag.
    </canvas>
    <script>
      window.onload = function() {
        const canvas = document.getElementById("exampleCanvas");
        const ctx = canvas.getContext("2d");
        const img = document.getElementById("photo");
        ctx.drawImage(img, 20, 20);
      };
    </script>
  </body>
</html>
Danger

SVG images must define the width and height in the root <svg> element.

Using frames from a video

It is also possible to use frames from a video that is presented by a <video> element, even when the video is not visible. E.g., if you have a <video> element with the ID "videoCanvas", do the following:

Example of drawing a video with canvas:

Canvas Images

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2>Video</h2>
    <video id="videoCanvas" controls width="350" autoplay>
      <source src="/build/videos/arcnet.io(7-sec).mp4" type="video/mp4" />
    </video>
    <h2>Canvas  draws the current video:</h2>
    <canvas id="exampleCanvas" width="310" height="190" style="border:1px solid #d3d3d3;">
      Your browser doesn't support the canvas tag.
    </canvas>
    <script>
      const v = document.getElementById("videoCanvas");
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      let animId;
      function drawFrame() {
        ctx.drawImage(v, 5, 5, 300, 180);
        animId = requestAnimationFrame(drawFrame);
      }
      v.addEventListener("play", function() {
        animId = requestAnimationFrame(drawFrame);
      }, false);
      v.addEventListener("pause", function() {
        cancelAnimationFrame(animId);
      }, false);
      v.addEventListener("ended", function() {
        cancelAnimationFrame(animId);
      }, false);
    </script>
  </body>
</html>

Practice

Practice
When you create an image in JavaScript to draw on the canvas, what is the correct order of steps?
When you create an image in JavaScript to draw on the canvas, what is the correct order of steps?
Was this page helpful?