WP开发笔记-gif图片的处理

本文详细介绍了在gif图片处理中遇到的问题及解决方案,包括修复数组越界异常、优化AnimatedImage类避免内存泄漏,以及手动加载、显示gif图片的方法。通过使用ExtendedImage类和定时器实现gif动画流畅播放,并在unload时正确清除资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上一篇:imagecacheservice 

gif图片的处理,这里使用image tools开源项目。

但是image tools里,存在一些bug,所以需要改动一下。

在gifDecoder.cs大约356行,会出现数组越界的异常,修改一下:

for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
                {
                    offset = (writeY * imageWidth + x) * 4;
                    if (offset >= _currentFrame.Length)
                        break;

                    index = indices[i];

                    if (_graphicsControl == null ||
                        _graphicsControl.TransparencyFlag == false ||
                        _graphicsControl.TransparencyIndex != index)
                    {
                        _currentFrame[offset + 0] = colorTable[index * 3 + 0];
                        _currentFrame[offset + 1] = colorTable[index * 3 + 1];
                        _currentFrame[offset + 2] = colorTable[index * 3 + 2];
                        _currentFrame[offset + 3] = (byte)255;
                    }

                    i++;
                }

不使用AnimatedImage显示gif图片:

image tools的AnimatedImage类在unload时不会被释放。会导致内存泄漏。需要手动释放。参考>>

下面的代码手动处理gif图片:

var memStream = new MemoryStream(data);
memStream.Position = 0;
var gifImage = new ExtendedImage();
gifImage.SetSource(memStream);
gifImage.LoadingCompleted += ExtendedImageLoadCompleted;
说明:这部分代码添加到ImageContainer的SetImageSource(byte[] data)的catch里面。

extendedImage读取stream是异步的,所以需要使用event模式。 

private void ExtendedImageLoadCompleted(object sender, EventArgs e)
{
    Deployment.Current.Dispatcher.BeginInvoke(
        () =>
        {
            var gifImage = sender as ExtendedImage;
            if (!gifImage.IsAnimated || gifImage.Frames.Count == 1)
                this.PngImage.Source = gifImage.ToBitmap();
            else
            {
                frames = new List<KeyValuePair<ImageBase, ImageSource>>();
                frames.Add(new KeyValuePair<ImageBase, ImageSource>(gifImage, gifImage.ToBitmap()));
                foreach (var frame in gifImage.Frames)
                {
                    if (frame != null && frame.IsFilled)
                        frames.Add(new KeyValuePair<ImageBase, ImageSource>(frame, frame.ToBitmap()));
                }
                DisplayGifImage();
            }
            gifImage.LoadingCompleted -= ExtendedImageLoadCompleted;
            gifImage = null;
            DownloadCompleted = true;
        });
}

说明:读取gif图片的frames。然后取消event。

#region use timer to display gif image
private void DisplayGifImage()
{
    timer = new DispatcherTimer();
    timer.Tick += DisplayGifImage;
    isAnimating = true;
    UpdateInterval();
    timer.Start();
}

private void UpdateInterval()
{
    var interval = frames[index].Key.DelayTime;
    interval = interval == 0 ? 20 : interval;
    timer.Interval = TimeSpan.FromMilliseconds(interval * 20);
}

private void DisplayGifImage(object sender, EventArgs e)
{
    #region display
    if (isAnimating)
    {
        if (index < frames.Count)
        {
            this.PngImage.Source = frames[index].Value;
            index++;
            if (index > frames.Count - 1)
                index = 0;
            UpdateInterval();
        }
    }
    #endregion
    #region clear image
    else
    {
        var timer = sender as DispatcherTimer;
        if (timer != null)
        {
            timer.Stop();
            timer.Tick -= DisplayGifImage;
            timer = null;
        }
        if (frames != null)
        {
            frames.Clear();
            frames = null;
        }
        this.PngImage.Source = null;
        DownloadCompleted = false;
        Debug.WriteLine("clear image.");
    }
    #endregion
}
#endregion

说明:使用timer播放gif图片。

在unload时,清除图片:

private void ClearImage()
        {
            isAnimating = false;
            if (timer == null)
                DisplayGifImage(null, null);
        }

一些说明:

0. gif图片会造成内存泄漏。执行效率也不理想。强烈不建议使用gif图片。在chicken4wp里,只显示第一帧。 

1. image tools存在一些小bug。所以最好是自己下载源码,处理一下。这是我修改之后的代码(不保证没有bug):GitHub>> 

示例代码:

这里查看示例代码>>

转载于:https://my.oschina.net/wower/blog/147825

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值