示例#1
0
        private static ColorData BuildHistogram(Bitmap sourceImage, int alphaThreshold, int alphaFader)
        {
            int bitmapWidth  = sourceImage.Width;
            int bitmapHeight = sourceImage.Height;

            BitmapData data = sourceImage.LockBits(
                Rectangle.FromLTRB(0, 0, bitmapWidth, bitmapHeight),
                ImageLockMode.ReadOnly,
                sourceImage.PixelFormat);
            ColorData colorData = new ColorData(MaxSideIndex, bitmapWidth, bitmapHeight);

            try
            {
                var bitDepth = Image.GetPixelFormatSize(sourceImage.PixelFormat);
                if (bitDepth != 32)
                {
                    throw new QuantizationException(string.Format("Thie image you are attempting to quantize does not contain a 32 bit ARGB palette. This image has a bit depth of {0} with {1} colors.", bitDepth, sourceImage.Palette.Entries.Length));
                }
                var byteLength = data.Stride < 0 ? -data.Stride : data.Stride;
                var byteCount  = Math.Max(1, bitDepth >> 3);
                var offset     = 0;
                var buffer     = new Byte[byteLength * sourceImage.Height];
                var value      = new Byte[byteCount];

                Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);

                for (int y = 0; y < bitmapHeight; y++)
                {
                    var index = 0;
                    for (int x = 0; x < bitmapWidth; x++)
                    {
                        var indexOffset = index >> 3;

                        for (var valueIndex = 0; valueIndex < byteCount; valueIndex++)
                        {
                            value[valueIndex] = buffer[offset + valueIndex + indexOffset];
                        }

                        var indexAlpha = (byte)((value[Alpha] >> 3) + 1);
                        var indexRed   = (byte)((value[Red] >> 3) + 1);
                        var indexGreen = (byte)((value[Green] >> 3) + 1);
                        var indexBlue  = (byte)((value[Blue] >> 3) + 1);

                        if (value[Alpha] > alphaThreshold)
                        {
                            if (value[Alpha] < 255)
                            {
                                var alpha = value[Alpha] + (value[Alpha] % alphaFader);
                                value[Alpha] = (byte)(alpha > 255 ? 255 : alpha);
                                indexAlpha   = (byte)((value[Alpha] >> 3) + 1);
                            }

                            colorData.Weights[indexAlpha, indexRed, indexGreen, indexBlue]++;
                            colorData.MomentsRed[indexAlpha, indexRed, indexGreen, indexBlue]   += value[Red];
                            colorData.MomentsGreen[indexAlpha, indexRed, indexGreen, indexBlue] += value[Green];
                            colorData.MomentsBlue[indexAlpha, indexRed, indexGreen, indexBlue]  += value[Blue];
                            colorData.MomentsAlpha[indexAlpha, indexRed, indexGreen, indexBlue] += value[Alpha];
                            colorData.Moments[indexAlpha, indexRed, indexGreen, indexBlue]      += (value[Alpha] * value[Alpha]) +
                                                                                                   (value[Red] * value[Red]) +
                                                                                                   (value[Green] * value[Green]) +
                                                                                                   (value[Blue] * value[Blue]);
                        }

                        colorData.AddPixel(
                            new Pixel(value[Alpha], value[Red], value[Green], value[Blue]),
                            BitConverter.ToInt32(new[] { indexAlpha, indexRed, indexGreen, indexBlue }, 0));
                        index += bitDepth;
                    }

                    offset += byteLength;
                }
            }
            finally
            {
                sourceImage.UnlockBits(data);
            }
            return(colorData);
        }
