KevinRethwisch
KevinRethwisch

Reputation: 237

Very High Resolution Images in HTML5 Canvas

At the end of this question is an SSCCE to display a 24000x12000 Miller projection of satellite imagery on an HTML5 canvas. It has a couple problems:

  1. Rather than showing the entire image in one screen as I desire only a small section of the upper left corner is displayed.
  2. The image suffers from extreme pixellation that should not appear at the scale displayed because the image is very high resolution

enter image description here

This is the code.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>The Earth</title>
<script type="text/javascript">
function draw() {
   var canvas = document.getElementById("canvas");
   var ctx = canvas.getContext("2d");
   var map = new Image();
   map.src = "world.jpg";
   map.onload = function() {
      var width = window.innerWidth;
      var height = window.innerHeight;
      ctx.drawImage(map, 0, 0, width, height);
   };
}
</script>
<style>
html, body {
  width:  100%;
  height: 100%;
  margin: 0px;
}
#canvas {
   width: 100%;
   height: 100%;
   position: absolute;
   top: 0px;
   left: 0px;
   background-color: rgba(0, 0, 0, 0);
}
</style>
</head>
<body onload="draw();">
   <canvas id="canvas"></canvas>
</body>
</html>

Upvotes: 1

Views: 5498

Answers (2)

KevinRethwisch
KevinRethwisch

Reputation: 237

Here's the working javascript code, formatted nicely.

function draw() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");
  var map = new Image();
  map.src = "world.jpg";
  map.onload = function() {
    var width = window.innerWidth;
    var height = window.innerHeight;
    canvas.width=width;
    canvas.height=height;
    var mapWidth=map.width;
    var mapHeight=map.height;
    var scale=scalePreserveAspectRatio(mapWidth,mapHeight,width,height);
    ctx.mozImageSmoothingEnabled = false;
    ctx.imageSmoothingEnabled = false;
    ctx.webkitImageSmoothingEnabled = false;
    ctx.drawImage(map, 0, 0, mapWidth, mapHeight, 0, 0, mapWidth*scale, mapHeight*scale);
  };
}
function scalePreserveAspectRatio(imgW,imgH,maxW,maxH){
  return(Math.min((maxW/imgW),(maxH/imgH)));
}

The key is the two lines

canvas.width=width;
canvas.height=height;

Simply setting these to 100% in CSS doesn't work, the 100% is apparently not 100% of the inner dimensions of the window as I assumed. Since these dimensions are dynamic they must be set via JS not CSS.

Upvotes: 1

markE
markE

Reputation: 105015

Use the version of context.drawImage that clips and scales the original image:

context.drawImage(
    sourceImage,
    clipSourceAtX, clipSourceAtY, sourceClipWidth, sourceClipHeight,
    canvasX, canvasY, canvasDrawWidth, canvasDrawHeight
)

For example, assume that you are focusing on coordinate [x==1000,y==500] on the image.

To display the 640px x 512px portion of the image at [1000,500] you can use drawImage like this:

context.drawImage(

    // use "sourceImage" 
    sourceImage

    // clip a 640x512 portion of the source image at left-top = [1000,500]
    sourceImage,1000,500,640,512,

    // draw the 640x512 clipped subimage at 0,0 on the canvas
    0,0,640,512            
);

A demo: http://jsfiddle.net/m1erickson/MtAEY/

enter image description here

Upvotes: 2

Related Questions