I've just stumbled upon this question and though it is quite an old one maybe it still can be useful to mention that last year I made my Drawing Libraries public (NuGet), which happens to support quantization, too.
Note: As the question contains the GDI+
tag the examples below go for the Bitmap
type but the library supports completely managed bitmap data manipulation as well, which supports all pixel formats on every platform (see BitmapDataFactory
and BitmapDataExtensions
classes).
If you have a Bitmap
instance, quantization is as simple as follows:
using System.Drawing;
using System.Drawing.Imaging;
using KGySoft.Drawing;
using KGySoft.Drawing.Imaging;
// [...]
IQuantizer quantizer = PredefinedColorsQuantizer.FromCustomPalette(myColors, backColor);
// getting a quantized clone of a Bitmap with arbitrary PixelFormat:
Bitmap quantizedBitmap = originalBitmap.ConvertPixelFormat(PixelFormat.Format8bppIndexed,
quantizer);
// or, you can quantize a Bitmap in-place (which does not change PixelFormat):
originalBitmap.Quantize(quantizer);
Original bitmap:
Quantized bitmap using a custom 8 colors palette and silver background (which appears white with this palette):
In the example above I used the FromCustomPalette
method but there are many other predefined quantizers available in the PredefinedColorsQuantizer
and OptimizedPaletteQuantizer classes (see the members for image and code examples).
And since reducing colors may severely affect the quality of the result you might want to use dithering with the quantization:
IQuantizer quantizer = PredefinedColorsQuantizer.FromCustomPalette(myColors, backColor);
IDitherer = OrderedDitherer.Bayer8x8;
// ConvertPixelFormat can be used also with a ditherer
Bitmap quantizedBitmap = originalBitmap.ConvertPixelFormat(PixelFormat.Format8bppIndexed,
quantizer, ditherer);
// Or use the Dither extension method to change the Bitmap in-place
originalBitmap.Dither(quantizer, ditherer);
The difference is quite significant, even though the same colors are used:
You will find a lot of image examples in the description of the OrderedDitherer
, ErrorDiffusionDitherer
, RandomNoiseDitherer
and InterleavedGradientNoiseDitherer classes.
To try the possible built-in quantizers and ditherers in an application you can use my Imaging Tools app. In the link you can find also its source, which provides a bit more advanced examples with cancellable async conversions with progress tracking, etc.