diff --git a/src/ImageSharp/Formats/Ani/AniDecoderCore.cs b/src/ImageSharp/Formats/Ani/AniDecoderCore.cs index 539c3db2d5..57f9d4031f 100644 --- a/src/ImageSharp/Formats/Ani/AniDecoderCore.cs +++ b/src/ImageSharp/Formats/Ani/AniDecoderCore.cs @@ -36,13 +36,6 @@ internal class AniDecoderCore : ImageDecoderCore : base(options) => this.configuration = options.Configuration; - private enum ListIconChunkType : byte - { - Ico = 1, - Cur, - Bmp - } - protected override Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) { this.currentStream = stream; @@ -54,7 +47,7 @@ internal class AniDecoderCore : ImageDecoderCore ImageMetadata metadata = new(); AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata); - List<(ListIconChunkType Type, Image Image)> frames = []; + List<(AniFrameFormat Type, Image Image)> frames = []; this.HandleRiffChunk(out Span sequence, out Span rate, dataStartPosition, dataSize, aniMetadata, frames, DecodeFrameChunk); List> list = []; @@ -62,7 +55,7 @@ internal class AniDecoderCore : ImageDecoderCore for (int i = 0; i < sequence.Length; i++) { int sequenceIndex = sequence[i]; - (ListIconChunkType type, Image? img) = frames[sequenceIndex]; + (AniFrameFormat type, Image? img) = frames[sequenceIndex]; AniFrameMetadata aniFrameMetadata = new() { @@ -80,23 +73,24 @@ internal class AniDecoderCore : ImageDecoderCore AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone(); source.Metadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata); + clonedMetadata.FrameFormat = type; switch (type) { - case ListIconChunkType.Ico: + case AniFrameFormat.Ico: IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata(); // TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null); clonedMetadata.IcoFrameMetadata = icoFrameMetadata; clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth; clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight; break; - case ListIconChunkType.Cur: + case AniFrameFormat.Cur: CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata(); // TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null); clonedMetadata.CurFrameMetadata = curFrameMetadata; clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth; clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight; break; - case ListIconChunkType.Bmp: + case AniFrameFormat.Bmp: clonedMetadata.EncodingWidth = Narrow(source.Width); clonedMetadata.EncodingHeight = Narrow(source.Height); break; @@ -108,7 +102,7 @@ internal class AniDecoderCore : ImageDecoderCore })); } - foreach ((ListIconChunkType _, Image img) in frames) + foreach ((AniFrameFormat _, Image img) in frames) { img.Dispose(); } @@ -128,7 +122,7 @@ internal class AniDecoderCore : ImageDecoderCore long endPosition = this.currentStream.Position + chunk.Size; Image? frame = null; - ListIconChunkType type = default; + AniFrameFormat type = default; if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon)) { if (this.currentStream.TryReadUnmanaged(out IconDir dir)) @@ -139,11 +133,11 @@ internal class AniDecoderCore : ImageDecoderCore { case IconFileType.CUR: frame = CurDecoder.Instance.Decode(this.Options, this.currentStream); - type = ListIconChunkType.Cur; + type = AniFrameFormat.Cur; break; case IconFileType.ICO: frame = IcoDecoder.Instance.Decode(this.Options, this.currentStream); - type = ListIconChunkType.Ico; + type = AniFrameFormat.Ico; break; } } @@ -151,7 +145,7 @@ internal class AniDecoderCore : ImageDecoderCore else { frame = BmpDecoder.Instance.Decode(this.Options, this.currentStream); - type = ListIconChunkType.Bmp; + type = AniFrameFormat.Bmp; } if (frame is not null) @@ -176,7 +170,7 @@ internal class AniDecoderCore : ImageDecoderCore ImageMetadata metadata = new(); AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata); - List<(ListIconChunkType Type, ImageInfo Info)> infoList = []; + List<(AniFrameFormat Type, ImageInfo Info)> infoList = []; this.HandleRiffChunk(out Span sequence, out Span rate, dataStartPosition, dataSize, aniMetadata, infoList, IdentifyFrameChunk); List frameMetadataCollection = new(sequence.Length); @@ -184,7 +178,7 @@ internal class AniDecoderCore : ImageDecoderCore for (int i = 0; i < sequence.Length; i++) { int sequenceIndex = sequence[i]; - (ListIconChunkType type, ImageInfo info) = infoList[sequenceIndex]; + (AniFrameFormat type, ImageInfo info) = infoList[sequenceIndex]; AniFrameMetadata aniFrameMetadata = new() { @@ -199,16 +193,17 @@ internal class AniDecoderCore : ImageDecoderCore { AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone(); frameMetadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata); + clonedMetadata.FrameFormat = type; switch (type) { - case ListIconChunkType.Ico: + case AniFrameFormat.Ico: IcoFrameMetadata icoFrameMetadata = frameMetadata.GetIcoMetadata(); // TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null); clonedMetadata.IcoFrameMetadata = icoFrameMetadata; clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth; clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight; break; - case ListIconChunkType.Cur: + case AniFrameFormat.Cur: CurFrameMetadata curFrameMetadata = frameMetadata.GetCurMetadata(); // TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null); clonedMetadata.CurFrameMetadata = curFrameMetadata; @@ -227,6 +222,7 @@ internal class AniDecoderCore : ImageDecoderCore { aniFrameMetadata.EncodingWidth = Narrow(info.Width); aniFrameMetadata.EncodingHeight = Narrow(info.Height); + aniFrameMetadata.FrameFormat = type; ImageFrameMetadata frameMetadata = new(); frameMetadata.SetFormatMetadata(AniFormat.Instance, aniFrameMetadata); frameMetadataCollection.Add(frameMetadata); @@ -248,7 +244,7 @@ internal class AniDecoderCore : ImageDecoderCore long endPosition = this.currentStream.Position + chunk.Size; ImageInfo? info = null; - ListIconChunkType type = default; + AniFrameFormat type = default; if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon)) { if (this.currentStream.TryReadUnmanaged(out IconDir dir)) @@ -259,11 +255,11 @@ internal class AniDecoderCore : ImageDecoderCore { case IconFileType.CUR: info = CurDecoder.Instance.Identify(this.Options, this.currentStream); - type = ListIconChunkType.Cur; + type = AniFrameFormat.Cur; break; case IconFileType.ICO: info = IcoDecoder.Instance.Identify(this.Options, this.currentStream); - type = ListIconChunkType.Ico; + type = AniFrameFormat.Ico; break; } } @@ -271,7 +267,7 @@ internal class AniDecoderCore : ImageDecoderCore else { info = BmpDecoder.Instance.Identify(this.Options, this.currentStream); - type = ListIconChunkType.Bmp; + type = AniFrameFormat.Bmp; } if (info is not null) diff --git a/src/ImageSharp/Formats/Ani/AniFrameFormat.cs b/src/ImageSharp/Formats/Ani/AniFrameFormat.cs new file mode 100644 index 0000000000..661aae7fc3 --- /dev/null +++ b/src/ImageSharp/Formats/Ani/AniFrameFormat.cs @@ -0,0 +1,25 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Ani; + +/// +/// Specifies the format of the frame data. +/// +public enum AniFrameFormat +{ + /// + /// The frame data is in ICO format. + /// + Ico = 1, + + /// + /// The frame data is in CUR format. + /// + Cur, + + /// + /// The frame data is in BMP format. + /// + Bmp +} diff --git a/src/ImageSharp/Formats/Ani/AniFrameMetadata.cs b/src/ImageSharp/Formats/Ani/AniFrameMetadata.cs index 6e7f220bd6..f024c1c8ad 100644 --- a/src/ImageSharp/Formats/Ani/AniFrameMetadata.cs +++ b/src/ImageSharp/Formats/Ani/AniFrameMetadata.cs @@ -43,11 +43,9 @@ public class AniFrameMetadata : IFormatFrameMetadata public byte? EncodingHeight { get; set; } /// - /// Gets or sets a value indicating whether the frame will be encoded as an ICO or CUR file. + /// Gets or sets a value indicating whether the frame will be encoded as an ICO or CUR or BMP file. /// - [MemberNotNullWhen(true, nameof(IcoFrameMetadata))] - [MemberNotNullWhen(false, nameof(CurFrameMetadata))] - public bool IsIco { get; set; } + public AniFrameFormat FrameFormat { get; set; } /// /// Gets or sets the of one "icon" chunk.