Friday, May 14, 2010

PhoneGap iPad Large Image Problems

The Problem:
I'm loading between 6-10 1-2 MB images in a page on PhoneGap. The view is essentially an image slider that you zoom into. It works fine in a browser, so I figured there would be no problem in an app. Boy was I wrong. (Also, I later checked and even in the ipad web browser it seems pretty bad).

Usually the first few images work fine and then after that they randomly work or don't work. It's very intermittent and no memory errors appear. These are images that I am loading locally. I found this very troubling at first, and it took me a while to figure out what to do.

My first thought:
Pre-loading

If I pre-loaded the images they would be ready to render at a moments notice. I tried some various pre-loading techniques people have suggested with jQuery and none seemed to work. Obviously putting more things in memory isn't going to help if it's a memory problem.

The second attempt:
Lazy-Loading

I start with all of the images unloaded (set to a low res placeholder).
<img src="grey.gif" alt="real_image.jpg" />

As they image come is approaching the screen I load it up:
var el = $("img.next");
el.attr("src", el.attr("alt")+"");

This seems to work better but with the side effect that sometimes the next image isn't loaded before it starts coming into view. And then as I carry on it still has the problem of not all of the information working properly. #fail

The third and final solution:
Lazy-loading and Pre-loading and Post-unloading

I have to lazy load the images and then UNLOAD the unused images by setting their src to a place holder image.

In order to make this work smoothly I'm using opacity and CSS3 transitions:

The CSS:
img {
-webkit-transition: all 1.5s ease-in;
}

The JS:
$("#img2").css({zIndex:1,left:0,top:0}); // put the second picture in place
$("#img1").css({zIndex:2,opacity:0}); // first image will slowly fade out

3 comments:

Very interesting solution. Since you're deep into images on the iPad, maybe you can suggest a fix for my problem. I need to know the dimensions of an image from the Camera or Photo Library, which are base64 data strings. Standard jQuery in a .load function does fine on the iPhone, but all I get are 0 width and height on the iPad. Any ideas for me? (I don't expect an answer, but this problem is preventing me from submitting a finished iPhone app, since now they have to run on the iPad.)

Interesting problem, not many people are documenting it. I just fell cropper to the same thing i think. My images however are not in the range of your filesize BUT in iOS 5.1 my sliding images in a swipe gallery work fine in browser but in IOS I could only describe Apples logic as

"This image off the side on the screen is not visible so i'm not going to put those pixels into memory yet, when you bring it across i will load it finally then."

So even with it loaded its not truelly fully loaded until first use, as a result what i get is almost a catch up loading feeling where the image reveals the final third of the image in large buckets/blocks.

My issue now is the client "NEEDS" it to be swipey "like the native". I now wish i'd just gone native, not something i expected to run into issues with...