private static int GetMask(WuPixel[] palette) { IEnumerable <byte> alphas = from pixel in palette select pixel.Alpha; byte maxAlpha = alphas.Max(); int uniqueAlphas = alphas.Distinct().Count(); IEnumerable <byte> reds = from pixel in palette select pixel.Red; byte maxRed = reds.Max(); int uniqueReds = reds.Distinct().Count(); IEnumerable <byte> greens = from pixel in palette select pixel.Green; byte maxGreen = greens.Max(); int uniqueGreens = greens.Distinct().Count(); IEnumerable <byte> blues = from pixel in palette select pixel.Blue; byte maxBlue = blues.Max(); int uniqueBlues = blues.Distinct().Count(); double totalUniques = uniqueAlphas + uniqueReds + uniqueGreens + uniqueBlues; double AvailableBits = 1.0 + Math.Log(uniqueAlphas * uniqueReds * uniqueGreens * uniqueBlues); byte alphaMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueAlphas / totalUniques * AvailableBits))); byte redMask = ComputeBitMask(maxRed, Convert.ToInt32(Math.Round(uniqueReds / totalUniques * AvailableBits))); byte greenMask = ComputeBitMask(maxGreen, Convert.ToInt32(Math.Round(uniqueGreens / totalUniques * AvailableBits))); byte blueMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueBlues / totalUniques * AvailableBits))); WuPixel maskedPixel = new WuPixel(alphaMask, redMask, greenMask, blueMask); return(maskedPixel.Argb); }
public void AddPixel(WuPixel pixel) { Alpha += pixel.Alpha; Red += pixel.Red; Green += pixel.Green; Blue += pixel.Blue; Sum++; }
public void Add(WuPixel p) { byte pAlpha = p.Alpha; byte pRed = p.Red; byte pGreen = p.Green; byte pBlue = p.Blue; Alpha += pAlpha; Red += pRed; Green += pGreen; Blue += pBlue; Weight++; Moment += pAlpha * pAlpha + pRed * pRed + pGreen * pGreen + pBlue * pBlue; }
public byte GetPaletteIndex(WuPixel pixel) { int pixelKey = pixel.Argb & mMask; LookupNode[] bucket; if (!mLookup.TryGetValue(pixelKey, out bucket)) { bucket = Palette; } if (bucket.Length == 1) { return(bucket[0].PaletteIndex); } int bestDistance = int.MaxValue; byte bestMatch = 0; foreach (var lookup in bucket) { var lookupPixel = lookup.Pixel; var deltaAlpha = pixel.Alpha - lookupPixel.Alpha; int distance = deltaAlpha * deltaAlpha; var deltaRed = pixel.Red - lookupPixel.Red; distance += deltaRed * deltaRed; var deltaGreen = pixel.Green - lookupPixel.Green; distance += deltaGreen * deltaGreen; var deltaBlue = pixel.Blue - lookupPixel.Blue; distance += deltaBlue * deltaBlue; if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch = lookup.PaletteIndex; } if ((bucket == Palette) && (pixelKey != 0)) { mLookup[pixelKey] = new LookupNode[] { bucket[bestMatch] }; } return(bestMatch); }
private static byte[] IndexedPixels(Color[] pixels, WuPixel[] lookups, int alphaThreshold, int maxColors, PaletteColorHistory[] paletteHistogram) { var length = maxColors == 256 ? pixels.Length : maxColors == 16 ? pixels.Length / 2 : throw new Exception("IndexedPixels: unknown pixelformat"); byte[] returned = new byte[length]; PaletteLookup lookup = new PaletteLookup(lookups); --maxColors; for (int i = 0; i < pixels.Length; i++) { WuPixel pixel = new WuPixel(pixels[i].A, pixels[i].R, pixels[i].G, pixels[i].B); byte bestMatch = (byte)maxColors; if (pixel.Alpha > alphaThreshold) { bestMatch = lookup.GetPaletteIndex(pixel); paletteHistogram[bestMatch].AddPixel(pixel); } switch (maxColors) { case 256 - 1: returned[i] = bestMatch; break; case 16 - 1: if (i % 2 == 0) { returned[i / 2] = (byte)(bestMatch << 4); } else { returned[i / 2] |= (byte)(bestMatch & 0x0F); } break; case 2 - 1: if (i % 8 == 0) { returned[i / 8] = (byte)(bestMatch << 7); } else { returned[i / 8] |= (byte)((bestMatch & 0x01) << (7 - (i % 8))); } break; } } return(returned); }
private static WuPixel[] BuildLookups(Box[] cubes, ColorMoment[,,,] moments) { WuPixel[] lookups = new WuPixel[cubes.Length]; for (int cubeIndex = 0; cubeIndex < cubes.Length; cubeIndex++) { var volume = Volume(cubes[cubeIndex], moments); if (volume.Weight <= 0) { continue; } var lookup = new WuPixel { Alpha = (byte)(volume.Alpha / volume.Weight), Red = (byte)(volume.Red / volume.Weight), Green = (byte)(volume.Green / volume.Weight), Blue = (byte)(volume.Blue / volume.Weight) }; lookups[cubeIndex] = lookup; } return(lookups); }