We have many picture viewers on Pandora, most of them directly ported from the Linux world. While most of them are decent, I have always had the same problem with them. They are slow as a dead horse. Note that it’s not just a complaint related to the Pandora, the same viewers are also quite slow even on my all powerful desktop with 4 cores. Thanks to wb, the age of slow picture viewers is over. At least on Pandora.
Note that if you are looking for a picture viewer with a nice GUI, this one does not have it. wb went straight for a command line kind of utility, interfaced with Zenity for minimal user input. In the end, it does not really matter since a Picture Viewer’s key purpose is to view pictures, and PIV does that pretty well.
You may wonder why we need another picture viewing utility? After all, we have so many already on the repo… I’ll let wb answer that question himself:
The Pandora has two full SD slots, very good controls, and a small but nice display. In terms of hardware, it is very suitable to view and manage pictures taken with a digital camera. However, in terms of software, there was a kind of gap. The default viewer (Ristretto) is slow and does not have many features. There are several viewers and photo managers on the repo, some with a lot of features, but they all tend to be slow. I hate slow things. A computer should be waiting for human input, not the other way around. When I tried to use my Pandora to view pictures taken with my 10 megapixel camera, it took several seconds to load each image, which is very annoying if you’re trying to navigate through hundreds of holiday pictures. So I decided to try to make something faster. That was my only concern at first – getting a fast viewer.
Well, as wb mentioned, the focus was on speed, and it’s actually super fast. Most pictures appear instantaneously (or at least it feels that way) for most formats (there are a few exceptions). For very large pictures (straight out of you 20M pixels camera), you sometimes have to wait a little (a second or so) but this is such a major improvement over what we had, there’s really no reason to complain. PIV also supports full 24 bits colors, while other viewers usually only reproduce 16 bits colors on Pandora. Honestly speaking, unless I compare pictures side by side, it’s difficult to tell the difference in rendering.
So why is PIV so much faster than anything out there? Is everything out there just crap, and wb a genius ? Well, there are several reasons, coming from the way it was designed from the ground up:
There are several things that affect the speed of a viewer. Firstly, you need to load and decode the image. Secondly, you need to scale it to a resolution that fits the screen or whatever zoom level the user wants. Thirdly, you have to render the image (or a portion of it) on the screen. And finally, you can optionally pre-load the next image(s) in the list.
PIV is fast because all of these aspects were taken into account.
For the loading, instead of using the default image libraries (libjpeg and libpng and so on), NEON-optimized versions of them are used, in particular libjpeg-turbo. This makes the decoding step significantly faster.
For the scaling, the hardware scaler is used. It is straightforward to use thanks to notaz’ tweaked SDL. You can set the Pandora screen resolution to basically anything between 200×120 and 1200×720 and the hardware scaler will nicely scale it up or down. This is the final step of the scaling – so if we can get in that range, it’s good enough, no need to get it to exactly 800×480 (the native resolution of the Pandora screen).
How to get it in that range? If the image is a JPEG file, there is a nice feature of libjpeg (and libjpeg-turbo) which lets you decode the image at a reduced scale. This is because the JPEG format is based on blocks of 8×8 pixels, so you can do a faster decode at scales 1/2, 1/4 and 1/8. So for example, if PIV has to load a 4000×2800 (11.2 megapixel) JPEG file, it will at first not load the entire image, but only a reduced image at scale 1/4. That results in a 1000×700 image, which then gets scaled down by the hardware scaler. Of course if you zoom in, more detail has to be loaded. If the image is not a JPEG file, or it is so large that even at 1/8 scale it is too large, then the image is scaled down with a series of fast (but a bit rough) 50% downscales: from every 2×2 pixels, just the top-left one pixel is kept. This downscaling is rather rough, but it’s very fast and the difference with more accurate scaling is rarely noticeable.
For the rendering on the screen, notaz’ SDL is used. This means the hardware scaler can be used, but also you get full 24 bit color (remember that X on the Pandora uses only 16 bit color by default), and you can blit directly to the framebuffer using fast NEON blitters, which is quite a bit faster than using default blitters with the overhead of X. In order to make blitting as fast as possible (essentially just a memcpy), it is important to store the image surfaces in the exact same pixel format as the framebuffer itself. So after loading/decoding an image, sometimes a transformation to the right format is needed. In the case of JPEG, we are lucky: there is an option in libjpeg-turbo to decode straight to the pixel format we need, so we can avoid that overhead as well.
Finally, PIV does a lot of pre-loading. Most other viewers do either no pre-loading at all, or they pre-load just the next image. PIV aggressively pre-loads as much as it can until it starts to get low on memory. So while you’re looking at the first image in the list, behind the scenes it could very well be loading all other images. This means that if you press the “next” or “previous” button, even if you press it quickly several times in a row, you are likely to get instant response.
And if you need numbers to be convinced…
For the 10 megapixel JPEGs my camera produces, ristretto takes about 2.8 seconds per image (on my 1GHz unit), and all the other viewers I tried still take at least 2 seconds. PIV takes about 0.4 seconds per image – and thanks to the pre-loading, it feels like it needs no time at all.
Then, the user interface itself is great. Nothing much displayed on screen, thanks to Pandora controls used to do about everything: shoulder buttons to move from one picture to another, buttons to zoom in or out, left nub to scroll inside a zoomed picture fast, right nub to scroll more slowly… another button for rotation… and several keyboard shortcuts for specific functions. Just hit H in case you are confused or forgot what you can actually do with the software, it will display a reminder of how keys are mapped.
Another great feature (which I requested, thanks wb for implementing it) is the Manga / Comic mode. If you like to read Manga or Comics in digital format, sure, you can use Comix which does a decent job, but after trying PIV I was convinced it could be a better tool than Comix for that purpose. To enable the manga/comic mode, just create an empty file called .comic in your manga/comic folder, and launch PIV to read the images of that folder. By default, it will recognize the .comic file, and show each page adjusted to fit width for a great reading experience. Then you can use the nubs to scroll down in each page (instead of the Dpad in Comix), which is very comfortable. Excellent feature, demonstrated in the below video.
What’s interesting is that most of these features did not really exist in the first place. wb wanted something simple and straightforward, but the community following his project was very reactive and interested to see how far wb could go with it.
I received quite a lot of useful suggestions from the community. This has certainly been a good motivation to keep adding functionality. The community has also helped me to make right design decisions – e.g. at first, rotation and cropping would just silently overwrite the original files, which can cause “accidents” (especially the cropping), so it was a good thing that the community complained about that and made me change my mind.
While the community has been instrumental in getting PIV from the simple image viewer it was to where it is right now, there are some negative aspects to it: the lack of feedback on the repo, for example.
To be honest, I expected to get more community reactions about PIV. It did not get downloaded very often on the repo, and it did not get a lot of ratings nor particularly positive ones. I don’t mind if someone thinks my work is worth only 3 or 4 out of 5 stars, but it’s not going to improve if you don’t let me know what needs to be improved in your opinion. Getting downloads, positive ratings and constructive comments is surprisingly motivating. I never suspected I would care much about such “ego-boosting”, but to be honest, I do – maybe that’s because I like this community enough to actually care about their opinions.
After all, wb does all this for free, does not ask for donations, and if you enjoy his creations, please be considerate and leave a rating and feedback on the repo. Consider it as a tip for all his work he’s done for us.
While PIV is certainly not a small project, wb was able nonetheless to complete it to its current iteration in a relatively short time.
I usually code on the train to work, so that’s about one hour per day. I also usually code while taking my weekly “long bath” (2-3 hours). So I think on average, I probably worked about one hour per day on PIV. I started working on it beginning of October, and by the end of November most of the work was done. So I probably spent about 50 hours or so on this.
The reason is simple. PIV does not reinvent the wheel everywhere. It’s using a lot of other FOSS (Free and Open Source Software) to apply many of its features. The number of tools from external sources which made it into PIV is impressive:
PIV is very much “built on the shoulders of giants” – this is what I like so much about FOSS. It helped to start from something (vp, which is GPL’ed), but that was not essential – it just saved me a few hours. The essential ingredient in PIV is libSDL (which has the LGPL license), and in particular notaz’ tweaks of it. It also heavily relies on libjpeg-turbo (itself a fork of libjpeg), a recent version of libpng, and libwebp, all of which are FOSS. It uses JHead (public domain) and Exiv2 (GPL) to display metadata and to extract previews from RAW formats. It uses ImageMagick (Apache license) to convert more exotic file formats to something that can be loaded, and IM itself relies on several external programs and libraries, some of which are included in PIV too. In particular, UFRaw (GPL) is included to convert RAW formats (it’s normally not used in the viewer itself because it is too slow, but it can be used if select RAW images to resize or convert them). Sigal (MIT license) is used to generate web galleries. And of course all of these libraries and tools have their dependencies which are also FOSS and the tools I used for coding (in particular, the compiler gcc) are also FOSS.
Because PIV is a child of the FOSS world, it’s natural for it to be also released in a FOSS license. But the choice of the license type is critical to ensure the proper future use:
PIV is licensed under the GNU GPL v3, because that license offers the best guarantees that it remains Free Software forever. With a more permissive license (e.g. public domain), the software is free now but you never know for how long. Say some media player manufacturer X wants to take PIV and port it to his media player to be used as an image viewer. That is perfectly possible with any free software license. But now consider a scenario where X starts to add his own extra features to the viewer, making it an even more awesome piece of software. Here’s where the licenses start to behave differently.
If PIV had been public domain, then X could release his improved PIV as closed-source software, gratis or for a price. If the improvements are good, people may very well end up using the improved version instead of the original, and development of the original might come to a standstill because there is no user base left. Although the original PIV is still public domain, the version anyone cares about has become non-free.
This is impossible for GPL’ed software. If X wants to improve PIV, he has to release his modified version of PIV also under the GPL license – in other words, he is forced to “share back” the modifications.
In the case of PIV, this may very well be just theory and not so important in practice, but you never know in advance what lies in the future. Who would have thought in 1991 that Linux would become more than a pet project? Yet if Linus hadn’t decided to GPL his kernel, then Linux would probably not still be Free Software by now.
If you don’t use PIV yet, I hope you are now convinced it’s a great tool for your Pandora. Go and grab it, and don’t forget to rate it and leave a comment, alright ? 🙂