Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to produce thumbnails in real-time?

Is there a program or script that can read an image on standard input and write a resized image to standard output without waiting for EOF on standard input? Poor quality is acceptable; waiting for the whole image to load is not.

ImageMagick (convert and stream alike) will read, then process, then output. What I want is more like a real-time stream processor: if I'm scaling down 50%, it should output one row of thumbnail for every two rows of input (roughly), regardless of the state of the input stream.

If this doesn't make sense yet, imagine you're loading an image over a slow network connection. As soon as it can, the browser starts displaying the top edge of the image. If the image is larger than the window, the browser scales it down to fit the window. It doesn't have to wait for the whole image to load.

Here are some of the tools I've used for testing. This serves an image on port 8080 in ten slices, with a one-second delay between slices to simulate a slow network connection:

IMAGE=test.jpg; SLICES=10; SIZE=$(stat -c "%s" $IMAGE); BS=$(($SIZE / $SLICES + 1)); (echo HTTP/1.0 200 OK; echo Content-Type: image/jpeg; echo; for i in $(seq 0 $(($SLICES - 1))); do dd if=$IMAGE bs=$BS skip=$i count=1; sleep 1; done) | nc -lp8080 -q0

Run that and immediately open localhost:8080 in your browser to see the image slowly load. If you pipe the image slices to convert or stream instead of nc (omitting all the echoes), no output appears for ten seconds, and then you get the whole thumbnail at once.

like image 740
skeltoac Avatar asked Jan 20 '23 19:01

skeltoac


1 Answers

This is difficult depending on the image format. PNG, for example, is chunked, and each chunk zlib-compressed, so you have to read in a potentially large portion of the file before you can start rendering the image. BMP images are stored "bottom-up", where it renders from the lower right to the upper left, so unless your thumbnail will also be a BMP, you will have either read in the entire image or process the file backwards. JPEG can do this more readily; it's stored in order, and if it's a progressive JPEG you can abuse that and read in only the first N passes to get the thumbnail resolution you need. Wavelet formats like DJVU might also be more straightforward.

I don't think you'll find general-purpose tools that do this, but you could write a custom format-specific streaming decoder to handle it.

like image 187
Vitorio Avatar answered Jan 29 '23 07:01

Vitorio