My blog has been moved to ariya.ofilabs.com.

Thursday, October 25, 2007

Still PictureFlow: improving the rendering quality

Still about PictureFlow, my CoverFlow-effect clone, I did give some thoughts on improving its rendering quality without sacrificing the performance and still doing it in software (no help from graphics card).

The first that came to my mind is by using bilinear filtering in the texture mapper. As you might predict, the texture mapper itself needs only affine transformation, each cover/slide is rendered column-by-column. Since the z distance for all pixels in a column is constant, affine transformation is enough and can be implemented efficiently. Adding bilinear filter, however, means doing linear interpolation for each and every pixel. If it is done in one dimension only, i.e. vertically, that is still manageable. But since (to assure the quality), we need to perform it in both dimension, the whole stuff would become too slow.

Then one morning I realized that I don't really need to do the filtering on-the-fly. Just transform the cover image before it is rendered to screen, we can take advantage of Qt's smooth pixmap scaling for this purpose. Won't be as good as real interpolations, but everything up to now are dirty hacks anyway.

Here is the result so far (clink to enlarge). Compare the filtered version against the original nearest-neighbor approach. Can you spot the improvement?

For starter, you can see that the jaggy lines between the cover images and the black background (obvious when the cover is white) become less noticeable in the filtered version, as shown below. Left is nearest neighbor, right is bilinear filter:

There is no impact at all on performance when doing the animation effect, everything is as smooth as before.

There are however disadvantages with my first approach. First, the cover image is enlarged four times in both dimension, thus making it consuming 16x more memory space. The surface cache becomes very large. Even for book covers (150x200, stored in ARGB32 format), each of them requires 1.8 MB. This is terrible for portable device, although still manageable on modern desktop machine. In addition, creating the surface cache is slower now due to the necessary image scaling.

The next steps would be more optimizations. First, the surface cache will still keep the original dimension (150x200 in the above example). The scaled version will be constructed only whenever necessary, i.e. right before it is texture-mapped. In addition, there is no need to perform filtering while the animation still takes place. The covers move so fast, a bit sacrifice in the quality won't be noticeable to human eyes.

Let's see where this brings me further. Seems that software-rendered CoverFlow effect done in C++ with a quality that can match hardware-assisted version is quite feasible.

1 comment:

Anonymous said...

Hey,

I found your PictureFlow-widget on qt-apps.org and was quite impressed on how good the realization was.

I was wondering if there's anything new regarding those bilinear filters or something. Because that's actually the reason I went to your site (I wanted to ask about some kind of anti-aliasing for the slides ;)).

Furthermore I wanted to say: in the main.cpp I saw theres a shortcut Alt+F10 to have the FPS shown. What's weird is that in the default small window that starts up, I have an FPS rate of about 92. However, if I make the window maximized the FPS drop to about 32 - but the only visual difference is that the black area is around the slides got bigger (since it's maximized).

Anyway, great widget. Hope to see your reply regarding the bilinear filtering (or so) :)

ellekz {at} gmx {dot} net