From 3fc504a4f68e7e6713229ef737521b729e6670a5 Mon Sep 17 00:00:00 2001 From: Lani Aung Date: Mon, 4 Oct 2021 19:50:22 -0600 Subject: [PATCH] Using system agnostic image processing --- Models/CelModel.cs | 14 ++--- Models/PaletteModel.cs | 20 +------ Models/PlaysetModel.cs | 9 --- Services/ConfigurationReaderService.cs | 6 +- Services/FileParserService.cs | 83 ++++++++++++++++++++++---- fxl.codes.kisekae.csproj | 1 + 6 files changed, 83 insertions(+), 50 deletions(-) diff --git a/Models/CelModel.cs b/Models/CelModel.cs index be2a314..77644f1 100644 --- a/Models/CelModel.cs +++ b/Models/CelModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Text.RegularExpressions; namespace fxl.codes.kisekae.Models @@ -6,6 +7,7 @@ namespace fxl.codes.kisekae.Models public class CelModel { public const string Regex = "#([0-9]*)[\\.]?([0-9]*?)\\s([a-zA-Z\\-0-9]*\\.[cCeElL]+)\\s[\\*]?([0-9]*)?\\s?:([0-9\\s]*);(.*)"; + public Dictionary ImageByPalette = new(); public CelModel(string line) { @@ -15,7 +17,7 @@ namespace fxl.codes.kisekae.Models foreach (var group in matcher.GetGroupNames()) { if (group == "0") continue; - + match.Groups.TryGetValue(group, out var value); if (string.IsNullOrEmpty(value?.Value)) continue; @@ -34,10 +36,7 @@ namespace fxl.codes.kisekae.Models PaletteId = int.Parse(value.Value); break; case "5": - foreach (var id in value.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries)) - { - Sets[int.Parse(id)] = true; - } + foreach (var id in value.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries)) Sets[int.Parse(id)] = true; break; case "6": Comment = value.Value; @@ -52,9 +51,6 @@ namespace fxl.codes.kisekae.Models public int PaletteId { get; } public bool[] Sets { get; } = new bool[10]; public string Comment { get; } - - public int CurrentPaletteId { get; set; } - public Point[] InitialPositions { get; set; } = new Point[10]; - public Point[] CurrentPositions { get; set; } = new Point[10]; + public Point[] InitialPositions { get; } = new Point[10]; } } \ No newline at end of file diff --git a/Models/PaletteModel.cs b/Models/PaletteModel.cs index d8acada..20576cd 100644 --- a/Models/PaletteModel.cs +++ b/Models/PaletteModel.cs @@ -1,3 +1,4 @@ +using System.Drawing; using System.Text.RegularExpressions; namespace fxl.codes.kisekae.Models @@ -32,23 +33,6 @@ namespace fxl.codes.kisekae.Models public string FileName { get; } public string Comment { get; } - public Color[] Colors { get; set; } - } - - public class Color - { - public Color(int red, int green, int blue, int group, int depth) - { - var multiplier = depth == 12 ? 16 : 1; - Red = red * multiplier; - Green = green * multiplier; - Blue = blue * multiplier; - Group = group; - } - - public int Red { get; } - public int Green { get; } - public int Blue { get; } - public int Group { get; } + internal Color[] Colors { get; set; } } } \ No newline at end of file diff --git a/Models/PlaysetModel.cs b/Models/PlaysetModel.cs index 917195e..f5cdb0a 100644 --- a/Models/PlaysetModel.cs +++ b/Models/PlaysetModel.cs @@ -11,14 +11,5 @@ namespace fxl.codes.kisekae.Models public List Palettes { get; } = new(); public List Cels { get; } = new(); public int[] CurrentPalettes = new int[10]; - - public void Reset() - { - foreach (var cel in Cels) - { - cel.CurrentPositions = cel.InitialPositions; - cel.CurrentPaletteId = cel.PaletteId; - } - } } } \ No newline at end of file diff --git a/Services/ConfigurationReaderService.cs b/Services/ConfigurationReaderService.cs index 8da6ce4..4ef599d 100644 --- a/Services/ConfigurationReaderService.cs +++ b/Services/ConfigurationReaderService.cs @@ -62,7 +62,6 @@ namespace fxl.codes.kisekae.Services } SetInitialPositions(model, initialPositions.ToString()); - model.Reset(); if (string.IsNullOrEmpty(directory)) return model; @@ -71,6 +70,11 @@ namespace fxl.codes.kisekae.Services _fileParser.ParsePalette(directory, palette); } + foreach (var cel in model.Cels) + { + _fileParser.ParseCel(directory, cel, model.Palettes); + } + return model; } diff --git a/Services/FileParserService.cs b/Services/FileParserService.cs index 04e23db..34370bf 100644 --- a/Services/FileParserService.cs +++ b/Services/FileParserService.cs @@ -1,16 +1,22 @@ using System; using System.Collections; +using System.Collections.Generic; using System.IO; using System.IO.IsolatedStorage; using System.Linq; using System.Text; using fxl.codes.kisekae.Models; using Microsoft.Extensions.Logging; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using Color = System.Drawing.Color; namespace fxl.codes.kisekae.Services { public class FileParserService { + private static readonly byte[] KissHeader = Encoding.ASCII.GetBytes("KiSS"); + private readonly ILogger _logger; private readonly IsolatedStorageFile _storage; @@ -23,14 +29,9 @@ namespace fxl.codes.kisekae.Services public void ParsePalette(string directory, PaletteModel palette) { _logger.LogTrace($"Reading palette {palette.FileName} from {directory}"); - using var stream = _storage.OpenFile(Path.Combine(directory, palette.FileName), FileMode.Open); - if (!stream.CanRead) throw new InvalidDataException(); + var buffer = ReadToBuffer(directory, palette.FileName); - var buffer = new byte[stream.Length]; - stream.Read(buffer, 0, buffer.Length); - - var header = Encoding.ASCII.GetBytes("KiSS"); - if (buffer[..header.Length].SequenceEqual(header)) + if (buffer[..KissHeader.Length].SequenceEqual(KissHeader)) { // Verify palette mark? if (buffer[4] != 16) throw new InvalidDataException("File provided is not a valid palette file"); @@ -46,11 +47,49 @@ namespace fxl.codes.kisekae.Services } } + public void ParseCel(string directory, CelModel cel, IEnumerable palettes) + { + _logger.LogTrace($"Reading cel {cel.FileName} from {directory}"); + var buffer = ReadToBuffer(directory, cel.FileName); + + if (buffer[..KissHeader.Length].SequenceEqual(KissHeader)) + { + // Verify cel mark? + if (buffer[4] != 16) throw new InvalidDataException("File provided is not a valid palette file"); + var pixelBits = Convert.ToInt32(buffer[5]); + var width = BitConverter.ToInt16(buffer, 8); + var height = BitConverter.ToInt16(buffer, 10); + var xOffset = BitConverter.ToInt16(buffer, 12); + var yOffset = BitConverter.ToInt16(buffer, 14); + + GetCelImages(new BitArray(buffer[32..]), palettes, width, height, pixelBits, xOffset, yOffset); + } + else + { + var width = BitConverter.ToInt16(buffer, 0); + var height = BitConverter.ToInt16(buffer, 2); + + GetCelImages(new BitArray(buffer[4..]), palettes, width, height); + } + } + + private byte[] ReadToBuffer(string directory, string filename) + { + using var stream = _storage.OpenFile(Path.Combine(directory, filename), FileMode.Open); + if (!stream.CanRead) throw new InvalidDataException(); + + var buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + + return buffer; + } + private Color[] GetColors(BitArray bitArray, int depth = 12, int colorsPerGroup = 16, int groups = 10) { - _logger.LogTrace($"Converting bit array to colors"); + _logger.LogTrace("Converting bit array to colors"); var colorCounter = 0; var colors = new Color[colorsPerGroup * groups]; + var multiplier = depth == 12 ? 16 : 1; var data = new bool[bitArray.Length]; bitArray.CopyTo(data, 0); @@ -59,17 +98,35 @@ namespace fxl.codes.kisekae.Services { var greenStart = index + length; var blueStart = index + length * 2; - - var red = GetValue(data[index..greenStart]); - var green = GetValue(data[greenStart..blueStart]); - var blue = GetValue(data[blueStart..(index + depth)]); - colors[colorCounter] = new Color(red, green, blue, colorCounter / colorsPerGroup, depth); + + var red = GetValue(data[index..greenStart]) * multiplier; + var green = GetValue(data[greenStart..blueStart]) * multiplier; + var blue = GetValue(data[blueStart..(index + depth)]) * multiplier; + colors[colorCounter] = Color.FromArgb(255, red, green, blue); colorCounter++; } return colors; } + private void GetCelImages(BitArray bitArray, IEnumerable palettes, int width, int height, int pixelBits = 4, int xOffset = 0, int yOffset = 0) + { + _logger.LogTrace("Converting bit array to base64 encoded gifs per palette"); + var data = new bool[bitArray.Length]; + bitArray.CopyTo(data, 0); + + foreach (var palette in palettes) + { + using var bitmap = new Image(width, height); + var pixelCounter = 0; + + for (var row = 0; row < height; row++) + { + var span = bitmap.GetPixelRowSpan(row); + } + } + } + private static int GetValue(bool[] data) { var bits = new BitArray(data); diff --git a/fxl.codes.kisekae.csproj b/fxl.codes.kisekae.csproj index c28f949..42dfe25 100644 --- a/fxl.codes.kisekae.csproj +++ b/fxl.codes.kisekae.csproj @@ -11,5 +11,6 @@ +