@@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Gif;
99/// <summary>
1010/// Provides Gif specific metadata information for the image frame.
1111/// </summary>
12- public class GifFrameMetadata : IDeepCloneable
12+ public class GifFrameMetadata : IFormatFrameMetadata < GifFrameMetadata >
1313{
1414 /// <summary>
1515 /// Initializes a new instance of the <see cref="GifFrameMetadata"/> class.
@@ -73,10 +73,65 @@ private GifFrameMetadata(GifFrameMetadata other)
7373 /// Primarily used in Gif animation, this field indicates the way in which the graphic is to
7474 /// be treated after being displayed.
7575 /// </summary>
76- public GifDisposalMethod DisposalMethod { get ; set ; }
76+ public FrameDisposalMode DisposalMethod { get ; set ; }
77+
78+ /// <inheritdoc />
79+ public static GifFrameMetadata FromFormatConnectingFrameMetadata ( FormatConnectingFrameMetadata metadata )
80+ {
81+ int index = - 1 ;
82+ const float background = 1f ;
83+ if ( metadata . ColorTable . HasValue )
84+ {
85+ ReadOnlySpan < Color > colorTable = metadata . ColorTable . Value . Span ;
86+ for ( int i = 0 ; i < colorTable . Length ; i ++ )
87+ {
88+ Vector4 vector = colorTable [ i ] . ToScaledVector4 ( ) ;
89+ if ( vector . W < background )
90+ {
91+ index = i ;
92+ }
93+ }
94+ }
95+
96+ bool hasTransparency = index >= 0 ;
97+
98+ return new ( )
99+ {
100+ LocalColorTable = metadata . ColorTable ,
101+ ColorTableMode = metadata . ColorTableMode ,
102+ FrameDelay = ( int ) Math . Round ( metadata . Duration . TotalMilliseconds / 10 ) ,
103+ DisposalMethod = metadata . DisposalMode ,
104+ HasTransparency = hasTransparency ,
105+ TransparencyIndex = hasTransparency ? unchecked ( ( byte ) index ) : byte . MinValue ,
106+ } ;
107+ }
108+
109+ /// <inheritdoc />
110+ public FormatConnectingFrameMetadata ToFormatConnectingFrameMetadata ( )
111+ {
112+ // throw new NotImplementedException();
113+ // For most scenarios we would consider the blend method to be 'Over' however if a frame has a disposal method of 'RestoreToBackground' or
114+ // has a local palette with 256 colors and is not transparent we should use 'Source'.
115+ bool blendSource = this . DisposalMethod == FrameDisposalMode . RestoreToBackground || ( this . LocalColorTable ? . Length == 256 && ! this . HasTransparency ) ;
116+
117+ // If the color table is global and frame has no transparency. Consider it 'Source' also.
118+ blendSource |= this . ColorTableMode == FrameColorTableMode . Global && ! this . HasTransparency ;
119+
120+ return new ( )
121+ {
122+ ColorTable = this . LocalColorTable ,
123+ ColorTableMode = this . ColorTableMode ,
124+ Duration = TimeSpan . FromMilliseconds ( this . FrameDelay * 10 ) ,
125+ DisposalMode = this . DisposalMethod ,
126+ BlendMode = blendSource ? FrameBlendMode . Source : FrameBlendMode . Over ,
127+ } ;
128+ }
129+
130+ /// <inheritdoc/>
131+ IDeepCloneable IDeepCloneable . DeepClone ( ) => this . DeepClone ( ) ;
77132
78133 /// <inheritdoc/>
79- public IDeepCloneable DeepClone ( ) => new GifFrameMetadata ( this ) ;
134+ public GifFrameMetadata DeepClone ( ) => new ( this ) ;
80135
81136 internal static GifFrameMetadata FromAnimatedMetadata ( AnimatedImageFrameMetadata metadata )
82137 {
@@ -103,17 +158,9 @@ internal static GifFrameMetadata FromAnimatedMetadata(AnimatedImageFrameMetadata
103158 LocalColorTable = metadata . ColorTable ,
104159 ColorTableMode = metadata . ColorTableMode ,
105160 FrameDelay = ( int ) Math . Round ( metadata . Duration . TotalMilliseconds / 10 ) ,
106- DisposalMethod = GetMode ( metadata . DisposalMode ) ,
161+ DisposalMethod = metadata . DisposalMode ,
107162 HasTransparency = hasTransparency ,
108163 TransparencyIndex = hasTransparency ? unchecked ( ( byte ) index ) : byte . MinValue ,
109164 } ;
110165 }
111-
112- private static GifDisposalMethod GetMode ( FrameDisposalMode mode ) => mode switch
113- {
114- FrameDisposalMode . DoNotDispose => GifDisposalMethod . NotDispose ,
115- FrameDisposalMode . RestoreToBackground => GifDisposalMethod . RestoreToBackground ,
116- FrameDisposalMode . RestoreToPrevious => GifDisposalMethod . RestoreToPrevious ,
117- _ => GifDisposalMethod . Unspecified ,
118- } ;
119166}
0 commit comments