接上一篇: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>>
示例代码: