-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
1,928 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Windows.Media; | ||
using System.Windows.Media.Animation; | ||
using System.Windows.Media.Imaging; | ||
|
||
namespace WpfAnimatedGif | ||
{ | ||
static class AnimationCache | ||
{ | ||
private class CacheKey | ||
{ | ||
private readonly ImageSource _source; | ||
private readonly RepeatBehavior _repeatBehavior; | ||
|
||
public CacheKey(ImageSource source, RepeatBehavior repeatBehavior) | ||
{ | ||
_source = source; | ||
_repeatBehavior = repeatBehavior; | ||
} | ||
|
||
private bool Equals(CacheKey other) | ||
{ | ||
return ImageEquals(_source, other._source) | ||
&& Equals(_repeatBehavior, other._repeatBehavior); | ||
} | ||
|
||
public override bool Equals(object obj) | ||
{ | ||
if (ReferenceEquals(null, obj)) return false; | ||
if (ReferenceEquals(this, obj)) return true; | ||
if (obj.GetType() != this.GetType()) return false; | ||
return Equals((CacheKey)obj); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
unchecked | ||
{ | ||
return (ImageGetHashCode(_source) * 397) ^ _repeatBehavior.GetHashCode(); | ||
} | ||
} | ||
|
||
private static int ImageGetHashCode(ImageSource image) | ||
{ | ||
if (image != null) | ||
{ | ||
var uri = GetUri(image); | ||
if (uri != null) | ||
return uri.GetHashCode(); | ||
} | ||
return 0; | ||
} | ||
|
||
private static bool ImageEquals(ImageSource x, ImageSource y) | ||
{ | ||
if (Equals(x, y)) | ||
return true; | ||
if ((x == null) != (y == null)) | ||
return false; | ||
// They can't both be null or Equals would have returned true | ||
// and if any is null, the previous would have detected it | ||
// ReSharper disable PossibleNullReferenceException | ||
if (x.GetType() != y.GetType()) | ||
return false; | ||
// ReSharper restore PossibleNullReferenceException | ||
var xUri = GetUri(x); | ||
var yUri = GetUri(y); | ||
return xUri != null && xUri == yUri; | ||
} | ||
|
||
private static Uri GetUri(ImageSource image) | ||
{ | ||
var bmp = image as BitmapImage; | ||
if (bmp != null && bmp.UriSource != null) | ||
{ | ||
if (bmp.UriSource.IsAbsoluteUri) | ||
return bmp.UriSource; | ||
if (bmp.BaseUri != null) | ||
return new Uri(bmp.BaseUri, bmp.UriSource); | ||
} | ||
var frame = image as BitmapFrame; | ||
if (frame != null) | ||
{ | ||
string s = frame.ToString(); | ||
if (s != frame.GetType().FullName) | ||
{ | ||
Uri fUri; | ||
if (Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out fUri)) | ||
{ | ||
if (fUri.IsAbsoluteUri) | ||
return fUri; | ||
if (frame.BaseUri != null) | ||
return new Uri(frame.BaseUri, fUri); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
} | ||
|
||
private static readonly Dictionary<CacheKey, ObjectAnimationUsingKeyFrames> _animationCache = new Dictionary<CacheKey, ObjectAnimationUsingKeyFrames>(); | ||
private static readonly Dictionary<CacheKey, int> _referenceCount = new Dictionary<CacheKey, int>(); | ||
|
||
public static void IncrementReferenceCount(ImageSource source, RepeatBehavior repeatBehavior) | ||
{ | ||
var cacheKey = new CacheKey(source, repeatBehavior); | ||
int count; | ||
_referenceCount.TryGetValue(cacheKey, out count); | ||
count++; | ||
_referenceCount[cacheKey] = count; | ||
} | ||
|
||
public static void DecrementReferenceCount(ImageSource source, RepeatBehavior repeatBehavior) | ||
{ | ||
var cacheKey = new CacheKey(source, repeatBehavior); | ||
int count; | ||
_referenceCount.TryGetValue(cacheKey, out count); | ||
if (count > 0) | ||
{ | ||
count--; | ||
_referenceCount[cacheKey] = count; | ||
} | ||
if (count == 0) | ||
{ | ||
_animationCache.Remove(cacheKey); | ||
_referenceCount.Remove(cacheKey); | ||
} | ||
} | ||
|
||
public static void AddAnimation(ImageSource source, RepeatBehavior repeatBehavior, ObjectAnimationUsingKeyFrames animation) | ||
{ | ||
var key = new CacheKey(source, repeatBehavior); | ||
_animationCache[key] = animation; | ||
} | ||
|
||
public static void RemoveAnimation(ImageSource source, RepeatBehavior repeatBehavior, ObjectAnimationUsingKeyFrames animation) | ||
{ | ||
var key = new CacheKey(source, repeatBehavior); | ||
_animationCache.Remove(key); | ||
} | ||
|
||
public static ObjectAnimationUsingKeyFrames GetAnimation(ImageSource source, RepeatBehavior repeatBehavior) | ||
{ | ||
var key = new CacheKey(source, repeatBehavior); | ||
ObjectAnimationUsingKeyFrames animation; | ||
_animationCache.TryGetValue(key, out animation); | ||
return animation; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using System; | ||
using System.IO; | ||
using System.Text; | ||
|
||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
// label 0xFF | ||
internal class GifApplicationExtension : GifExtension | ||
{ | ||
internal const int ExtensionLabel = 0xFF; | ||
|
||
public int BlockSize { get; private set; } | ||
public string ApplicationIdentifier { get; private set; } | ||
public byte[] AuthenticationCode { get; private set; } | ||
public byte[] Data { get; private set; } | ||
|
||
private GifApplicationExtension() | ||
{ | ||
} | ||
|
||
internal override GifBlockKind Kind | ||
{ | ||
get { return GifBlockKind.SpecialPurpose; } | ||
} | ||
|
||
internal static GifApplicationExtension ReadApplication(Stream stream) | ||
{ | ||
var ext = new GifApplicationExtension(); | ||
ext.Read(stream); | ||
return ext; | ||
} | ||
|
||
private void Read(Stream stream) | ||
{ | ||
// Note: at this point, the label (0xFF) has already been read | ||
|
||
byte[] bytes = new byte[12]; | ||
stream.ReadAll(bytes, 0, bytes.Length); | ||
BlockSize = bytes[0]; // should always be 11 | ||
if (BlockSize != 11) | ||
throw GifHelpers.InvalidBlockSizeException("Application Extension", 11, BlockSize); | ||
|
||
ApplicationIdentifier = Encoding.ASCII.GetString(bytes, 1, 8); | ||
byte[] authCode = new byte[3]; | ||
Array.Copy(bytes, 9, authCode, 0, 3); | ||
AuthenticationCode = authCode; | ||
Data = GifHelpers.ReadDataBlocks(stream, false); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System.Collections.Generic; | ||
using System.IO; | ||
|
||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
internal abstract class GifBlock | ||
{ | ||
internal static GifBlock ReadBlock(Stream stream, IEnumerable<GifExtension> controlExtensions, bool metadataOnly) | ||
{ | ||
int blockId = stream.ReadByte(); | ||
if (blockId < 0) | ||
throw GifHelpers.UnexpectedEndOfStreamException(); | ||
switch (blockId) | ||
{ | ||
case GifExtension.ExtensionIntroducer: | ||
return GifExtension.ReadExtension(stream, controlExtensions, metadataOnly); | ||
case GifFrame.ImageSeparator: | ||
return GifFrame.ReadFrame(stream, controlExtensions, metadataOnly); | ||
case GifTrailer.TrailerByte: | ||
return GifTrailer.ReadTrailer(); | ||
default: | ||
throw GifHelpers.UnknownBlockTypeException(blockId); | ||
} | ||
} | ||
|
||
internal abstract GifBlockKind Kind { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
internal enum GifBlockKind | ||
{ | ||
Control, | ||
GraphicRendering, | ||
SpecialPurpose, | ||
Other | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
internal struct GifColor | ||
{ | ||
private readonly byte _r; | ||
private readonly byte _g; | ||
private readonly byte _b; | ||
|
||
internal GifColor(byte r, byte g, byte b) | ||
{ | ||
_r = r; | ||
_g = g; | ||
_b = b; | ||
} | ||
|
||
public byte R { get { return _r; } } | ||
public byte G { get { return _g; } } | ||
public byte B { get { return _b; } } | ||
|
||
public override string ToString() | ||
{ | ||
return string.Format("#{0:x2}{1:x2}{2:x2}", _r, _g, _b); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System.IO; | ||
using System.Text; | ||
|
||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
internal class GifCommentExtension : GifExtension | ||
{ | ||
internal const int ExtensionLabel = 0xFE; | ||
|
||
public string Text { get; private set; } | ||
|
||
private GifCommentExtension() | ||
{ | ||
} | ||
|
||
internal override GifBlockKind Kind | ||
{ | ||
get { return GifBlockKind.SpecialPurpose; } | ||
} | ||
|
||
internal static GifCommentExtension ReadComment(Stream stream) | ||
{ | ||
var comment = new GifCommentExtension(); | ||
comment.Read(stream); | ||
return comment; | ||
} | ||
|
||
private void Read(Stream stream) | ||
{ | ||
// Note: at this point, the label (0xFE) has already been read | ||
|
||
var bytes = GifHelpers.ReadDataBlocks(stream, false); | ||
if (bytes != null) | ||
Text = Encoding.ASCII.GetString(bytes); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using System; | ||
|
||
namespace WpfAnimatedGif.Decoding | ||
{ | ||
[Serializable] | ||
internal class GifDecoderException : Exception | ||
{ | ||
internal GifDecoderException() { } | ||
internal GifDecoderException(string message) : base(message) { } | ||
internal GifDecoderException(string message, Exception inner) : base(message, inner) { } | ||
protected GifDecoderException( | ||
System.Runtime.Serialization.SerializationInfo info, | ||
System.Runtime.Serialization.StreamingContext context) | ||
: base(info, context) { } | ||
} | ||
} |
Oops, something went wrong.