Advertisement
Zeus81

WPF Advanced Image

Sep 29th, 2012
375
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.41 KB | None | 0 0
  1. using System;
  2. using System.Text;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Media;
  6. using System.Windows.Media.Animation;
  7. using System.Windows.Media.Imaging;
  8.  
  9. namespace WpfApplication1 {
  10.  
  11.     public static class BitmapMetadataExtension {
  12.         public static object GetQueryOrNull(this BitmapMetadata metadata, string query) {
  13.             return metadata.ContainsQuery(query) ? metadata.GetQuery(query) : null;
  14.         }
  15.     }
  16.  
  17.     public class AdvancedImage : Image {
  18.  
  19.         new private static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(AdvancedImage), new UIPropertyMetadata(null, new PropertyChangedCallback(SourceChanged)));
  20.        
  21.         new public ImageSource Source {
  22.             get { return (ImageSource)GetValue(SourceProperty); }
  23.             set { SetValue(SourceProperty, value); }
  24.         }
  25.  
  26.         private static void SourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs ev) {
  27.             ((AdvancedImage)obj).SourceChanged(ev);
  28.         }
  29.  
  30.         private void SourceChanged(DependencyPropertyChangedEventArgs ev) {
  31.             string oldValue = ev.OldValue == null ? null : ev.OldValue.ToString();
  32.             string newValue = ev.NewValue == null ? null : ev.NewValue.ToString();
  33.             if (oldValue == newValue) return;
  34.             base.Source = Source;
  35.             BeginAnimation(Image.SourceProperty, null);
  36.             GifBitmapDecoder decoder = GetDecoder(Source) as GifBitmapDecoder;
  37.             if (decoder == null || decoder.Frames.Count <= 1) return;
  38.             ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames();
  39.             animation.Duration = TimeSpan.Zero;
  40.             animation.RepeatBehavior = GetRepeatBehavior(decoder);
  41.             GifFrame frame = new GifFrame(Source);
  42.             foreach (BitmapFrame rawFrame in decoder.Frames) {
  43.                 frame = new GifFrame(rawFrame, frame);
  44.                 animation.KeyFrames.Add(new DiscreteObjectKeyFrame(frame.Bitmap, animation.Duration.TimeSpan));
  45.                 animation.Duration += frame.Delay;
  46.             }
  47.             BeginAnimation(Image.SourceProperty, animation);
  48.         }
  49.  
  50.         private BitmapDecoder GetDecoder(ImageSource source) {
  51.         try {
  52.                 if (source is BitmapImage) {
  53.                     BitmapImage bmp = (BitmapImage)source;
  54.                     if (bmp.UriSource != null) {
  55.                         Uri uri = bmp.UriSource;
  56.                         if (bmp.BaseUri != null && !uri.IsAbsoluteUri)
  57.                             uri = new Uri(bmp.BaseUri, uri);
  58.                         return BitmapDecoder.Create(uri, bmp.CreateOptions, bmp.CacheOption);
  59.                     } else if (bmp.StreamSource != null)
  60.                         return BitmapDecoder.Create(bmp.StreamSource, bmp.CreateOptions, bmp.CacheOption);
  61.                 } else if (source is BitmapFrame)
  62.                     return ((BitmapFrame)source).Decoder;
  63.         } catch {}
  64.             return null;
  65.         }
  66.  
  67.         private RepeatBehavior GetRepeatBehavior(GifBitmapDecoder decoder) {
  68.             BitmapMetadata metadata = decoder.Metadata as BitmapMetadata;
  69.             if (metadata != null) {
  70.                 byte[] application = metadata.GetQueryOrNull("/appext/Application") as byte[];
  71.                 if (application != null && Encoding.Default.GetString(application) == "NETSCAPE2.0") {
  72.                     byte[] data = metadata.GetQueryOrNull("/appext/Data") as byte[];
  73.                     if (data != null && data.Length >= 4) {
  74.                         int count = BitConverter.ToUInt16(data, 2);
  75.                         if (count != 0) return new RepeatBehavior(count);
  76.                     }
  77.                 } else return new RepeatBehavior(1);
  78.             }
  79.             return RepeatBehavior.Forever;
  80.         }
  81.        
  82.         private class GifFrame {
  83.             private enum FrameDisposalMethod { Replace, Combine, RestoreBackground, RestorePrevious }
  84.             private FrameDisposalMethod Disposal { get; set; }
  85.             public BitmapSource Bitmap { get; set; }
  86.             public TimeSpan Delay { get; set; }
  87.  
  88.             public GifFrame(ImageSource source) {
  89.                 Disposal = FrameDisposalMethod.Replace;
  90.                 Bitmap = source as BitmapSource;
  91.             }
  92.  
  93.             public GifFrame(BitmapFrame rawFrame, GifFrame previousFrame) {
  94.                 Disposal = FrameDisposalMethod.Replace;
  95.                 Delay = TimeSpan.FromMilliseconds(100);
  96.                 Rect rect = new Rect(0, 0, rawFrame.Width, rawFrame.Height);
  97.                 BitmapMetadata metadata = rawFrame.Metadata as BitmapMetadata;
  98.                 if (metadata != null) {
  99.                     object value;
  100.                     if ((value = metadata.GetQueryOrNull("/grctlext/Delay")   ) != null) Delay = TimeSpan.FromMilliseconds(10 * (ushort)value);
  101.                     if ((value = metadata.GetQueryOrNull("/grctlext/Disposal")) != null) Disposal = (FrameDisposalMethod)(byte)value;
  102.                     if ((value = metadata.GetQueryOrNull("/imgdesc/Left")     ) != null) rect.X = (ushort)value;
  103.                     if ((value = metadata.GetQueryOrNull("/imgdesc/Top")      ) != null) rect.Y = (ushort)value;
  104.                     if ((value = metadata.GetQueryOrNull("/imgdesc/Width")    ) != null) rect.Width = (ushort)value;
  105.                     if ((value = metadata.GetQueryOrNull("/imgdesc/Height")   ) != null) rect.Height = (ushort)value;
  106.                 }
  107.                 Rect sourceRect = new Rect(0, 0, previousFrame.Bitmap.Width, previousFrame.Bitmap.Height);
  108.                 if (previousFrame.Disposal == FrameDisposalMethod.Combine || rect != sourceRect) {
  109.                     DrawingVisual visual = new DrawingVisual();
  110.                     using (DrawingContext context = visual.RenderOpen()) {
  111.                         if (previousFrame.Disposal == FrameDisposalMethod.Combine)
  112.                             context.DrawImage(previousFrame.Bitmap, sourceRect);
  113.                         context.DrawImage(rawFrame, rect);
  114.                     }
  115.                     RenderTargetBitmap bmp = new RenderTargetBitmap((int)sourceRect.Width, (int)sourceRect.Height, 96, 96, PixelFormats.Pbgra32);
  116.                     bmp.Render(visual);
  117.                     bmp.Freeze();
  118.                     Bitmap = bmp;
  119.                 } else Bitmap = rawFrame;
  120.             }
  121.         }
  122.  
  123.     }
  124.  
  125. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement