Mukund

Mukund's Blog

Archive for November, 2006

Smooth smoothing :)

Monday, November 13th, 2006

Following up on the last post, we now have smoother loglog smoothing, for the Fractal Explorer plug-in of GIMP. Mmmm. Will be committed after some cleanups of the plug-in code though.

Classic smoothing (or lack of it)

Classic smoothing (or lack of it)

loglog smoothing

loglog smoothing

On finding bugs

Monday, November 13th, 2006

I often tell my friends that cooking, unless one’s doing it for recreation, is crazy as one spends way too much time cooking and cleaning up than eating the result. Fixing bugs is something like this, but worse. It’s probably someone else’s code who wrote it back in 1999 and somehow the bug has been there all along undiscovered; you know where the bug is; you probably even know how to quick-fix it; but to really fix the bug knowing what you’re doing means having to understand the code. Take a graphics application and you spend more time following the code. You spend a few hours doing that, and then the patch to fix it is 6 lines long, and it’s something very very simple. You put an if somewhere to handle a condition.

Last week, the Fractal Explorer plug-in of GIMP had a bug like this. The code for handling the loglog checkbox was added back in 1999. It has never worked on the complete classic Mandelbrot set (or if it ever did work, that must have been due to a bug in some other product). Looks like nobody used it like that. Kevin Cozens was porting the plug-in to GEGL when he discovered that it crashed with the loglog setting (#372671).

GIMP Fractal Explorer plug-in

GIMP Fractal Explorer plug-in

For a Mandelbrot set, the classic method of rendering the set is to map the escape loop counter (once the modulus has escaped) directly to a colormap. This counter is an integer and the method causes banding due to non-smooth shading. The loglog implementation uses a method by Linas Vepstas to renormalize the escape loop counter by finding out how far away the integer counter has strayed outside the escape radius. It involves calculating a double log to map z^(2^i) to i, i.e., log (log (|z|^(2^i))) / log (2). The final divide by log (2) is so that the outer logarithm is done to the base 2 to reduce the 2^i to i. For reference, the end-result normalized loop counter is calculated as: mu = N - log (log (|Z(N)|)) / log (2) where N is the integer escape counter.

The problem with this method was that in the “inner lake” of the Mandelbrot set, where for example c can be 0 + 0i, the loop always exits after a full run with the loop counter at the maximum value, and |z| < 2.0. When |z| < e, the double log starts returning negative values. When |z| < 1, the double log returns inf. This is then subtracted from N and the resulting value mu is used to lookup RGB values for the point from the colormap array. This caused the plug-in to crash (when inf is used or mu exceeds the length of the colormap array).

So what we did to fix this was check to see if |z| < e at the end of the escape loop and clamp mu to N - 1 in that case. The result:

Classic smoothing (or lack of it)

Classic smoothing (or lack of it)

loglog smoothing

loglog smoothing

Open them in two tabs to see how they differ. Of course, as we still use entries directly from a colormap (after rounding), it isn’t as smooth as we’d really like, but interpolation using the real values should be an exercise for another day. Now fixing the actual bug was a 2-line if condition. Imagine hours spent studying the algorithm used, and a 2-line fix (and perhaps this lousy blog post). The plug-in still needs to be fixed as it’s got the code for the fractal algorithms repeated for the actual filter and for the dialog’s preview, which needs to be moved to a common function, and we’d like to implement the really smooth shading as well.

Do you find all this cooking interesting? Do you want to be a GIMP developer? Come and participate by picking an open bug and hacking it into submission. Join #gimp on irc.gimp.org to talk to developers, or the gimp-developer mailing list. Or you may want to try #gegl if you think you’ve got the skills.