Example #1
0
        protected override void Run(Workbench workbench, ILogger logger)
        {
            int maxTilesPerRow = FindNamedParameter("--colors-per-row").Values[0].ToInt32();

            if (maxTilesPerRow < 0)
            {
                logger?.Log("Invalid colors per row.", LogLevel.Error);
                return;
            }

            int tw = 8;
            int th = 8;

            int maxColors = workbench.PaletteSet.Max(pe => pe.Palette.Count);
            int palCount  = workbench.PaletteSet.Count;

            if (maxTilesPerRow == 0)
            {
                maxTilesPerRow = maxColors;
            }

            int w = maxTilesPerRow;
            int h = workbench.PaletteSet.Sum(pe => (pe.Palette.Count + maxTilesPerRow - 1) / maxTilesPerRow);

            if (w <= 0 || h <= 0)
            {
                logger?.Log("Cannot render empty palette set.", LogLevel.Error);
                return;
            }

            int count = 0;

            ColorFormat fmt = ColorFormat.BGRA8888;

            workbench.ClearBitmap(w * tw, h * th);
            workbench.Graphics.CompositingMode = CompositingMode.SourceCopy;
            using (SolidBrush brush = new SolidBrush(Color.Black)) {
                int p = 0;
                int c = 0;
                for (int j = 0; j < h; j++)
                {
                    Palette pal = workbench.PaletteSet[p].Palette;
                    for (int i = 0; i < w; i++)
                    {
                        // Draw transparent if we ran out of colors.
                        if (c >= pal.Count)
                        {
                            brush.Color = Color.Transparent;
                        }
                        else
                        {
                            brush.Color = Color.FromArgb(fmt.Convert(pal[c++], pal.Format));
                        }
                        workbench.Graphics.FillRectangle(brush, i * tw, j * th, tw, th);
                        count++;
                    }
                    // Go to next palette.
                    if (c >= pal.Count)
                    {
                        p++;
                        c = 0;
                    }
                }
            }
            workbench.Graphics.Flush();

            logger?.Log("Rendered " + w + "x" + h + " palette set containing " + count + " colors.", LogLevel.Information);
        }
Example #2
0
        private static int DeduplicatePalette(Palette palette, Random rng, ILogger logger)
        {
            // Create sequential color format to remove alpha channel and padding.
            ColorFormat seqFmt = ColorFormat.SequentialBGRA(
                palette.Format.RedBits,
                palette.Format.GreenBits,
                palette.Format.BlueBits,
                0
                );
            int n = seqFmt.MaxValue;

            if (palette.Count > n)
            {
                logger?.Log("Cannot deduplicate palette; palette size exceeds color space.", LogLevel.Error);
                return(0);
            }

            // Set of distinct colors with lookup O(1).
            // Use Dictionary instead of HashSet to pre-allocate capacity.
            Dictionary <int, int> colToIdxDict = new Dictionary <int, int>(palette.Count);

            // Put colors in the dictionary and count dupes.
            List <int> dupes = new List <int>();

            for (int i = 0; i < palette.Count; i++)
            {
                int c = seqFmt.Convert(palette[i], palette.Format);

                if (!colToIdxDict.ContainsKey(c))
                {
                    colToIdxDict[c] = i;
                }
                else
                {
                    dupes.Add(i);
                }
            }

            // Sort colors ascending.
            List <int> colSet = colToIdxDict.Keys.ToList();

            colSet.Sort();

            // For each dupe, add a new color.
            foreach (int dupe in dupes)
            {
                int?candidate = RandomIntByBinarySearch(colSet, rng, n);
                if (candidate is int c)
                {
                    colSet.Add(c);
                    colSet.Sort();
                    palette[dupe] = palette.Format.Convert(c, seqFmt);
                }
                else
                {
                    logger?.Log("Failed to deduplicate palette .", LogLevel.Error);
                    return(0);
                }
            }

            return(dupes.Count);
        }