Caching images to disk

I am writing a web-start application that will be downloading hundreds of JPEG 2000 files over the net. This application will also need to iterate effectively over these images. Clearly it is not possible to cache 300-400 images in memory, rather I store these images on disk (this is a signed app). I then have a priority based cache where I can explicitly cache a "window" of images depending upon which image a user is currently looking at and the images "near" that image.

Here is my problem, the time it takes to save the JPEG 2000 file to disk, then to read it back in as a BufferedImage is too slow. If I were dealing with C/C++ I would write the actual BufferedImage into a large swap file with a pointer always open to it. Then I could read the image directly from swap.

Since BufferedImage is not serializable, nor are its components, what are my options?

[884 byte] By [raf2003a] at [2007-11-15]
# 1

Are you sure it is too slow to just read it with ImageIO from disk? I have done this when caching CD Album Covers where 5 album covers were shown at a time. The user could move to the next album covers either to the left or to the righ, so I cached 8 new album covers in each direction. A separate prefetching thread updated the cache whenever the user clicked to see more covers, making the update transparent to the user.

You already say that you can cache a "window" of the images. You just have to make sure the window is big enough to allow a separate thread to read new images from disk when the user wants to see different images. I used a simple LRU cache, which would probably work in you case too.

How many images does a user look at a time?

matsma at 2007-7-29 > top of java,Security,Cryptography...
# 2

The users for this system will sometimes flip back and forth between images rather quickly. Also, the series of images we're talking about here are anywhere between 8 and 600 images in the stack. When the quantity is small, there isn't really any problem. I can usually fit 40-50 images in cache. The problem is when I have more than 50 images, then I have to wait to reload those images from the hard disk.

raf2003a at 2007-7-29 > top of java,Security,Cryptography...
# 3

What is the on screen pixel size of each image displayed to the user?

If you can save in memory a low resolution jpeg thumbnail for each image you should have no problem fitting 600 images in memory.

Also decompressing a byte buffer representing a jpeg to BufferedImage using JPEGImageDecoder should be fast enough.

Rodney_McKaya at 2007-7-29 > top of java,Security,Cryptography...
# 4

Well, I still want to know how many pictures is displayed to the user at any given time? If you display 50 pictures to the user and he can flip forwards/backwards to see a whole new set of 50 pictures I see how that can be problematic. However, if you only display a couple of pictures then I do not see why it won't be fast enough. Unless the pictures are huge...

> Also, the series of images we're talking about here are

> anywhere between 8 and 600 images in the stack.

Not sure if I understood this correctly. Do you mean 8-600 images displayed to the user at any given time or 8-600 images total that can be displayed? If you need to display more than 50 pictures at a time and you cache can only fit 50 pictures then obviously you need to fetch the rest from disk.

matsma at 2007-7-29 > top of java,Security,Cryptography...
# 5

There is only one image displayed at a time, however the user can move at move through the images so fast that it is almost a movie. the images are always displayed at 1024 x 1024 and 16 bpp. They must be full resolution JPEG 2000 images. When I did the initial testing with JPEG it was very fast, but the requirements call for JPEG 2000 at 16 bit pixel depth. Also because the images are "sensitive" they must also be encrypted on the hard disk in such a way that if the user looses his/her session, the images cannot be decrypted again. This also slows down the loading process. It seams that the ImageIO API to read a JPEG 2000 image at full resolution through an encryption stream (CodecInputStream) is slower than I would like. This may just be a limitation of Java. I've been lobbying my bosses to let me write the image disk cache in C as a native library, but they're against it. So I'm trying to find a workaround in Java.

raf2003a at 2007-7-29 > top of java,Security,Cryptography...
# 6

ok, that pretty much means you need to load them faster from disk and I do not know how that can be improved any further. It may be that JPEG 2000 support in ImageIO is not very optimized compared to regular jpeg since you see such a big difference between the two.

I am sorry I cant be of more help, but good luck :)

matsma at 2007-7-29 > top of java,Security,Cryptography...