Esempio n. 1
0
        // メディアンカット
        private unsafe ColorBox[] medianCut(ColorEntry[] colors, ArgbColor[] importantColors, int paletteSize) {
#if DEBUG
            var stopWatch = new System.Diagnostics.Stopwatch();
            stopWatch.Start();
#endif

            ColorBox[] boxes = new ColorBox[paletteSize];
            int boxCount = 0;
            boxes[boxCount++] = new ColorBox(0, colors.Length - 1) ;
            boxes[0].CalcWeight(colors, importantColors);

            fixed (ColorEntry* table = colors)
            while (boxCount < paletteSize) {
                // 分散が最も大きなBoxを探す
                int divIndex = -1;
                int maxWeight = int.MinValue;
                for (int i = 0; i < boxCount; i++) {
                    if (boxes[i].DivWeight >= maxWeight) {
                        maxWeight = boxes[i].DivWeight;
                        divIndex = i;
                    }
                }

                int minIdx = boxes[divIndex].ColorIndexMin;
                int maxIdx = boxes[divIndex].ColorIndexMax;
                int ch = boxes[divIndex].DivChannel;

                // 中央値を決めて分割
                int median = boxes[divIndex].MedianValue;
                int l = minIdx;
                int r = maxIdx;
                do {
                    while (l + 1 < r && table[l].Color.Channels[ch] <= median) l++;
                    while (l < r - 1 && table[r].Color.Channels[ch] >= median) r--;
                    if (table[l].Color.Channels[ch] > table[r].Color.Channels[ch]) {
                        ColorEntry temp = table[l];
                        table[l] = table[r];
                        table[r] = temp;
                    }
                } while (l + 1 < r);

                ColorBox leftBox = new ColorBox( minIdx, l);
                leftBox.CalcWeight(colors, importantColors);
                boxes[divIndex] = leftBox;

                ColorBox rightBox = new ColorBox( r, maxIdx);
                rightBox.CalcWeight(colors, importantColors);
                boxes[boxCount++] = rightBox;
            }
            
#if DEBUG
            Console.WriteLine("median cut ({0} msec).", stopWatch.ElapsedMilliseconds);
#endif
            return boxes;
        }