From a9a16f88e9a2174ce565e7268505e99a23d4cc70 Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Fri, 6 Sep 2024 18:55:34 +0100 Subject: [PATCH] Initial handling of interlaced GIFs --- project/code/Images/GifDecoder.cs | 66 +++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/project/code/Images/GifDecoder.cs b/project/code/Images/GifDecoder.cs index 2d2439e..e389a55 100644 --- a/project/code/Images/GifDecoder.cs +++ b/project/code/Images/GifDecoder.cs @@ -86,6 +86,7 @@ public class GifDecoder private byte[] _colors; private byte[] _pixelIndices; private int _transparentIndex; + private readonly bool _interlaced; public ImageData(BinaryReader reader, byte[] globalColors, int transparentIndex) { @@ -95,7 +96,7 @@ public class GifDecoder var height = reader.ReadUInt16(); var flags = reader.ReadByte(); var hasLocalColorTable = ((flags >> 7) & 0x1) != 0; - var interlaced = ((flags >> 6) & 0x1) != 0; // See appendix E for interlacing + _interlaced = ((flags >> 6) & 0x1) != 0; // See appendix E for interlacing var isLocalColorTableSorted = ((flags >> 5) & 0x1) != 0; var sizeOfLocalColorTable = (byte)Math.Pow(2, (flags & 0x7) + 1); byte[] colors; @@ -256,14 +257,65 @@ public class GifDecoder { var bytesIdx = 0; var bytes = new byte[Width * Height * 4]; - foreach (var colorIndex in _pixelIndices) + + void WritePixelBytes(int bytesOffset, int colorIndex) { - bytes[bytesIdx++] = _colors[colorIndex * 3]; - bytes[bytesIdx++] = _colors[colorIndex * 3 + 1]; - bytes[bytesIdx++] = _colors[colorIndex * 3 + 2]; + bytes[bytesOffset] = _colors[colorIndex * 3]; + bytes[bytesOffset + 1] = _colors[colorIndex * 3 + 1]; + bytes[bytesOffset + 2] = _colors[colorIndex * 3 + 2]; // Fuck you LGS hardcoding the transparent index suck my balls - // bytes[bytesIdx++] = (byte)((colorIndex == _transparentIndex) ? 0 : 255); - bytes[bytesIdx++] = (byte)((colorIndex == 0) ? 0 : 255); + // bytes[bytesOffset++] = (byte)((colorIndex == _transparentIndex) ? 0 : 255); + bytes[bytesOffset + 3] = (byte)((colorIndex == 0) ? 0 : 255); + } + + if (!_interlaced) + { + foreach (var colorIndex in _pixelIndices) + { + WritePixelBytes(bytesIdx, colorIndex); + bytesIdx += 4; + } + return bytes; + } + + var pass1Count = (int)Math.Ceiling(Height / 8.0f); + var pass2Count = (int)Math.Ceiling((Height - 4) / 8.0f); + var pass3Count = (int)Math.Ceiling((Height - 2) / 4.0f); + var pass4Count = (int)Math.Ceiling((Height - 1) / 2.0f); + + var indicesOffset = 0; + var bytesPerRow = Width * 4; + for (var i = 0; i < pass1Count; i++) + { + bytesIdx = 8 * i * bytesPerRow; + for (var x = 0; x < Width; x++) + { + WritePixelBytes(bytesIdx + x * 4, _pixelIndices[indicesOffset++]); + } + } + for (var i = 0; i < pass2Count; i++) + { + bytesIdx = (4 + 8 * i) * bytesPerRow; + for (var x = 0; x < Width; x++) + { + WritePixelBytes(bytesIdx + x * 4, _pixelIndices[indicesOffset++]); + } + } + for (var i = 0; i < pass3Count; i++) + { + bytesIdx = (2 + 4 * i) * bytesPerRow; + for (var x = 0; x < Width; x++) + { + WritePixelBytes(bytesIdx + x * 4, _pixelIndices[indicesOffset++]); + } + } + for (var i = 0; i < pass4Count; i++) + { + bytesIdx = (1 + 2 * i) * bytesPerRow; + for (var x = 0; x < Width; x++) + { + WritePixelBytes(bytesIdx + x * 4, _pixelIndices[indicesOffset++]); + } } return bytes; }