Exemplo n.º 1
0
        public async Task ParseAsync(Stream stream, bool skipTypeIdentifier = false, bool ignoreImageData = false)
        {
            if (stream != null)
            {
                GIFBitmap previousBitmap = null;
                GIFBitmap currentBitmap  = null;

                GIFBitmapDecoder       decoder = new GIFBitmapDecoder();
                GIFDecoderStreamReader reader  = new GIFDecoderStreamReader(stream);

                StartParsing();

                GIFHeader header = await GIFHeader.CreateHeaderAsync(reader, skipTypeIdentifier).ConfigureAwait(false);

                currentBitmap = await GIFBitmap.CreateBitmapAsync(reader, header, decoder, previousBitmap, ignoreImageData).ConfigureAwait(false);

                while (currentBitmap != null)
                {
                    AddBitmap(header, currentBitmap, ignoreImageData);
                    previousBitmap = currentBitmap;
                    currentBitmap  = await GIFBitmap.CreateBitmapAsync(reader, header, decoder, previousBitmap, ignoreImageData).ConfigureAwait(false);
                }

                FinishedParsing();
            }
            else
            {
                throw new ArgumentNullException(nameof(stream));
            }
        }
Exemplo n.º 2
0
        public static async Task <GIFBitmap> CreateBitmapAsync(GIFDecoderStreamReader stream, GIFHeader header, GIFBitmapDecoder decoder, GIFBitmap previousBitmap, bool ignoreImageData = false)
        {
            GIFBitmap currentBitmap = null;
            bool      haveImage     = false;
            bool      done          = false;

            while (!done)
            {
                int blockCode = stream.Read();
                if (blockCode == -1)
                {
                    currentBitmap = null;
                    break;
                }

                switch (blockCode)
                {
                case GIFBlockCodes.ImageSeparator:
                    if (currentBitmap == null)
                    {
                        currentBitmap = new GIFBitmap(header);
                    }
                    await currentBitmap.ParseImageDescriptorAsync(stream, decoder, previousBitmap, ignoreImageData).ConfigureAwait(false);

                    haveImage = true;
                    done      = true;
                    break;

                case GIFBlockCodes.Extension:
                    if (currentBitmap == null)
                    {
                        currentBitmap = new GIFBitmap(header);
                    }
                    await currentBitmap.ParseExtensionAsync(stream).ConfigureAwait(false);

                    break;

                case GIFBlockCodes.Trailer:
                    done = true;
                    if (!haveImage)
                    {
                        currentBitmap = null;
                    }
                    break;

                default:
                    break;
                }
            }

            return(currentBitmap);
        }
Exemplo n.º 3
0
        void RestoreToBackground(GIFHeader header, GIFBitmap currentBitmap, GIFBitmap previousBitmap, int[] bitmapData)
        {
            int color = 0;

            if (!currentBitmap.IsTransparent)
            {
                color = previousBitmap.BackgroundColor;
            }

            var previousBitmapBounds = previousBitmap.Bounds;

            for (int currentRow = 0; currentRow < previousBitmapBounds.Height; currentRow++)
            {
                int startBitmapIndex = (previousBitmapBounds.Y + currentRow) * header.Width + previousBitmapBounds.X;
                int endBitmapIndex   = startBitmapIndex + previousBitmapBounds.Width;
                for (int currentBitmapIndex = startBitmapIndex; currentBitmapIndex < endBitmapIndex; currentBitmapIndex++)
                {
                    bitmapData[currentBitmapIndex] = color;
                }
            }
        }
Exemplo n.º 4
0
 protected abstract void AddBitmap(GIFHeader header, GIFBitmap bitmap, bool ignoreImageData);
Exemplo n.º 5
0
        public void Compose(GIFHeader header, GIFBitmap currentBitmap, GIFBitmap previousBitmap)
        {
            int[] bitmapData = null;
            var   width      = header.Width;
            var   height     = header.Height;

            if (previousBitmap != null && previousBitmap.Dispose != GIFBitmap.DisposeMethod.NoAction)
            {
                if (previousBitmap.Data != null)
                {
                    bitmapData = previousBitmap.Data;
                    if (previousBitmap.Dispose == GIFBitmap.DisposeMethod.RestoreToBackground)
                    {
                        RestoreToBackground(header, currentBitmap, previousBitmap, bitmapData);
                    }
                }
            }

            // Reuse previous bitmap buffer or allocate new.
            if (bitmapData == null)
            {
                bitmapData = new int[width * height];
            }

            int interlacePass     = 1;
            int interlaceRowInc   = 8;
            int interlaceStartRow = 0;
            var bounds            = currentBitmap.Bounds;
            var isInterlaced      = currentBitmap.IsInterlaced;
            var colorTable        = currentBitmap.ColorTable.Data;

            for (int sourceRow = 0; sourceRow < bounds.Height; sourceRow++)
            {
                int targetRow = sourceRow;
                if (isInterlaced)
                {
                    if (interlaceStartRow >= bounds.Height)
                    {
                        interlacePass++;
                        switch (interlacePass)
                        {
                        case 2:
                            interlaceStartRow = 4;
                            break;

                        case 3:
                            interlaceStartRow = 2;
                            interlaceRowInc   = 4;
                            break;

                        case 4:
                            interlaceStartRow = 1;
                            interlaceRowInc   = 2;
                            break;

                        default:
                            break;
                        }
                    }
                    targetRow          = interlaceStartRow;
                    interlaceStartRow += interlaceRowInc;
                }
                targetRow += bounds.Y;
                if (targetRow < height)
                {
                    int startBitmapIndex   = targetRow * width;
                    int currentBitmapIndex = startBitmapIndex + bounds.X;
                    int endBitmapIndex     = currentBitmapIndex + bounds.Width;
                    if ((startBitmapIndex + width) < endBitmapIndex)
                    {
                        endBitmapIndex = startBitmapIndex + width;
                    }

                    int currentPixelIndex = sourceRow * bounds.Width;
                    while (currentBitmapIndex < endBitmapIndex)
                    {
                        int colorIndex = _pixels[currentPixelIndex++];
                        int color      = colorTable[colorIndex];
                        if (color != 0)
                        {
                            bitmapData[currentBitmapIndex] = color;
                        }
                        currentBitmapIndex++;
                    }
                }
            }

            currentBitmap.Data = bitmapData;
        }
Exemplo n.º 6
0
        async Task ParseImageDescriptorAsync(GIFDecoderStreamReader stream, GIFBitmapDecoder decoder, GIFBitmap previousBitmap, bool ignoreImageData)
        {
            await ParseGIFBitmapHeaderAsync(stream).ConfigureAwait(false);

            if (IsTransparent)
            {
                ColorTable.SetTransparency(TransparencyIndex);
            }

            DataPosition = stream.CurrentPosition;

            if (!ignoreImageData)
            {
                // Decode LZW data stream.
                await decoder.DecodeAsync(stream, _header.Width, _header.Height).ConfigureAwait(false);

                // Compose bitmap from decoded data stream.
                decoder.Compose(_header, this, previousBitmap);

                // Consume block terminator.
                await stream.SkipBlockAsync().ConfigureAwait(false);
            }
            else
            {
                // Read pass variable length LZW data stream.
                // First byte is LZW code size followed by data blocks repeated until block terminator.
                stream.Read();
                await stream.SkipBlockAsync().ConfigureAwait(false);
            }

            if (IsTransparent)
            {
                ColorTable.ResetTransparency();
            }
        }