With Enblend versions 1.3 and earlier, users reported seeing unusual artifacts in the skies of some images. In this article, I discuss the cause and solution of these artifacts.
Here is an example of an image with banding. The version on the left is the unmodified Enblend v1.3 output. The version on the right has been adjusted in brightness and contrast to make the bands more visible. If you have a good eye, you can see the bands in the original. It may help to smoothly scroll the page up and down. It has been reported that the bands are more visible in printed images.
Original Enblend 1.3 Output
In this project, there are two input images side-by-side. The seam runs vertically through the center of the image. The overlap region starts at 1/4 of the way across the image and ends at 3/4 of the way across the image.
My initial hypothesis was that numerical precision alone was at fault. In Enblend versions 1.3 and earlier, integer arithmetic is used to store intermediate calculations. Over the course of a blending iteration, rounding errors gradually accumulate and can lead to artifacts. To test this theory I modified the blending algorithm to use fixed-point arithmetic to store intermediate results. This gives higher accuracy without requiring more memory than what was necessary before. The next three figures show the enhanced output of 1.3, the enhanced output with fixed-point math, and the difference image.
With Fixed-Point Math
According to the difference image, the bands can be explained by rounding errors, especially in the green channel. The magnitude of these errors is surprising. The brightest spots in the difference image correspond to a difference of only 2 pixel values! The integer approximation was not really that bad. I believe the only reason you can see these errors is because the human eye is more sensitive to green than red or blue. Secondly, the errors occur in groups with clearly defined boundaries that give the eye something to latch on to.
Unfortunately, numerical precision is only part of the problem. There is still a visible artifact in the middle image above. There is a vertical line that starts at the top middle, goes straight down to the image center, and then heads in a 5 o'clock direction to the bottom.
As it turns out, the average color of the sky in each input image is nearly identical. I measured the average value of the green channel on either side of the seam in the middle image and found that it differed by only 1 color value! Since the sky has the lowest spatial frequency, Enblend tries to blend this small color difference over as wide a region as possible. However, with only 256 possible color values for each channel, there are simply not enough colors available to smooth out the differences gradually. There cannot be a gradient here. At the seam, the green channel is going to switch from N to N+1. That is what we are seeing in the middle image.
In Enblend version 1.3 and earlier, integer arithmetic rounding errors caused this step change to occur at unpredictable locations. Hence the banding artifacts. With fixed-point arithmetic, the step change happens exactly at the seam line.
There are two ways to solve this problem. First, you can use a 16-bit workflow. With 16 bits/channel there are enough colors available to make a gradual change between very closely matched colors. While the eye can see a color difference of 1 part in 256 on a computer monitor, we cannot see a difference of 1 part in 65536.
Alternatively, one can use dithering to trick the eye into seeing a gradient even when there are only two colors, for example in the switch between green N and green N+1. I implemented this for blending 8-bit images. The results are shown below.
With Fixed-Point Math
Difference (green channel only)
The dithering introduces some randomness when fixed-point values are quantized back into 8-bit color values. This prevents the sudden step in color at the seam line. The transition is still there, but it no longer has a definite edge that the eye can pick out. In the difference image above only the green channel is shown, and each dot represents a difference of only one color value. The final image without brightness and contrast correction is show below.
Final Image Using Fixed-Point and Dithering
In summary, it is a combination of numerical precision errors and limitations of an 8 bit/channel color format that is the cause of the banding artifacts. Rounding errors were responsible for the shape of the bands, but this was just hiding the underlying issue that 256 levels of green is not enough for quality digital imaging.
Thanks to John Houghton for providing the Tower Bridge images I used as examples.