Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...


Some extra alpha bits

I just had an interesting bug wrt handling alpha in the System.Drawing.Imaging.ColorMatrix class. The most surprising fact is that running unit tests actually confused me, instead of helping me find the issue (but don't worry I'm still a big fan), because some unit tests (namely System.Drawing.Brushes) were destructive (i.e. the Brushes.* properties were unusable, wrong color, afterward). Eventually running only a subset of the tests (instead of the whole System.Drawing test suite) revealed the treachery.

The fix itself was simple, well once I stopped doubting the code itself and looked at libgdiplus/cairo interaction. One must remember, or (re)learn, that Cairo use pre-multipled alpha for it's ARGB buffers. When fixing such bugs it's clear, very early, that it will require a lot of small changes, compile & test cycles. This makes it a great opportunity to try/time some optimizations on each iteration...

Running the original code, while drawing 32768 times the bitmap using the ColorMatrix, required:
Time: 1:03.5967720 seconds

First I removed an indirection to get matrix values as it also makes the code easier to read and added a check for 100% transparency results. However this last optimization not used in the benchmarked code.
Time: 0:58.8520390 seconds

Then I removed the call to GdipBitmapGetPixel because, despite the removed comment about very little penalty in performance, there is just too many checks that we know, for sure, as valid not to be required in the loops.
Time: 0:54.7671440 seconds

Also I removed the call to GdipBitmapSetPixel for the same (previous) reason and also to avoid computing, again, the pixel memory position (it won't move).
Time: 0:48.3151360 seconds

Finally a few other minor changes, while tracking a memory corruption bug I (of course) introduced during the previous optimizations ;-). Luckily I just don't change much in libgdiplus anymore without running valgrind on the System.Drawing unit tests...
Final time: 0:44.1136470 seconds

So a reduction of about 30%, not so bad for an early (and unplanned) xmas present :-)

12/21/2006 21:23:17 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.