mirror of
https://github.com/lscharen/iigs-sprite-compiler.git
synced 2024-12-21 16:30:15 +00:00
Add more tests and allow images to be loaded from the comomand line
This commit is contained in:
parent
4861c84279
commit
2bf19084f7
@ -53,7 +53,7 @@ namespace SpriteCompiler.Problem
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return (offset == 0) ? "TSC" : ("ADC #" + offset.ToString() + " / TSC");
|
||||
return (offset == 0) ? "TCS" : ("ADC #" + offset.ToString() + " / TCS");
|
||||
}
|
||||
|
||||
public override string Emit()
|
||||
|
@ -7,6 +7,24 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static void Dump(this int[,] array)
|
||||
{
|
||||
var rows = array.GetLength(1);
|
||||
var cols = array.GetLength(0);
|
||||
|
||||
for (int r = 0; r < rows; r++)
|
||||
{
|
||||
for (int c = 0; c < cols; c++)
|
||||
{
|
||||
Console.Write(array[c, r].ToString("X1"));
|
||||
}
|
||||
Console.Write(Environment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public class ApplicationArguments
|
||||
{
|
||||
public List<string> Data { get; set; }
|
||||
@ -27,84 +45,119 @@
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
IEnumerable<SpriteByte> data = null;
|
||||
var data = new List<byte>();
|
||||
var mask = new List<byte>();
|
||||
var filename = (string)null;
|
||||
Color? maskColor = null;
|
||||
var sprite = new List<SpriteByte>();
|
||||
|
||||
try
|
||||
var p = new FluentCommandLineParser();
|
||||
|
||||
p.Setup<List<string>>('d', "data")
|
||||
.Callback(_ => data = _.Select(s => Convert.ToByte(s, 16)).ToList());
|
||||
|
||||
p.Setup<List<string>>('m', "mask")
|
||||
.Callback(_ => data = _.Select(s => Convert.ToByte(s, 16)).ToList());
|
||||
|
||||
p.Setup<string>('i', "image")
|
||||
.Callback(_ => filename = _);
|
||||
|
||||
p.Setup<string>("bg-color")
|
||||
.Callback(_ => maskColor = Color.FromArgb(0xFF, Color.FromArgb(Convert.ToInt32(_, 16))));
|
||||
|
||||
p.Parse(args);
|
||||
|
||||
Console.WriteLine("Manual data has " + data.Count + " bytes");
|
||||
Console.WriteLine("Manual mask has " + mask.Count + " bytes");
|
||||
Console.WriteLine("Input filename is " + filename);
|
||||
Console.WriteLine("Image mask color is " + (maskColor.HasValue ? maskColor.ToString() : "(none)"));
|
||||
|
||||
if (!String.IsNullOrEmpty(filename))
|
||||
{
|
||||
data = args.Select((s, i) => new SpriteByte(Convert.ToByte(s, 16), (ushort)i));
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
// If there is only one or two arguments, them marybe the user passed in a file
|
||||
if (args.Length <= 2)
|
||||
var palette = new Dictionary<Color, int>();
|
||||
int nextIndex = 1;
|
||||
|
||||
// Convert the image / mask to a paletted image
|
||||
var bitmap = new Bitmap(filename);
|
||||
int[,] data_buffer = new int[bitmap.Width, bitmap.Height];
|
||||
int[,] mask_buffer = new int[bitmap.Width, bitmap.Height];
|
||||
|
||||
Console.WriteLine(String.Format(" Image is {0} x {1}", bitmap.Width, bitmap.Height));
|
||||
|
||||
if (maskColor.HasValue)
|
||||
{
|
||||
var palette = new Dictionary<Color, int>();
|
||||
int nextIndex = 1;
|
||||
palette[maskColor.Value] = 0;
|
||||
}
|
||||
|
||||
// Convert the image / mask to a paletted image
|
||||
var bitmap = new Bitmap(args[0]);
|
||||
int[,] buffer = new int[bitmap.Width, bitmap.Height];
|
||||
|
||||
for (int r = 0; r < bitmap.Height; r++)
|
||||
for (int r = 0; r < bitmap.Height; r++)
|
||||
{
|
||||
for (int w = 0; w < bitmap.Width; w++)
|
||||
{
|
||||
for (int w = 0; w < bitmap.Width; w++)
|
||||
{
|
||||
var rgb = bitmap.GetPixel(w, r);
|
||||
var rgb = bitmap.GetPixel(w, r);
|
||||
|
||||
if (!palette.ContainsKey(rgb))
|
||||
if (!palette.ContainsKey(rgb))
|
||||
{
|
||||
if (palette.Count >= 15)
|
||||
{
|
||||
if (palette.Count >= 15)
|
||||
{
|
||||
throw new Exception("Image cannot have more than 15 unique colors");
|
||||
}
|
||||
palette[rgb] = nextIndex++;
|
||||
throw new Exception("Image cannot have more than 15 unique colors");
|
||||
}
|
||||
|
||||
buffer[w, r] = palette[rgb];
|
||||
palette[rgb] = nextIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Pair up pixles to build bytes
|
||||
var sprite = new List<SpriteByte>();
|
||||
data_buffer[w, r] = palette[rgb];
|
||||
|
||||
for (int r = 0; r < bitmap.Height; r++)
|
||||
{
|
||||
for (int w = 0; w < bitmap.Width; w += 2)
|
||||
if (maskColor.HasValue)
|
||||
{
|
||||
sprite.Add(new SpriteByte((byte)((buffer[w, r] << 4) + buffer[w + 1, r]), (ushort)(r * 160 + (w / 2))));
|
||||
if (rgb.Equals(maskColor.Value))
|
||||
{
|
||||
data_buffer[w, r] = 0x0;
|
||||
mask_buffer[w, r] = 0xF;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_buffer[w, r] = palette[rgb];
|
||||
mask_buffer[w, r] = 0x0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data_buffer[w, r] = palette[rgb];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = sprite;
|
||||
data_buffer.Dump();
|
||||
Console.WriteLine();
|
||||
mask_buffer.Dump();
|
||||
|
||||
// Pair up pixels to build bytes
|
||||
for (int r = 0; r < bitmap.Height; r++)
|
||||
{
|
||||
for (int w = 0; w < bitmap.Width; w += 2)
|
||||
{
|
||||
var mask_byte = (byte)((mask_buffer[w, r] << 4) + mask_buffer[w + 1, r]);
|
||||
var data_byte = (byte)((data_buffer[w, r] << 4) + data_buffer[w + 1, r]);
|
||||
var offset = (ushort)(r * 160 + (w / 2));
|
||||
|
||||
// Skip fully transparent bytes
|
||||
if (mask_byte == 0xFF)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(String.Format("Adding ({0:X2}, {1:X2}, {2})", data_byte, mask_byte, offset));
|
||||
|
||||
sprite.Add(new SpriteByte(data_byte, mask_byte, offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
return;
|
||||
|
||||
var p = new FluentCommandLineParser<ApplicationArguments>();
|
||||
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
|
||||
var search = SpriteGeneratorSearchProblem.Create();
|
||||
|
||||
// specify which property the value will be assigned too.
|
||||
p.Setup<List<string>>(arg => arg.Data)
|
||||
.As('d', "data") // define the short and long option name
|
||||
.Required() // using the standard fluent Api to declare this Option as required.
|
||||
.Callback(d => d.Select(s => Convert.ToByte(s, 16)).ToArray());
|
||||
var solution = search.Search(problem, new SpriteGeneratorState(sprite));
|
||||
|
||||
p.Setup<List<string>>(arg => arg.Mask)
|
||||
.As('m', "mask");
|
||||
|
||||
var result = p.Parse(args);
|
||||
|
||||
if (!result.HasErrors)
|
||||
{
|
||||
*/
|
||||
|
||||
var problem = SpriteGeneratorSearchProblem.CreateSearchProblem();
|
||||
var search = SpriteGeneratorSearchProblem.Create();
|
||||
|
||||
var solution = search.Search(problem, new SpriteGeneratorState(data));
|
||||
|
||||
WriteOutSolution(solution);
|
||||
//}
|
||||
WriteOutSolution(solution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
SpriteCompiler/Samples/Mario_000.png
Normal file
BIN
SpriteCompiler/Samples/Mario_000.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 361 B |
BIN
SpriteCompiler/Samples/SpriteX1_000.png
Normal file
BIN
SpriteCompiler/Samples/SpriteX1_000.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 626 B |
@ -94,6 +94,8 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Content Include="Samples\Mario_000.png" />
|
||||
<Content Include="Samples\SpriteX1_000.png" />
|
||||
<Content Include="Samples\SpriteX2_000.gif" />
|
||||
<Content Include="Samples\SpriteX2_001.gif" />
|
||||
</ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user