Each image in the Data Stream is composed of an Image Descriptor, an optional Local Color Table, and the image data. Each image must fit within the boundaries of the Logical Screen, as defined in the Logical Screen Descriptor.
Пример #1
0
        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);
        }
Пример #2
0
        private void ReadFrame()
        {
            GifImageDescriptor imageDescriptor = ReadImageDescriptor();

            byte[] localColorTable = ReadFrameLocalColorTable(imageDescriptor);

            byte[] indices = ReadFrameIndices(imageDescriptor);

            // Determine the color table for this frame. If there is a local one, use it
            // otherwise use the global color table.
            byte[] colorTable = localColorTable != null ? localColorTable : _globalColorTable;

            ReadFrameColors(indices, colorTable, imageDescriptor);

            Skip(0); // skip any remaining blocks
        }
Пример #3
0
        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);
        }
        private void ReadFrame()
        {
            GifImageDescriptor imageDescriptor = ReadImageDescriptor();

            byte[] localColorTable = ReadFrameLocalColorTable(imageDescriptor);

            byte[] indices = ReadFrameIndices(imageDescriptor);

            // Determine the color table for this frame. If there is a local one, use it
            // otherwise use the global color table.
            byte[] colorTable = localColorTable != null ? localColorTable : _globalColorTable;

            ReadFrameColors(indices, colorTable, imageDescriptor);

            int blockSize = _stream.ReadByte();

            if (blockSize > 0)
            {
                _stream.Seek(blockSize, SeekOrigin.Current);
            }
        }
Пример #5
0
        private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
        {
            int imageWidth  = _logicalScreenDescriptor.Width;
            int imageHeight = _logicalScreenDescriptor.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;
                }

                //TODO: review performance here

                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 + 0];
                        _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                        _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 2];
                        _currentFrame[offset * 4 + 3] = (byte)255;
                    }

                    i++;
                }
            }

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

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

            SimpleImage currentImage = null;

            if (_image.Pixels == null)
            {
                currentImage = _image;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
            }
            else
            {
                SimpleImage frame = new SimpleImage();

                currentImage = frame;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);

                _image.Frames.Add(frame);
            }

            if (_graphicsControl != null)
            {
                if (_graphicsControl.DelayTime > 0)
                {
                    ExtraImageInfo extraImgInfo = currentImage.ExtraImageInfo;
                    if (extraImgInfo == null)
                    {
                        currentImage.ExtraImageInfo = extraImgInfo = new ExtraImageInfo();
                    }
                    extraImgInfo.DelayTime = _graphicsControl.DelayTime;
                }

                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;
                }
            }
        }
Пример #6
0
        private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
        {
            int imageWidth  = _logicalScreenDescriptor.Width;
            int imageHeight = _logicalScreenDescriptor.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 + 0];
                        _currentFrame[offset * 4 + 1] = colorTable[index * 3 + 1];
                        _currentFrame[offset * 4 + 2] = colorTable[index * 3 + 2];
                        _currentFrame[offset * 4 + 3] = (byte)255;
                    }

                    i++;
                }
            }

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

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

            ImageBase currentImage = null;

            if (_image.Pixels == null)
            {
                currentImage = _image;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
            }
            else
            {
                ImageFrame frame = new ImageFrame();

                currentImage = frame;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);

                _image.Frames.Add(frame);
            }

            if (_graphicsControl != null)
            {
                if (_graphicsControl.DelayTime > 0)
                {
                    currentImage.DelayTime = _graphicsControl.DelayTime;
                }

                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;
                }
            }
        }
Пример #7
0
        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;
        }
Пример #8
0
        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;
        }
Пример #9
0
        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;
        }