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 = [];
foreach (int i in sequence)
for (int i = 0; i < sequence.Length; i++)
{
(ListIconChunkType type, Image<TPixel>? img) = frames[i];
byte? encodingWidth = null;
byte? encodingHeight = null;
bool isRootFrame = true;
int sequenceIndex = sequence[i];
(ListIconChunkType type, Image<TPixel>? img) = frames[sequenceIndex];
AniFrameMetadata aniFrameMetadata = new()
{
FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[sequenceIndex],
SequenceNumber = i
};
list.AddRange(img.Frames.Select(source =>
{
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));
}
AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
source.Metadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
switch (type)
{
case ListIconChunkType.Ico:
IcoFrameMetadata icoFrameMetadata = source.Metadata.GetIcoMetadata();
target.Metadata.SetFormatMetadata(IcoFormat.Instance, icoFrameMetadata);
if (isRootFrame)
{
encodingWidth ??= icoFrameMetadata.EncodingWidth;
encodingHeight ??= icoFrameMetadata.EncodingHeight;
}
// TODO source.Metadata.SetFormatMetadata(IcoFormat.Instance, null);
clonedMetadata.IcoFrameMetadata = icoFrameMetadata;
clonedMetadata.EncodingWidth = icoFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = icoFrameMetadata.EncodingHeight;
break;
case ListIconChunkType.Cur:
CurFrameMetadata curFrameMetadata = source.Metadata.GetCurMetadata();
target.Metadata.SetFormatMetadata(CurFormat.Instance, curFrameMetadata);
if (isRootFrame)
{
encodingWidth ??= curFrameMetadata.EncodingWidth;
encodingHeight ??= curFrameMetadata.EncodingHeight;
}
// TODO source.Metadata.SetFormatMetadata(CurFormat.Instance, null);
clonedMetadata.CurFrameMetadata = curFrameMetadata;
clonedMetadata.EncodingWidth = curFrameMetadata.EncodingWidth;
clonedMetadata.EncodingHeight = curFrameMetadata.EncodingHeight;
break;
case ListIconChunkType.Bmp:
if (isRootFrame)
{
encodingWidth = Narrow(source.Width);
encodingHeight = Narrow(source.Height);
}
clonedMetadata.EncodingWidth = Narrow(source.Width);
clonedMetadata.EncodingHeight = Narrow(source.Height);
break;
default:
break;
}
isRootFrame = false;
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)
@ -193,34 +179,62 @@ internal class AniDecoderCore : ImageDecoderCore
List<(ListIconChunkType Type, ImageInfo Info)> infoList = [];
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 = rootFrameMetadata.GetAniMetadata();
aniFrameMetadata.FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[i];
aniFrameMetadata.FrameCount = info.FrameMetadataCollection.Count;
aniFrameMetadata.EncodingWidth = type switch
AniFrameMetadata aniFrameMetadata = new()
{
ListIconChunkType.Bmp => Narrow(info.Width),
ListIconChunkType.Cur => rootFrameMetadata.GetCurMetadata().EncodingWidth,
ListIconChunkType.Ico => rootFrameMetadata.GetIcoMetadata().EncodingWidth,
_ => null
FrameDelay = rate.IsEmpty ? aniMetadata.DisplayRate : rate[sequenceIndex],
SequenceNumber = i
};
aniFrameMetadata.EncodingHeight = type switch
if (info.FrameMetadataCollection.Count is not 0)
{
ListIconChunkType.Bmp => Narrow(info.Height),
ListIconChunkType.Cur => rootFrameMetadata.GetCurMetadata().EncodingHeight,
ListIconChunkType.Ico => rootFrameMetadata.GetIcoMetadata().EncodingHeight,
_ => null
};
aniFrameMetadata.SubImageMetadata = info.Metadata;
aniMetadata.IconFrames.Add(rootFrameMetadata);
frameMetadataCollection.AddRange(
info.FrameMetadataCollection.Select(frameMetadata =>
{
AniFrameMetadata clonedMetadata = aniFrameMetadata.DeepClone();
frameMetadata.SetFormatMetadata(AniFormat.Instance, clonedMetadata);
switch (type)
{
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;
void IdentifyFrameChunk()

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

@ -1,7 +1,9 @@
// Copyright (c) Six Labors.
// 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;
namespace SixLabors.ImageSharp.Formats.Ani;
@ -24,9 +26,9 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
public uint FrameDelay { get; set; }
/// <summary>
/// Gets or sets the frames count of **one** "icon" chunk.
/// Gets or sets the sequence number of current frame.
/// </summary>
public int FrameCount { get; set; } = 1;
public int SequenceNumber { get; set; } = 1;
/// <summary>
/// Gets or sets the encoding width. <br />
@ -41,9 +43,21 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
public byte? EncodingHeight { get; set; }
/// <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>
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/>
public static AniFrameMetadata FromFormatConnectingFrameMetadata(FormatConnectingFrameMetadata metadata) =>
@ -70,7 +84,10 @@ public class AniFrameMetadata : IFormatFrameMetadata<AniFrameMetadata>
FrameDelay = this.FrameDelay,
EncodingHeight = this.EncodingHeight,
EncodingWidth = this.EncodingWidth,
FrameCount = this.FrameCount
SequenceNumber = this.SequenceNumber,
IsIco = this.IsIco,
IcoFrameMetadata = this.IcoFrameMetadata?.DeepClone(),
CurFrameMetadata = this.CurFrameMetadata?.DeepClone(),
// TODO SubImageMetadata
};

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

@ -70,11 +70,6 @@ public class AniMetadata : IFormatMetadata<AniMetadata>
/// </summary>
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/>
public static AniMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata)
=> throw new NotImplementedException();

Loading…
Cancel
Save