Esempio n. 1
0
        /// <summary>
        /// Reads the local color table from the current frame.
        /// </summary>
        /// <param name="imageDescriptor">The <see cref="GifImageDescriptor"/>.</param>
        /// <returns>The <see cref="T:byte[]"/></returns>
        private byte[] ReadFrameLocalColorTable(GifImageDescriptor imageDescriptor)
        {
            byte[] localColorTable = null;

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

                this.currentStream.Read(localColorTable, 0, localColorTable.Length);
            }

            return(localColorTable);
        }
Esempio n. 2
0
        /// <summary>
        /// Reads an individual gif frame.
        /// </summary>
        private void ReadFrame()
        {
            GifImageDescriptor imageDescriptor = this.ReadImageDescriptor();

            byte[] localColorTable = this.ReadFrameLocalColorTable(imageDescriptor);

            byte[] indices = this.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 ?? this.globalColorTable;

            this.ReadFrameColors(indices, colorTable, imageDescriptor);

            // Skip any remaining blocks
            this.Skip(0);
        }
Esempio n. 3
0
        /// <summary>
        /// Reads the image descriptor
        /// </summary>
        /// <returns><see cref="GifImageDescriptor"/></returns>
        private GifImageDescriptor ReadImageDescriptor()
        {
            byte[] buffer = new byte[9];

            this.currentStream.Read(buffer, 0, buffer.Length);

            byte packed = buffer[8];

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

            return(imageDescriptor);
        }
Esempio n. 4
0
        /// <summary>
        /// Reads the frames colors, mapping indices to colors.
        /// </summary>
        /// <param name="indices">The indexed pixels.</param>
        /// <param name="colorTable">The color table containing the available colors.</param>
        /// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
        private void ReadFrameColors(byte[] indices, byte[] colorTable, GifImageDescriptor descriptor)
        {
            int imageWidth  = this.logicalScreenDescriptor.Width;
            int imageHeight = this.logicalScreenDescriptor.Height;

            if (this.currentFrame == null)
            {
                this.currentFrame = new T[imageWidth * imageHeight];
            }

            T[] lastFrame = null;

            if (this.graphicsControlExtension != null &&
                this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
            {
                lastFrame = new T[imageWidth * imageHeight];

                Array.Copy(this.currentFrame, lastFrame, lastFrame.Length);
            }

            int offset, i = 0;
            int interlacePass      = 0; // The interlace pass
            int interlaceIncrement = 8; // The interlacing line increment
            int interlaceY         = 0; // The current interlaced line

            for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++)
            {
                // Check if this image is interlaced.
                int writeY; // the target y offset to write to
                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 (interlaceY >= descriptor.Height)
                    {
                        interlacePass++;
                        switch (interlacePass)
                        {
                        case 1:
                            interlaceY = 4;
                            break;

                        case 2:
                            interlaceY         = 2;
                            interlaceIncrement = 4;
                            break;

                        case 3:
                            interlaceY         = 1;
                            interlaceIncrement = 2;
                            break;
                        }
                    }

                    writeY = interlaceY + descriptor.Top;

                    interlaceY += interlaceIncrement;
                }
                else
                {
                    writeY = y;
                }

                for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                {
                    offset = (writeY * imageWidth) + x;
                    int index = indices[i];

                    if (this.graphicsControlExtension == null ||
                        this.graphicsControlExtension.TransparencyFlag == false ||
                        this.graphicsControlExtension.TransparencyIndex != index)
                    {
                        // Stored in r-> g-> b-> a order.
                        int indexOffset = index * 3;

                        T pixel = default(T);
                        pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
                        this.currentFrame[offset] = pixel;
                    }

                    i++;
                }
            }

            T[] pixels = new T[imageWidth * imageHeight];

            Array.Copy(this.currentFrame, pixels, pixels.Length);

            ImageBase <T, TP> currentImage;

            if (this.decodedImage.Pixels == null)
            {
                currentImage = this.decodedImage;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
                currentImage.Quality = colorTable.Length / 3;

                if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
                {
                    this.decodedImage.FrameDelay = this.graphicsControlExtension.DelayTime;
                }
            }
            else
            {
                ImageFrame <T, TP> frame = new ImageFrame <T, TP>();

                currentImage = frame;
                currentImage.SetPixels(imageWidth, imageHeight, pixels);
                currentImage.Quality = colorTable.Length / 3;

                if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
                {
                    currentImage.FrameDelay = this.graphicsControlExtension.DelayTime;
                }

                this.decodedImage.Frames.Add(frame);
            }

            if (this.graphicsControlExtension != null)
            {
                if (this.graphicsControlExtension.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;

                            // Stored in r-> g-> b-> a order.
                            this.currentFrame[offset] = default(T);
                        }
                    }
                }
                else if (this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    this.currentFrame = lastFrame;
                }
            }
        }