Browse Source

update AniFrameFormat

pull/2899/head
Poker 2 years ago
parent
commit
256934344c
No known key found for this signature in database GPG Key ID: C65A6AD457D5C8F8
  1. 46
      src/ImageSharp/Formats/Ani/AniDecoderCore.cs
  2. 25
      src/ImageSharp/Formats/Ani/AniFrameFormat.cs
  3. 6
      src/ImageSharp/Formats/Ani/AniFrameMetadata.cs

46
src/ImageSharp/Formats/Ani/AniDecoderCore.cs

@ -36,13 +36,6 @@ internal class AniDecoderCore : ImageDecoderCore
: base(options) => : base(options) =>
this.configuration = options.Configuration; this.configuration = options.Configuration;
private enum ListIconChunkType : byte
{
Ico = 1,
Cur,
Bmp
}
protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken) protected override Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
{ {
this.currentStream = stream; this.currentStream = stream;
@ -54,7 +47,7 @@ internal class AniDecoderCore : ImageDecoderCore
ImageMetadata metadata = new(); ImageMetadata metadata = new();
AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata); AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata);
List<(ListIconChunkType Type, Image<TPixel> Image)> frames = []; List<(AniFrameFormat Type, Image<TPixel> Image)> frames = [];
this.HandleRiffChunk(out Span<int> sequence, out Span<uint> rate, dataStartPosition, dataSize, aniMetadata, frames, DecodeFrameChunk); this.HandleRiffChunk(out Span<int> sequence, out Span<uint> rate, dataStartPosition, dataSize, aniMetadata, frames, DecodeFrameChunk);
List<ImageFrame<TPixel>> list = []; List<ImageFrame<TPixel>> list = [];
@ -62,7 +55,7 @@ internal class AniDecoderCore : ImageDecoderCore
for (int i = 0; i < sequence.Length; i++) for (int i = 0; i < sequence.Length; i++)
{ {
int sequenceIndex = sequence[i]; int sequenceIndex = sequence[i];
(ListIconChunkType type, Image<TPixel>? img) = frames[sequenceIndex]; (AniFrameFormat type, Image<TPixel>? img) = frames[sequenceIndex];
AniFrameMetadata aniFrameMetadata = new() AniFrameMetadata aniFrameMetadata = new()
{ {
@ -80,23 +73,24 @@ internal class AniDecoderCore : ImageDecoderCore
AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone(); AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
source.Metadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata); source.Metadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
clonedMetadata.FrameFormat = type;
switch (type) switch (type)
{ {
case ListIconChunkType.Ico: case AniFrameFormat.Ico:
IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata(); IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata();
// TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null); // TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null);
clonedMetadata.IcoFrameMetadata = icoFrameMetadata; clonedMetadata.IcoFrameMetadata = icoFrameMetadata;
clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth; clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight; clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight;
break; break;
case ListIconChunkType.Cur: case AniFrameFormat.Cur:
CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata(); CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata();
// TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null); // TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null);
clonedMetadata.CurFrameMetadata = curFrameMetadata; clonedMetadata.CurFrameMetadata = curFrameMetadata;
clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth; clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight; clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight;
break; break;
case ListIconChunkType.Bmp: case AniFrameFormat.Bmp:
clonedMetadata.EncodingWidth = Narrow(source.Width); clonedMetadata.EncodingWidth = Narrow(source.Width);
clonedMetadata.EncodingHeight = Narrow(source.Height); clonedMetadata.EncodingHeight = Narrow(source.Height);
break; break;
@ -108,7 +102,7 @@ internal class AniDecoderCore : ImageDecoderCore
})); }));
} }
foreach ((ListIconChunkType _, Image<TPixel> img) in frames) foreach ((AniFrameFormat _, Image<TPixel> img) in frames)
{ {
img.Dispose(); img.Dispose();
} }
@ -128,7 +122,7 @@ internal class AniDecoderCore : ImageDecoderCore
long endPosition = this.currentStream.Position + chunk.Size; long endPosition = this.currentStream.Position + chunk.Size;
Image<TPixel>? frame = null; Image<TPixel>? frame = null;
ListIconChunkType type = default; AniFrameFormat type = default;
if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon)) if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon))
{ {
if (this.currentStream.TryReadUnmanaged(out IconDir dir)) if (this.currentStream.TryReadUnmanaged(out IconDir dir))
@ -139,11 +133,11 @@ internal class AniDecoderCore : ImageDecoderCore
{ {
case IconFileType.CUR: case IconFileType.CUR:
frame = CurDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream); frame = CurDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream);
type = ListIconChunkType.Cur; type = AniFrameFormat.Cur;
break; break;
case IconFileType.ICO: case IconFileType.ICO:
frame = IcoDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream); frame = IcoDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream);
type = ListIconChunkType.Ico; type = AniFrameFormat.Ico;
break; break;
} }
} }
@ -151,7 +145,7 @@ internal class AniDecoderCore : ImageDecoderCore
else else
{ {
frame = BmpDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream); frame = BmpDecoder.Instance.Decode<TPixel>(this.Options, this.currentStream);
type = ListIconChunkType.Bmp; type = AniFrameFormat.Bmp;
} }
if (frame is not null) if (frame is not null)
@ -176,7 +170,7 @@ internal class AniDecoderCore : ImageDecoderCore
ImageMetadata metadata = new(); ImageMetadata metadata = new();
AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata); AniMetadata aniMetadata = this.ReadHeader(dataStartPosition, dataSize, metadata);
List<(ListIconChunkType Type, ImageInfo Info)> infoList = []; List<(AniFrameFormat Type, ImageInfo Info)> infoList = [];
this.HandleRiffChunk(out Span<int> sequence, out Span<uint> rate, dataStartPosition, dataSize, aniMetadata, infoList, IdentifyFrameChunk); this.HandleRiffChunk(out Span<int> sequence, out Span<uint> rate, dataStartPosition, dataSize, aniMetadata, infoList, IdentifyFrameChunk);
List<ImageFrameMetadata> frameMetadataCollection = new(sequence.Length); List<ImageFrameMetadata> frameMetadataCollection = new(sequence.Length);
@ -184,7 +178,7 @@ internal class AniDecoderCore : ImageDecoderCore
for (int i = 0; i < sequence.Length; i++) for (int i = 0; i < sequence.Length; i++)
{ {
int sequenceIndex = sequence[i]; int sequenceIndex = sequence[i];
(ListIconChunkType type, ImageInfo info) = infoList[sequenceIndex]; (AniFrameFormat type, ImageInfo info) = infoList[sequenceIndex];
AniFrameMetadata aniFrameMetadata = new() AniFrameMetadata aniFrameMetadata = new()
{ {
@ -199,16 +193,17 @@ internal class AniDecoderCore : ImageDecoderCore
{ {
AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone(); AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
frameMetadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata); frameMetadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
clonedMetadata.FrameFormat = type;
switch (type) switch (type)
{ {
case ListIconChunkType.Ico: case AniFrameFormat.Ico:
IcoFrameMetadata icoFrameMetadata = frameMetadata.GetIcoMetadata(); IcoFrameMetadata icoFrameMetadata = frameMetadata.GetIcoMetadata();
// TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null); // TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null);
clonedMetadata.IcoFrameMetadata = icoFrameMetadata; clonedMetadata.IcoFrameMetadata = icoFrameMetadata;
clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth; clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight; clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight;
break; break;
case ListIconChunkType.Cur: case AniFrameFormat.Cur:
CurFrameMetadata curFrameMetadata = frameMetadata.GetCurMetadata(); CurFrameMetadata curFrameMetadata = frameMetadata.GetCurMetadata();
// TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null); // TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null);
clonedMetadata.CurFrameMetadata = curFrameMetadata; clonedMetadata.CurFrameMetadata = curFrameMetadata;
@ -227,6 +222,7 @@ internal class AniDecoderCore : ImageDecoderCore
{ {
aniFrameMetadata.EncodingWidth = Narrow(info.Width); aniFrameMetadata.EncodingWidth = Narrow(info.Width);
aniFrameMetadata.EncodingHeight = Narrow(info.Height); aniFrameMetadata.EncodingHeight = Narrow(info.Height);
aniFrameMetadata.FrameFormat = type;
ImageFrameMetadata frameMetadata = new(); ImageFrameMetadata frameMetadata = new();
frameMetadata.SetFormatMetadata(AniFormat.Instance, aniFrameMetadata); frameMetadata.SetFormatMetadata(AniFormat.Instance, aniFrameMetadata);
frameMetadataCollection.Add(frameMetadata); frameMetadataCollection.Add(frameMetadata);
@ -248,7 +244,7 @@ internal class AniDecoderCore : ImageDecoderCore
long endPosition = this.currentStream.Position + chunk.Size; long endPosition = this.currentStream.Position + chunk.Size;
ImageInfo? info = null; ImageInfo? info = null;
ListIconChunkType type = default; AniFrameFormat type = default;
if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon)) if (aniMetadata.Flags.HasFlag(AniHeaderFlags.IsIcon))
{ {
if (this.currentStream.TryReadUnmanaged(out IconDir dir)) if (this.currentStream.TryReadUnmanaged(out IconDir dir))
@ -259,11 +255,11 @@ internal class AniDecoderCore : ImageDecoderCore
{ {
case IconFileType.CUR: case IconFileType.CUR:
info = CurDecoder.Instance.Identify(this.Options, this.currentStream); info = CurDecoder.Instance.Identify(this.Options, this.currentStream);
type = ListIconChunkType.Cur; type = AniFrameFormat.Cur;
break; break;
case IconFileType.ICO: case IconFileType.ICO:
info = IcoDecoder.Instance.Identify(this.Options, this.currentStream); info = IcoDecoder.Instance.Identify(this.Options, this.currentStream);
type = ListIconChunkType.Ico; type = AniFrameFormat.Ico;
break; break;
} }
} }
@ -271,7 +267,7 @@ internal class AniDecoderCore : ImageDecoderCore
else else
{ {
info = BmpDecoder.Instance.Identify(this.Options, this.currentStream); info = BmpDecoder.Instance.Identify(this.Options, this.currentStream);
type = ListIconChunkType.Bmp; type = AniFrameFormat.Bmp;
} }
if (info is not null) if (info is not null)

25
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;
/// <summary>
/// Specifies the format of the frame data.
/// </summary>
public enum AniFrameFormat
{
/// <summary>
/// The frame data is in ICO format.
/// </summary>
Ico = 1,
/// <summary>
/// The frame data is in CUR format.
/// </summary>
Cur,
/// <summary>
/// The frame data is in BMP format.
/// </summary>
Bmp
}

6
src/ImageSharp/Formats/Ani/AniFrameMetadata.cs

@ -43,11 +43,9 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
public byte? EncodingHeight { get; set; } public byte? EncodingHeight { get; set; }
/// <summary> /// <summary>
/// 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.
/// </summary> /// </summary>
[MemberNotNullWhen(true, nameof(IcoFrameMetadata))] public AniFrameFormat FrameFormat { get; set; }
[MemberNotNullWhen(false, nameof(CurFrameMetadata))]
public bool IsIco { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="IcoFrameMetadata"/> of one "icon" chunk. /// Gets or sets the <see cref="IcoFrameMetadata"/> of one "icon" chunk.

Loading…
Cancel
Save