some encoding tweaks

main
cosmonaut 2021-11-30 19:35:00 -08:00
parent 3a5705eb17
commit b65ea2ca66
2 changed files with 95 additions and 78 deletions

View File

@ -11,7 +11,7 @@ namespace Palettizer
public List<byte[]> AlternateColorRows { get; } public List<byte[]> AlternateColorRows { get; }
public int Width { get => 256; } public int Width { get => 256; }
public int Height { get => AlternateColorRows.Count + 2; } public int Height { get => AlternateColorRows.Count + 1; }
public Palette() public Palette()
{ {
@ -36,7 +36,7 @@ namespace Palettizer
break; break;
} }
increment = ((increment > 0) ? (increment + 1) : (increment - 1)) * -1; increment = ((increment > 0) ? (increment + 1) : (increment - 1)) * -1; // up by 1, down by 2, up by 3, etc
} }
} }
@ -61,39 +61,51 @@ namespace Palettizer
AlternateColorRows.Add(byteArray); AlternateColorRows.Add(byteArray);
} }
public void ClearAlternateColorRows()
{
AlternateColorRows.Clear();
}
public byte[] CreateIndexedPaletteBitmap() public byte[] CreateIndexedPaletteBitmap()
{ {
var paletteBitmap = new byte[256 * (AlternateColorRows.Count + 2) * 4]; var paletteBitmap = new byte[256 * (AlternateColorRows.Count + 1) * 4];
for (var i = 0; i < 256; i += 1) for (var i = 0; i < 256; i += 1)
{ {
paletteBitmap[i * 4] = (byte)i; var color = new Color();
paletteBitmap[i * 4 + 1] = (byte)i; color.A = 255;
paletteBitmap[i * 4 + 2] = (byte)i;
paletteBitmap[i * 4 + 3] = 255;
}
for (var i = 0; i < 256; i += 1) if (GrayscaleToColorMap.ContainsKey((byte)i))
{
var color = new Color();
if (GrayscaleToColorMap.ContainsKey((byte)i))
{ {
color = GrayscaleToColorMap[(byte)i]; color = GrayscaleToColorMap[(byte)i];
} }
paletteBitmap[(256 + i) * 4] = color.R;
paletteBitmap[(256 + i) * 4 + 1] = color.G; paletteBitmap[i * 4] = color.R;
paletteBitmap[(256 + i) * 4 + 2] = color.B; paletteBitmap[i * 4 + 1] = color.G;
paletteBitmap[(256 + i) * 4 + 3] = color.A; paletteBitmap[i * 4 + 2] = color.B;
} paletteBitmap[i * 4 + 3] = color.A;
}
for (var i = 0; i < 256; i += 1) for (var i = 0; i < 256; i += 1)
{ {
for (var j = 0; j < AlternateColorRows.Count; j += 1) for (var j = 0; j < AlternateColorRows.Count; j += 1)
{ {
paletteBitmap[(i + (256 * (j + 2))) * 4] = AlternateColorRows[j][i * 4]; var alpha = AlternateColorRows[j][i * 4 + 3];
paletteBitmap[(i + (256 * (j + 2))) * 4 + 1] = AlternateColorRows[j][i * 4 + 1]; if (alpha == 0)
paletteBitmap[(i + (256 * (j + 2))) * 4 + 2] = AlternateColorRows[j][i * 4 + 2]; {
paletteBitmap[(i + (256 * (j + 2))) * 4 + 3] = AlternateColorRows[j][i * 4 + 3]; // grab from top row
paletteBitmap[(i + (256 * (j + 1))) * 4] = paletteBitmap[i * 4];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 1] = paletteBitmap[i * 4 + 1];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 2] = paletteBitmap[i * 4 + 2];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 3] = paletteBitmap[i * 4 + 3];
}
else
{
paletteBitmap[(i + (256 * (j + 1))) * 4] = AlternateColorRows[j][i * 4];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 1] = AlternateColorRows[j][i * 4 + 1];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 2] = AlternateColorRows[j][i * 4 + 2];
paletteBitmap[(i + (256 * (j + 1))) * 4 + 3] = alpha;
}
} }
} }

View File

