private static IEnumerable<byte[]> indexedPixels(ImageBuffer image, Pixel[] lookups, int alphaThreshold, int maxColors, PaletteColorHistory[] paletteHistogram) { int pixelsCount = image.Image.Width * image.Image.Height; var lineIndexes = new byte[(int)System.Math.Ceiling(image.Image.Width / System.Math.Log(256.0, maxColors))]; PaletteLookup lookup = new PaletteLookup(lookups); --maxColors; foreach (var pixelLine in image.PixelLines) { for (int pixelIndex = 0; pixelIndex < pixelLine.Length; pixelIndex++) { Pixel pixel = pixelLine[pixelIndex]; byte bestMatch = (byte)maxColors; if (pixel.Alpha > alphaThreshold) { bestMatch = lookup.GetPaletteIndex(pixel); paletteHistogram[bestMatch].AddPixel(pixel); } switch (maxColors) { case 256 - 1: lineIndexes[pixelIndex] = bestMatch; break; case 16 - 1: if (pixelIndex % 2 == 0) { lineIndexes[pixelIndex / 2] = (byte)(bestMatch << 4); } else { lineIndexes[pixelIndex / 2] |= (byte)(bestMatch & 0x0F); } break; case 2 - 1: if (pixelIndex % 8 == 0) { lineIndexes[pixelIndex / 8] = (byte)(bestMatch << 7); } else { lineIndexes[pixelIndex / 8] |= (byte)((bestMatch & 0x01) << (7 - (pixelIndex % 8))); } break; } } yield return lineIndexes; } }
public void AddPixel(Pixel pixel) { Alpha += pixel.Alpha; Red += pixel.Red; Green += pixel.Green; Blue += pixel.Blue; Sum++; }
internal override Image GetQuantizedImage(ImageBuffer image, int colorCount, int maxColors, Pixel[] lookups, int alphaThreshold) { PixelFormat pf; switch (maxColors) { case 256: pf = PixelFormat.Format8bppIndexed; break; case 16: pf = PixelFormat.Format4bppIndexed; break; case 2: pf = PixelFormat.Format1bppIndexed; break; default: throw new QuantizationException(string.Format("The target amount of colors is not supported. Requested {0} colors.", maxColors)); } var result = new Bitmap(image.Image.Width, image.Image.Height, pf); var resultBuffer = new ImageBuffer(result); var paletteHistogram = new PaletteColorHistory[colorCount + 1]; resultBuffer.UpdatePixelIndexes(indexedPixels(image, lookups, alphaThreshold, maxColors, paletteHistogram)); result.Palette = BuildPalette(result.Palette, paletteHistogram); return result; }
protected override QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes, int alphaThreshold) { int imageSize = data.PixelsCount; LookupData lookups = BuildLookups(cubes, data); IList <int> quantizedPixels = data.QuantizedPixels; for (var index = 0; index < imageSize; ++index) { var indexParts = BitConverter.GetBytes(quantizedPixels[index]); quantizedPixels[index] = lookups.Tags[indexParts[Alpha], indexParts[Red], indexParts[Green], indexParts[Blue]]; } var alphas = new int[colorCount + 1]; var reds = new int[colorCount + 1]; var greens = new int[colorCount + 1]; var blues = new int[colorCount + 1]; var sums = new int[colorCount + 1]; var palette = new QuantizedPalette(imageSize); IList <Pixel> pixels = data.Pixels; int pixelsCount = data.PixelsCount; IList <Lookup> lookupsList = lookups.Lookups; int lookupsCount = lookupsList.Count; Dictionary <int, int> cachedMaches = new Dictionary <int, int>(); for (int pixelIndex = 0; pixelIndex < pixelsCount; pixelIndex++) { Pixel pixel = pixels[pixelIndex]; palette.PixelIndex[pixelIndex] = -1; if (pixel.Alpha <= alphaThreshold) { continue; } int bestMatch; int argb = pixel.Argb; if (!cachedMaches.TryGetValue(argb, out bestMatch)) { int match = quantizedPixels[pixelIndex]; bestMatch = match; int bestDistance = int.MaxValue; for (int lookupIndex = 0; lookupIndex < lookupsCount; lookupIndex++) { Lookup lookup = lookupsList[lookupIndex]; var deltaAlpha = pixel.Alpha - lookup.Alpha; var deltaRed = pixel.Red - lookup.Red; var deltaGreen = pixel.Green - lookup.Green; var deltaBlue = pixel.Blue - lookup.Blue; int distance = deltaAlpha * deltaAlpha + deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch = lookupIndex; } cachedMaches[argb] = bestMatch; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[pixelIndex] = bestMatch; } for (var paletteIndex = 0; paletteIndex < colorCount; paletteIndex++) { if (sums[paletteIndex] > 0) { alphas[paletteIndex] /= sums[paletteIndex]; reds[paletteIndex] /= sums[paletteIndex]; greens[paletteIndex] /= sums[paletteIndex]; blues[paletteIndex] /= sums[paletteIndex]; } var color = Color.FromArgb(alphas[paletteIndex], reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]); palette.Colors.Add(color); } palette.Colors.Add(Color.FromArgb(0, 0, 0, 0)); return(palette); }