Color Image Quantization in .NET
Asked Answered
L

3

5

I want to reduce the number of unique colors of a bitmap in c#.

The reason I want to do this is that an image which is initially created with three color but due to many factors (including compression) has now more than three colors (i.e neighbour pixels has affected each other)

Any idea of how to do that?

The solution maybe something to convert the whole bitmap from RGB to Indexed color system or some function that can be applied to a single pixel.

Any GDI+ or Emgu (opencv) solutions are good for me.

Lukasz answered 8/7, 2011 at 10:18 Comment(0)
I
6

Check out nQuant at http://nquant.codeplex.com. This yields much higher quality than the code in the MSDN article that Magnus references. It also takes the Alpha layer into consideration while the msdn article only evaluates RGB. Source code is available and there is an accompanying blog post that discusses the code and algorithm in detail.

Imposition answered 11/9, 2011 at 8:14 Comment(0)
B
3

There is an article on msdn called Optimizing Color Quantization for ASP.NET Images that might help you, it has good example code.

Borodin answered 8/7, 2011 at 10:53 Comment(0)
H
0

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:

Original image: Color hues with alpha gradient

Quantized bitmap using a custom 8 colors palette and silver background (which appears white with this palette):

Color hues quantized with custom 8 color palette and silver background, no dithering.

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:

Color hues quantized with custom 8 color palette and silver background, using Bayer 8x8 dithering

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.

Changing Pixel Format with Quantizing and Dithering

Haire answered 7/10, 2020 at 19:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.