How to save an image to disk from a canvas
      The Canvas object includes a toDataURL method that returns a dataURI (a really really long URI that contains a base64-encoded version of the image)
canvas = $('<canvas>');
...
superLongURI = canvas.toDataURL("image/png");
This is super handy if you want to to generate images from javascript.
I’ve never had trouble using these images-encoded-within-urls within javascript, for example within an img tag’s src attribute.
The problem comes if you want to link to the image, or if the user tries to save it: Google Chrome’s address bar can’t handle URLs longer than 2 megabytes.
The solution is to convert the super-long URI to a blob, and link to that blob’s URI rather than the really-long dataURI.
usage
canvas = $('<canvas>');
...
superLongURI = canvas.toDataURL("image/png");
// to save the image to the user's computer with a specified filename:
ImageSaver.download_data_uri(superLongURI, fileName);
// to only generate a shortened URI, not saving it.
shortURI = ImageSaver.make_url_from_data(dataURI);
javascript
The following javascirpt object provides three functions:
- ImageSaver.download_data_uri(dataURI, fileName)main wrapper function to download an image, requires both functions below
- ImageSaver.make_url_from_data(dataURI)makes a blob from a dataURI and returns that blob’s URI, requires make_blob
- ImageSaver.make_blob(dataURI)makes a blob from a dataURI and returns that blob.
the script
ImageSaver = {
  // function to force-download from a data uri as a filename
  // nb the download="filename" attribute isn't yet supported by safari
  download_data_uri: function(dataURI, fileName) {
    var tempUrl = ImageSaver.make_url_from_data(dataURI);
    var link = $('<a href="' + tempUrl + '" id="download" download="' + fileName + '" target="_blank"> </a>');
    $("body").append(link);
    $("#download").get(0).click();
  },
  // function to generate a temporary browser index url for a datauri
  // if a data-uri is larger than 2mb, chrome's address bar can't handle it.
  // fortunately, you can blob it and then use a temporary blob url
  make_url_from_data: function(dataURI) {
    var blob = ImageSaver.make_blob(dataURI);
    var tempUrl = URL.createObjectURL(blob);
    return tempUrl;
  },
  // function to convert a datauri to a blob
  // Blobs are temporary data structures that can hold binary data, and make that data accessible through a short url. They can probably do other things too; I have no idea.
  make_blob: function(dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
      byteString = atob(dataURI.split(',')[1]);
    else
      byteString = unescape(dataURI.split(',')[1]);
    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
    // write the bytes of the string to an ArrayBuffer
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
      ia[i] = byteString.charCodeAt(i);
    };
    // write the ArrayBuffer to a blob, and you're done
    return new Blob([ab], {
      type: mimeString
    });
  }
}