示例#1
0
        internal new static async Task<GifFrame> ReadAsync(Stream stream, IEnumerable<GifExtension> controlExtensions)
        {
            var frame = new GifFrame();

            await frame.ReadInternalAsync(stream, controlExtensions).ConfigureAwait(false);

            return frame;
        }
示例#2
0
 private static TimeSpan GetFrameDelay(GifFrame frame)
 {
     var gce = frame.GraphicControl;
     if (gce != null)
     {
         if (gce.Delay != 0)
             return TimeSpan.FromMilliseconds(gce.Delay);
     }
     return TimeSpan.FromMilliseconds(100);
 }
示例#3
0
 private async Task<Stream> GetIndexStreamAsync(GifFrame frame, CancellationToken cancellationToken)
 {
     var data = frame.ImageData;
     cancellationToken.ThrowIfCancellationRequested();
     _sourceStream.Seek(data.CompressedDataStartOffset, SeekOrigin.Begin);
     using (var ms = new MemoryStream(_indexStreamBuffer))
     {
         await GifHelpers.CopyDataBlocksToStreamAsync(_sourceStream, ms, cancellationToken).ConfigureAwait(false);
     }
     var lzwStream = new LzwDecompressStream(_indexStreamBuffer, data.LzwMinimumCodeSize);
     return lzwStream;
 }
示例#4
0
        private void DisposePreviousFrame(GifFrame currentFrame)
        {
            var pgce = _previousFrame?.GraphicControl;
            if (pgce != null)
            {
                switch (pgce.DisposalMethod)
                {
                    case GifFrameDisposalMethod.None:
                    case GifFrameDisposalMethod.DoNotDispose:
                    {
                        // Leave previous frame in place
                        break;
                    }
                    case GifFrameDisposalMethod.RestoreBackground:
                    {
                        ClearArea(_previousFrame.Descriptor);
                        break;
                    }
                    case GifFrameDisposalMethod.RestorePrevious:
                    {
                        CopyToBitmap(_previousBackBuffer, _bitmap, 0, _previousBackBuffer.Length);
#if WPF
                        var desc = _metadata.Header.LogicalScreenDescriptor;
                        var rect = new Int32Rect(0, 0, desc.Width, desc.Height);
                        _bitmap.AddDirtyRect(rect);
#endif
                        break;
                    }
                    default:
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }

            var gce = currentFrame.GraphicControl;
            if (gce != null && gce.DisposalMethod == GifFrameDisposalMethod.RestorePrevious)
            {
                CopyFromBitmap(_previousBackBuffer, _bitmap, 0, _previousBackBuffer.Length);
            }
        }
示例#5
0
        private async Task RenderFrameAsync(int frameIndex, CancellationToken cancellationToken)
        {
            if (frameIndex < 0)
                return;

            var frame = _metadata.Frames[frameIndex];
            var desc = frame.Descriptor;
            using (var indexStream = await GetIndexStreamAsync(frame, cancellationToken))
            {
#if WPF
                _bitmap.Lock();
                try
                {
#endif
                    if (frameIndex < _previousFrameIndex)
                        ClearArea(_metadata.Header.LogicalScreenDescriptor);
                    else
                        DisposePreviousFrame(frame);

                    int bufferLength = 4 * desc.Width;
                    byte[] indexBuffer = new byte[desc.Width];
                    byte[] lineBuffer = new byte[bufferLength];

                    var palette = _palettes[frameIndex];
                    int transparencyIndex = palette.TransparencyIndex ?? -1;

                    var rows = frame.Descriptor.Interlace
                        ? InterlacedRows(frame.Descriptor.Height)
                        : NormalRows(frame.Descriptor.Height);

                    foreach (int y in rows)
                    {
                        int read = indexStream.Read(indexBuffer, 0, desc.Width);
                        if (read != desc.Width)
                            throw new EndOfStreamException();

                        int offset = (desc.Top + y) * _stride + desc.Left * 4;

                        if (transparencyIndex >= 0)
                        {
                            CopyFromBitmap(lineBuffer, _bitmap, offset, bufferLength);
                        }

                        for (int x = 0; x < desc.Width; x++)
                        {
                            byte index = indexBuffer[x];
                            int i = 4 * x;
                            if (index != transparencyIndex)
                            {
                                WriteColor(lineBuffer, palette[index], i);
                            }
                        }
                        CopyToBitmap(lineBuffer, _bitmap, offset, bufferLength);
                    }
#if WPF
                    var rect = new Int32Rect(desc.Left, desc.Top, desc.Width, desc.Height);
                    _bitmap.AddDirtyRect(rect);
                }
                finally
                {
                    _bitmap.Unlock();
                }
#elif WINRT
                _bitmap.Invalidate();
#endif
                _previousFrame = frame;
                _previousFrameIndex = frameIndex;
            }
        }