Skip to content

Commit 14a95a8

Browse files
Rename properties and add metadata tests
1 parent 66f444d commit 14a95a8

File tree

8 files changed

+83
-31
lines changed

8 files changed

+83
-31
lines changed

src/ImageSharp/Formats/Png/PngDecoderCore.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ private void ReadAnimationControlChunk(PngMetadata pngMetadata, ReadOnlySpan<byt
12581258
{
12591259
this.animationControl = AnimationControl.Parse(data);
12601260

1261-
pngMetadata.NumberPlays = this.animationControl.NumberPlays;
1261+
pngMetadata.RepeatCount = this.animationControl.NumberPlays;
12621262
}
12631263

12641264
/// <summary>

src/ImageSharp/Formats/Png/PngEncoderCore.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
176176

177177
if (image.Frames.Count > 1)
178178
{
179-
this.WriteAnimationControlChunk(stream, image.Frames.Count, pngMetadata.NumberPlays);
179+
this.WriteAnimationControlChunk(stream, image.Frames.Count, pngMetadata.RepeatCount);
180180

181181
// TODO: We should attempt to optimize the output by clipping the indexed result to
182182
// non-transparent bounds. That way we can assign frame control bounds and encode
@@ -996,8 +996,8 @@ private FrameControl WriteFrameControlChunk(Stream stream, ImageFrame imageFrame
996996
height: (uint)imageFrame.Height,
997997
xOffset: 0,
998998
yOffset: 0,
999-
delayNumerator: frameMetadata.DelayNumerator,
1000-
delayDenominator: frameMetadata.DelayDenominator,
999+
delayNumerator: (ushort)frameMetadata.FrameDelay.Numerator,
1000+
delayDenominator: (ushort)frameMetadata.FrameDelay.Denominator,
10011001
disposeOperation: frameMetadata.DisposalMethod,
10021002
blendOperation: frameMetadata.BlendMethod);
10031003

src/ImageSharp/Formats/Png/PngFrameMetadata.cs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,21 +23,18 @@ public PngFrameMetadata()
2323
/// <param name="other">The metadata to create an instance from.</param>
2424
private PngFrameMetadata(PngFrameMetadata other)
2525
{
26-
this.DelayNumerator = other.DelayNumerator;
27-
this.DelayDenominator = other.DelayDenominator;
26+
this.FrameDelay = other.FrameDelay;
2827
this.DisposalMethod = other.DisposalMethod;
2928
this.BlendMethod = other.BlendMethod;
3029
}
3130

3231
/// <summary>
33-
/// Gets or sets the frame delay fraction numerator
32+
/// Gets or sets the frame delay for animated images.
33+
/// If not 0, when utilized in Png animation, this field specifies the number of hundredths (1/100) of a second to
34+
/// wait before continuing with the processing of the Data Stream.
35+
/// The clock starts ticking immediately after the graphic is rendered.
3436
/// </summary>
35-
public ushort DelayNumerator { get; set; }
36-
37-
/// <summary>
38-
/// Gets or sets the frame delay fraction denominator
39-
/// </summary>
40-
public ushort DelayDenominator { get; set; }
37+
public Rational FrameDelay { get; set; }
4138

4239
/// <summary>
4340
/// Gets or sets the type of frame area disposal to be done after rendering this frame
@@ -55,8 +52,7 @@ private PngFrameMetadata(PngFrameMetadata other)
5552
/// <param name="frameControl">The chunk to create an instance from.</param>
5653
internal void FromChunk(in FrameControl frameControl)
5754
{
58-
this.DelayNumerator = frameControl.DelayNumerator;
59-
this.DelayDenominator = frameControl.DelayDenominator;
55+
this.FrameDelay = new Rational(frameControl.DelayNumerator, frameControl.DelayDenominator);
6056
this.DisposalMethod = frameControl.DisposeOperation;
6157
this.BlendMethod = frameControl.BlendOperation;
6258
}

src/ImageSharp/Formats/Png/PngMetadata.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ private PngMetadata(PngMetadata other)
2929
this.Gamma = other.Gamma;
3030
this.InterlaceMethod = other.InterlaceMethod;
3131
this.TransparentColor = other.TransparentColor;
32-
this.NumberPlays = other.NumberPlays;
32+
this.RepeatCount = other.RepeatCount;
3333

3434
if (other.ColorTable?.Length > 0)
3535
{
@@ -80,9 +80,9 @@ private PngMetadata(PngMetadata other)
8080
public IList<PngTextData> TextData { get; set; } = new List<PngTextData>();
8181

8282
/// <summary>
83-
/// Gets or sets the number of times to loop this APNG. 0 indicates infinite looping. TODO: RepeatCount!!
83+
/// Gets or sets the number of times to loop this APNG. 0 indicates infinite looping.
8484
/// </summary>
85-
public int NumberPlays { get; set; }
85+
public int RepeatCount { get; set; }
8686

8787
/// <inheritdoc/>
8888
public IDeepCloneable DeepClone() => new PngMetadata(this);

src/ImageSharp/Primitives/Rational.cs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public Rational(double value)
7070
/// <param name="bestPrecision">Whether to use the best possible precision when parsing the value.</param>
7171
public Rational(double value, bool bestPrecision)
7272
{
73-
var rational = LongRational.FromDouble(Math.Abs(value), bestPrecision);
73+
LongRational rational = LongRational.FromDouble(Math.Abs(value), bestPrecision);
7474

7575
this.Numerator = (uint)rational.Numerator;
7676
this.Denominator = (uint)rational.Denominator;
@@ -109,7 +109,7 @@ public Rational(double value, bool bestPrecision)
109109
/// <returns>
110110
/// The <see cref="Rational"/>.
111111
/// </returns>
112-
public static Rational FromDouble(double value) => new Rational(value, false);
112+
public static Rational FromDouble(double value) => new(value, false);
113113

114114
/// <summary>
115115
/// Converts the specified <see cref="double"/> to an instance of this type.
@@ -119,24 +119,19 @@ public Rational(double value, bool bestPrecision)
119119
/// <returns>
120120
/// The <see cref="Rational"/>.
121121
/// </returns>
122-
public static Rational FromDouble(double value, bool bestPrecision) => new Rational(value, bestPrecision);
122+
public static Rational FromDouble(double value, bool bestPrecision) => new(value, bestPrecision);
123123

124124
/// <inheritdoc/>
125125
public override bool Equals(object? obj) => obj is Rational other && this.Equals(other);
126126

127127
/// <inheritdoc/>
128128
public bool Equals(Rational other)
129-
{
130-
var left = new LongRational(this.Numerator, this.Denominator);
131-
var right = new LongRational(other.Numerator, other.Denominator);
132-
133-
return left.Equals(right);
134-
}
129+
=> this.Numerator == other.Numerator && this.Denominator == other.Denominator;
135130

136131
/// <inheritdoc/>
137132
public override int GetHashCode()
138133
{
139-
var self = new LongRational(this.Numerator, this.Denominator);
134+
LongRational self = new(this.Numerator, this.Denominator);
140135
return self.GetHashCode();
141136
}
142137

@@ -169,7 +164,7 @@ public override int GetHashCode()
169164
/// <returns>The <see cref="string"/></returns>
170165
public string ToString(IFormatProvider provider)
171166
{
172-
var rational = new LongRational(this.Numerator, this.Denominator);
167+
LongRational rational = new(this.Numerator, this.Denominator);
173168
return rational.ToString(provider);
174169
}
175170
}

tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,23 @@ public void Encode_APng<TPixel>(TestImageProvider<TPixel> provider)
457457
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
458458
ImageComparer.Exact.VerifySimilarity(output, image);
459459

460-
// TODO: Additional assertations regarding metadata.
461460
Assert.Equal(5, image.Frames.Count);
461+
Assert.Equal(image.Frames.Count, output.Frames.Count);
462+
463+
PngMetadata originalMetadata = image.Metadata.GetPngMetadata();
464+
PngMetadata outputMetadata = output.Metadata.GetPngMetadata();
465+
466+
Assert.Equal(originalMetadata.RepeatCount, outputMetadata.RepeatCount);
467+
468+
for (int i = 0; i < image.Frames.Count; i++)
469+
{
470+
PngFrameMetadata originalFrameMetadata = image.Frames[i].Metadata.GetPngFrameMetadata();
471+
PngFrameMetadata outputFrameMetadata = output.Frames[i].Metadata.GetPngFrameMetadata();
472+
473+
Assert.Equal(originalFrameMetadata.FrameDelay, outputFrameMetadata.FrameDelay);
474+
Assert.Equal(originalFrameMetadata.BlendMethod, outputFrameMetadata.BlendMethod);
475+
Assert.Equal(originalFrameMetadata.DisposalMethod, outputFrameMetadata.DisposalMethod);
476+
}
462477
}
463478

464479
[Theory]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using SixLabors.ImageSharp.Formats.Png;
5+
6+
namespace SixLabors.ImageSharp.Tests.Formats.Png;
7+
8+
[Trait("Format", "Png")]
9+
public class PngFrameMetadataTests
10+
{
11+
[Fact]
12+
public void CloneIsDeep()
13+
{
14+
PngFrameMetadata meta = new()
15+
{
16+
FrameDelay = new(1, 0),
17+
DisposalMethod = PngDisposalMethod.Background,
18+
BlendMethod = PngBlendMethod.Over,
19+
};
20+
21+
PngFrameMetadata clone = (PngFrameMetadata)meta.DeepClone();
22+
23+
Assert.True(meta.FrameDelay.Equals(clone.FrameDelay));
24+
Assert.True(meta.DisposalMethod.Equals(clone.DisposalMethod));
25+
Assert.True(meta.BlendMethod.Equals(clone.BlendMethod));
26+
27+
clone.FrameDelay = new(2, 1);
28+
clone.DisposalMethod = PngDisposalMethod.Previous;
29+
clone.BlendMethod = PngBlendMethod.Source;
30+
31+
Assert.False(meta.FrameDelay.Equals(clone.FrameDelay));
32+
Assert.False(meta.DisposalMethod.Equals(clone.DisposalMethod));
33+
Assert.False(meta.BlendMethod.Equals(clone.BlendMethod));
34+
}
35+
}

tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,33 @@ public void CloneIsDeep()
3131
ColorType = PngColorType.GrayscaleWithAlpha,
3232
InterlaceMethod = PngInterlaceMode.Adam7,
3333
Gamma = 2,
34-
TextData = new List<PngTextData> { new PngTextData("name", "value", "foo", "bar") }
34+
TextData = new List<PngTextData> { new PngTextData("name", "value", "foo", "bar") },
35+
RepeatCount = 123
3536
};
3637

3738
PngMetadata clone = (PngMetadata)meta.DeepClone();
3839

40+
Assert.True(meta.BitDepth == clone.BitDepth);
41+
Assert.True(meta.ColorType == clone.ColorType);
42+
Assert.True(meta.InterlaceMethod == clone.InterlaceMethod);
43+
Assert.True(meta.Gamma.Equals(clone.Gamma));
44+
Assert.False(meta.TextData.Equals(clone.TextData));
45+
Assert.True(meta.TextData.SequenceEqual(clone.TextData));
46+
Assert.True(meta.RepeatCount == clone.RepeatCount);
47+
3948
clone.BitDepth = PngBitDepth.Bit2;
4049
clone.ColorType = PngColorType.Palette;
4150
clone.InterlaceMethod = PngInterlaceMode.None;
4251
clone.Gamma = 1;
52+
clone.RepeatCount = 321;
4353

4454
Assert.False(meta.BitDepth == clone.BitDepth);
4555
Assert.False(meta.ColorType == clone.ColorType);
4656
Assert.False(meta.InterlaceMethod == clone.InterlaceMethod);
4757
Assert.False(meta.Gamma.Equals(clone.Gamma));
4858
Assert.False(meta.TextData.Equals(clone.TextData));
4959
Assert.True(meta.TextData.SequenceEqual(clone.TextData));
60+
Assert.False(meta.RepeatCount == clone.RepeatCount);
5061
}
5162

5263
[Theory]

0 commit comments

Comments
 (0)