Color Image Quantization in .NET

前端 未结 3 1041
南方客
南方客 2021-01-18 20:48

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

相关标签:
3条回答
  • 2021-01-18 20:55

    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

    0 讨论(0)
  • 2021-01-18 21:00

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

    0 讨论(0)
  • 2021-01-18 21:07

    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.

    0 讨论(0)
提交回复
热议问题