We Create Games

JavaScript HTML5 Image Caching

Posted November 20th by Jay Crossler in Code, Games, iPhone, Media, Web

I’ve been focusing on HTML5 over the past year, and am beginning to unravel it’s inner secrets. One of the most interesting concepts is the dynamic tension between native apps and web apps for mobile devices.

Categories of Mobile Apps

Mobile applications provide huge opportunities and some risks for the developers via common middleware, GUI, tools for downloading and reading blogs, and web connectivity. There are four major categories of applications that developers frequently refer to. From a technical point of view, we differentiate mobile applications by the runtime environment in which they are executed:

  • Native platform and OS such as iOS, Android, Symbian, Windows Mobile, and BlackBerry. These applications are built or compiled using a tailored programming workflow process through a tool like Visual Studio or Apple’s Xcode. These will be referred to as native apps.
  • Mobile web/browser runtime environment such as Webkit, Mozilla/Firefox, Opera Mini, and RIM. These will be referred to as mobile web apps.
  • Native applications that incorporate large sections of mobile web/browser runtime environments in them. These will be referred to as hybrid apps.
  • Other managed platforms and virtual machines such as Java/Java to Mobile Enterprise (J2ME) Flash Lite, and Silverlight. These will be referred to as Rich Internet Applications (RIA). These are sometimes referred to as native, rich client apps.

Mobile applications have evolved to the point that they now provide developers with ample mature tools, which enable developers to rapidly build and deploy new apps. Open source tools are the primary enabler of these native development environments. Native apps are different from mobile web apps, which require web connectivity and are sometimes characterized by latencies due to page load times. RIAs use an interpreter platform and are frequently resource intensive, draining the mobile device’s battery or performing poorly.

Each of these app categories have different requirements for integrating, deploying, and managing them within an enterprise. There are specific tools to aid in this, which differ by platform, and are frequently called middleware.

In terms of development quality, a skilled developer can almost always make a more efficient mobile app that provides a better experience with fewer errors that any of the other categories, though these take more time to build. An emerging category of hybrid apps incorporates some native application logic along with mobile web browsing, allowing for much of the development to be done with HTML, a widely known environment.

Handling offline caching

In the HTML5 Database and Canvas article on this site, I delve into how to use the canvas to load images from the web, then save them into the local SqlLite database that is part of HTML5′s offline storage capability. Long story short: you can only save strings/integers into offline storage, so first we convert an image into a base64-encoded string, then save that.  Kinda tricky… and not very efficient, but it works.  Other options are to use the HTML5 Manifest File to specify exactly what files to cache, but it works intermittently and isn’t good at allowing you to dynamically decide which images you want to cache. Also, support is a little varied on each browser…. so we need another option.

A hard part about offline caching of images into base64 strings is that it’s a pretty inefficient process. It works, and is pretty cool… but can be slow with larger files.  Also, as every database interaction is asymmetric (meaning that if you run a query, you don’t know how long it might take to complete), it can sometimes be a few seconds before a larger image is saved or loaded.  This requires some pretty fancy JavaScript.  So, without further ado, I’ve posted some pretty fancy JavaScript for this caching library at: https://github.com/jaycrossler/JavaScript-Cash

After adding the cash.js library to your code and initializing it when the page loads, it’s as simple as calling:

var imgtarget = document.getElementById('myimage');
Cash.loadToImg(file, imgtarget, true);

This will first check the cache to see if the image is saved in the local database, and if so it will pull the image from there.  Otherwise, it will pull the image from the web, write it to a canvas tag, then save that data to the database.  This way, you can programmatically save a large amount of images in the background, then call them later when bandwidth is limited (or if you want to reduce impact on the server).

A big issue still to be addressed is that on most iOS devices (iPhone and iPad), you have limited resources available.  After using 5mb of offline database, the user will be prompted to ask if they will allow more to be saved.  Also, if any single Mobile Safari tab uses more than 10mb of RAM from a programmatic call, it will automatically hard-crash the browser through an exception.  This is painful, and I haven’t found a way to see how much RAM you’re using… so the next version will keep an internal estimate of how much RAM is being used.  Any time you pull a 1mb image, it looks like you’re using 1.5mb of RAM.  Converting that to a <canvas> tag, then writing it to a string and sending that to the database seems to take another 1mb of RAM.  So, you’re looking at only really being able to play with 4mb of images this way at any one time.  I’ll do a more detailed analysis for the next article.

This is optimized for working on mobile devices, such as iPhones, iPads, and Android phones.  I’ve tested it on each, though there is still a bit of fine-tuning required.

I’ll be posting a follow-on article showing how best to use it within a map-based game engine, so stay tuned!




(required)



(required) (Won't be displayed)


Your Comment: