Browse Source

apply new metadata layout

pull/2899/head
Poker 1 year ago
parent
commit
ceb0d51fa9
No known key found for this signature in database GPG Key ID: C65A6AD457D5C8F8
  1. 126
      src/ImageSharp/Formats/Ani/AniDecoderCore.cs
  2. 29
      src/ImageSharp/Formats/Ani/AniFrameMetadata.cs
  3. 5
      src/ImageSharp/Formats/Ani/AniMetadata.cs

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

@ -59,12 +59,17 @@ internal class AniDecoderCore : ImageDecoderCore
List<ImageFrame<TPixel>> list = []; List<ImageFrame<TPixel>> list = [];
foreach (int i in sequence) for (int i = 0; i < sequence.Length; i++)
{ {
(ListIconChunkType type, Image<TPixel>? img) = frames[i]; int sequenceIndex = sequence[i];
byte? encodingWidth = null; (ListIconChunkType type, Image<TPixel>? img) = frames[sequenceIndex];
byte? encodingHeight = null;
bool isRootFrame = true; AniFrameMetadata aniFrameMetadata = new()
{
FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[sequenceIndex],
SequenceNumber = i
};
list.AddRange(img.Frames.Select(source => list.AddRange(img.Frames.Select(source =>
{ {
ImageFrame<TPixel> target = new(this.Options.Configuration, this.Dimensions); ImageFrame<TPixel> target = new(this.Options.Configuration, this.Dimensions);
@ -73,53 +78,34 @@ internal class AniDecoderCore : ImageDecoderCore
source.PixelBuffer.DangerousGetRowSpan(y).CopyTo(target.PixelBuffer.DangerousGetRowSpan(y)); source.PixelBuffer.DangerousGetRowSpan(y).CopyTo(target.PixelBuffer.DangerousGetRowSpan(y));
} }
AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
source.Metadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
switch (type) switch (type)
{ {
case ListIconChunkType.Ico: case ListIconChunkType.Ico:
IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata(); IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata();
target.Metadata.SetFormatMetadata(IcoFormat.Instance, icoFrameMetadata); // TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null);
if (isRootFrame) clonedMetadata.IcoFrameMetadata = icoFrameMetadata;
{ clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth;
encodingWidth ??= icoFrameMetadata.EncodingWidth; clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight;
encodingHeight ??= icoFrameMetadata.EncodingHeight;
}
break; break;
case ListIconChunkType.Cur: case ListIconChunkType.Cur:
CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata(); CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata();
target.Metadata.SetFormatMetadata(CurFormat.Instance, curFrameMetadata); // TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null);
if (isRootFrame) clonedMetadata.CurFrameMetadata = curFrameMetadata;
{ clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth;
encodingWidth ??= curFrameMetadata.EncodingWidth; clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight;
encodingHeight ??= curFrameMetadata.EncodingHeight;
}
break; break;
case ListIconChunkType.Bmp: case ListIconChunkType.Bmp:
if (isRootFrame) clonedMetadata.EncodingWidth = Narrow(source.Width);
{ clonedMetadata.EncodingHeight = Narrow(source.Height);
encodingWidth = Narrow(source.Width);
encodingHeight = Narrow(source.Height);
}
break; break;
default: default:
break; break;
} }
isRootFrame = false;
return target; return target;
})); }));
ImageFrameMetadata rootFrameMetadata = img.Frames.RootFrame.Metadata;
AniFrameMetadata aniFrameMetadata = rootFrameMetadata.GetAniMetadata();
aniFrameMetadata.FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[i];
aniFrameMetadata.FrameCount = img.Frames.Count;
aniFrameMetadata.EncodingWidth = encodingWidth;
aniFrameMetadata.EncodingHeight = encodingHeight;
aniFrameMetadata.SubImageMetadata = img.Metadata;
aniMetadata.IconFrames.Add(rootFrameMetadata);
} }
foreach ((ListIconChunkType _, Image<TPixel> img) in frames) foreach ((ListIconChunkType _, Image<TPixel> img) in frames)
@ -193,34 +179,62 @@ internal class AniDecoderCore : ImageDecoderCore
List<(ListIconChunkType Type, ImageInfo Info)> infoList = []; List<(ListIconChunkType 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);
ImageInfo imageInfo = new(this.Dimensions, metadata, (IReadOnlyList<ImageFrameMetadata>)aniMetadata.IconFrames); List<ImageFrameMetadata> frameMetadataCollection = new(sequence.Length);
foreach (int i in sequence) for (int i = 0; i < sequence.Length; i++)
{ {
(ListIconChunkType type, ImageInfo info) = infoList[i]; int sequenceIndex = sequence[i];
(ListIconChunkType type, ImageInfo info) = infoList[sequenceIndex];
ImageFrameMetadata rootFrameMetadata = imageInfo.FrameMetadataCollection is [var first, ..] ? first : new(); AniFrameMetadata aniFrameMetadata = new()
AniFrameMetadata aniFrameMetadata = rootFrameMetadata.GetAniMetadata();
aniFrameMetadata.FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[i];
aniFrameMetadata.FrameCount = info.FrameMetadataCollection.Count;
aniFrameMetadata.EncodingWidth = type switch
{ {
ListIconChunkType.Bmp => Narrow(info.Width), FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[sequenceIndex],
ListIconChunkType.Cur => rootFrameMetadata.GetCurMetadata().EncodingWidth, SequenceNumber = i
ListIconChunkType.Ico => rootFrameMetadata.GetIcoMetadata().EncodingWidth,
_ => null
}; };
aniFrameMetadata.EncodingHeight = type switch
if (info.FrameMetadataCollection.Count is not 0)
{ {
ListIconChunkType.Bmp => Narrow(info.Height), frameMetadataCollection.AddRange(
ListIconChunkType.Cur => rootFrameMetadata.GetCurMetadata().EncodingHeight, info.FrameMetadataCollection.Select(frameMetadata =>
ListIconChunkType.Ico => rootFrameMetadata.GetIcoMetadata().EncodingHeight, {
_ => null AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
}; frameMetadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
aniFrameMetadata.SubImageMetadata = info.Metadata; switch (type)
aniMetadata.IconFrames.Add(rootFrameMetadata); {
case ListIconChunkType.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:
CurFrameMetadata curFrameMetadata = frameMetadata.GetCurMetadata();
// TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null);
clonedMetadata.CurFrameMetadata = curFrameMetadata;
clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight;
break;
default:
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(type), "FrameMetadata must be ICO or CUR");
break;
}
return frameMetadata;
}));
}
else // BMP
{
aniFrameMetadata.EncodingWidth = Narrow(info.Width);
aniFrameMetadata.EncodingHeight = Narrow(info.Height);
ImageFrameMetadata frameMetadata = new();
frameMetadata.SetFormatMetadata(AniFormat.Instance, aniFrameMetadata);
frameMetadataCollection.Add(frameMetadata);
}
} }
ImageInfo imageInfo = new(this.Dimensions, metadata, frameMetadataCollection);
return imageInfo; return imageInfo;
void IdentifyFrameChunk() void IdentifyFrameChunk()

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

@ -1,7 +1,9 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using SixLabors.ImageSharp.Metadata; using System.Diagnostics.CodeAnalysis;
using SixLabors.ImageSharp.Formats.Cur;
using SixLabors.ImageSharp.Formats.Ico;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Ani; namespace SixLabors.ImageSharp.Formats.Ani;
@ -24,9 +26,9 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
public uint FrameDelay { get; set; } public uint FrameDelay { get; set; }
/// <summary> /// <summary>
/// Gets or sets the frames count of **one** "icon" chunk. /// Gets or sets the sequence number of current frame.
/// </summary> /// </summary>
public int FrameCount { get; set; } = 1; public int SequenceNumber { get; set; } = 1;
/// <summary> /// <summary>
/// Gets or sets the encoding width. <br /> /// Gets or sets the encoding width. <br />
@ -41,9 +43,21 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
public byte? EncodingHeight { get; set; } public byte? EncodingHeight { get; set; }
/// <summary> /// <summary>
/// Gets or sets the <see cref="ImageMetadata"/> of one "icon" chunk. /// Gets or sets a value indicating whether the frame will be encoded as an ICO or CUR file.
/// </summary> /// </summary>
public ImageMetadata? SubImageMetadata { get; set; } [MemberNotNullWhen(true, nameof(IcoFrameMetadata))]
[MemberNotNullWhen(false, nameof(CurFrameMetadata))]
public bool IsIco { get; set; }
/// <summary>
/// Gets or sets the <see cref="IcoFrameMetadata"/> of one "icon" chunk.
/// </summary>
public IcoFrameMetadata? IcoFrameMetadata { get; set; }
/// <summary>
/// Gets or sets the <see cref="CurFrameMetadata"/> of one "icon" chunk.
/// </summary>
public CurFrameMetadata? CurFrameMetadata { get; set; }
/// <inheritdoc/> /// <inheritdoc/>
public static AniFrameMetadata FromFormatConnectingFrameMetadata(FormatConnectingFrameMetadata metadata) => public static AniFrameMetadata FromFormatConnectingFrameMetadata(FormatConnectingFrameMetadata metadata) =>
@ -70,7 +84,10 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
FrameDelay = this.FrameDelay, FrameDelay = this.FrameDelay,
EncodingHeight = this.EncodingHeight, EncodingHeight = this.EncodingHeight,
EncodingWidth = this.EncodingWidth, EncodingWidth = this.EncodingWidth,
FrameCount = this.FrameCount SequenceNumber = this.SequenceNumber,
IsIco = this.IsIco,
IcoFrameMetadata = this.IcoFrameMetadata?.DeepClone(),
CurFrameMetadata = this.CurFrameMetadata?.DeepClone(),
// TODO SubImageMetadata // TODO SubImageMetadata
}; };

5
src/ImageSharp/Formats/Ani/AniMetadata.cs

@ -70,11 +70,6 @@ public class AniMetadata : IFormatMetadata<AniMetadata>
/// </summary> /// </summary>
public string? Artist { get; set; } public string? Artist { get; set; }
/// <summary>
/// Gets or sets the <see cref="ImageFrameMetadata"/> each "icon" chunk in ANI file.
/// </summary>
public IList<ImageFrameMetadata> IconFrames { get; set; } = [];
/// <inheritdoc/> /// <inheritdoc/>
public static AniMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) public static AniMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata)
=> throw new NotImplementedException(); => throw new NotImplementedException();

Loading…
Cancel
Save