Oversampling Canvas for better quality

The html5 canvas is a very fast and simple immediate mode graphics system, but unfortunately the image quality (especially text rendering) is often lacking. A quick and easy way to address this is to oversample the canvas.  This works by making the internal size of the canvas a multiple of the size you want it to appear on the screen. Doubling the size is generally good enough for most purposes.

The following image (made with chrome) shows the difference. The text on top was rendered with a standard canvas and the bottom text was rendered with an oversampled canvas.


The code for this is pretty straightforward.

In the document you can set up a canvas with double the resolution “canvas_big”  you need and then use a css style to resize it to the same visual size as “canvas_small”.

<!DOCTYPE html>
  <!-- A style to scale down the oversampled canvas -->
  <style> #canvas_big { width: 300px; } </style>
  <!-- This is a standard html5 canvas -->
  <canvas id="canvas_small" width=300 height=50></canvas>
  <br />
  <!-- This canvas is oversampled. -->
  <!-- Its internal size is 600 but it is set to display at 300 -->
  <canvas id="canvas_big" width=600 height=100></canvas>

In the javascript you can use scale on the oversampled canvas so that the same coordinates you were using before will still work on the larger canvas.

<script type="text/javascript" language="javascript">
  // Get the context for the standard canvas
  context = document.getElementById('canvas_small').getContext('2d')
  // Draw some text
  context.font = "22pt Arial"
  context.fillText("This text looks bad", 20, 25)
  // Grab the context for the oversampled canvas
  context = document.getElementById('canvas_big').getContext('2d')
  // Scale the transform so the coordinates are the same as before
  // USe the same drawing commands as before
  context.font = "22pt Arial"
  context.fillText("This text looks better", 20, 25)

2 Replies to “Oversampling Canvas for better quality”

  1. It looks like the first text was rendered with only 50% sample coverage in the first place… interesting, I’d basically consider that a bug in the browser. I wonder if this behaviour is shared across all browsers or if it’s just Chrome/Webkit!

  2. The image is scaled up a little to show the effect better. I seem to get essentially the same quality difference on Firefox. Have not tried a PC.

Leave a Reply

Your email address will not be published. Required fields are marked *