Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Media.Imaging;
- namespace WpfApplication1 {
- public static class BitmapMetadataExtension {
- public static object GetQueryOrNull(this BitmapMetadata metadata, string query) {
- return metadata.ContainsQuery(query) ? metadata.GetQuery(query) : null;
- }
- }
- public class AdvancedImage : Image {
- new private static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(AdvancedImage), new UIPropertyMetadata(null, new PropertyChangedCallback(SourceChanged)));
- new public ImageSource Source {
- get { return (ImageSource)GetValue(SourceProperty); }
- set { SetValue(SourceProperty, value); }
- }
- private static void SourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs ev) {
- ((AdvancedImage)obj).SourceChanged(ev);
- }
- private void SourceChanged(DependencyPropertyChangedEventArgs ev) {
- string oldValue = ev.OldValue == null ? null : ev.OldValue.ToString();
- string newValue = ev.NewValue == null ? null : ev.NewValue.ToString();
- if (oldValue == newValue) return;
- base.Source = Source;
- BeginAnimation(Image.SourceProperty, null);
- GifBitmapDecoder decoder = GetDecoder(Source) as GifBitmapDecoder;
- if (decoder == null || decoder.Frames.Count <= 1) return;
- ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
- animation.Duration = TimeSpan.Zero;
- animation.RepeatBehavior = GetRepeatBehavior(decoder);
- GifFrame frame = new GifFrame(Source);
- foreach (BitmapFrame rawFrame in decoder.Frames) {
- frame = new GifFrame(rawFrame, frame);
- animation.KeyFrames.Add(new DiscreteObjectKeyFrame(frame.Bitmap, animation.Duration.TimeSpan));
- animation.Duration += frame.Delay;
- }
- BeginAnimation(Image.SourceProperty, animation);
- }
- private BitmapDecoder GetDecoder(ImageSource source) {
- try {
- if (source is BitmapImage) {
- BitmapImage bmp = (BitmapImage)source;
- if (bmp.UriSource != null) {
- Uri uri = bmp.UriSource;
- if (bmp.BaseUri != null && !uri.IsAbsoluteUri)
- uri = new Uri(bmp.BaseUri, uri);
- return BitmapDecoder.Create(uri, bmp.CreateOptions, bmp.CacheOption);
- } else if (bmp.StreamSource != null)
- return BitmapDecoder.Create(bmp.StreamSource, bmp.CreateOptions, bmp.CacheOption);
- } else if (source is BitmapFrame)
- return ((BitmapFrame)source).Decoder;
- } catch {}
- return null;
- }
- private RepeatBehavior GetRepeatBehavior(GifBitmapDecoder decoder) {
- BitmapMetadata metadata = decoder.Metadata as BitmapMetadata;
- if (metadata != null) {
- byte[] application = metadata.GetQueryOrNull("/appext/Application") as byte[];
- if (application != null && Encoding.Default.GetString(application) == "NETSCAPE2.0") {
- byte[] data = metadata.GetQueryOrNull("/appext/Data") as byte[];
- if (data != null && data.Length >= 4) {
- int count = BitConverter.ToUInt16(data, 2);
- if (count != 0) return new RepeatBehavior(count);
- }
- } else return new RepeatBehavior(1);
- }
- return RepeatBehavior.Forever;
- }
- private class GifFrame {
- private enum FrameDisposalMethod { Replace, Combine, RestoreBackground, RestorePrevious }
- private FrameDisposalMethod Disposal { get; set; }
- public BitmapSource Bitmap { get; set; }
- public TimeSpan Delay { get; set; }
- public GifFrame(ImageSource source) {
- Disposal = FrameDisposalMethod.Replace;
- Bitmap = source as BitmapSource;
- }
- public GifFrame(BitmapFrame rawFrame, GifFrame previousFrame) {
- Disposal = FrameDisposalMethod.Replace;
- Delay = TimeSpan.FromMilliseconds(100);
- Rect rect = new Rect(0, 0, rawFrame.Width, rawFrame.Height);
- BitmapMetadata metadata = rawFrame.Metadata as BitmapMetadata;
- if (metadata != null) {
- object value;
- if ((value = metadata.GetQueryOrNull("/grctlext/Delay") ) != null) Delay = TimeSpan.FromMilliseconds(10 * (ushort)value);
- if ((value = metadata.GetQueryOrNull("/grctlext/Disposal")) != null) Disposal = (FrameDisposalMethod)(byte)value;
- if ((value = metadata.GetQueryOrNull("/imgdesc/Left") ) != null) rect.X = (ushort)value;
- if ((value = metadata.GetQueryOrNull("/imgdesc/Top") ) != null) rect.Y = (ushort)value;
- if ((value = metadata.GetQueryOrNull("/imgdesc/Width") ) != null) rect.Width = (ushort)value;
- if ((value = metadata.GetQueryOrNull("/imgdesc/Height") ) != null) rect.Height = (ushort)value;
- }
- Rect sourceRect = new Rect(0, 0, previousFrame.Bitmap.Width, previousFrame.Bitmap.Height);
- if (previousFrame.Disposal == FrameDisposalMethod.Combine || rect != sourceRect) {
- DrawingVisual visual = new DrawingVisual();
- using (DrawingContext context = visual.RenderOpen()) {
- if (previousFrame.Disposal == FrameDisposalMethod.Combine)
- context.DrawImage(previousFrame.Bitmap, sourceRect);
- context.DrawImage(rawFrame, rect);
- }
- RenderTargetBitmap bmp = new RenderTargetBitmap((int)sourceRect.Width, (int)sourceRect.Height, 96, 96, PixelFormats.Pbgra32);
- bmp.Render(visual);
- bmp.Freeze();
- Bitmap = bmp;
- } else Bitmap = rawFrame;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement