From cedf29ff0250a06d99570eaafa1caa64a0ff81bb Mon Sep 17 00:00:00 2001 From: Alexey 'Cluster' Avdyukhin Date: Fri, 28 Oct 2022 15:52:01 +0400 Subject: Palette class is immutable now. Faster and uses less memory. --- NesTiler/Palette.cs | 59 ++++++++++++----------------------------------------- NesTiler/Program.cs | 23 ++++++++------------- 2 files changed, 21 insertions(+), 61 deletions(-) (limited to 'NesTiler') diff --git a/NesTiler/Palette.cs b/NesTiler/Palette.cs index 224c29b..5944b1c 100644 --- a/NesTiler/Palette.cs +++ b/NesTiler/Palette.cs @@ -10,28 +10,19 @@ namespace com.clusterrr.Famicom.NesTiler { class Palette : IEquatable, IEnumerable { - private SKColor?[] colors = new SKColor?[3]; + private SKColor[] colors; private Dictionary deltaCache = new(); public SKColor? this[int i] { get { - if (i < 1 || i > 3) throw new IndexOutOfRangeException("Color index must be between 1 and 3"); + if (i > colors.Length) return null; + if (i <= 0) throw new ArgumentOutOfRangeException("Invalid color index"); return colors[i - 1]; } - set - { - if (i < 1 || i > 3) throw new IndexOutOfRangeException("Color index must be between 1 and 3"); - colors[i - 1] = value; - } - } - public int Count { get => colors.Where(c => c.HasValue).Count(); } - - public Palette() - { - // Empty palette } + public int Count => colors.Length; public Palette(FastBitmap image, int leftX, int topY, int width, int height, SKColor bgColor) { @@ -48,25 +39,13 @@ namespace com.clusterrr.Famicom.NesTiler } } - var sortedColors = colorCounter - .OrderByDescending(kv => kv.Value).ToArray(); - for (int i = 0; i < 3; i++) - if (sortedColors.Length > i) - this[i + 1] = sortedColors[i].Key; - } - - public void Add(SKColor color) - { - if (Count >= 3) throw new IndexOutOfRangeException(); - this[Count + 1] = color; - deltaCache.Clear(); + // TODO: one more lossy level? + colors = colorCounter.OrderByDescending(kv => kv.Value).Take(3).OrderBy(kv => kv.Key.ToArgb()).Select(kv => kv.Key).ToArray(); } public Palette(IEnumerable colors) { - var colorsList = colors.ToList(); - for (int i = 0; i < 3; i++) - if (colorsList.Count > i) this[i + 1] = colorsList[i]; + this.colors = colors.OrderBy(c => c.ToArgb()).Take(3).ToArray(); } public double GetTileDelta(FastBitmap image, int leftX, int topY, int width, int height, SKColor bgColor) @@ -92,7 +71,7 @@ namespace com.clusterrr.Famicom.NesTiler Color2 = bgColor }; if (deltaCache.ContainsKey(pair)) return deltaCache[pair]; - var ac = Enumerable.Concat(colors.Where(c => c.HasValue).Select(c => c!.Value), new SKColor[] { bgColor }); + var ac = Enumerable.Concat(colors, new SKColor[] { bgColor }); var result = ac.OrderBy(c => c.GetDelta(color)).First(); var r = (result, result.GetDelta(color)); deltaCache[pair] = r; @@ -102,27 +81,15 @@ namespace com.clusterrr.Famicom.NesTiler public bool Equals(Palette? other) { if (other == null) return false; - var colors1 = colors.Where(c => c.HasValue) - .Select(c => c!.Value.ToArgb()) - .OrderBy(c => c) - .ToArray(); - var colors2 = new SKColor?[] { other[1], other[2], other[3] } - .Where(c => c.HasValue) - .Select(c => c!.Value.ToArgb()) - .OrderBy(c => c) - .ToArray(); - var r = Enumerable.SequenceEqual(colors1, colors2); + var r = Enumerable.SequenceEqual(this, other); return r; } public bool Contains(Palette other) { - var thisColors = colors.Where(c => c.HasValue); - var otherColors = new SKColor?[] { other[1], other[2], other[3] }.Where(c => c.HasValue).Select(c => c!.Value); - - foreach (var color in otherColors) + foreach (var color in other) { - if (!thisColors.Contains(color)) + if (!this.Contains(color)) return false; } return true; @@ -130,7 +97,7 @@ namespace com.clusterrr.Famicom.NesTiler public IEnumerator GetEnumerator() { - return colors.Where(c => c.HasValue).Select(c => c!.Value).GetEnumerator(); + return colors.Select(c => c).GetEnumerator(); // wtf? } IEnumerator IEnumerable.GetEnumerator() @@ -138,7 +105,7 @@ namespace com.clusterrr.Famicom.NesTiler return GetEnumerator(); } - public override string ToString() => string.Join(", ", colors.Where(c => c.HasValue).Select(c => ColorTranslator.ToHtml(c!.Value.ToColor())).OrderBy(c => c)); + public override string ToString() => string.Join(", ", colors.Select(c => ColorTranslator.ToHtml(c.ToColor())).OrderBy(c => c)); public override int GetHashCode() => (int)((this[1]?.ToArgb() ?? 0) + ((this[2]?.ToArgb() ?? 0) << 4) + ((this[3]?.ToArgb() ?? 0) << 8)); } diff --git a/NesTiler/Program.cs b/NesTiler/Program.cs index 9d210e0..92f50fd 100644 --- a/NesTiler/Program.cs +++ b/NesTiler/Program.cs @@ -141,6 +141,7 @@ namespace com.clusterrr.Famicom.NesTiler var color = image.GetPixelColor(x, y); if (color.Alpha >= 0x80 || c.Mode == Config.TilesMode.Backgrounds) { + // TODO: more lossy levels? var similarColor = nesColors.FindSimilarColor(color); image.SetPixelColor(x, y, similarColor); } @@ -241,15 +242,8 @@ namespace com.clusterrr.Famicom.NesTiler } else if (calculatedPalettes.Any()) { - if (calculatedPalettes.Any()) - { - palettes[i] = calculatedPalettes.First(); - calculatedPalettes.RemoveAt(0); - } - else - { - palettes[i] = new Palette(); - } + palettes[i] = calculatedPalettes.First(); + calculatedPalettes.RemoveAt(0); } if (palettes[i] != null) @@ -544,8 +538,7 @@ namespace com.clusterrr.Famicom.NesTiler foreach (var imageNum in images.Keys) { var image = images[imageNum]; - int attributeTableOffset; - attributeTableOffsets.TryGetValue(imageNum, out attributeTableOffset); + attributeTableOffsets.TryGetValue(imageNum, out int attributeTableOffset); // For each tile/sprite for (int tileY = 0; tileY < (image.Height + attributeTableOffset) / tilePalHeight; tileY++) { @@ -604,19 +597,19 @@ namespace com.clusterrr.Famicom.NesTiler bool grouped = false; foreach (var t in top) { - if (t.Count < 3) + if (paletteCounter[t] > 0 && t.Count < 3) { foreach (var p in result) { var newColors = p.Where(c => !t.Contains(c)); - if (p != t && (newColors.Count() + t.Count <= 3)) + if ((p != t) && (paletteCounter[p] > 0) && (newColors.Count() + t.Count <= 3)) { var count1 = paletteCounter[t]; var count2 = paletteCounter[p]; paletteCounter[t] = 0; paletteCounter[p] = 0; - foreach (var c in newColors) t.Add(c); - paletteCounter[t] = count1 + count2; + var newPalette = new Palette(Enumerable.Concat(t, p).Distinct()); + paletteCounter[newPalette] = count1 + count2; grouped = true; } } -- cgit v1.2.3