Image Caching with the HTML5 Canvas | September 24th, 2009
Lately I have been working on an iPhone app ( using PhoneGap of course ) and needed to implement image caching on the client with javascript.
I am already using an SQLite database in mobile safari, so I decided I could store images in Base64 in the DB. I was able to load the binary image data using XHR, but could not correctly encode it to base64 in javascript.
Exploring another path, I found that there is a method of the HTML5 Canvas toDataURL();
So I wrote this to download the image, instead of my XHR method :
ImageCacheManager.prototype.fetchImage = function(url)
{
var alias = this;
var img = new Image();
img.onload = function()
{
alias.onImageLoaded(this);
};
img.src = url;
}
Then this to handle the loaded image and cache it :
ImageCacheManager.prototype.onImageLoaded = function(img)
{
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img,0,0);
var dataURL = canvas.toDataURL();
this.cacheImageData(img.src, dataURL);
}
To keep things short I have excluded the DB sections, I always check if I have an image cached already before I fetch one, and always write it to the DB when I do fetch. If an image is retrieved from the DB it can simply be written to the img.src as is.
I foresee all kinds of uses for this, like a javascript based image editor, or a water-marking script ( you can also draw text on the canvas before you pull out it’s bits … )
September 24th, 2009 at 3:32 pm
[...] This post was mentioned on Twitter by Fil Maj. Fil Maj said: RT @purplecabbage New blog post on image caching from javascript. http://bit.ly/rJVCy [...]
September 25th, 2009 at 1:22 am
I would be interested in seeing the DB code as well, if you wouldn’t mind.
Awesome technique to say the least…
September 25th, 2009 at 2:25 am
Joe
My DB code is very similar to this project by Rob:
Git : Silent Rob
I use the imageURL as the key and the dataURL as the value.
October 30th, 2010 at 9:04 am
Thanks for the links, Jesse.
I am working on a magazine engine/prototype for school (ACAD) to build magazines & portfolios.
It’s the database that is currently killing the concept for me right now. The 5M limit is keeping the 6.7M of images from loading properly, so any hints to complete it helps.
Gerry
October 30th, 2010 at 9:14 am
sorry. my bad. that link to git:silent rob (sqlstore?) doesn’t work.
November 15th, 2010 at 9:46 pm
I do not understand how this code work? Is it only able to run in phonegap and not in WebKit?
I want to cache image file for the phonegap iphone app, which the image url was taken from a XML file. Do you might share some of the idea how to get it done.
November 15th, 2010 at 10:23 pm
This code works in browsers that support localData + the canvas API.
The important thing I think you are missing is that you need to cache the image, and not just the image URL.
Given an image URL
a) create a DOM image object
b) make the image download it’s data
c) create a canvas object and render the image on a canvas
d) ask the canvas for it’s dataUrl ( which returns a base64 png encoded version of the image data )
e) save the dataUrl to the database.
I usually use the original URL of the image as the key in the DB, that way I can check if the value exists in the DB and it does, I can just use it, otherwise I will cache it.
November 15th, 2010 at 11:01 pm
ya, I know I must need to cache the image but not the URL. How to force the app to download the image data instead ?
December 7th, 2010 at 7:25 am
Now there is the application cache, no ?
http://ofps.oreilly.com/titles/9780596805784/ch06.html
BTW, I’ve got a question : how to access in the same way images stored in the phonegap www folder, and image cached with window.applicationCache ?
For example, is it possible to put images from www folder in the applicationCache DB ?
(congrats for your work)
December 7th, 2010 at 11:51 am
Damn shame that toDataUrl is busted for Android (upto and include 2.3). Please star http://code.google.com/p/android/issues/detail?id=7901
March 7th, 2011 at 2:26 pm
Unfortunately the cache manifest is not supported when your html is running in a UIWebView.