diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-07-11 12:37:11 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-07-11 12:37:11 +0300 |
| commit | bd49bdcb109a227130d7db6856e659b435d16530 (patch) | |
| tree | db55cfdc5dae423ccdba5c7efb1162d33bdcdc48 /Software/Visual_Studio/Tango.AnimatedGif/Decoding | |
| parent | d65e5f1a23374de2872a73034e430e4a70ee4269 (diff) | |
| download | Tango-bd49bdcb109a227130d7db6856e659b435d16530.tar.gz Tango-bd49bdcb109a227130d7db6856e659b435d16530.zip | |
Embedded Tango.AnimatedGif !
Diffstat (limited to 'Software/Visual_Studio/Tango.AnimatedGif/Decoding')
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(); + } + } +} |