@ -22,9 +22,9 @@ namespace Palettizer
"textureGroup", "textureGroup",
"The name of the texture group to palettize." "The name of the texture group to palettize."
), ),
new Argument<string>( new Argument<string[]>(
"paletteSpriteName", "paletteSpriteNames",
"The palette sprite to use in indexing." "A series of palette sprites to use in indexing."
) )
}; };
@ -32,11 +32,11 @@ namespace Palettizer
project project
}; };
project.Handler = CommandHandler.Create<FileInfo, string, string, IConsole>(HandleProject); project.Handler = CommandHandler.Create<FileInfo, string, string[], IConsole>(HandleProject);
return root.Invoke(args); return root.Invoke(args);
} }
static void HandleProject(FileInfo project, string textureGroup, string paletteSpriteName, IConsole console) static void HandleProject(FileInfo project, string textureGroup, string[] paletteSpriteNames, IConsole console)
{ {
var jsonReaderOptions = new JsonDocumentOptions(); var jsonReaderOptions = new JsonDocumentOptions();
jsonReaderOptions.AllowTrailingCommas = true; jsonReaderOptions.AllowTrailingCommas = true;
@ -103,65 +103,70 @@ namespace Palettizer
} }
} }
var paletteSpriteJSONDir = Path.Combine(projectDir.FullName, "sprites", paletteSpriteName); foreach (var paletteSpriteName in paletteSpriteNames)
var paletteSpriteJSONPath = Path.Combine(paletteSpriteJSONDir, paletteSpriteName + ".yy"); {
var paletteSpriteJSONDir = Path.Combine(projectDir.FullName, "sprites", paletteSpriteName);
var paletteSpriteJSONPath = Path.Combine(paletteSpriteJSONDir, paletteSpriteName + ".yy");
var paletteSpriteData = Importer.ImportSprite(new FileInfo(paletteSpriteJSONPath)); var paletteSpriteData = Importer.ImportSprite(new FileInfo(paletteSpriteJSONPath));
var paletteSpriteImagePath = Path.Combine(paletteSpriteJSONDir, paletteSpriteData.Frames[0].CompositeImage.FrameID.Name + ".png"); var paletteSpriteImagePath = Path.Combine(paletteSpriteJSONDir, paletteSpriteData.Frames[0].CompositeImage.FrameID.Name + ".png");
// Add alternate color palettes to palette // Add alternate color palettes to palette
// NOTE: our original palettes were column-indexed, we want to convert to row-index // NOTE: our original palettes were column-indexed, we want to convert to row-index
using (var stream = File.OpenRead(paletteSpriteImagePath)) using (var stream = File.OpenRead(paletteSpriteImagePath))
{
ImageResult paletteImage = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
var indexToGrayscaleMap = new Dictionary<int, byte>();
// build the color index
for (var i = 0; i < paletteImage.Height; i += 1)
{ {
var sourceColor = new Color ImageResult paletteImage = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
{
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)) var indexToGrayscaleMap = new Dictionary<int, byte>();
{
indexToGrayscaleMap.Add(i, palette.ColorToGrayscaleMap[sourceColor]); // 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[256];
for (var i = 0; i < paletteImage.Height; i += 1)
{
if (!indexToGrayscaleMap.ContainsKey(i)) { continue; }
var grayscale = indexToGrayscaleMap[i];
colorPalette[grayscale] = new Color
{
R = paletteImage.Data[(j + i * paletteImage.Width) * 4],
G = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 1],
B = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 2],
A = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 3]
};
}
palette.AddAlternateColorRow(colorPalette);
} }
} }
for (var j = 1; j < paletteImage.Width; j += 1) // Write final palette sprite to PNG
var paletteOutputPath = Path.Combine(outputDir.FullName, textureGroup + "_" + paletteSpriteName + "_Palette.png");
using (var stream = File.OpenWrite(paletteOutputPath))
{ {
var colorPalette = new Color[256]; writer.WritePng(palette.CreateIndexedPaletteBitmap(), palette.Width, palette.Height, StbImageWriteSharp.ColorComponents.RedGreenBlueAlpha, stream);
for (var i = 0; i < paletteImage.Height; i += 1)
{
if (!indexToGrayscaleMap.ContainsKey(i)) { continue; }
var grayscale = indexToGrayscaleMap[i];
colorPalette[grayscale] = new Color
{
R = paletteImage.Data[(j + i * paletteImage.Width) * 4],
G = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 1],
B = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 2],
A = paletteImage.Data[(j + i * paletteImage.Width) * 4 + 3]
};
}
palette.AddAlternateColorRow(colorPalette);
} }
}
// Write final palette sprite to PNG palette.ClearAlternateColorRows();
var paletteOutputPath = Path.Combine(outputDir.FullName, textureGroup + "_Palette.png"); }
using (var stream = File.OpenWrite(paletteOutputPath))
{
writer.WritePng(palette.CreateIndexedPaletteBitmap(), palette.Width, palette.Height, StbImageWriteSharp.ColorComponents.RedGreenBlueAlpha, stream);
}
} }
static byte[] AddSpriteToPalette(Palette palette, ImageResult image, IConsole console) static byte[] AddSpriteToPalette(Palette palette, ImageResult image, IConsole console)