示例#2
0
        private bool Cut(ColorData data, ref Box first, ref Box second)
        {
            int direction;
            var wholeAlpha  = Volume(first, data.MomentsAlpha);
            var wholeRed    = Volume(first, data.MomentsRed);
            var wholeGreen  = Volume(first, data.MomentsGreen);
            var wholeBlue   = Volume(first, data.MomentsBlue);
            var wholeWeight = Volume(first, data.Weights);

            var maxAlpha = Maximize(data, first, Alpha, (byte)(first.AlphaMinimum + 1), first.AlphaMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
            var maxRed   = Maximize(data, first, Red, (byte)(first.RedMinimum + 1), first.RedMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
            var maxGreen = Maximize(data, first, Green, (byte)(first.GreenMinimum + 1), first.GreenMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);
            var maxBlue  = Maximize(data, first, Blue, (byte)(first.BlueMinimum + 1), first.BlueMaximum, wholeAlpha, wholeRed, wholeGreen, wholeBlue, wholeWeight);

            if ((maxAlpha.Value >= maxRed.Value) && (maxAlpha.Value >= maxGreen.Value) && (maxAlpha.Value >= maxBlue.Value))
            {
                direction = Alpha;
                if (maxAlpha.Position == null)
                {
                    return(false);
                }
            }
            else if ((maxRed.Value >= maxAlpha.Value) && (maxRed.Value >= maxGreen.Value) && (maxRed.Value >= maxBlue.Value))
            {
                direction = Red;
            }
            else
            {
                if ((maxGreen.Value >= maxAlpha.Value) && (maxGreen.Value >= maxRed.Value) && (maxGreen.Value >= maxBlue.Value))
                {
                    direction = Green;
                }
                else
                {
                    direction = Blue;
                }
            }

            second.AlphaMaximum = first.AlphaMaximum;
            second.RedMaximum   = first.RedMaximum;
            second.GreenMaximum = first.GreenMaximum;
            second.BlueMaximum  = first.BlueMaximum;

            switch (direction)
            {
            case Alpha:
                second.AlphaMinimum = first.AlphaMaximum = (byte)maxAlpha.Position;
                second.RedMinimum   = first.RedMinimum;
                second.GreenMinimum = first.GreenMinimum;
                second.BlueMinimum  = first.BlueMinimum;
                break;

            case Red:
                second.RedMinimum   = first.RedMaximum = (byte)maxRed.Position;
                second.AlphaMinimum = first.AlphaMinimum;
                second.GreenMinimum = first.GreenMinimum;
                second.BlueMinimum  = first.BlueMinimum;
                break;

            case Green:
                second.GreenMinimum = first.GreenMaximum = (byte)maxGreen.Position;
                second.AlphaMinimum = first.AlphaMinimum;
                second.RedMinimum   = first.RedMinimum;
                second.BlueMinimum  = first.BlueMinimum;
                break;

            case Blue:
                second.BlueMinimum  = first.BlueMaximum = (byte)maxBlue.Position;
                second.AlphaMinimum = first.AlphaMinimum;
                second.RedMinimum   = first.RedMinimum;
                second.GreenMinimum = first.GreenMinimum;
                break;
            }

            first.Size  = (first.AlphaMaximum - first.AlphaMinimum) * (first.RedMaximum - first.RedMinimum) * (first.GreenMaximum - first.GreenMinimum) * (first.BlueMaximum - first.BlueMinimum);
            second.Size = (second.AlphaMaximum - second.AlphaMinimum) * (second.RedMaximum - second.RedMinimum) * (second.GreenMaximum - second.GreenMinimum) * (second.BlueMaximum - second.BlueMinimum);

            return(true);
        }
示例#3
0
 protected abstract QuantizedPalette GetQuantizedPalette(int colorCount, ColorData data, IEnumerable <Box> cubes, int alphaThreshold);
示例#4
0
        private static ColorData CalculateMoments(ColorData data)
        {
            for (var alphaIndex = 1; alphaIndex <= MaxSideIndex; ++alphaIndex)
            {
                var xarea      = new long[SideSize, SideSize, SideSize];
                var xareaAlpha = new long[SideSize, SideSize, SideSize];
                var xareaRed   = new long[SideSize, SideSize, SideSize];
                var xareaGreen = new long[SideSize, SideSize, SideSize];
                var xareaBlue  = new long[SideSize, SideSize, SideSize];
                var xarea2     = new float[SideSize, SideSize, SideSize];
                for (var redIndex = 1; redIndex <= MaxSideIndex; ++redIndex)
                {
                    var area      = new long[SideSize];
                    var areaAlpha = new long[SideSize];
                    var areaRed   = new long[SideSize];
                    var areaGreen = new long[SideSize];
                    var areaBlue  = new long[SideSize];
                    var area2     = new float[SideSize];
                    for (var greenIndex = 1; greenIndex <= MaxSideIndex; ++greenIndex)
                    {
                        long line      = 0;
                        long lineAlpha = 0;
                        long lineRed   = 0;
                        long lineGreen = 0;
                        long lineBlue  = 0;
                        var  line2     = 0.0f;
                        for (var blueIndex = 1; blueIndex <= MaxSideIndex; ++blueIndex)
                        {
                            line      += data.Weights[alphaIndex, redIndex, greenIndex, blueIndex];
                            lineAlpha += data.MomentsAlpha[alphaIndex, redIndex, greenIndex, blueIndex];
                            lineRed   += data.MomentsRed[alphaIndex, redIndex, greenIndex, blueIndex];
                            lineGreen += data.MomentsGreen[alphaIndex, redIndex, greenIndex, blueIndex];
                            lineBlue  += data.MomentsBlue[alphaIndex, redIndex, greenIndex, blueIndex];
                            line2     += data.Moments[alphaIndex, redIndex, greenIndex, blueIndex];

                            area[blueIndex]      += line;
                            areaAlpha[blueIndex] += lineAlpha;
                            areaRed[blueIndex]   += lineRed;
                            areaGreen[blueIndex] += lineGreen;
                            areaBlue[blueIndex]  += lineBlue;
                            area2[blueIndex]     += line2;

                            xarea[redIndex, greenIndex, blueIndex]      = xarea[redIndex - 1, greenIndex, blueIndex] + area[blueIndex];
                            xareaAlpha[redIndex, greenIndex, blueIndex] = xareaAlpha[redIndex - 1, greenIndex, blueIndex] + areaAlpha[blueIndex];
                            xareaRed[redIndex, greenIndex, blueIndex]   = xareaRed[redIndex - 1, greenIndex, blueIndex] + areaRed[blueIndex];
                            xareaGreen[redIndex, greenIndex, blueIndex] = xareaGreen[redIndex - 1, greenIndex, blueIndex] + areaGreen[blueIndex];
                            xareaBlue[redIndex, greenIndex, blueIndex]  = xareaBlue[redIndex - 1, greenIndex, blueIndex] + areaBlue[blueIndex];
                            xarea2[redIndex, greenIndex, blueIndex]     = xarea2[redIndex - 1, greenIndex, blueIndex] + area2[blueIndex];

                            data.Weights[alphaIndex, redIndex, greenIndex, blueIndex]      = data.Weights[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xarea[redIndex, greenIndex, blueIndex];
                            data.MomentsAlpha[alphaIndex, redIndex, greenIndex, blueIndex] = data.MomentsAlpha[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xareaAlpha[redIndex, greenIndex, blueIndex];
                            data.MomentsRed[alphaIndex, redIndex, greenIndex, blueIndex]   = data.MomentsRed[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xareaRed[redIndex, greenIndex, blueIndex];
                            data.MomentsGreen[alphaIndex, redIndex, greenIndex, blueIndex] = data.MomentsGreen[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xareaGreen[redIndex, greenIndex, blueIndex];
                            data.MomentsBlue[alphaIndex, redIndex, greenIndex, blueIndex]  = data.MomentsBlue[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xareaBlue[redIndex, greenIndex, blueIndex];
                            data.Moments[alphaIndex, redIndex, greenIndex, blueIndex]      = data.Moments[alphaIndex - 1, redIndex, greenIndex, blueIndex] + xarea2[redIndex, greenIndex, blueIndex];
                        }
                    }
                }
            }
            return(data);
        }