private static Bitmap ProcessImagePixels(Image sourceImage, QuantizedPalette palette) { var result = new Bitmap(sourceImage.Width, sourceImage.Height, PixelFormat.Format8bppIndexed); var newPalette = result.Palette; for (var index = 0; index < palette.Colors.Count; index++) { newPalette.Entries[index] = palette.Colors[index]; } result.Palette = newPalette; BitmapData targetData = null; try { targetData = result.LockBits(Rectangle.FromLTRB(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, result.PixelFormat); const byte targetBitDepth = 8; var targetByteLength = targetData.Stride < 0 ? -targetData.Stride : targetData.Stride; var targetByteCount = Math.Max(1, targetBitDepth >> 3); var targetSize = targetByteLength * result.Height; var targetOffset = 0; var targetBuffer = new byte[targetSize]; var targetValue = new byte[targetByteCount]; var pixelIndex = 0; for (var y = 0; y < result.Height; y++) { var targetIndex = 0; for (var x = 0; x < result.Width; x++) { var targetIndexOffset = targetIndex >> 3; targetValue[0] = (byte)(palette.PixelIndex[pixelIndex] == -1 ? palette.Colors.Count - 1 : palette.PixelIndex[pixelIndex]); pixelIndex++; for (var valueIndex = 0; valueIndex < targetByteCount; valueIndex++) { targetBuffer[targetOffset + valueIndex + targetIndexOffset] = targetValue[valueIndex]; } targetIndex += targetBitDepth; } targetOffset += targetByteLength; } Marshal.Copy(targetBuffer, 0, targetData.Scan0, targetSize); } finally { if (targetData != null) { result.UnlockBits(targetData); } } return(result); }
private static QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes) { var imageSize = data.Pixels.Count; var lookups = BuildLookups(cubes, data); for (var index = 0; index < imageSize; ++index) { var indexParts = BitConverter.GetBytes(data.QuantizedPixels[index]); data.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); var index2 = -1; foreach (var pixel in data.Pixels) { palette.PixelIndex[++index2] = -1; if (pixel.Alpha <= AlphaThreshold) { continue; } var match = data.QuantizedPixels[index2]; var bestMatch = match; var bestDistance = 100000000; var index = -1; foreach (var lookup in lookups.Lookups) { ++index; var deltaAlpha = pixel.Alpha - lookup.Alpha; var deltaRed = pixel.Red - lookup.Red; var deltaGreen = pixel.Green - lookup.Green; var deltaBlue = pixel.Blue - lookup.Blue; var distance = deltaAlpha * deltaAlpha + deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue; if (distance >= bestDistance) { continue; } bestDistance = distance; bestMatch = index; } alphas[bestMatch] += pixel.Alpha; reds[bestMatch] += pixel.Red; greens[bestMatch] += pixel.Green; blues[bestMatch] += pixel.Blue; sums[bestMatch]++; palette.PixelIndex[index2] = 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); }