private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
            {
                int imageWidth = _descriptor.Width;
                int imageHeight = _descriptor.Height;

                if (_currentFrame == null)
                {
                    _currentFrame = new byte[imageWidth * imageHeight * 4];
                }

                byte[] lastFrame = null;

                if (_graphicsControl != null &&
                    _graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    lastFrame = new byte[imageWidth * imageHeight * 4];

                    Array.Copy(_currentFrame, lastFrame, lastFrame.Length);
                }

                int offset = 0, i = 0, index = -1;

                int iPass = 0; // the interlace pass
                int iInc = 8; // the interlacing line increment
                int iY = 0; // the current interlaced line
                int writeY = 0; // the target y offset to write to

                for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                {
                    // Check if this image is interlaced.
                    if (descriptor.InterlaceFlag)
                    {
                        // If so then we read lines at predetermined offsets.
                        // When an entire image height worth of offset lines has been read we consider this a pass.
                        // With each pass the number of offset lines changes and the starting line changes.
                        if (iY >= descriptor.Height)
                        {
                            iPass++;
                            switch (iPass)
                            {
                                case 1:
                                    iY = 4;
                                    break;
                                case 2:
                                    iY = 2;
                                    iInc = 4;
                                    break;
                                case 3:
                                    iY = 1;
                                    iInc = 2;
                                    break;
                            }
                        }

                        writeY = iY + descriptor.Top;

                        iY += iInc;
                    }
                    else
                    {
                        writeY = y;
                    }

                    for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                    {
                        offset = writeY * imageWidth + x;

                        index = indices[i];

                        if (_graphicsControl == null ||
                            _graphicsControl.TransparencyFlag == false ||
                            _graphicsControl.TransparencyIndex != index)
                        {
                            _currentFrame[offset * 4 + 0] = colorTable[index * 3 + 2];
                            _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                            _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 0];
                            _currentFrame[offset * 4 + 3] = (byte)255;
                        }

                        i++;
                    }
                }

                var pixels = new byte[imageWidth * imageHeight * 4];

                Array.Copy(_currentFrame, pixels, pixels.Length);

                _frames.Add(new Image(imageWidth, imageHeight, pixels));

                if (_graphicsControl != null)
                {
                    if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToBackground)
                    {
                        for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
                        {
                            for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                            {
                                offset = y * imageWidth + x;

                                _currentFrame[offset * 4 + 0] = 0;
                                _currentFrame[offset * 4 + 1] = 0;
                                _currentFrame[offset * 4 + 2] = 0;
                                _currentFrame[offset * 4 + 3] = 0;
                            }
                        }
                    }
                    else if (_graphicsControl.DisposalMethod == DisposalMethod.RestoreToPrevious)
                    {
                        _currentFrame = lastFrame;
                    }
                }
            }
            private byte[] ReadFrameIndices(GifImageDescriptor imageDescriptor)
            {
                int dataSize = _stream.ReadByte();

                LZWDecoder lzwDecoder = new LZWDecoder(_stream);

                byte[] indices = lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize);
                return indices;
            }
            private byte[] ReadFrameLocalColorTable(GifImageDescriptor imageDescriptor)
            {
                byte[] localColorTable = null;

                if (imageDescriptor.LocalColorTableFlag == true)
                {
                    localColorTable = new byte[imageDescriptor.LocalColorTableSize * 3];

                    _stream.Read(localColorTable, 0, localColorTable.Length);
                }

                return localColorTable;
            }
            private GifImageDescriptor ReadImageDescriptor()
            {
                byte[] buffer = new byte[9];

                _stream.Read(buffer, 0, buffer.Length);

                byte packed = buffer[8];

                GifImageDescriptor imageDescriptor = new GifImageDescriptor();
                imageDescriptor.Left = BitConverter.ToInt16(buffer, 0);
                imageDescriptor.Top = BitConverter.ToInt16(buffer, 2);
                imageDescriptor.Width = BitConverter.ToInt16(buffer, 4);
                imageDescriptor.Height = BitConverter.ToInt16(buffer, 6);
                imageDescriptor.LocalColorTableFlag = ((packed & 0x80) >> 7) == 1;
                imageDescriptor.LocalColorTableSize = 2 << (packed & 0x07);
                imageDescriptor.InterlaceFlag = ((packed & 0x40) >> 6) == 1;

                return imageDescriptor;
            }