Exemplo n.º 1
0
            public Color32[] GeneratePalette(IAsyncContext context)
            {
                // Occurs when bitmap is completely transparent
                if (root.Count == 0)
                {
                    Debug.Assert(hasTransparency);
                    return(new Color32[1]);
                }

                Color32[] result;
                if (root.IsSingleColor)
                {
                    result    = new Color32[hasTransparency ? 2 : 1];
                    result[0] = root.ToColor();
                    return(result);
                }

                context.Progress?.New(DrawingOperation.GeneratingPalette, MaxActualColors, 1);
                var buckets = new ColorBucketCollection(MaxActualColors);

                buckets.AddBucket(root);

                // splitting the initial bucket until no more split can be done or desired color amount is reached
                int startIndex = 0;

                while (buckets.ColorsCount < MaxActualColors)
                {
                    if (buckets.SplitBuckets(context, ref startIndex))
                    {
                        startIndex = 0;
                    }
                    else
                    {
                        break;
                    }
                }

                // finalizing colors and continuing splitting if some buckets map to the same colors
                while (buckets.FinalColorsCount < MaxActualColors)
                {
                    ColorBucket first = buckets.RemoveFirstBucket();
                    if (first == null)
                    {
                        break;
                    }
                    if (startIndex > 0)
                    {
                        startIndex -= 1;
                    }
                    if (!buckets.AddFinalColor(first.ToColor()))
                    {
                        buckets.SplitBuckets(context, ref startIndex);
                    }
                }

                if (context.IsCancellationRequested)
                {
                    return(null);
                }

                Debug.Assert(buckets.FinalColorsCount <= MaxActualColors);
                result = new Color32[buckets.FinalColorsCount + (hasTransparency ? 1 : 0)];
                buckets.CopyFinalColorsTo(result);
                context.Progress?.Complete();

                // If transparent color is needed, then it will be automatically the last color in the result
                return(result);
            }
Exemplo n.º 2
0
                internal void Split(ColorComponent component, ColorBucketCollection buckets, ref int index, ref int endIndex)
                {
                    Debug.Assert(colors.Count > 1);

                    // always sorting by all of the components so then we can eliminate same color groups easily
                    switch (component)
                    {
                    case ColorComponent.R:
                        colors.Sort(redSorter);
                        break;

                    case ColorComponent.G:
                        colors.Sort(greenSorter);
                        break;

                    case ColorComponent.B:
                        colors.Sort(blueSorter);
                        break;
                    }

                    int medianIndex = colors.Count >> 1;

                    // single color check is correct because we sorted by all of the components
                    bool        isLeftSingleColor  = colors[0] == colors[medianIndex - 1];
                    bool        isRightSingleColor = colors[medianIndex] == colors[colors.Count - 1];
                    ColorBucket left  = isLeftSingleColor ? null : new ColorBucket(medianIndex);
                    ColorBucket right = isRightSingleColor ? null : new ColorBucket(colors.Count - medianIndex);

                    // populating the left and right buckets
                    int from = isLeftSingleColor ? (isRightSingleColor ? Int32.MaxValue : medianIndex) : 0;
                    int to   = isRightSingleColor ? (isLeftSingleColor ? 0 : medianIndex) : colors.Count;

                    for (int i = from; i < to; i++)
                    {
                        if (i < medianIndex)
                        {
                            left.AddColor(colors[i]);
                        }
                        else
                        {
                            right.AddColor(colors[i]);
                        }
                    }

                    if (isLeftSingleColor)
                    {
                        buckets.AddFinalColor(colors[0]);

                        // if none of the halves could be added, we remove the current bucket and reduce the number of buckets to scan
                        if (isRightSingleColor)
                        {
                            buckets.AddFinalColor(colors[medianIndex]);
                            buckets.RemoveBucket(index);
                            endIndex -= 1;

                            return;
                        }

                        // the right half is assigned back to the original position
                        buckets.ReplaceBucket(index, right);
                        index += 1;
                        return;
                    }

                    // the left half is assigned back to the original position
                    buckets.ReplaceBucket(index, left);
                    index += 1;

                    if (isRightSingleColor)
                    {
                        buckets.AddFinalColor(colors[medianIndex]);
                        return;
                    }

                    // the right half is added as a new bucket
                    buckets.AddBucket(right);
                }