aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.AnimatedGif/Decoding
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-07-11 12:37:11 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-07-11 12:37:11 +0300
commitbd49bdcb109a227130d7db6856e659b435d16530 (patch)
treedb55cfdc5dae423ccdba5c7efb1162d33bdcdc48 /Software/Visual_Studio/Tango.AnimatedGif/Decoding
parentd65e5f1a23374de2872a73034e430e4a70ee4269 (diff)
downloadTango-bd49bdcb109a227130d7db6856e659b435d16530.tar.gz
Tango-bd49bdcb109a227130d7db6856e659b435d16530.zip
Embedded Tango.AnimatedGif !
Diffstat (limited to 'Software/Visual_Studio/Tango.AnimatedGif/Decoding')
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs50
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs28
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs10
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs25
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs37
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs16
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs32
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs86
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs47
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs52
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs38
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs110
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs27
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs43
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs43
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs68
-rw-r--r--Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs21
17 files changed, 733 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs
new file mode 100644
index 000000000..bbf8a5820
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifApplicationExtension.cs
@@ -0,0 +1,50 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0xFF
+ internal class GifApplicationExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xFF;
+
+ public int BlockSize { get; private set; }
+ public string ApplicationIdentifier { get; private set; }
+ public byte[] AuthenticationCode { get; private set; }
+ public byte[] Data { get; private set; }
+
+ private GifApplicationExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.SpecialPurpose; }
+ }
+
+ internal static GifApplicationExtension ReadApplication(Stream stream)
+ {
+ var ext = new GifApplicationExtension();
+ ext.Read(stream);
+ return ext;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFF) has already been read
+
+ byte[] bytes = new byte[12];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 11
+ if (BlockSize != 11)
+ throw GifHelpers.InvalidBlockSizeException("Application Extension", 11, BlockSize);
+
+ ApplicationIdentifier = Encoding.ASCII.GetString(bytes, 1, 8);
+ byte[] authCode = new byte[3];
+ Array.Copy(bytes, 9, authCode, 0, 3);
+ AuthenticationCode = authCode;
+ Data = GifHelpers.ReadDataBlocks(stream, false);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs
new file mode 100644
index 000000000..331e7bd8f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlock.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal abstract class GifBlock
+ {
+ internal static GifBlock ReadBlock(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ int blockId = stream.ReadByte();
+ if (blockId < 0)
+ throw GifHelpers.UnexpectedEndOfStreamException();
+ switch (blockId)
+ {
+ case GifExtension.ExtensionIntroducer:
+ return GifExtension.ReadExtension(stream, controlExtensions, metadataOnly);
+ case GifFrame.ImageSeparator:
+ return GifFrame.ReadFrame(stream, controlExtensions, metadataOnly);
+ case GifTrailer.TrailerByte:
+ return GifTrailer.ReadTrailer();
+ default:
+ throw GifHelpers.UnknownBlockTypeException(blockId);
+ }
+ }
+
+ internal abstract GifBlockKind Kind { get; }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs
new file mode 100644
index 000000000..eab7ea2c1
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifBlockKind.cs
@@ -0,0 +1,10 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal enum GifBlockKind
+ {
+ Control,
+ GraphicRendering,
+ SpecialPurpose,
+ Other
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs
new file mode 100644
index 000000000..8c0461941
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifColor.cs
@@ -0,0 +1,25 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal struct GifColor
+ {
+ private readonly byte _r;
+ private readonly byte _g;
+ private readonly byte _b;
+
+ internal GifColor(byte r, byte g, byte b)
+ {
+ _r = r;
+ _g = g;
+ _b = b;
+ }
+
+ public byte R { get { return _r; } }
+ public byte G { get { return _g; } }
+ public byte B { get { return _b; } }
+
+ public override string ToString()
+ {
+ return string.Format("#{0:x2}{1:x2}{2:x2}", _r, _g, _b);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs
new file mode 100644
index 000000000..cde458d0f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifCommentExtension.cs
@@ -0,0 +1,37 @@
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifCommentExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xFE;
+
+ public string Text { get; private set; }
+
+ private GifCommentExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.SpecialPurpose; }
+ }
+
+ internal static GifCommentExtension ReadComment(Stream stream)
+ {
+ var comment = new GifCommentExtension();
+ comment.Read(stream);
+ return comment;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xFE) has already been read
+
+ var bytes = GifHelpers.ReadDataBlocks(stream, false);
+ if (bytes != null)
+ Text = Encoding.ASCII.GetString(bytes);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs
new file mode 100644
index 000000000..7ff8ef6e0
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifDecoderException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ [Serializable]
+ internal class GifDecoderException : Exception
+ {
+ internal GifDecoderException() { }
+ internal GifDecoderException(string message) : base(message) { }
+ internal GifDecoderException(string message, Exception inner) : base(message, inner) { }
+ protected GifDecoderException(
+ System.Runtime.Serialization.SerializationInfo info,
+ System.Runtime.Serialization.StreamingContext context)
+ : base(info, context) { }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs
new file mode 100644
index 000000000..fda8909ec
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifExtension.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal abstract class GifExtension : GifBlock
+ {
+ internal const int ExtensionIntroducer = 0x21;
+
+ internal static GifExtension ReadExtension(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Extension Introducer (0x21) has already been read
+
+ int label = stream.ReadByte();
+ if (label < 0)
+ throw GifHelpers.UnexpectedEndOfStreamException();
+ switch (label)
+ {
+ case GifGraphicControlExtension.ExtensionLabel:
+ return GifGraphicControlExtension.ReadGraphicsControl(stream);
+ case GifCommentExtension.ExtensionLabel:
+ return GifCommentExtension.ReadComment(stream);
+ case GifPlainTextExtension.ExtensionLabel:
+ return GifPlainTextExtension.ReadPlainText(stream, controlExtensions, metadataOnly);
+ case GifApplicationExtension.ExtensionLabel:
+ return GifApplicationExtension.ReadApplication(stream);
+ default:
+ throw GifHelpers.UnknownExtensionTypeException(label);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs
new file mode 100644
index 000000000..500ce12a8
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFile.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifFile
+ {
+ public GifHeader Header { get; private set; }
+ public GifColor[] GlobalColorTable { get; set; }
+ public IList<GifFrame> Frames { get; set; }
+ public IList<GifExtension> Extensions { get; set; }
+ public ushort RepeatCount { get; set; }
+
+ private GifFile()
+ {
+ }
+
+ internal static GifFile ReadGifFile(Stream stream, bool metadataOnly)
+ {
+ var file = new GifFile();
+ file.Read(stream, metadataOnly);
+ return file;
+ }
+
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ Header = GifHeader.ReadHeader(stream);
+
+ if (Header.LogicalScreenDescriptor.HasGlobalColorTable)
+ {
+ GlobalColorTable = GifHelpers.ReadColorTable(stream, Header.LogicalScreenDescriptor.GlobalColorTableSize);
+ }
+ ReadFrames(stream, metadataOnly);
+
+ var netscapeExtension =
+ Extensions
+ .OfType<GifApplicationExtension>()
+ .FirstOrDefault(GifHelpers.IsNetscapeExtension);
+
+ if (netscapeExtension != null)
+ RepeatCount = GifHelpers.GetRepeatCount(netscapeExtension);
+ else
+ RepeatCount = 1;
+ }
+
+ private void ReadFrames(Stream stream, bool metadataOnly)
+ {
+ List<GifFrame> frames = new List<GifFrame>();
+ List<GifExtension> controlExtensions = new List<GifExtension>();
+ List<GifExtension> specialExtensions = new List<GifExtension>();
+ while (true)
+ {
+ var block = GifBlock.ReadBlock(stream, controlExtensions, metadataOnly);
+
+ if (block.Kind == GifBlockKind.GraphicRendering)
+ controlExtensions = new List<GifExtension>();
+
+ if (block is GifFrame)
+ {
+ frames.Add((GifFrame)block);
+ }
+ else if (block is GifExtension)
+ {
+ var extension = (GifExtension)block;
+ switch (extension.Kind)
+ {
+ case GifBlockKind.Control:
+ controlExtensions.Add(extension);
+ break;
+ case GifBlockKind.SpecialPurpose:
+ specialExtensions.Add(extension);
+ break;
+ }
+ }
+ else if (block is GifTrailer)
+ {
+ break;
+ }
+ }
+
+ this.Frames = frames.AsReadOnly();
+ this.Extensions = specialExtensions.AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs
new file mode 100644
index 000000000..85740ec87
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifFrame.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifFrame : GifBlock
+ {
+ internal const int ImageSeparator = 0x2C;
+
+ public GifImageDescriptor Descriptor { get; private set; }
+ public GifColor[] LocalColorTable { get; private set; }
+ public IList<GifExtension> Extensions { get; private set; }
+ public GifImageData ImageData { get; private set; }
+
+ private GifFrame()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.GraphicRendering; }
+ }
+
+ internal static GifFrame ReadFrame(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ var frame = new GifFrame();
+
+ frame.Read(stream, controlExtensions, metadataOnly);
+
+ return frame;
+ }
+
+ private void Read(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the Image Separator (0x2C) has already been read
+
+ Descriptor = GifImageDescriptor.ReadImageDescriptor(stream);
+ if (Descriptor.HasLocalColorTable)
+ {
+ LocalColorTable = GifHelpers.ReadColorTable(stream, Descriptor.LocalColorTableSize);
+ }
+ ImageData = GifImageData.ReadImageData(stream, metadataOnly);
+ Extensions = controlExtensions.ToList().AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs
new file mode 100644
index 000000000..a3782c011
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifGraphicControlExtension.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0xF9
+ internal class GifGraphicControlExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0xF9;
+
+ public int BlockSize { get; private set; }
+ public int DisposalMethod { get; private set; }
+ public bool UserInput { get; private set; }
+ public bool HasTransparency { get; private set; }
+ public int Delay { get; private set; }
+ public int TransparencyIndex { get; private set; }
+
+ private GifGraphicControlExtension()
+ {
+
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Control; }
+ }
+
+ internal static GifGraphicControlExtension ReadGraphicsControl(Stream stream)
+ {
+ var ext = new GifGraphicControlExtension();
+ ext.Read(stream);
+ return ext;
+ }
+
+ private void Read(Stream stream)
+ {
+ // Note: at this point, the label (0xF9) has already been read
+
+ byte[] bytes = new byte[6];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ BlockSize = bytes[0]; // should always be 4
+ if (BlockSize != 4)
+ throw GifHelpers.InvalidBlockSizeException("Graphic Control Extension", 4, BlockSize);
+ byte packedFields = bytes[1];
+ DisposalMethod = (packedFields & 0x1C) >> 2;
+ UserInput = (packedFields & 0x02) != 0;
+ HasTransparency = (packedFields & 0x01) != 0;
+ Delay = BitConverter.ToUInt16(bytes, 2) * 10; // milliseconds
+ TransparencyIndex = bytes[4];
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs
new file mode 100644
index 000000000..b903b83c9
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHeader.cs
@@ -0,0 +1,38 @@
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifHeader : GifBlock
+ {
+ public string Signature { get; private set; }
+ public string Version { get; private set; }
+ public GifLogicalScreenDescriptor LogicalScreenDescriptor { get; private set; }
+
+ private GifHeader()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Other; }
+ }
+
+ internal static GifHeader ReadHeader(Stream stream)
+ {
+ var header = new GifHeader();
+ header.Read(stream);
+ return header;
+ }
+
+ private void Read(Stream stream)
+ {
+ Signature = GifHelpers.ReadString(stream, 3);
+ if (Signature != "GIF")
+ throw GifHelpers.InvalidSignatureException(Signature);
+ Version = GifHelpers.ReadString(stream, 3);
+ if (Version != "87a" && Version != "89a")
+ throw GifHelpers.UnsupportedVersionException(Version);
+ LogicalScreenDescriptor = GifLogicalScreenDescriptor.ReadLogicalScreenDescriptor(stream);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs
new file mode 100644
index 000000000..801b3da27
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifHelpers.cs
@@ -0,0 +1,110 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal static class GifHelpers
+ {
+ public static string ReadString(Stream stream, int length)
+ {
+ byte[] bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ return Encoding.ASCII.GetString(bytes);
+ }
+
+ public static byte[] ReadDataBlocks(Stream stream, bool discard)
+ {
+ MemoryStream ms = discard ? null : new MemoryStream();
+ using (ms)
+ {
+ int len;
+ while ((len = stream.ReadByte()) > 0)
+ {
+ byte[] bytes = new byte[len];
+ stream.ReadAll(bytes, 0, len);
+ if (ms != null)
+ ms.Write(bytes, 0, len);
+ }
+ if (ms != null)
+ return ms.ToArray();
+ return null;
+ }
+ }
+
+ public static GifColor[] ReadColorTable(Stream stream, int size)
+ {
+ int length = 3 * size;
+ byte[] bytes = new byte[length];
+ stream.ReadAll(bytes, 0, length);
+ GifColor[] colorTable = new GifColor[size];
+ for (int i = 0; i < size; i++)
+ {
+ byte r = bytes[3 * i];
+ byte g = bytes[3 * i + 1];
+ byte b = bytes[3 * i + 2];
+ colorTable[i] = new GifColor(r, g, b);
+ }
+ return colorTable;
+ }
+
+ public static bool IsNetscapeExtension(GifApplicationExtension ext)
+ {
+ return ext.ApplicationIdentifier == "NETSCAPE"
+ && Encoding.ASCII.GetString(ext.AuthenticationCode) == "2.0";
+ }
+
+ public static ushort GetRepeatCount(GifApplicationExtension ext)
+ {
+ if (ext.Data.Length >= 3)
+ {
+ return BitConverter.ToUInt16(ext.Data, 1);
+ }
+ return 1;
+ }
+
+ public static Exception UnexpectedEndOfStreamException()
+ {
+ return new GifDecoderException("Unexpected end of stream before trailer was encountered");
+ }
+
+ public static Exception UnknownBlockTypeException(int blockId)
+ {
+ return new GifDecoderException("Unknown block type: 0x" + blockId.ToString("x2"));
+ }
+
+ public static Exception UnknownExtensionTypeException(int extensionLabel)
+ {
+ return new GifDecoderException("Unknown extension type: 0x" + extensionLabel.ToString("x2"));
+ }
+
+ public static Exception InvalidBlockSizeException(string blockName, int expectedBlockSize, int actualBlockSize)
+ {
+ return new GifDecoderException(
+ string.Format(
+ "Invalid block size for {0}. Expected {1}, but was {2}",
+ blockName,
+ expectedBlockSize,
+ actualBlockSize));
+ }
+
+ public static Exception InvalidSignatureException(string signature)
+ {
+ return new GifDecoderException("Invalid file signature: " + signature);
+ }
+
+ public static Exception UnsupportedVersionException(string version)
+ {
+ return new GifDecoderException("Unsupported version: " + version);
+ }
+
+ public static void ReadAll(this Stream stream, byte[] buffer, int offset, int count)
+ {
+ int totalRead = 0;
+ while (totalRead < count)
+ {
+ totalRead += stream.Read(buffer, offset + totalRead, count - totalRead);
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs
new file mode 100644
index 000000000..32ae1359b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageData.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifImageData
+ {
+ public byte LzwMinimumCodeSize { get; set; }
+ public byte[] CompressedData { get; set; }
+
+ private GifImageData()
+ {
+ }
+
+ internal static GifImageData ReadImageData(Stream stream, bool metadataOnly)
+ {
+ var imgData = new GifImageData();
+ imgData.Read(stream, metadataOnly);
+ return imgData;
+ }
+
+ private void Read(Stream stream, bool metadataOnly)
+ {
+ LzwMinimumCodeSize = (byte)stream.ReadByte();
+ CompressedData = GifHelpers.ReadDataBlocks(stream, metadataOnly);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs
new file mode 100644
index 000000000..ad344ef4e
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifImageDescriptor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifImageDescriptor
+ {
+ public int Left { get; private set; }
+ public int Top { get; private set; }
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public bool HasLocalColorTable { get; private set; }
+ public bool Interlace { get; private set; }
+ public bool IsLocalColorTableSorted { get; private set; }
+ public int LocalColorTableSize { get; private set; }
+
+ private GifImageDescriptor()
+ {
+ }
+
+ internal static GifImageDescriptor ReadImageDescriptor(Stream stream)
+ {
+ var descriptor = new GifImageDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
+
+ private void Read(Stream stream)
+ {
+ byte[] bytes = new byte[9];
+ stream.ReadAll(bytes, 0, bytes.Length);
+ Left = BitConverter.ToUInt16(bytes, 0);
+ Top = BitConverter.ToUInt16(bytes, 2);
+ Width = BitConverter.ToUInt16(bytes, 4);
+ Height = BitConverter.ToUInt16(bytes, 6);
+ byte packedFields = bytes[8];
+ HasLocalColorTable = (packedFields & 0x80) != 0;
+ Interlace = (packedFields & 0x40) != 0;
+ IsLocalColorTableSorted = (packedFields & 0x20) != 0;
+ LocalColorTableSize = 1 << ((packedFields & 0x07) + 1);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs
new file mode 100644
index 000000000..55bcb860b
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifLogicalScreenDescriptor.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifLogicalScreenDescriptor
+ {
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public bool HasGlobalColorTable { get; private set; }
+ public int ColorResolution { get; private set; }
+ public bool IsGlobalColorTableSorted { get; private set; }
+ public int GlobalColorTableSize { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
+ public double PixelAspectRatio { get; private set; }
+
+ internal static GifLogicalScreenDescriptor ReadLogicalScreenDescriptor(Stream stream)
+ {
+ var descriptor = new GifLogicalScreenDescriptor();
+ descriptor.Read(stream);
+ return descriptor;
+ }
+
+ private void Read(Stream stream)
+ {
+ byte[] bytes = new byte[7];
+ stream.ReadAll(bytes, 0, bytes.Length);
+
+ Width = BitConverter.ToUInt16(bytes, 0);
+ Height = BitConverter.ToUInt16(bytes, 2);
+ byte packedFields = bytes[4];
+ HasGlobalColorTable = (packedFields & 0x80) != 0;
+ ColorResolution = ((packedFields & 0x70) >> 4) + 1;
+ IsGlobalColorTableSorted = (packedFields & 0x08) != 0;
+ GlobalColorTableSize = 1 << ((packedFields & 0x07) + 1);
+ BackgroundColorIndex = bytes[5];
+ PixelAspectRatio =
+ bytes[5] == 0
+ ? 0.0
+ : (15 + bytes[5]) / 64.0;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs
new file mode 100644
index 000000000..ddd20c7b7
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifPlainTextExtension.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Tango.AnimatedGif.Decoding
+{
+ // label 0x01
+ internal class GifPlainTextExtension : GifExtension
+ {
+ internal const int ExtensionLabel = 0x01;
+
+ public int BlockSize { get; private set; }
+ public int Left { get; private set; }
+ public int Top { get; private set; }
+ public int Width { get; private set; }
+ public int Height { get; private set; }
+ public int CellWidth { get; private set; }
+ public int CellHeight { get; private set; }
+ public int ForegroundColorIndex { get; private set; }
+ public int BackgroundColorIndex { get; private set; }
+ public string Text { get; private set; }
+
+ public IList<GifExtension> Extensions { get; private set; }
+
+ private GifPlainTextExtension()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.GraphicRendering; }
+ }
+
+ internal static GifPlainTextExtension ReadPlainText(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ var plainText = new GifPlainTextExtension();
+ plainText.Read(stream, controlExtensions, metadataOnly);
+ return plainText;
+ }
+
+ private void Read(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly)
+ {
+ // Note: at this point, the label (0x01) has already been read
+
+ byte[] bytes = new byte[13];
+ stream.ReadAll(bytes,0, bytes.Length);
+
+ BlockSize = bytes[0];
+ if (BlockSize != 12)
+ throw GifHelpers.InvalidBlockSizeException("Plain Text Extension", 12, BlockSize);
+
+ Left = BitConverter.ToUInt16(bytes, 1);
+ Top = BitConverter.ToUInt16(bytes, 3);
+ Width = BitConverter.ToUInt16(bytes, 5);
+ Height = BitConverter.ToUInt16(bytes, 7);
+ CellWidth = bytes[9];
+ CellHeight = bytes[10];
+ ForegroundColorIndex = bytes[11];
+ BackgroundColorIndex = bytes[12];
+
+ var dataBytes = GifHelpers.ReadDataBlocks(stream, metadataOnly);
+ Text = Encoding.ASCII.GetString(dataBytes);
+ Extensions = controlExtensions.ToList().AsReadOnly();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs
new file mode 100644
index 000000000..82e153ad3
--- /dev/null
+++ b/Software/Visual_Studio/Tango.AnimatedGif/Decoding/GifTrailer.cs
@@ -0,0 +1,21 @@
+namespace Tango.AnimatedGif.Decoding
+{
+ internal class GifTrailer : GifBlock
+ {
+ internal const int TrailerByte = 0x3B;
+
+ private GifTrailer()
+ {
+ }
+
+ internal override GifBlockKind Kind
+ {
+ get { return GifBlockKind.Other; }
+ }
+
+ internal static GifTrailer ReadTrailer()
+ {
+ return new GifTrailer();
+ }
+ }
+}