// メディアンカット 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; }