async Task ParseAsync(GIFDecoderStreamReader stream, bool skipTypeIdentifier) { if (!skipTypeIdentifier) { TypeIdentifier = stream.ReadString(3); } else { TypeIdentifier = "GIF"; } if (IsGIFHeader) { Version = stream.ReadString(3); Width = stream.ReadShort(); Height = stream.ReadShort(); int flags = stream.Read(); BackgroundColorIndex = stream.Read(); PixelAspectRatio = stream.Read(); if (UseGlobalColorTable(flags)) { GlobalColorTable = await GIFColorTable.CreateColorTableAsync(stream, GlobalColorTableSize(flags)).ConfigureAwait(false); BackgroundColor = GlobalColorTable.Data[BackgroundColorIndex]; } } else { throw new GIFDecoderFormatException("Unknown GIF format type identifier: " + TypeIdentifier); } }
async Task ParseImageDescriptorAsync(GIFDecoderStreamReader stream, GIFBitmapDecoder decoder, GIFBitmap previousBitmap, bool ignoreImageData) { await ParseGIFBitmapHeaderAsync(stream).ConfigureAwait(false); if (IsTransparent) { ColorTable.SetTransparency(TransparencyIndex); } DataPosition = stream.CurrentPosition; if (!ignoreImageData) { // Decode LZW data stream. await decoder.DecodeAsync(stream, _header.Width, _header.Height).ConfigureAwait(false); // Compose bitmap from decoded data stream. decoder.Compose(_header, this, previousBitmap); // Consume block terminator. await stream.SkipBlockAsync().ConfigureAwait(false); } else { // Read pass variable length LZW data stream. // First byte is LZW code size followed by data blocks repeated until block terminator. stream.Read(); await stream.SkipBlockAsync().ConfigureAwait(false); } if (IsTransparent) { ColorTable.ResetTransparency(); } }
void ParseGraphicControlExtension(GIFDecoderStreamReader stream) { int blockSize = stream.Read(); if (blockSize != 4) { throw new GIFDecoderFormatException("Invalid graphic control extension size."); } int flags = stream.Read(); SetDisposeMethod(flags); SetDelay(stream.ReadShort()); SetTransparency(flags, stream.Read()); // Consume block terminator. stream.Read(); }
public static async Task <GIFBitmap> CreateBitmapAsync(GIFDecoderStreamReader stream, GIFHeader header, GIFBitmapDecoder decoder, GIFBitmap previousBitmap, bool ignoreImageData = false) { GIFBitmap currentBitmap = null; bool haveImage = false; bool done = false; while (!done) { int blockCode = stream.Read(); if (blockCode == -1) { currentBitmap = null; break; } switch (blockCode) { case GIFBlockCodes.ImageSeparator: if (currentBitmap == null) { currentBitmap = new GIFBitmap(header); } await currentBitmap.ParseImageDescriptorAsync(stream, decoder, previousBitmap, ignoreImageData).ConfigureAwait(false); haveImage = true; done = true; break; case GIFBlockCodes.Extension: if (currentBitmap == null) { currentBitmap = new GIFBitmap(header); } await currentBitmap.ParseExtensionAsync(stream).ConfigureAwait(false); break; case GIFBlockCodes.Trailer: done = true; if (!haveImage) { currentBitmap = null; } break; default: break; } } return(currentBitmap); }
async Task ParseGIFBitmapHeaderAsync(GIFDecoderStreamReader stream) { Bounds = new GIFBitmap.Rect(stream.ReadShort(), stream.ReadShort(), stream.ReadShort(), stream.ReadShort()); ColorTable = _header.GlobalColorTable; int flags = stream.Read(); if (UseLocalColorTable(flags)) { ColorTable = await GIFColorTable.CreateColorTableAsync(stream, LocalColorTableSize(flags)).ConfigureAwait(false); } BackgroundColor = _header.BackgroundColor; IsInterlaced = UseInterlace(flags); }
async Task ParseExtensionAsync(GIFDecoderStreamReader stream) { int blockCode = stream.Read(); switch (blockCode) { case GIFBlockCodes.GraphicsControlExtension: ParseGraphicControlExtension(stream); break; case GIFBlockCodes.ApplicationExtensionBlock: await ParseApplicationExtensionAsync(stream).ConfigureAwait(false); break; default: await stream.SkipBlockAsync().ConfigureAwait(false); break; } }
public async Task DecodeAsync(GIFDecoderStreamReader stream, int width, int height) { int pixelCount = width * height; InitializeBuffers(pixelCount); int nullCode = -1; int inCode = nullCode; int oldCode = nullCode; int currentCode = nullCode; int dataSize = stream.Read(); int codeSize = dataSize + 1; int codeMask = (1 << codeSize) - 1; int clearCode = 1 << dataSize; int endOfInformationCode = clearCode + 1; int availableCode = clearCode + 2; for (currentCode = 0; currentCode < clearCode; currentCode++) { _prefix[currentCode] = 0; _suffix[currentCode] = (byte)currentCode; } int datum = 0; int bits = 0; int count = 0; int firstCode = 0; int currentStackIndex = 0; int currentPixelIndex = 0; int currentBitIndex = 0; int i = 0; for (i = 0; i < pixelCount;) { if (currentStackIndex == 0) { if (bits < codeSize) { if (count == 0) { count = await stream.ReadBlockAsync().ConfigureAwait(false); if (count <= 0) { break; } currentBitIndex = 0; } datum += (stream.CurrentBlockBuffer[currentBitIndex] << bits); bits += 8; currentBitIndex++; count--; continue; } currentCode = datum & codeMask; datum >>= codeSize; bits -= codeSize; if ((currentCode > availableCode) || (currentCode == endOfInformationCode)) { break; } if (currentCode == clearCode) { codeSize = dataSize + 1; codeMask = (1 << codeSize) - 1; availableCode = clearCode + 2; oldCode = nullCode; continue; } if (oldCode == nullCode) { _pixelStack[currentStackIndex++] = _suffix[currentCode]; oldCode = currentCode; firstCode = currentCode; continue; } inCode = currentCode; if (currentCode == availableCode) { _pixelStack[currentStackIndex++] = (byte)firstCode; currentCode = oldCode; } while (currentCode > clearCode) { _pixelStack[currentStackIndex++] = _suffix[currentCode]; currentCode = _prefix[currentCode]; } firstCode = _suffix[currentCode]; if (availableCode >= DecoderStackSize) { break; } _pixelStack[currentStackIndex++] = (byte)firstCode; _prefix[availableCode] = (short)oldCode; _suffix[availableCode] = (byte)firstCode; availableCode++; if (((availableCode & codeMask) == 0) && (availableCode < DecoderStackSize)) { codeSize++; codeMask += availableCode; } oldCode = inCode; } currentStackIndex--; _pixels[currentPixelIndex++] = _pixelStack[currentStackIndex]; i++; } for (i = currentPixelIndex; i < pixelCount; i++) { _pixels[i] = 0; } }