From 6e1280a62a787b3996f50ed4704a01ce9c434909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:53:09 +0300 Subject: [PATCH 1/2] Implement RLE decoding for images --- .editorconfig | 1 + OpenLocoToolGui/MainForm.cs | 93 +++++++++++++++++++------------------ 2 files changed, 49 insertions(+), 45 deletions(-) diff --git a/.editorconfig b/.editorconfig index be6ba837..45c91558 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,5 @@ [*.{cs,vb}] +indent_style = tab # IDE0040: Add accessibility modifiers dotnet_style_require_accessibility_modifiers = always diff --git a/OpenLocoToolGui/MainForm.cs b/OpenLocoToolGui/MainForm.cs index 9a37c699..129b9b0a 100644 --- a/OpenLocoToolGui/MainForm.cs +++ b/OpenLocoToolGui/MainForm.cs @@ -1,7 +1,6 @@ using OpenLocoTool.DatFileParsing; using OpenLocoTool.Headers; using OpenLocoToolCommon; -using System; using System.Drawing.Imaging; using System.Text.Json; using System.Text.Json.Serialization; @@ -221,73 +220,77 @@ private void CreateImages(ILocoObject obj) flpImageTable.ResumeLayout(true); } - byte[] DecodeRLEImageData(G1Element32 img) + public byte[] DecodeRLEImageData(G1Element32 img) { - var newData = new List(); - var zoom = 1; - var src0 = img.ImageData; - var srcX = 0; + var width = img.width; + var height = img.height; - for (var i = 0; i < img.height; i += zoom) + var dstLineWidth = img.width; + var dst0Index = 0; // dstLineWidth * img.yOffset + img.xOffset; + + byte[] srcBuf = img.ImageData; + byte[] dstBuf = new byte[img.width * img.height]; // Assuming a single byte per pixel + + var srcY = 0; + + if (srcY < 0) { - var y = i; - var lineOffset = src0[y * 2] | (src0[y * 2 + 1] << 8); - var nextRun = lineOffset; + srcY++; + height--; + dst0Index += dstLineWidth; + } + + for (int i = 0; i < height; i++) + { + var y = srcY + i; + + var lineOffset = srcBuf[y * 2] | (srcBuf[y * 2 + 1] << 8); - var endOfLine = false; - while (!endOfLine) + var nextRunIndex = lineOffset; + var dstLineStartIndex = dst0Index + dstLineWidth * i; + + while (true) { - var srcPtr = nextRun; - var dataSize = src0[srcPtr++]; - var firstPixelX = src0[srcPtr++]; - endOfLine = (dataSize & 0x80) != 0; - dataSize &= 0x7F; + var srcIndex = nextRunIndex; + + var rleInfoByte = srcBuf[srcIndex++]; + var dataSize = rleInfoByte & 0x7F; + var isEndOfLine = (rleInfoByte & 0x80) != 0; - nextRun = srcPtr + dataSize; - var x = firstPixelX - srcX; - int numPixels = dataSize; + var firstPixelX = srcBuf[srcIndex++]; + nextRunIndex = srcIndex + dataSize; + + var x = firstPixelX - 0; // img.xOffset; + var numPixels = dataSize; if (x > 0) { - // If x is not a multiple of zoom, round it up to a multiple - var mod = x & (zoom - 1); - if (mod != 0) - { - var offset = zoom - mod; - x += offset; - srcPtr += offset; - numPixels -= offset; - } + x++; + srcIndex++; + numPixels--; } else if (x < 0) { - // Clamp x to zero if negative - srcPtr += -x; + srcIndex += -x; numPixels += x; x = 0; } - numPixels = (byte)Math.Min(numPixels, img.width - x); + numPixels = Math.Min(numPixels, width - x); - var sizePre = newData.Count; - newData.AddRange(Enumerable.Repeat((byte)0, firstPixelX)); // pre-pad with transparent - newData.AddRange(src0[srcPtr..(srcPtr + numPixels)]); - var remaining = img.width - firstPixelX - numPixels; - newData.AddRange(Enumerable.Repeat((byte)0, remaining)); // post-pad with transparent + var dstIndex = dstLineStartIndex + x; - if (newData.Count != img.width * (i + 1)) + if (numPixels > 0) { - throw new ArgumentException("image size wrong"); + Array.Copy(srcBuf, srcIndex, dstBuf, dstIndex, numPixels); } - } - } - if (newData.Count != img.width * img.height) - { - throw new ArgumentException("image size wrong"); + if (isEndOfLine) + break; + } } - return newData.ToArray(); + return dstBuf; } ILocoObject? LoadAndCacheObject(string filename) From b8a88e73cc2a2e221f2239df7fb9c333fd9caf02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Sun, 20 Aug 2023 15:00:30 +0300 Subject: [PATCH 2/2] Fix mutating ImageData in G1Element --- OpenLocoToolGui/MainForm.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenLocoToolGui/MainForm.cs b/OpenLocoToolGui/MainForm.cs index 129b9b0a..3196e2f5 100644 --- a/OpenLocoToolGui/MainForm.cs +++ b/OpenLocoToolGui/MainForm.cs @@ -177,9 +177,10 @@ private void CreateImages(ILocoObject obj) for (var i = 0; i < obj.G1Elements.Count; ++i) { var currElement = obj.G1Elements[i]; + byte[] imageData = currElement.ImageData; if (currElement.flags.HasFlag(G1ElementFlags.IsRLECompressed)) { - currElement.ImageData = DecodeRLEImageData(currElement); + imageData = DecodeRLEImageData(currElement); } if (currElement.ImageData.Length == 0 || currElement.flags.HasFlag(G1ElementFlags.IsR8G8B8Palette)) { @@ -193,7 +194,7 @@ private void CreateImages(ILocoObject obj) { for (var x = 0; x < currElement.width; ++x) { - var paletteIndex = currElement.ImageData[(y * currElement.width) + x]; + var paletteIndex = imageData[(y * currElement.width) + x]; // the issue with greyscale here is it isn't normalised so all heightmaps are really dark and hard to see //var colour = obj.Object is HillShapesObject