The black magic of GDI+

One of the things I am most ashamed of on Quivi is its speed when opening large images (which are not uncommon nowadays, specially with digital photos). It’s embarrassing that the lame Windows Picture and Fax Viewer is lightning fast when opening those images!

I’ve always wondered how the Viewer did that. I’ve searched about it in the past but could never find anything about it. Then one of these days I was browsing the Wikipedia page about the Viewer and there I learned that it uses GDI+.

GDI+ is a C++ library, but it is built upon a flat C API which I could easily use in Python via ctypes. Long story short, I was able to modify Quivi to add support for viewing images with GDI+. And the result was amazing!

What about Linux? Well, something “equivalent” to GDI+ would be Cairo, so I did some tests with it too (luckily, support for it was included in wxPython recently).

Here are the results for the time to load a huge 5704px x 5659px PNG image and rescale it to 1/20 of its size:

Time to load and scale a PNG image
Library Time (s)
FreeImage 10.38
PIL 9.90
GDI+ 2.22
Cairo (from FreeImage) 3.60
Cairo (direct) 3.28

The reason for the two Cairo timings is that it supports reading directly from a PNG file but for e.g. JPG files you need to read the image with another library and to the format Cairo uses. I’ve used FreeImage to load the image and converted it to a Cairo surface.

Here are the results for the time to load and scaling the same image, but as a JPG:

Time to load and scale a JPG image
Library Time (s)
FreeImage 6.91
PIL 8.38
GDI+ 0.19
Cairo (from FreeImage) 1.43

Scary! How does GDI+ manages to do that? According to Wikipedia it uses hardware acceleration… Cairo doesn’t lag begind considering that the scaling only takes 0.015 (!) but I did notice that even its best quality scaling isn’t so good in comparison to the others, which is kinda odd.

Anyway, I’ll try to release a new version of Quivi with GDI+ and Cairo support soon. Stay tuned.