Barton's Picture linux counter image.
IMAGE NOT LOADED YET

LocalStorage Example: Resize a big image in JavaScript

Size of the picture

To remove the localStorage and start over and notice the difference in load time.

The first time this page is viewed the image is loaded from the web. The image is 1.6 Meg and takes a while to load. We then resize the image via a <canvas> to a 500 pixel wide image. We get the image URI which is the image data encoded as a base64 string. The URI is saved in localStorage.

The next time the page is accessed via the same browser the image is loaded from localStorage. The base64 URI is 457,054 bytes versus 1,653,948 bytes for the original image. Even if the original image is cached by the browser the cache file is still 1.6 Meg while the base64 URI is 458k.

A More Detailed Explanation

I used the JQuery library (framework) to make the JavaScript a little easier. I use the local storage 'length' property to tell me if this is the first time the page has been loaded:

if(localStorage.length) { ... } // already been here at least once
else { ... } // this is the very first time here

When the page is initally loaded localStorage.length is zero. I Create the image object and load the image:

var image = new Image;
image.src = "/images/CIMG00020.JPG"; // 1.6 Meg file, width=3,264, height=2,448

This is pretty standard stuff. You can access localStorage as an object localStorage.clickcount as an array localStorage['clickcount'] or via functions localStorage.getItem('clickcount') or localStorage.setItem('clickcount', 1). Also localStorage can only hold strings.

We now have to wait until the image object is loaded before we can proceed to resize it. The original image is 3,264 by 2,448 pixels and we want the resized image to be 500 pixels wide.

$(image).load(function() {
  var ratio = 500 / this.width; // we are going to scale the image via the width to 500 pixels wide
  this.width = 500;
  this.height = this.height * ratio; // we keep the aspect ratio the same as in the original image
  var canvas = document.createElement("canvas");
  canvas.width = this.width; // make canvas big enough
  canvas.height = this.height;

  var ctx = canvas.getContext("2d");
  ctx.drawImage(this, 0, 0, this.width, this.height); // origine 0x0 with width and height as scaled
  try {
    var dataUri = canvas.toDataURL(); // get the base64 URI
    var img = $('#image');
    img.css({'width': this.width, 'height': this.height});
    img.attr('src', dataUri);
  } catch(e) {
    // if there is an error do something here. e has the reason for the error.
  }

  // Local Storage is only 5 Meg so we could get an error if the resized image is too big.
  try {
    localStorage.setItem('img', dataUri);
  } catch(e) {
    // if there is an error do something here. e has the reason for the error.
  }
}

The actual source of this page has some additional logic for errors and fetching the size of the image at various stages.

The first time the load is quite long and you will notice a pause while the image is loaded. I could have waited to display any of the page until the image logic was done but I wanted to make it easy to see the delay of loading a 1.6 Meg image that is only going to be 500 pixels wide on the page. If you had access to the server where the picture resides you could scale the image many ways, but without access the the image you can still resize the image in JavaScript.

On subsequent page loads we use the saved base64 URI instead of loading the image via a seperate internet get.

if(localStorage.length) {
  localStorage.clickcount = Number(localStorage.clickcount)+1; // add on to count

  // Get the image URI from local storage. This URI is much smaller than the original image.
      
  img = localStorage.getItem('img');
  $("#image").attr('src', img);
}

The load time is much faster as you can see.

I have tested this on Linux with Firefox and Chrome and it works just great. I imagine that there may be problems with various versions of Internet Explorer on MS-Windows as there always are. I would expect this to work OK on Apple Mac's running Safari but I don't have a Mac.


Last Modified Nov 10, 2012 15:55:37 MST

Contact Us