async Task ParseNetscapeApplicationExtensionAsync(GIFDecoderStreamReader stream) { int blockSize = await stream.ReadBlockAsync().ConfigureAwait(false); while (blockSize > 0) { if (stream.CurrentBlockBuffer[0] == 1 && blockSize == 3) { int count = (stream.CurrentBlockBuffer[2] << 8) | stream.CurrentBlockBuffer[1]; if (count == 0) { LoopCount = int.MaxValue; } else if (count != 0) { LoopCount = count; } } blockSize = await stream.ReadBlockAsync().ConfigureAwait(false); } }
async Task ParseApplicationExtensionAsync(GIFDecoderStreamReader stream) { var blockSize = await stream.ReadBlockAsync().ConfigureAwait(false); if (blockSize >= NetscapeApplicationExtensionID.Length) { var buffer = stream.CurrentBlockBuffer; string identifier = System.Text.Encoding.UTF8.GetString(buffer, 0, NetscapeApplicationExtensionID.Length); if (identifier.Equals(NetscapeApplicationExtensionID, StringComparison.OrdinalIgnoreCase)) { await ParseNetscapeApplicationExtensionAsync(stream).ConfigureAwait(false); return; } } await stream.SkipBlockAsync().ConfigureAwait(false); return; }
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; } }