> Christopher Howard wrote:
>> Jay Cox wrote:
>> On Oct 20, 2009, at 1:39 PM, Sven Neumann wrote:
>>> Hi,
>>> On Tue, 2009-10-20 at 12:22 -0800, Christopher Howard wrote:
>>>> Though having a far from sufficient understanding of how the GIMP brush
>>>> painting process works, it seems to me like this is the fundamental
>>>> problem: In making black-and-white brushes semi-transparent, GIMP
>>>> somehow "levels out" the grey-scale, so that certain ranges of darkness
>>>> become the same. On a fuzzy brush, the result is that the fine
>>>> graduation is changed to appear stepped or banded.
>>> The problem here is that the brush masks are 8bit only. With such a
>>> limited set of values to start with, banding is basically unavoidable.
>>> Sven
>> You should be able to get rid of most of the banding by performing error
>> diffusion when multiplying the opacity into the brush mask.  I suspect
>> that a simple 1d error diffusion algorithm will be sufficient and I
>> wouldn't bother with a Floyd-Steinberg type algorithm unless you could
>> come up with an example where the simpler algorithm showed visible
>> artifacts.
>> I believe the function that introduces the banding is
>> apply_mask_to_sub_region in paint-funcs.c or in the function
>> apply_mask_to_alpha_channel depending on your point of view.  I have not
>> worked with that code in a long time and I could be wrong about that.
>> You will need to make the starting error term  effectively random or you
>> run the risk of letting the upper-left pixel in each tile get special
>> treatment.
>> Good luck,
>> Jay Cox
>> jay...@gimp.org
>Thank you for your guidance in this matter. However, I am wondering:
>Wouldn't error diffusion tend to sharpen, rather than smooth out, the
>banding? It seems like some kind of blurring is more what we need.
>I played around in apply_mask_to_alpha_channel() a little bit and my
>results seemed to confirm that. But maybe I misunderstand error
>diffusion or precisely what you mean about how to use it?

Error diffusion will get rid of banding at the cost of a small amount of
noise.   If you paint with the same error diffused mask multiple times you
will amplify the noise.  Blurring the mask can not help.

An Example:
  The input mask is a smooth gradient from 0 to 10 that we are scaling to 10%

current scaling:
      0  0  0  0  0  1  1  1  1  1
current painted 10X in the same location:
      0  0  0  0  0 10 10 10 10 10

Obviously that leaves a hard break between the 5th and 6th value.

Note that if we blurred the resulting mask we would end up with the exact
same values.

Error diffusion (static):
      0  0  0  1  0  1  0  1  1  1
Error diffusion (static) painted 10X in the same location:
      0  0  0 10  0 10  0 10 10 10

It looks like we have even more banding, though it would likely look like
noise in a real image.

Error diffusion with a random initial error term:
     0  0  0  1  0  1  0  1  1  1 or
     0  1  0  0  1  0  1  0  1  1 or
     0  0  1  0  0  1  0  1  0  1 or ......
Error diffusion with a random initial error term painted 10X in the same
     0  1  2  3  4  5  6  7  8  9 10 or
     0  1  3  3  4  5  6  7  7  9  9  or ......

The results are not mathematically perfect, but should look very good

If you are initializing the error term to a random value and still seeing
banding I would suspect that the brush system is caching the results of
your function and applying the same mask over again.  (simple way to check
is to put a printf statement in your function and check to see if it prints
out every time you click with the paintbrush)

Thinking about this some more, the error diffusion is probably not even
necessary.  You should be able to get by with some random dithering like
the following (if it wasn't slower than molasses):

  result = floor(input * opacity + g_random_double());

Jay Cox

PS: If this message came through twice I apologize.  The other one (if it
exists) contains errors (more errors?) and should be ignored.

Gimp-developer mailing list

Reply via email to