various palette gen fixes

main
cosmonaut 2021-11-30 15:21:47 -08:00
parent 1713c86afe
commit 3a5705eb17
2 changed files with 102 additions and 63 deletions

View File

@ -4,81 +4,98 @@ namespace Palettizer
{ {
public class Palette public class Palette
{ {
public Dictionary<Color, byte> ColorToGrayscaleMap { get; } public Dictionary<byte, Color> GrayscaleToColorMap { get; }
public byte GrayscaleIndex { get; set; } public Color[] GrayscaleToColor { get; }
public List<byte[]> AlternateColorRows { get; } public Dictionary<Color, byte> ColorToGrayscaleMap { get; }
public int GrayscaleCount { get; set; }
public List<byte[]> AlternateColorRows { get; }
public int Width { get => ColorToGrayscaleMap.Count; } public int Width { get => 256; }
public int Height { get => AlternateColorRows.Count + 1; } public int Height { get => AlternateColorRows.Count + 2; }
public Palette() public Palette()
{ {
GrayscaleToColorMap = new Dictionary<byte, Color>();
ColorToGrayscaleMap = new Dictionary<Color, byte>(); ColorToGrayscaleMap = new Dictionary<Color, byte>();
GrayscaleIndex = 0; GrayscaleCount = 0;
AlternateColorRows = new List<byte[]>(); AlternateColorRows = new List<byte[]>();
} }
public void AddColor(Color color, byte grayscaleIndex) public void AddColor(Color color)
{ {
ColorToGrayscaleMap.Add(color, grayscaleIndex); var average = (color.R + color.G + color.B) / 3;
} if (GrayscaleToColorMap.ContainsKey((byte)average))
{
var increment = 1;
for (var i = 0; i < 256 - GrayscaleCount; i += 1)
{
average += increment;
if (!GrayscaleToColorMap.ContainsKey((byte)average))
{
break;
}
increment = ((increment > 0) ? (increment + 1) : (increment - 1)) * -1;
}
}
GrayscaleToColorMap.Add((byte)average, color);
ColorToGrayscaleMap.Add(color, (byte)average);
GrayscaleCount += 1;
}
public void AddAlternateColorRow(Color[] colors) public void AddAlternateColorRow(Color[] colors)
{ {
var byteArray = new byte[ColorToGrayscaleMap.Count * 4]; var byteArray = new byte[256 * 4];
foreach (var color in colors) for (var i = 0; i < 256; i += 1)
{ {
if (ColorToGrayscaleMap.ContainsKey(color)) byteArray[i * 4] = colors[i].R;
{ byteArray[i * 4 + 1] = colors[i].G;
var grayscaleIndex = ColorToGrayscaleMap[color]; byteArray[i * 4 + 2] = colors[i].B;
byteArray[i * 4 + 3] = colors[i].A;
}
byteArray[grayscaleIndex] = color.R; AlternateColorRows.Add(byteArray);
byteArray[grayscaleIndex + 1] = color.G;
byteArray[grayscaleIndex + 2] = color.B;
byteArray[grayscaleIndex + 3] = color.A;
}
else
{
System.Console.WriteLine($"Color {color.ToString()} doesn't exist in the grayscale palette!! Bailing!!!");
return;
}
}
AlternateColorRows.Add(byteArray);
} }
public byte[] CreateIndexedPaletteBitmap() public byte[] CreateIndexedPaletteBitmap()
{ {
var paletteBitmap = new byte[ColorToGrayscaleMap.Count * 4 * (AlternateColorRows.Count + 1)]; var paletteBitmap = new byte[256 * (AlternateColorRows.Count + 2) * 4];
var index = 0; for (var i = 0; i < 256; i += 1)
foreach (KeyValuePair<Color, byte> kv in ColorToGrayscaleMap)
{ {
var color = kv.Key; paletteBitmap[i * 4] = (byte)i;
var grayscale = kv.Value; paletteBitmap[i * 4 + 1] = (byte)i;
paletteBitmap[i * 4 + 2] = (byte)i;
paletteBitmap[i * 4 + 3] = 255;
}
paletteBitmap[index] = grayscale; for (var i = 0; i < 256; i += 1)
paletteBitmap[index + 1] = grayscale; {
paletteBitmap[index + 2] = grayscale; var color = new Color();
paletteBitmap[index + 3] = 255; if (GrayscaleToColorMap.ContainsKey((byte)i))
var alternateIndex = 1;
foreach (var alternateColorRow in AlternateColorRows)
{ {
for (var j = 0; j < ColorToGrayscaleMap.Count * 4; j += 4) color = GrayscaleToColorMap[(byte)i];
{ }
paletteBitmap[index + (ColorToGrayscaleMap.Count * alternateIndex)] = alternateColorRow[j]; paletteBitmap[(256 + i) * 4] = color.R;
paletteBitmap[index + 1 + (ColorToGrayscaleMap.Count * alternateIndex)] = alternateColorRow[j + 1]; paletteBitmap[(256 + i) * 4 + 1] = color.G;
paletteBitmap[index + 2 + (ColorToGrayscaleMap.Count * alternateIndex)] = alternateColorRow[j + 2]; paletteBitmap[(256 + i) * 4 + 2] = color.B;
paletteBitmap[index + 3 + (ColorToGrayscaleMap.Count * alternateIndex)] = alternateColorRow[j + 3]; paletteBitmap[(256 + i) * 4 + 3] = color.A;
} }
alternateIndex += 1; for (var i = 0; i < 256; i += 1)
} {
for (var j = 0; j < AlternateColorRows.Count; j += 1)
index += 4; {
} paletteBitmap[(i + (256 * (j + 2))) * 4] = AlternateColorRows[j][i * 4];
paletteBitmap[(i + (256 * (j + 2))) * 4 + 1] = AlternateColorRows[j][i * 4 + 1];
paletteBitmap[(i + (256 * (j + 2))) * 4 + 2] = AlternateColorRows[j][i * 4 + 2];
paletteBitmap[(i + (256 * (j + 2))) * 4 + 3] = AlternateColorRows[j][i * 4 + 3];
}
}
return paletteBitmap; return paletteBitmap;
} }

View File

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.CommandLine; using System.CommandLine;
using System.CommandLine.Invocation; using System.CommandLine.Invocation;
using System.IO; using System.IO;
@ -114,24 +115,46 @@ namespace Palettizer
{ {
ImageResult paletteImage = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha); ImageResult paletteImage = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
for (var j = 0; j < paletteImage.Width; j += 1) var indexToGrayscaleMap = new Dictionary<int, byte>();
// build the color index
for (var i = 0; i < paletteImage.Height; i += 1)
{
var sourceColor = new Color
{
R = paletteImage.Data[i * paletteImage.Width * 4],
G = paletteImage.Data[i * paletteImage.Width * 4 + 1],
B = paletteImage.Data[i * paletteImage.Width * 4 + 2],
A = paletteImage.Data[i * paletteImage.Width * 4 + 3]
};
if (palette.ColorToGrayscaleMap.ContainsKey(sourceColor))
{
indexToGrayscaleMap.Add(i, palette.ColorToGrayscaleMap[sourceColor]);
}
}
for (var j = 1; j < paletteImage.Width; j += 1)
{ {
var colorPalette = new Color[paletteImage.Height]; var colorPalette = new Color[256];
for (var i = 0; i < paletteImage.Height; i += 1) for (var i = 0; i < paletteImage.Height; i += 1)
{ {
colorPalette[i] = new Color if (!indexToGrayscaleMap.ContainsKey(i)) { continue; }
var grayscale = indexToGrayscaleMap[i];
colorPalette[grayscale] = new Color
{ {
R = paletteImage.Data[j * 4 + i * paletteImage.Width * 4], R = paletteImage.Data[(j + i * paletteImage.Width) * 4],
G = paletteImage.Data[(j * 4 + i * paletteImage.Width * 4) + 1], G = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 1],
B = paletteImage.Data[(j * 4 + i * paletteImage.Width * 4) + 2], B = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 2],
A = paletteImage.Data[(j * 4 + i * paletteImage.Width * 4) + 3] A = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 3]
}; };
} }
palette.AddAlternateColorRow(colorPalette); palette.AddAlternateColorRow(colorPalette);
} }
} }
// Write final palette sprite to PNG // Write final palette sprite to PNG
var paletteOutputPath = Path.Combine(outputDir.FullName, textureGroup + "_Palette.png"); var paletteOutputPath = Path.Combine(outputDir.FullName, textureGroup + "_Palette.png");
@ -171,15 +194,14 @@ namespace Palettizer
} }
else else
{ {
if (palette.GrayscaleIndex == 255) if (palette.GrayscaleCount == 256)
{ {
console.Out.Write("Too many colors! Bailing!\n"); console.Out.Write("Too many colors! Bailing!\n");
return grayscaleImage; return grayscaleImage;
} }
else else
{ {
palette.ColorToGrayscaleMap.Add(color, palette.GrayscaleIndex); palette.AddColor(color);
palette.GrayscaleIndex += 1;
} }
} }
} }