public static void InsertIntoSortedList(List <ColorQuantizationBox> list, ColorQuantizationBox newItem, Func <ColorQuantizationBox, long> sortPriority) { if (list.Count == 0) { list.Add(newItem); return; } long newItemPriority = sortPriority(newItem); if (newItemPriority < sortPriority(list[0])) { list.Insert(0, newItem); return; } if (newItemPriority > sortPriority(list.Last())) { list.Add(newItem); return; } int newIndex = 0; for (int i = 0; i < list.Count; i++) { if (newItemPriority <= sortPriority(list[i])) { newIndex = i; break; } } list.Insert(newIndex, newItem); }
public ColorQuantizationBox(ColorQuantizationBox source) { SignifigantBits = source.SignifigantBits; Histogram = source.Histogram; HistogramTotal = source.HistogramTotal; MinRed = source.MinRed; MaxRed = source.MaxRed; MinGreen = source.MinGreen; MaxGreen = source.MaxGreen; MinBlue = source.MinBlue; MaxBlue = source.MaxBlue; }
public Tuple <ColorQuantizationBox, ColorQuantizationBox> MedianCut() { if (this.HistogramTotal <= 1) { return(new Tuple <ColorQuantizationBox, ColorQuantizationBox>(this, null)); } uint total = 0; uint[] partialSum = null; RGBAxis primaryAxis = WidestAxis; byte primaryMin, primaryMax; if (primaryAxis == RGBAxis.Red) { primaryMin = MinRed; primaryMax = MaxRed; partialSum = new uint[RedRange + 1]; for (byte i = MinRed; i <= MaxRed; i++) { uint sum = 0; for (byte j = MinGreen; j <= MaxGreen; j++) { for (byte k = MinBlue; k <= MaxBlue; k++) { var index = GetColorIndex(i, j, k, SignifigantBits); sum += Histogram[index]; } } total += sum; partialSum[i - primaryMin] = total; } } else if (primaryAxis == RGBAxis.Green) { primaryMin = MinGreen; primaryMax = MaxGreen; partialSum = new uint[GreenRange + 1]; for (byte i = MinGreen; i <= MaxGreen; i++) { uint sum = 0; for (byte j = MinRed; j <= MaxRed; j++) { for (byte k = MinBlue; k <= MaxBlue; k++) { var index = GetColorIndex(j, i, k, SignifigantBits); sum += Histogram[index]; } } total += sum; partialSum[i - primaryMin] = total; } } else { primaryMin = MinBlue; primaryMax = MaxBlue; partialSum = new uint[BlueRange + 1]; for (byte i = MinBlue; i <= MaxBlue; i++) { uint sum = 0; for (byte j = MinRed; j <= MaxRed; j++) { for (byte k = MinGreen; k <= MaxGreen; k++) { var index = GetColorIndex(j, k, i, SignifigantBits); sum += Histogram[index]; } } total += sum; partialSum[i - primaryMin] = total; } } if (primaryMin == primaryMax) { return(new Tuple <ColorQuantizationBox, ColorQuantizationBox>(this, null)); } uint[] lookAheadSum = new uint[partialSum.Length]; for (int i = 0; i < partialSum.Length; i++) { lookAheadSum[i] = total - partialSum[i]; } for (byte i = primaryMin; i <= primaryMax; i++) { var partial = partialSum[i - primaryMin]; if (partial > total / 2) { float left = i - primaryMin; float right = primaryMax - i; int cutValue = 0; if (left <= right) { cutValue = Math.Min(primaryMax - 1, (int)Math.Floor((float)i + right / 2f)); } else { cutValue = Math.Max(primaryMin, (int)Math.Floor((float)i - 1f - left / 2f)); } while (partialSum[cutValue - primaryMin] <= 0) { cutValue++; } if (cutValue - primaryMin >= partialSum.Length) { cutValue = partialSum.Length - 1 + primaryMin; } uint lookAhead = lookAheadSum[cutValue - primaryMin]; while (lookAhead == 0 && cutValue > primaryMin && partialSum[cutValue - primaryMin - 1] != 0) { cutValue--; lookAhead = lookAheadSum[cutValue - primaryMin]; } ColorQuantizationBox leftBox = null, rightBox = null; if (primaryAxis == RGBAxis.Red) { leftBox = new ColorQuantizationBox(Histogram, MinRed, (byte)(cutValue), MinGreen, MaxGreen, MinBlue, MaxBlue, SignifigantBits); rightBox = new ColorQuantizationBox(Histogram, (byte)(cutValue + 1), MaxRed, MinGreen, MaxGreen, MinBlue, MaxBlue, SignifigantBits); } else if (primaryAxis == RGBAxis.Green) { leftBox = new ColorQuantizationBox(Histogram, MinRed, MaxRed, MinGreen, (byte)(cutValue), MinBlue, MaxBlue, SignifigantBits); rightBox = new ColorQuantizationBox(Histogram, MinRed, MaxRed, (byte)(cutValue + 1), MaxGreen, MinBlue, MaxBlue, SignifigantBits); } else { leftBox = new ColorQuantizationBox(Histogram, MinRed, MaxRed, MinGreen, MaxGreen, MinBlue, (byte)(cutValue), SignifigantBits); rightBox = new ColorQuantizationBox(Histogram, MinRed, MaxRed, MinGreen, MaxGreen, (byte)(cutValue + 1), MaxBlue, SignifigantBits); } return(new Tuple <ColorQuantizationBox, ColorQuantizationBox>(leftBox, rightBox)); } } throw new Exception("Unable to find median partial sum. This should never happen"); }