Skip to content

Commit 66f444d

Browse files
Fix alpha blending and add tests
1 parent 56588d3 commit 66f444d

File tree

58 files changed

+302
-104
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+302
-104
lines changed

src/ImageSharp/Formats/Png/PngDecoderCore.cs

Lines changed: 105 additions & 69 deletions
Large diffs are not rendered by default.

src/ImageSharp/ImageFrameCollection{TPixel}.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the Six Labors Split License.
33

44
using System.Collections;
5-
using SixLabors.ImageSharp.Advanced;
65
using SixLabors.ImageSharp.Memory;
76
using SixLabors.ImageSharp.PixelFormats;
87

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

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@ public partial class PngDecoderTests
7878
{ TestImages.Png.Rgba64Bpp, typeof(Image<Rgba64>) },
7979
};
8080

81+
public static readonly string[] MultiFrameTestFiles =
82+
{
83+
//TestImages.Png.APng,
84+
//TestImages.Png.SplitIDatZeroLength,
85+
//TestImages.Png.DisposeNone,
86+
//TestImages.Png.DisposeBackground,
87+
//TestImages.Png.DisposeBackgroundRegion,
88+
//TestImages.Png.DisposePreviousFirst,
89+
//TestImages.Png.DisposeBackgroundBeforeRegion,
90+
TestImages.Png.BlendOverMultiple
91+
};
92+
8193
[Theory]
8294
[MemberData(nameof(PixelFormatRange))]
8395
public void Decode_NonGeneric_CreatesCorrectImageType(string path, Type type)
@@ -107,16 +119,16 @@ public void Decode<TPixel>(TestImageProvider<TPixel> provider)
107119
}
108120

109121
[Theory]
110-
[WithFile(TestImages.Png.APng, PixelTypes.Rgba32)]
111-
public void Decode_APng<TPixel>(TestImageProvider<TPixel> provider)
112-
where TPixel : unmanaged, IPixel<TPixel>
122+
[WithFileCollection(nameof(MultiFrameTestFiles), PixelTypes.Rgba32)]
123+
public void Decode_VerifyAllFrames<TPixel>(TestImageProvider<TPixel> provider)
124+
where TPixel : unmanaged, IPixel<TPixel>
113125
{
114126
using Image<TPixel> image = provider.GetImage(PngDecoder.Instance);
115127

116-
Assert.Equal(5, image.Frames.Count);
117-
118-
// TODO: Assertations.
119-
// MagickReferenceDecoder cannot decode APNGs (Though ImageMagick can, we likely need to update our mapping implementation)
128+
// Some images have many frames, only compare a selection of them.
129+
static bool Predicate(int i, int _) => i <= 8 || i % 8 == 0;
130+
image.DebugSaveMultiFrame(provider, predicate: Predicate);
131+
image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact, predicate: Predicate);
120132
}
121133

122134
[Theory]

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,17 @@ public static class Png
6161
public const string TestPattern31x31 = "Png/testpattern31x31.png";
6262
public const string TestPattern31x31HalfTransparent = "Png/testpattern31x31-halftransparent.png";
6363
public const string XmpColorPalette = "Png/xmp-colorpalette.png";
64-
public const string APng = "Png/apng.png";
64+
65+
// Animated
66+
// https://philip.html5.org/tests/apng/tests.html
67+
public const string APng = "Png/animated/apng.png";
68+
public const string SplitIDatZeroLength = "Png/animated/4-split-idat-zero-length.png";
69+
public const string DisposeNone = "Png/animated/7-dispose-none.png";
70+
public const string DisposeBackground = "Png/animated/8-dispose-background.png";
71+
public const string DisposeBackgroundBeforeRegion = "Png/animated/14-dispose-background-before-region.png";
72+
public const string DisposeBackgroundRegion = "Png/animated/15-dispose-background-region.png";
73+
public const string DisposePreviousFirst = "Png/animated/12-dispose-prev-first.png";
74+
public const string BlendOverMultiple = "Png/animated/21-blend-over-multiple.png";
6575

6676
// Filtered test images from http://www.schaik.com/pngsuite/pngsuite_fil_png.html
6777
public const string Filter0 = "Png/filter0.png";

tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public string SaveTestOutputFile(
179179
return path;
180180
}
181181

182-
public IEnumerable<string> GetTestOutputFileNamesMultiFrame(
182+
public IEnumerable<(int Index, string FileName)> GetTestOutputFileNamesMultiFrame(
183183
int frameCount,
184184
string extension = null,
185185
object testOutputDetails = null,
@@ -201,11 +201,11 @@ public IEnumerable<string> GetTestOutputFileNamesMultiFrame(
201201
continue;
202202
}
203203

204-
yield return $"{baseDir}/{i:D2}.{extension}";
204+
yield return (i, $"{baseDir}/{i:D2}.{extension}");
205205
}
206206
}
207207

