Preserving Transparency During Color Reduction

When reducing the colors of a bitmap which has an alpha channel (i.e. when some portions of the bitmap are transparent), you may need to keep the transparency location. The article below describes how you can do this in Graphics Mill.

There are two approaches to preserving transparency:

  • Mark one of palette entries with the transparent flag. As a result all transparent pixels should be equal to the index of this entry, so no semi-transparent entries are in the indexed image. This approach is supported by several formats. The transparency threshold value determines which pixels are trnasparent, and which are opaque.
  • Define the alpha value of each color in the color table. The NeuQuant algorithm supports this approach. Using NeuQuant you can create only PNG images.

Using Transparency Threshold

To keep transparency in indexed bitmaps one of palette entries is marked with the transparent flag. All transparent pixels should be equal to the index of this entry. This approach does not allow an image to have semi-transparent entries, which can result in artifacts on the edges, between opaque and transparent areas of the image. However there are several advantages with this approach regardless of the drawbacks. The palette size is quite small and usually each palette entry is important; GIF file format for example supports only one transparent entry in a palette.

To decide if a semi-transparent pixel will be fully transparent or opaque, the transparency treshold is used. You can set it via the ColorManagementProvider.TransparentIndexThreshold or the ColorConverter.TransparentIndexThreshold property. This value defines the minimum alpha channel value for pixels which should be considered as opaque. If a pixel has a smaller alpha channel value it becomes fully transparent.

The following threshold values are frequently used:

  1. If you want to make only those pixels which are really 100% opaque display that way, set the transparency treshold to 255.
  2. Vice versa, if you want to make opaque all pixels which are not 100% transparent, set the transparency treshold to 1. If you set it to 0, there will be no transparent pixels.
  3. Pixels that have a value of 100% transparent are not the only pixels that can be displayed as such. You can also do so with pixels that are barely visible. Typically these are pixels on the edge between objects and a transparent background. In this case the value may vary, typically from 10 to 16.

Here is a code example that demonstrates the first method of preserving transparency:

C#
using (var bitmap = new Bitmap(@"Images\in.png"))
{
    bitmap.ColorManagement.TransparentIndexThreshold = 128;
    bitmap.ColorManagement.Palette = ColorPalette.Create(bitmap, 32);
    bitmap.ColorManagement.Convert(PixelFormat.Format8bppIndexed);
    bitmap.Save(@"Images\Output\out.png");
}

The following code snippet uses the ColorConverter transform to present the transparency:

C#
using (var bitmap = new Bitmap(@"Images\in.png"))
using (var converter = new ColorConverter())
{
    converter.TransparentIndexThreshold = 128;
    converter.Palette = ColorPalette.Create(bitmap, 32);
    converter.DestinationPixelFormat = PixelFormat.Format8bppIndexed;
    using (var newbitmap = converter.Apply(bitmap))
        newbitmap.Save(@"Images\Output\out.png");
}

Using NeuQuant

NeuQuant is a palette generation algorithm. It creates an optimal palette for a given image preserving alpha transparency. So, it allows converting real-color images with transparency to indexed PNG images almost without transparency information lost.

To use NeuQuant you should set a ColorPaletteType.NeuQuant palette as a ColorManagementProvider.Palette. The following snippet uses the NeuQuant algorithm:

C#
using (var bitmap = new Bitmap(@"Images\in.png"))
{
    bitmap.ColorManagement.Palette = new ColorPalette(ColorPaletteType.NeuQuant);
    bitmap.ColorManagement.Convert(PixelFormat.Format8bppIndexed);
    bitmap.Save(@"Images\Output\out.png");
}

See Also

Reference

Manual