diff options
author | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2022-10-23 20:45:53 +0300 |
---|---|---|
committer | Alexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com> | 2022-10-23 20:45:53 +0300 |
commit | 7dd48d7271047e2d18cc92d2fb0d3d4e9f62cb53 (patch) | |
tree | 77e1def438bcd11482517f73203c0f695035213c /NesTiler | |
parent | 2059d5e112e8a9bb0064c132677bd723154af424 (diff) |
Optimization.
Diffstat (limited to 'NesTiler')
-rw-r--r-- | NesTiler/ColorExtensions.cs | 6 | ||||
-rw-r--r-- | NesTiler/FastBitmap.cs | 61 | ||||
-rw-r--r-- | NesTiler/Palette.cs | 4 | ||||
-rw-r--r-- | NesTiler/Program.cs | 36 |
4 files changed, 82 insertions, 25 deletions
diff --git a/NesTiler/ColorExtensions.cs b/NesTiler/ColorExtensions.cs index d3d70be..39a48df 100644 --- a/NesTiler/ColorExtensions.cs +++ b/NesTiler/ColorExtensions.cs @@ -42,8 +42,10 @@ namespace com.clusterrr.Famicom.NesTiler public static Color GetPixelColor(this SKBitmap image, int x, int y)
{
- var skColor = image.GetPixel(x, y);
- var color = Color.FromArgb(skColor.Red, skColor.Green, skColor.Blue);
+ //var skColor = image.GetPixel(x, y);
+ var b = image.Bytes;
+ var offset = image.RowBytes * y + x * image.BytesPerPixel;
+ var color = Color.FromArgb(b[offset + 3], b[offset + 2], b[offset + 1], b[offset + 0]);
return color;
}
diff --git a/NesTiler/FastBitmap.cs b/NesTiler/FastBitmap.cs new file mode 100644 index 0000000..2ee9081 --- /dev/null +++ b/NesTiler/FastBitmap.cs @@ -0,0 +1,61 @@ +using SkiaSharp; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace com.clusterrr.Famicom.NesTiler +{ + public class FastBitmap + { + public int Width { get; } + public int Height { get; } + + private readonly Color[] colors; + private static Dictionary<string, SKBitmap> imagesCache = new Dictionary<string, SKBitmap>(); + + private FastBitmap(SKBitmap skBitmap, int verticalOffset = 0, int height = 0) + { + Width = skBitmap.Width; + Height = height <= 0 ? skBitmap.Height - verticalOffset : height; + var pixels = skBitmap.Pixels; + colors = skBitmap.Pixels.Skip(verticalOffset * Width).Take(Width * Height).Select(p => Color.FromArgb(p.Alpha, p.Red, p.Green, p.Blue)).ToArray(); + } + + public static FastBitmap Decode(string filename, int verticalOffset = 0, int height = 0) + { + using var image = SKBitmap.Decode(filename); + if (image == null) return null; + imagesCache[filename] = image; + return new FastBitmap(image, verticalOffset, height); + } + + public Color GetPixelColor(int x, int y) + { + return colors[y * Width + x]; + } + + public void SetPixelColor(int x, int y, Color color) + { + colors[y * Width + x] = color; + } + + public byte[] Encode(SKEncodedImageFormat format, int v) + { + using var skImage = new SKBitmap(Width, Height); + for (int y = 0; y < Height; y++) + { + for (int x = 0; x < Width; x++) + { + var color = colors[y * Width + x]; + var skColor = new SKColor(color.R, color.G, color.B); + skImage.SetPixel(x, y, skColor); + } + } + return skImage.Encode(format, v).ToArray(); + } + } +} diff --git a/NesTiler/Palette.cs b/NesTiler/Palette.cs index 6835dd2..0dc31ff 100644 --- a/NesTiler/Palette.cs +++ b/NesTiler/Palette.cs @@ -33,7 +33,7 @@ namespace com.clusterrr.Famicom.NesTiler // Empty palette
}
- public Palette(SKBitmap image, int leftX, int topY, int width, int height, Color bgColor)
+ public Palette(FastBitmap image, int leftX, int topY, int width, int height, Color bgColor)
{
Dictionary<Color, int> colorCounter = new Dictionary<Color, int>();
for (int y = topY; y < topY + height; y++)
@@ -69,7 +69,7 @@ namespace com.clusterrr.Famicom.NesTiler if (colorsList.Count > i) this[i + 1] = colorsList[i];
}
- public double GetTileDelta(SKBitmap image, int leftX, int topY, int width, int height, Color bgColor)
+ public double GetTileDelta(FastBitmap image, int leftX, int topY, int width, int height, Color bgColor)
{
double delta = 0;
for (int y = topY; y < topY + height; y++)
diff --git a/NesTiler/Program.cs b/NesTiler/Program.cs index 2695502..c8b34c3 100644 --- a/NesTiler/Program.cs +++ b/NesTiler/Program.cs @@ -95,7 +95,7 @@ namespace com.clusterrr.Famicom.NesTiler bool quiet = false;
// Data
- var images = new Dictionary<int, SKBitmap>();
+ var images = new Dictionary<int, FastBitmap>();
var paletteIndexes = new Dictionary<int, byte[,]>();
var patternTables = new Dictionary<int, Dictionary<int, Tile>>();
var nameTables = new Dictionary<int, List<int>>();
@@ -278,33 +278,27 @@ namespace com.clusterrr.Famicom.NesTiler }
// Loading images
- foreach (var image in imageFiles)
+ foreach (var imageFile in imageFiles)
{
- console($"Loading file #{image.Key} - {Path.GetFileName(image.Value)}...");
+ console($"Loading file #{imageFile.Key} - {Path.GetFileName(imageFile.Value)}...");
var offsetRegex = new Regex(@"^(?<filename>.*?)(:(?<offset>[0-9]+)(:(?<height>[0-9]+))?)?$");
- var match = offsetRegex.Match(image.Value);
+ var match = offsetRegex.Match(imageFile.Value);
var filename = match.Groups["filename"].Value;
- if (!File.Exists(filename)) throw new FileNotFoundException($"File {filename} not found");
- images[image.Key] = SKBitmap.Decode(filename);
- if (images[image.Key] == null) throw new InvalidDataException($"Can't load {filename}");
var offsetS = match.Groups["offset"].Value;
var heightS = match.Groups["height"].Value;
// Crop it if need
+ int offset = 0;
+ int height = 0;
if (!string.IsNullOrEmpty(offsetS))
{
- int offset = int.Parse(offsetS);
- int height = images[image.Key].Height - offset;
- if (!string.IsNullOrEmpty(heightS))
- height = int.Parse(heightS);
- console($"Cropping it to {offset}:{height}...");
- var cropped = new SKBitmap(images[image.Key].Width, height);
- using (SKCanvas bitmapCanvas = new SKCanvas(cropped))
- {
- bitmapCanvas.DrawBitmap(images[image.Key], 0, -offset);
- }
- images[image.Key].Dispose();
- images[image.Key] = cropped;
+ offset = int.Parse(offsetS);
+ if (!string.IsNullOrEmpty(heightS)) height = int.Parse(heightS);
}
+ if (!File.Exists(filename)) throw new FileNotFoundException($"File {filename} not found");
+ var image = FastBitmap.Decode(filename, offset, height);
+ if (image == null) throw new InvalidDataException($"Can't load {filename}");
+ images[imageFile.Key] = image;
+
//if ((imagesOriginal[image.Key].Width % tilePalWidth != 0) || (imagesOriginal[image.Key].Height % tilePalHeight != 0))
// throw new InvalidDataException("Invalid image size");
// TODO: more image size checks
@@ -496,7 +490,7 @@ namespace com.clusterrr.Famicom.NesTiler // Save preview if required
if (outPreview.ContainsKey(imageNum))
{
- File.WriteAllBytes(outPreview[imageNum], image.Encode(SKEncodedImageFormat.Png, 0).ToArray());
+ File.WriteAllBytes(outPreview[imageNum], image.Encode(SKEncodedImageFormat.Png, 0));
console($"Preview #{imageNum} saved to {outPreview[imageNum]}");
}
}
@@ -684,7 +678,7 @@ namespace com.clusterrr.Famicom.NesTiler }
}
- static Palette[] CalculatePalettes(Dictionary<int, SKBitmap> images, bool[] paletteEnabled, Palette[] fixedPalettes, Dictionary<int, int> attributeTableOffsets, int tilePalWidth, int tilePalHeight, Color bgColor)
+ static Palette[] CalculatePalettes(Dictionary<int, FastBitmap> images, bool[] paletteEnabled, Palette[] fixedPalettes, Dictionary<int, int> attributeTableOffsets, int tilePalWidth, int tilePalHeight, Color bgColor)
{
var required = Enumerable.Range(0, 4).Select(i => paletteEnabled[i] && fixedPalettes[i] == null);
// Creating and counting the palettes
|