208-
public string[] SaveTestOutputFileMultiFrame<TPixel>(
208+
public (int Index, string FileName)[] SaveTestOutputFileMultiFrame<TPixel>(
209209
Image<TPixel> image,
210210
string extension = "png",
211211
IImageEncoder encoder = null,
@@ -216,27 +216,17 @@ public string[] SaveTestOutputFileMultiFrame<TPixel>(
216216
{
217217
encoder ??= TestEnvironment.GetReferenceEncoder($"foo.{extension}");
218218

219-
string[] files = this.GetTestOutputFileNamesMultiFrame(
219+
(int Index, string FileName)[] files = this.GetTestOutputFileNamesMultiFrame(
220220
image.Frames.Count,
221221
extension,
222222
testOutputDetails,
223223
appendPixelTypeToFileName,
224224
predicate: predicate).ToArray();
225225

226-
for (int i = 0; i < image.Frames.Count; i++)
226+
foreach ((int Index, string FileName) file in files)
227227
{
228-
if (predicate != null && !predicate(i, image.Frames.Count))
229-
{
230-
continue;
231-
}
232-
233-
if (i >= files.Length)
234-
{
235-
break;
236-
}
237-
238-
using Image<TPixel> frameImage = image.Frames.CloneFrame(i);
239-
string filePath = files[i];
228+
using Image<TPixel> frameImage = image.Frames.CloneFrame(file.Index);
229+
string filePath = file.FileName;
240230
using FileStream stream = File.OpenWrite(filePath);
241231
frameImage.Save(stream, encoder);
242232
}
@@ -252,14 +242,14 @@ internal string GetReferenceOutputFileName(
252242
=> TestEnvironment.GetReferenceOutputFileName(
253243
this.GetTestOutputFileName(extension, testOutputDetails, appendPixelTypeToFileName, appendSourceFileOrDescription));
254244

255-
public string[] GetReferenceOutputFileNamesMultiFrame(
245+
public (int Index, string FileName)[] GetReferenceOutputFileNamesMultiFrame(
256246
int frameCount,
257247
string extension,
258248
object testOutputDetails,
259249
bool appendPixelTypeToFileName = true,
260250
Func<int, int, bool> predicate = null)
261251
=> this.GetTestOutputFileNamesMultiFrame(frameCount, extension, testOutputDetails, appendPixelTypeToFileName, predicate: predicate)
262-
.Select(TestEnvironment.GetReferenceOutputFileName).ToArray();
252+
.Select(x => (x.Index, TestEnvironment.GetReferenceOutputFileName(x.FileName))).ToArray();
263253

264254
internal void Init(string typeName, string methodName, string outputSubfolderName)
265255
{

tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ public static Image<TPixel> GetReferenceOutputImageMultiFrame<TPixel>(
336336
Func<int, int, bool> predicate = null)
337337
where TPixel : unmanaged, IPixel<TPixel>
338338
{
339-
string[] frameFiles = provider.Utility.GetReferenceOutputFileNamesMultiFrame(
339+
(int Index, string FileName)[] frameFiles = provider.Utility.GetReferenceOutputFileNamesMultiFrame(
340340
frameCount,
341341
extension,
342342
testOutputDetails,
@@ -345,10 +345,11 @@ public static Image<TPixel> GetReferenceOutputImageMultiFrame<TPixel>(
345345

346346
List<Image<TPixel>> temporaryFrameImages = new();
347347

348-
IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0]);
348+
IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0].FileName);
349349

350-
foreach (string path in frameFiles)
350+
for (int i = 0; i < frameFiles.Length; i++)
351351
{
352+
string path = frameFiles[i].FileName;
352353
if (!File.Exists(path))
353354
{
354355
throw new FileNotFoundException("Reference output file missing: " + path);

tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,13 @@ public void SaveTestOutputFileMultiFrame<TPixel>(TestImageProvider<TPixel> provi
200200
where TPixel : unmanaged, IPixel<TPixel>
201201
{
202202
using Image<TPixel> image = provider.GetImage();
203-
string[] files = provider.Utility.SaveTestOutputFileMultiFrame(image);
203+
(int Index, string FileName)[] files = provider.Utility.SaveTestOutputFileMultiFrame(image);
204204

205205
Assert.True(files.Length > 2);
206-
foreach (string path in files)
206+
foreach ((int Index, string FileName) file in files)
207207
{
208-
this.Output.WriteLine(path);
209-
Assert.True(File.Exists(path));
208+
this.Output.WriteLine(file.FileName);
209+
Assert.True(File.Exists(file.FileName));
210210
}
211211
}
212212

Lines changed: 3 additions & 0 deletions
Lines changed: 3 additions & 0 deletions
Lines changed: 3 additions & 0 deletions

0 commit comments

Comments
 (0)