In
my last post I showed how to use a 32bpp backbuffer to prevent banding in XNA games. But as it turns out, the WP7 hardware specifications only specify a 16-bit LCD at minimum - and that there are devices out there which only have a 16-bit LCD. (I've heard, but have not been able to confirm, that the Samsung devices suffer especially from this).
In that case, if a device only has an LCD capable of 16bpp, setting a 32bpp backbuffer isn't going to help. Instead, you need to
dither your images, which will reduce the bit-depth to 16bpp but in a way which reduces visible banding.
I stumbled across this blog post
"Photoshop Action for Windows Phone Dithering", which provides a photoshop script to dither images. It gets the job done, but I noticed that it produces a fairly low-quality dither - the end result is very grainy to my eyes.
A while back when I worked on
Metropolitan Melbourne, I wrote my own little tool to dither images because WM6.5 only supported 16-bit colour graphics and I couldn't find any other simple tools for high-quality dithering. My tool is called ReduceBitDepthCPP, and takes an input 24-bit/32-bit image in .png or .bmp format, and reduces it to 16-bit (R5G6B5) colour using the
Floyd-Steinberg algorithm. The Floyd-Steinberg algorithm eliminates banding while minimising quantisation error. Here's a comparison picture:
As expected, the undithered gradient has extreme banding. The "Photoshop" image was produced by using
the script mentioned earlier. If you look closely, the Photoshop image does get rid of banding but also introduces a lot of noise - which makes the image very grainy.
On the top right is the Floyd-Steinberg algorithm produced by my tool, ReduceBitDepthCPP. It also eliminates banding but does so in a way that doesn't introduce a lot of noise, and the end result looks very close to the original.
You can download ReduceBitDepthCPP below, with source as well. It's free for any use, and the source code is distributed under the MIT license.
Instructions
ReduceBitDepthCPP is a command-line tool, which makes it easier to integrate into your build. To use it:
- Extract the files somewhere (eg. C:\Temp\ReduceBitDepth\)
- Open up a command prompt by pressing [win]+[r] and typing in "cmd"
- Navigate to the directory where you extracted the files
- Run ReduceBitDepthCPP.exe using the following syntax:
ReduceBitDepthCPP.exe infile outfile
Sample:
ReduceBitDepthCPP.exe C:\Temp\meow_orig.png C:\Temp\meow_dithered.png
If you found this useful, don't forget to
follow me on Twitter, and check out some of the stuff
on my website!
Happy coding!