예제 #1
0
        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);
        }
예제 #2
0
        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);
        }