コード例 #1
0
ファイル: GifDecoderCore.cs プロジェクト: br3aker/ImageSharp
        /// <summary>
        /// Reads the image descriptor.
        /// </summary>
        private void ReadImageDescriptor()
        {
            this.stream.Read(this.buffer, 0, 9);

            this.imageDescriptor = GifImageDescriptor.Parse(this.buffer);
            if (this.imageDescriptor.Height == 0 || this.imageDescriptor.Width == 0)
            {
                GifThrowHelper.ThrowInvalidImageContentException("Width or height should not be 0");
            }
        }
コード例 #2
0
        /// <summary>
        /// Reads the image descriptor
        /// </summary>
        /// <returns><see cref="GifImageDescriptor"/></returns>
        private GifImageDescriptor ReadImageDescriptor()
        {
            this.currentStream.Read(this.buffer, 0, 9);

            byte packed = this.buffer[8];

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

            return(imageDescriptor);
        }
コード例 #3
0
        /// <summary>
        /// Reads an individual gif frame.
        /// </summary>
        private void ReadFrame()
        {
            GifImageDescriptor imageDescriptor = this.ReadImageDescriptor();

            byte[] localColorTable = null;
            byte[] indices         = null;
            try
            {
                // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table.
                int length = this.globalColorTableLength;
                if (imageDescriptor.LocalColorTableFlag)
                {
                    length          = imageDescriptor.LocalColorTableSize * 3;
                    localColorTable = ArrayPool <byte> .Shared.Rent(length);

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

                indices = ArrayPool <byte> .Shared.Rent(imageDescriptor.Width *imageDescriptor.Height);

                this.ReadFrameIndices(imageDescriptor, indices);
                this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, length, imageDescriptor);

                // Skip any remaining blocks
                this.Skip(0);
            }
            finally
            {
                if (localColorTable != null)
                {
                    ArrayPool <byte> .Shared.Return(localColorTable);
                }

                ArrayPool <byte> .Shared.Return(indices);
            }
        }
コード例 #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="colorTableLength">The color table length.</param>
        /// <param name="descriptor">The <see cref="GifImageDescriptor"/></param>
        private unsafe void ReadFrameColors(byte[] indices, byte[] colorTable, int colorTableLength, GifImageDescriptor descriptor)
        {
            int imageWidth  = this.logicalScreenDescriptor.Width;
            int imageHeight = this.logicalScreenDescriptor.Height;

            ImageFrame <TPixel> previousFrame = null;

            ImageFrame <TPixel> currentFrame = null;

            ImageFrame <TPixel> image;

            if (this.previousFrame == null)
            {
                // This initializes the image to become fully transparent because the alpha channel is zero.
                this.image = new Image <TPixel>(this.configuration, imageWidth, imageHeight, this.metaData);

                this.SetFrameMetaData(this.image.Frames.RootFrame.MetaData);

                image = this.image.Frames.RootFrame;
            }
            else
            {
                if (this.graphicsControlExtension != null &&
                    this.graphicsControlExtension.DisposalMethod == DisposalMethod.RestoreToPrevious)
                {
                    previousFrame = this.previousFrame;
                }

                currentFrame = this.image.Frames.AddFrame(this.previousFrame); // this clones the frame and adds it the collection

                this.SetFrameMetaData(currentFrame.MetaData);

                image = currentFrame;

                this.RestoreToBackground(image);
            }

            int 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;
                }

                Span <TPixel> rowSpan = image.GetPixelRowSpan(writeY);

                Rgba32 rgba = new Rgba32(0, 0, 0, 255);

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

                    if (this.graphicsControlExtension == null ||
                        this.graphicsControlExtension.TransparencyFlag == false ||
                        this.graphicsControlExtension.TransparencyIndex != index)
                    {
                        int indexOffset = index * 3;

                        ref TPixel pixel = ref rowSpan[x];
                        rgba.Rgb = colorTable.GetRgb24(indexOffset);

                        pixel.PackFromRgba32(rgba);
                    }

                    i++;
                }
            }
コード例 #5
0
        /// <summary>
        /// Reads the image descriptor.
        /// </summary>
        private void ReadImageDescriptor()
        {
            this.stream.Read(this.buffer, 0, 9);

            this.imageDescriptor = GifImageDescriptor.Parse(this.buffer);
        }
コード例 #6
0
        /// <summary>
        /// Reads the image descriptor
        /// </summary>
        /// <returns><see cref="GifImageDescriptor"/></returns>
        private GifImageDescriptor ReadImageDescriptor()
        {
            this.stream.Read(this.buffer, 0, 9);

            return(GifImageDescriptor.Parse(this.buffer));
        }