Compare commits

..

No commits in common. "354155db200738d5d0ed0e7d5f48451ffd78f515" and "3e4230e46f4516b700783d67511b56e43bb7faff" have entirely different histories.

1 changed files with 28 additions and 50 deletions

View File

@ -35,9 +35,11 @@ public class GifDecoder
LogicalScreenHeight = reader.ReadUInt16();
var flags = reader.ReadByte();
HasGlobalColorTable = ((flags >> 7) & 0x1) != 0;
// Godot.GD.Print($"HALLO WE HAVE GLOBAL TABLE? {HasGlobalColorTable}");
BitsPerColorChannel = (byte)(((flags >> 4) & 0x7) + 1);
IsGlobalColorTableSorted = ((flags >> 3) & 0x1) != 0;
GlobalColorTableSize = (int)Math.Pow(2, (flags & 0x7) + 1);
// Godot.GD.Print($"Global colour size? {GlobalColorTableSize}");
BackgroundColorIndex = reader.ReadByte();
var rawAspectRatio = reader.ReadByte();
if (rawAspectRatio == 0)
@ -84,7 +86,6 @@ public class GifDecoder
private byte[] _colors;
private byte[] _pixelIndices;
private int _transparentIndex;
private readonly bool _interlaced;
public ImageData(BinaryReader reader, byte[] globalColors, int transparentIndex)
{
@ -94,7 +95,7 @@ public class GifDecoder
var height = reader.ReadUInt16();
var flags = reader.ReadByte();
var hasLocalColorTable = ((flags >> 7) & 0x1) != 0;
_interlaced = ((flags >> 6) & 0x1) != 0; // See appendix E for interlacing
var 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;
@ -139,6 +140,7 @@ public class GifDecoder
compressedBytes.AddRange(bytes);
blockSize = reader.ReadByte();
}
// Godot.GD.Print($"End of image data: {reader.BaseStream.Position}");
using MemoryStream compressedStream = new(compressedBytes.ToArray());
using BinaryReader compressedReader = new(compressedStream, Encoding.UTF8, false);
@ -178,6 +180,7 @@ public class GifDecoder
}
else if (code == endCode)
{
// Godot.GD.Print($"CompressedBytesLeft: {compressedReader.BaseStream.Length - compressedReader.BaseStream.Position}");
break;
}
else if (code < codeCount)
@ -253,47 +256,15 @@ public class GifDecoder
{
var bytesIdx = 0;
var bytes = new byte[Width * Height * 4];
void WritePixelBytes(int bytesOffset, int colorIndex)
foreach (var colorIndex in _pixelIndices)
{
bytes[bytesOffset] = _colors[colorIndex * 3];
bytes[bytesOffset + 1] = _colors[colorIndex * 3 + 1];
bytes[bytesOffset + 2] = _colors[colorIndex * 3 + 2];
bytes[bytesOffset + 3] = (byte)((colorIndex == _transparentIndex) ? 0 : 255);
bytes[bytesIdx++] = _colors[colorIndex * 3];
bytes[bytesIdx++] = _colors[colorIndex * 3 + 1];
bytes[bytesIdx++] = _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);
}
if (!_interlaced)
{
foreach (var colorIndex in _pixelIndices)
{
WritePixelBytes(bytesIdx, colorIndex);
bytesIdx += 4;
}
return bytes;
}
var pass = 0;
var inc = 8;
var y = 0;
var indicesOffset = 0;
var bytesPerRow = Width * 4;
for (var i = 0; i < Height; i++)
{
bytesIdx = y * bytesPerRow;
for (var x = 0; x < Width; x++)
{
WritePixelBytes(bytesIdx + x * 4, _pixelIndices[indicesOffset++]);
}
y += inc;
if (y >= Height)
{
pass += 1;
y = (int)(8 / Math.Pow(2, pass));
inc = y * 2;
}
}
return bytes;
}
}
@ -309,12 +280,15 @@ public class GifDecoder
throw new FileNotFoundException();
}
// Godot.GD.Print($"Decoding image at: {path}");
using MemoryStream stream = new(File.ReadAllBytes(path));
using BinaryReader reader = new(stream, Encoding.UTF8, false);
_header = new Header(reader);
_globalColors = ReadColorTable(reader, _header.HasGlobalColorTable ? _header.GlobalColorTableSize : 0);
var images = new List<ImageData>();
var transparentIndex = -1;
while (true)
{
var id = reader.ReadByte();
@ -322,18 +296,22 @@ public class GifDecoder
switch (id)
{
case 0x2C: // Image
images.Add(new ImageData(reader, _globalColors, 0));
// Godot.GD.Print("Adding new image!!");
images.Add(new ImageData(reader, _globalColors, transparentIndex));
transparentIndex = -1;
break;
case 0x21: // Extension
// We don't need to actually handle any extensions. The only one that's
// potentially relevant is GraphicsControl, but Dark uses a hardcoded
// transparency palette index and doesn't use multi-frame GIFs with timing.
reader.ReadByte();
var blockSize = reader.ReadByte();
while (blockSize != 0)
var extId = reader.ReadByte();
if (extId == 0xF9)
{
reader.ReadBytes(blockSize);
blockSize = reader.ReadByte();
var graphicsControl = new GraphicsControl(reader);
transparentIndex = graphicsControl.TransparencyIndex;
// Godot.GD.Print($"We set the transparent index: {transparentIndex} for {path}");
}
else
{
// We don't support Comment (0xFE), Text (0x01), or Application (0xFF) extensions
throw new InvalidDataException($"Unknown or unsupported extension identifier in GIF file: {extId}");
}
break;
case 0x3B: