Fruits of YAPC::Europe - Image::JpegMinimal

In which we create "instant" image previews in HTML (with a smidgen of Javascript)

After reading a bit of how Facebook makes the transfer of profile images faster for low bandwidth connections and bringing my photo gallery generator up to speed to exhibit my pictures of YAPC::Europe 2015 and Granada (that's a transient link), I thought about reimplementing the "compression" in Perl and some Javascript on the client side to reconstruct the image. I was surprised that a JPEG header is so big (around 500 bytes) and so constant between images. For pages with many images. It seems like a nice latency win to do "compression of repeating data" and send a chunk of preview images with the HTML.

With the help of Imager, it turns this image

IMG_7468.JPG

into a tiny, tiny preview image like this

IMG_7468_preview.JPG

and then blows that image up and blurs it in the browser,
so that the user sees the following image until the real
image data has been loaded:

IMG_7468_blurred.JPG

Currently, loading the thumbnails takes 200 HTTP requests and during that time, the users see nothing. Adding "frosted" pre-previews inline in the HTML increases the page size by 250 bytes for each pre-preview and 2k for the HTML but gives an instant rendering of the whole page where the complete information gets loaded afterwards. The page still works without Javascript enabled, which is important to me.

IMG_7379_gray.jpg

Implementing this was quite straightforward thanks to Imager. I had to build a JPEG frame parser to strip out the unwanted JPEG frames from images and to reorder them so that the header can be patched in the
same position every time. I had to write the Javascript "decoder" which reassembles the fixed header and the image data to a data: inline image again, but all of those were quite simple to do.

IMG_7531.jpg

The CPAN release is quite rough on the edges and the Javascript can certainly be golfed to be smaller/faster. You will have to keep the Javascript inline, as the main goal of using this technique is to make a page appear to load faster even though not all assets have been loaded yet. Making a separate request for a Javascript file somewhat ruins this idea :-)

IMG_7551.jpg

Maybe there could be a JPEGmin standard which declares the header as constant and only sends the dimensions and the payload data and some magic bytes to identify JPEGmin files. At least for thumbnails, this could really reduce the amount of data transferred by 50%.

Of course, declaring such a preview JPEGmin standard would ruin the complete idea of sending the image data together with the HTML, as then the latency and size of the HTTP requests for the JPEGmin files dwarfs the payload of the JPEGmin data.

IMG_7365.jpg

I hope you enjoy the photos and maybe have some ideas on how this could be improved. The Github repo for the module is at https://github.com/Corion/image-jpegminimal, everything is licensed under the same terms as Perl.

2 Comments

Leave a comment

About Max Maischein

user-pic I'm the Treasurer for the Frankfurt Perlmongers e.V. . I have organized Perl events including 7 German Perl Workshops one YAPC::Europe.