From c573228b0900ea160103e5383a9bdd2802de3323 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 17 Mar 2025 16:52:45 +1000 Subject: [PATCH] Upstream fixes. --- .../Formats/Cur/CurFrameMetadata.cs | 2 - src/ImageSharp/Formats/Cur/CurMetadata.cs | 6 +- .../Formats/FormatConnectingFrameMetadata.cs | 5 - .../Formats/FormatConnectingMetadata.cs | 5 - src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 101 +++++++++++++----- .../Formats/Gif/GifFrameMetadata.cs | 26 +---- src/ImageSharp/Formats/Gif/GifMetadata.cs | 37 +------ .../Formats/Ico/IcoFrameMetadata.cs | 4 +- src/ImageSharp/Formats/Ico/IcoMetadata.cs | 6 +- .../Formats/Icon/IconEncoderCore.cs | 16 ++- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 3 +- src/ImageSharp/Formats/Png/PngMetadata.cs | 21 ---- .../Formats/Webp/Lossy/Vp8Decoder.cs | 10 +- .../Quantization/EuclideanPixelMap{TPixel}.cs | 10 +- .../Formats/Gif/GifDecoderTests.cs | 35 ++++++ .../Formats/Gif/GifEncoderTests.cs | 12 ++- .../Formats/Icon/Cur/CurEncoderTests.cs | 5 +- .../Formats/Png/PngEncoderTests.cs | 32 +++--- .../Formats/WebP/WebpEncoderTests.cs | 59 ++++++++++ tests/ImageSharp.Tests/TestImages.cs | 30 ++++++ .../TestUtilities/TestImageExtensions.cs | 91 ++++++++++++++++ .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + .../00.png | 3 + .../01.png | 3 + .../02.png | 3 + .../03.png | 3 + ...Animation_Rgba32_static_nontransparent.png | 3 + ...No_Animation_Rgba32_static_transparent.png | 3 + ...2012BadMinCode_Rgba32_issue2012_drona1.png | 4 +- .../00.png | 4 +- .../01.png | 4 +- .../02.png | 4 +- .../03.png | 4 +- .../04.png | 4 +- .../05.png | 4 +- .../06.png | 4 +- .../07.png | 4 +- .../00.gif | 3 + .../08.gif | 3 + .../104.gif | 3 + .../112.gif | 3 + .../16.gif | 3 + .../24.gif | 3 + .../32.gif | 3 + .../40.gif | 3 + .../48.gif | 3 + .../56.gif | 3 + .../64.gif | 3 + .../72.gif | 3 + .../80.gif | 3 + .../88.gif | 3 + .../96.gif | 3 + .../00.png | 3 + .../08.png | 3 + .../104.png | 3 + .../112.png | 3 + .../16.png | 3 + .../24.png | 3 + .../32.png | 3 + .../40.png | 3 + .../48.png | 3 + .../56.png | 3 + .../64.png | 3 + .../72.png | 3 + .../80.png | 3 + .../88.png | 3 + .../96.png | 3 + .../00.png | 3 + .../08.png | 3 + tests/Images/Input/Gif/animated_loop.gif | 3 + .../Input/Gif/animated_loop_interlaced.gif | 3 + ...transparent_firstframerestoreprev_loop.gif | 3 + ...mated_transparent_frame_norestore_loop.gif | 3 + ...ansparent_frame_restorebackground_loop.gif | 3 + ...ted_transparent_frame_restoreprev_loop.gif | 3 + .../Input/Gif/animated_transparent_loop.gif | 3 + .../animated_transparent_restoreprev_loop.gif | 3 + .../Input/Gif/static_nontransparent.gif | 3 + tests/Images/Input/Gif/static_transparent.gif | 3 + tests/Images/Input/Webp/alpha-blend-2.webp | 3 + tests/Images/Input/Webp/alpha-blend-3.webp | 3 + tests/Images/Input/Webp/alpha-blend-4.webp | 3 + tests/Images/Input/Webp/alpha-blend.webp | 3 + 102 files changed, 587 insertions(+), 181 deletions(-) create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/01.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/02.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/03.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_nontransparent.png create mode 100644 tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_transparent.png create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/00.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/08.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/104.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/112.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/16.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/24.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/32.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/40.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/48.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/56.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/64.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/72.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/80.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/88.gif create mode 100644 tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/96.gif create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/08.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/104.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/112.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/16.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/24.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/32.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/40.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/48.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/56.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/64.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/72.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/80.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/88.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/96.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/00.png create mode 100644 tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/08.png create mode 100644 tests/Images/Input/Gif/animated_loop.gif create mode 100644 tests/Images/Input/Gif/animated_loop_interlaced.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_firstframerestoreprev_loop.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_frame_norestore_loop.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_frame_restorebackground_loop.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_frame_restoreprev_loop.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_loop.gif create mode 100644 tests/Images/Input/Gif/animated_transparent_restoreprev_loop.gif create mode 100644 tests/Images/Input/Gif/static_nontransparent.gif create mode 100644 tests/Images/Input/Gif/static_transparent.gif create mode 100644 tests/Images/Input/Webp/alpha-blend-2.webp create mode 100644 tests/Images/Input/Webp/alpha-blend-3.webp create mode 100644 tests/Images/Input/Webp/alpha-blend-4.webp create mode 100644 tests/Images/Input/Webp/alpha-blend.webp diff --git a/src/ImageSharp/Formats/Cur/CurFrameMetadata.cs b/src/ImageSharp/Formats/Cur/CurFrameMetadata.cs index f1ebec72f..9854854aa 100644 --- a/src/ImageSharp/Formats/Cur/CurFrameMetadata.cs +++ b/src/ImageSharp/Formats/Cur/CurFrameMetadata.cs @@ -104,7 +104,6 @@ public class CurFrameMetadata : IFormatFrameMetadata Compression = compression, EncodingWidth = ClampEncodingDimension(metadata.EncodingWidth), EncodingHeight = ClampEncodingDimension(metadata.EncodingHeight), - ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null }; } @@ -113,7 +112,6 @@ public class CurFrameMetadata : IFormatFrameMetadata => new() { PixelTypeInfo = this.GetPixelTypeInfo(), - ColorTable = this.ColorTable, EncodingWidth = this.EncodingWidth, EncodingHeight = this.EncodingHeight }; diff --git a/src/ImageSharp/Formats/Cur/CurMetadata.cs b/src/ImageSharp/Formats/Cur/CurMetadata.cs index 5c725e291..d8fdb3290 100644 --- a/src/ImageSharp/Formats/Cur/CurMetadata.cs +++ b/src/ImageSharp/Formats/Cur/CurMetadata.cs @@ -71,8 +71,7 @@ public class CurMetadata : IFormatMetadata return new CurMetadata { BmpBitsPerPixel = bbpp, - Compression = compression, - ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null + Compression = compression }; } @@ -145,8 +144,7 @@ public class CurMetadata : IFormatMetadata EncodingType = this.Compression == IconFrameCompression.Bmp && this.BmpBitsPerPixel <= BmpBitsPerPixel.Bit8 ? EncodingType.Lossy : EncodingType.Lossless, - PixelTypeInfo = this.GetPixelTypeInfo(), - ColorTable = this.ColorTable + PixelTypeInfo = this.GetPixelTypeInfo() }; /// diff --git a/src/ImageSharp/Formats/FormatConnectingFrameMetadata.cs b/src/ImageSharp/Formats/FormatConnectingFrameMetadata.cs index ded220c9a..15a28c301 100644 --- a/src/ImageSharp/Formats/FormatConnectingFrameMetadata.cs +++ b/src/ImageSharp/Formats/FormatConnectingFrameMetadata.cs @@ -15,11 +15,6 @@ public class FormatConnectingFrameMetadata /// public PixelTypeInfo? PixelTypeInfo { get; init; } - /// - /// Gets the frame color table if any. - /// - public ReadOnlyMemory? ColorTable { get; init; } - /// /// Gets the frame color table mode. /// diff --git a/src/ImageSharp/Formats/FormatConnectingMetadata.cs b/src/ImageSharp/Formats/FormatConnectingMetadata.cs index 9cfe40f38..efa7acdc8 100644 --- a/src/ImageSharp/Formats/FormatConnectingMetadata.cs +++ b/src/ImageSharp/Formats/FormatConnectingMetadata.cs @@ -28,11 +28,6 @@ public class FormatConnectingMetadata /// public PixelTypeInfo PixelTypeInfo { get; init; } - /// - /// Gets the shared color table if any. - /// - public ReadOnlyMemory? ColorTable { get; init; } - /// /// Gets the shared color table mode. /// diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index e9012436e..f6e3643d5 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -90,9 +90,9 @@ internal sealed class GifDecoderCore : ImageDecoderCore private GifMetadata? gifMetadata; /// - /// The background color used to fill the frame. + /// The background color index. /// - private Color backgroundColor; + private byte backgroundColorIndex; /// /// Initializes a new instance of the class. @@ -115,11 +115,11 @@ internal sealed class GifDecoderCore : ImageDecoderCore ImageFrame? previousFrame = null; FrameDisposalMode? previousDisposalMode = null; bool globalColorTableUsed = false; + Color backgroundColor = Color.Transparent; try { this.ReadLogicalScreenDescriptorAndGlobalColorTable(stream); - TPixel backgroundPixel = this.backgroundColor.ToPixel(); // Loop though the respective gif parts and read the data. int nextFlag = stream.ReadByte(); @@ -132,7 +132,7 @@ internal sealed class GifDecoderCore : ImageDecoderCore break; } - globalColorTableUsed |= this.ReadFrame(stream, ref image, ref previousFrame, ref previousDisposalMode, backgroundPixel); + globalColorTableUsed |= this.ReadFrame(stream, ref image, ref previousFrame, ref previousDisposalMode, ref backgroundColor); // Reset per-frame state. this.imageDescriptor = default; @@ -442,14 +442,14 @@ internal sealed class GifDecoderCore : ImageDecoderCore /// The image to decode the information to. /// The previous frame. /// The previous frame disposal mode. - /// The background color pixel. + /// The background color. /// Whether the frame has a global color table. private bool ReadFrame( BufferedReadStream stream, ref Image? image, ref ImageFrame? previousFrame, ref FrameDisposalMode? previousDisposalMode, - TPixel backgroundPixel) + ref Color backgroundColor) where TPixel : unmanaged, IPixel { this.ReadImageDescriptor(stream); @@ -471,7 +471,47 @@ internal sealed class GifDecoderCore : ImageDecoderCore } ReadOnlySpan colorTable = MemoryMarshal.Cast(rawColorTable); - this.ReadFrameColors(stream, ref image, ref previousFrame, ref previousDisposalMode, colorTable, backgroundPixel); + + // First frame + if (image is null) + { + if (this.backgroundColorIndex < colorTable.Length) + { + backgroundColor = Color.FromPixel(colorTable[this.backgroundColorIndex]); + } + else + { + backgroundColor = Color.Transparent; + } + + if (this.graphicsControlExtension.TransparencyFlag) + { + backgroundColor = backgroundColor.WithAlpha(0); + } + } + + this.ReadFrameColors(stream, ref image, ref previousFrame, ref previousDisposalMode, colorTable, backgroundColor.ToPixel()); + + // Update from newly decoded frame. + if (this.graphicsControlExtension.DisposalMethod != FrameDisposalMode.RestoreToPrevious) + { + if (this.backgroundColorIndex < colorTable.Length) + { + backgroundColor = Color.FromPixel(colorTable[this.backgroundColorIndex]); + } + else + { + backgroundColor = Color.Transparent; + } + + // TODO: I don't understand why this is always set to alpha of zero. + // This should be dependent on the transparency flag of the graphics + // control extension. ImageMagick does the same. + // if (this.graphicsControlExtension.TransparencyFlag) + { + backgroundColor = backgroundColor.WithAlpha(0); + } + } // Skip any remaining blocks SkipBlock(stream); @@ -504,8 +544,9 @@ internal sealed class GifDecoderCore : ImageDecoderCore bool transFlag = this.graphicsControlExtension.TransparencyFlag; FrameDisposalMode disposalMethod = this.graphicsControlExtension.DisposalMethod; ImageFrame currentFrame; + ImageFrame? restoreFrame = null; - if (previousFrame is null) + if (previousFrame is null && previousDisposalMode is null) { image = transFlag ? new Image(this.configuration, imageWidth, imageHeight, this.metadata) @@ -516,26 +557,42 @@ internal sealed class GifDecoderCore : ImageDecoderCore } else { - // We create a clone of the frame and add it. - // We will overpaint the difference of pixels on the current frame to create a complete image. - // This ensures that we have enough pixel data to process without distortion. #2450 - currentFrame = image!.Frames.AddFrame(previousFrame); + if (previousFrame != null) + { + currentFrame = image!.Frames.AddFrame(previousFrame); + } + else + { + currentFrame = image!.Frames.CreateFrame(backgroundPixel); + } this.SetFrameMetadata(currentFrame.Metadata); + if (this.graphicsControlExtension.DisposalMethod == FrameDisposalMode.RestoreToPrevious) + { + restoreFrame = previousFrame; + } + if (previousDisposalMode == FrameDisposalMode.RestoreToBackground) { this.RestoreToBackground(currentFrame, backgroundPixel, transFlag); } } - Rectangle interest = Rectangle.Intersect(image.Bounds, new(descriptor.Left, descriptor.Top, descriptor.Width, descriptor.Height)); - previousFrame = currentFrame; + if (this.graphicsControlExtension.DisposalMethod == FrameDisposalMode.RestoreToPrevious) + { + previousFrame = restoreFrame; + } + else + { + previousFrame = currentFrame; + } + previousDisposalMode = disposalMethod; if (disposalMethod == FrameDisposalMode.RestoreToBackground) { - this.restoreArea = interest; + this.restoreArea = Rectangle.Intersect(image.Bounds, new(descriptor.Left, descriptor.Top, descriptor.Width, descriptor.Height)); } if (colorTable.Length == 0) @@ -814,19 +871,9 @@ internal sealed class GifDecoderCore : ImageDecoderCore } } - // If the global color table is present, we can set the background color - // otherwise we default to transparent to match browser behavior. - ReadOnlyMemory? table = this.gifMetadata.GlobalColorTable; byte index = this.logicalScreenDescriptor.BackgroundColorIndex; - if (table is not null && index < table.Value.Length) - { - this.backgroundColor = table.Value.Span[index]; - this.gifMetadata.BackgroundColorIndex = index; - } - else - { - this.backgroundColor = Color.Transparent; - } + this.backgroundColorIndex = index; + this.gifMetadata.BackgroundColorIndex = index; } private unsafe struct ScratchBuffer diff --git a/src/ImageSharp/Formats/Gif/GifFrameMetadata.cs b/src/ImageSharp/Formats/Gif/GifFrameMetadata.cs index 92bd114e8..e1b3354ad 100644 --- a/src/ImageSharp/Formats/Gif/GifFrameMetadata.cs +++ b/src/ImageSharp/Formats/Gif/GifFrameMetadata.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Numerics; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Gif; @@ -77,34 +76,12 @@ public class GifFrameMetadata : IFormatFrameMetadata /// public static GifFrameMetadata FromFormatConnectingFrameMetadata(FormatConnectingFrameMetadata metadata) - { - int index = -1; - const float background = 1f; - if (metadata.ColorTable.HasValue) + => new() { - ReadOnlySpan colorTable = metadata.ColorTable.Value.Span; - for (int i = 0; i < colorTable.Length; i++) - { - Vector4 vector = colorTable[i].ToScaledVector4(); - if (vector.W < background) - { - index = i; - } - } - } - - bool hasTransparency = index >= 0; - - return new() - { - LocalColorTable = metadata.ColorTable, ColorTableMode = metadata.ColorTableMode, FrameDelay = (int)Math.Round(metadata.Duration.TotalMilliseconds / 10), DisposalMode = metadata.DisposalMode, - HasTransparency = hasTransparency, - TransparencyIndex = hasTransparency ? unchecked((byte)index) : byte.MinValue, }; - } /// public FormatConnectingFrameMetadata ToFormatConnectingFrameMetadata() @@ -118,7 +95,6 @@ public class GifFrameMetadata : IFormatFrameMetadata return new() { - ColorTable = this.LocalColorTable, ColorTableMode = this.ColorTableMode, Duration = TimeSpan.FromMilliseconds(this.FrameDelay * 10), DisposalMode = this.DisposalMode, diff --git a/src/ImageSharp/Formats/Gif/GifMetadata.cs b/src/ImageSharp/Formats/Gif/GifMetadata.cs index fc6c9ab9a..77f600633 100644 --- a/src/ImageSharp/Formats/Gif/GifMetadata.cs +++ b/src/ImageSharp/Formats/Gif/GifMetadata.cs @@ -71,32 +71,14 @@ public class GifMetadata : IFormatMetadata /// public static GifMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) - { - int index = 0; - Color background = metadata.BackgroundColor; - if (metadata.ColorTable.HasValue) - { - ReadOnlySpan colorTable = metadata.ColorTable.Value.Span; - for (int i = 0; i < colorTable.Length; i++) - { - if (background != colorTable[i]) - { - continue; - } - - index = i; - break; - } - } - - return new() + => new() { - GlobalColorTable = metadata.ColorTable, + // Do not copy the color table or bit depth. + // This will lead to a mismatch when the image is comprised of frames + // extracted individually from a multi-frame image. ColorTableMode = metadata.ColorTableMode, RepeatCount = metadata.RepeatCount, - BackgroundColorIndex = (byte)Numerics.Clamp(index, 0, 255), }; - } /// public PixelTypeInfo GetPixelTypeInfo() @@ -114,22 +96,13 @@ public class GifMetadata : IFormatMetadata /// public FormatConnectingMetadata ToFormatConnectingMetadata() - { - bool global = this.ColorTableMode == FrameColorTableMode.Global; - Color color = global && this.GlobalColorTable.HasValue && this.GlobalColorTable.Value.Span.Length > this.BackgroundColorIndex - ? this.GlobalColorTable.Value.Span[this.BackgroundColorIndex] - : Color.Transparent; - - return new FormatConnectingMetadata() + => new() { AnimateRootFrame = true, - ColorTable = global ? this.GlobalColorTable : null, - BackgroundColor = color, ColorTableMode = this.ColorTableMode, PixelTypeInfo = this.GetPixelTypeInfo(), RepeatCount = this.RepeatCount, }; - } /// public void AfterImageApply(Image destination) diff --git a/src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs b/src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs index 77096d524..31f65133e 100644 --- a/src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs +++ b/src/ImageSharp/Formats/Ico/IcoFrameMetadata.cs @@ -96,8 +96,7 @@ public class IcoFrameMetadata : IFormatFrameMetadata BmpBitsPerPixel = bbpp, Compression = compression, EncodingWidth = ClampEncodingDimension(metadata.EncodingWidth), - EncodingHeight = ClampEncodingDimension(metadata.EncodingHeight), - ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null + EncodingHeight = ClampEncodingDimension(metadata.EncodingHeight) }; } @@ -106,7 +105,6 @@ public class IcoFrameMetadata : IFormatFrameMetadata => new() { PixelTypeInfo = this.GetPixelTypeInfo(), - ColorTable = this.ColorTable, EncodingWidth = this.EncodingWidth, EncodingHeight = this.EncodingHeight }; diff --git a/src/ImageSharp/Formats/Ico/IcoMetadata.cs b/src/ImageSharp/Formats/Ico/IcoMetadata.cs index 09c1da1b1..f8c2ff40f 100644 --- a/src/ImageSharp/Formats/Ico/IcoMetadata.cs +++ b/src/ImageSharp/Formats/Ico/IcoMetadata.cs @@ -71,8 +71,7 @@ public class IcoMetadata : IFormatMetadata return new IcoMetadata { BmpBitsPerPixel = bbpp, - Compression = compression, - ColorTable = compression == IconFrameCompression.Bmp ? metadata.ColorTable : null + Compression = compression }; } @@ -145,8 +144,7 @@ public class IcoMetadata : IFormatMetadata EncodingType = this.Compression == IconFrameCompression.Bmp && this.BmpBitsPerPixel <= BmpBitsPerPixel.Bit8 ? EncodingType.Lossy : EncodingType.Lossless, - PixelTypeInfo = this.GetPixelTypeInfo(), - ColorTable = this.ColorTable + PixelTypeInfo = this.GetPixelTypeInfo() }; /// diff --git a/src/ImageSharp/Formats/Icon/IconEncoderCore.cs b/src/ImageSharp/Formats/Icon/IconEncoderCore.cs index 03e01f912..76b14832a 100644 --- a/src/ImageSharp/Formats/Icon/IconEncoderCore.cs +++ b/src/ImageSharp/Formats/Icon/IconEncoderCore.cs @@ -120,17 +120,17 @@ internal abstract class IconEncoderCore this.entries = this.iconFileType switch { IconFileType.ICO => - image.Frames.Select(i => + [.. image.Frames.Select(i => { IcoFrameMetadata metadata = i.Metadata.GetIcoMetadata(); return new EncodingFrameMetadata(metadata.Compression, metadata.BmpBitsPerPixel, metadata.ColorTable, metadata.ToIconDirEntry(i.Size)); - }).ToArray(), + })], IconFileType.CUR => - image.Frames.Select(i => + [.. image.Frames.Select(i => { CurFrameMetadata metadata = i.Metadata.GetCurMetadata(); return new EncodingFrameMetadata(metadata.Compression, metadata.BmpBitsPerPixel, metadata.ColorTable, metadata.ToIconDirEntry(i.Size)); - }).ToArray(), + })], _ => throw new NotSupportedException(), }; } @@ -149,9 +149,15 @@ internal abstract class IconEncoderCore if (metadata.ColorTable is null) { + int count = metadata.Entry.ColorCount; + if (count == 0) + { + count = 256; + } + return new WuQuantizer(new() { - MaxColors = metadata.Entry.ColorCount + MaxColors = count }); } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 3f7f1e562..b90a9975d 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -1570,7 +1570,8 @@ internal sealed class PngEncoderCore : IDisposable } else { - // Don't use transparency threshold for quantization PNG can handle multiple transparent colors. + // Don't use the default transparency threshold for quantization as PNG can handle multiple transparent colors. + // We choose a value that is close to zero so that edge cases causes by lower bit depths for the alpha channel are handled correctly. this.quantizer = new WuQuantizer(new QuantizerOptions { TransparencyThreshold = 0, MaxColors = ColorNumerics.GetColorCountForBitDepth(bitDepth) }); } } diff --git a/src/ImageSharp/Formats/Png/PngMetadata.cs b/src/ImageSharp/Formats/Png/PngMetadata.cs index bb80438ba..59ca3b17a 100644 --- a/src/ImageSharp/Formats/Png/PngMetadata.cs +++ b/src/ImageSharp/Formats/Png/PngMetadata.cs @@ -93,25 +93,6 @@ public class PngMetadata : IFormatMetadata /// public static PngMetadata FromFormatConnectingMetadata(FormatConnectingMetadata metadata) { - // Should the conversion be from a format that uses a 24bit palette entries (gif) - // we need to clone and adjust the color table to allow for transparency. - Color[]? colorTable = metadata.ColorTable?.ToArray(); - if (colorTable != null) - { - for (int i = 0; i < colorTable.Length; i++) - { - ref Color c = ref colorTable[i]; - if (c != metadata.BackgroundColor) - { - continue; - } - - // Png treats background as fully empty - c = Color.Transparent; - break; - } - } - PngColorType color; PixelColorType colorType = metadata.PixelTypeInfo.ColorType; @@ -152,7 +133,6 @@ public class PngMetadata : IFormatMetadata { ColorType = color, BitDepth = bitDepth, - ColorTable = colorTable, RepeatCount = metadata.RepeatCount, }; } @@ -241,7 +221,6 @@ public class PngMetadata : IFormatMetadata public FormatConnectingMetadata ToFormatConnectingMetadata() => new() { - ColorTable = this.ColorTable, ColorTableMode = FrameColorTableMode.Global, PixelTypeInfo = this.GetPixelTypeInfo(), RepeatCount = (ushort)Numerics.Clamp(this.RepeatCount, 0, ushort.MaxValue), diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs index eb4a51751..3c8bafa1b 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs @@ -69,11 +69,11 @@ internal class Vp8Decoder : IDisposable this.YuvBuffer = memoryAllocator.Allocate((WebpConstants.Bps * 17) + (WebpConstants.Bps * 9) + extraY); this.CacheY = memoryAllocator.Allocate((16 * this.CacheYStride) + extraY, AllocationOptions.Clean); int cacheUvSize = (16 * this.CacheUvStride) + extraUv; - this.CacheU = memoryAllocator.Allocate(cacheUvSize, AllocationOptions.Clean); - this.CacheV = memoryAllocator.Allocate(cacheUvSize, AllocationOptions.Clean); - this.TmpYBuffer = memoryAllocator.Allocate((int)width, AllocationOptions.Clean); - this.TmpUBuffer = memoryAllocator.Allocate((int)width, AllocationOptions.Clean); - this.TmpVBuffer = memoryAllocator.Allocate((int)width, AllocationOptions.Clean); + this.CacheU = memoryAllocator.Allocate(cacheUvSize); + this.CacheV = memoryAllocator.Allocate(cacheUvSize); + this.TmpYBuffer = memoryAllocator.Allocate((int)width); + this.TmpUBuffer = memoryAllocator.Allocate((int)width); + this.TmpVBuffer = memoryAllocator.Allocate((int)width); this.Pixels = memoryAllocator.Allocate((int)(width * height * 4), AllocationOptions.Clean); #if DEBUG diff --git a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs index d11376e3b..250122e68 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/EuclideanPixelMap{TPixel}.cs @@ -116,7 +116,7 @@ internal sealed class EuclideanPixelMap : IDisposable } // Now I have the index, pop it into the cache for next time - this.cache.Add(rgba, (byte)index); + this.cache.Add(rgba, (short)index); match = Unsafe.Add(ref paletteRef, (uint)index); return index; @@ -131,9 +131,11 @@ internal sealed class EuclideanPixelMap : IDisposable [MethodImpl(MethodImplOptions.AggressiveInlining)] private static float DistanceSquared(Rgba32 a, Rgba32 b) { - Vector4 va = new(a.R, a.G, a.B, a.A); - Vector4 vb = new(b.R, b.G, b.B, b.A); - return Vector4.DistanceSquared(va, vb); + float deltaR = a.R - b.R; + float deltaG = a.G - b.G; + float deltaB = a.B - b.B; + float deltaA = a.A - b.A; + return (deltaR * deltaR) + (deltaG * deltaG) + (deltaB * deltaB) + (deltaA * deltaA); } public void Dispose() => this.cache.Dispose(); diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index bc6eeedcb..6593b8df7 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -34,6 +34,41 @@ public class GifDecoderTests image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); } + [Theory] + [WithFile(TestImages.Gif.AnimatedLoop, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.AnimatedLoopInterlaced, PixelTypes.Rgba32)] + public void Decode_Animated(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); + } + + [Theory] + [WithFile(TestImages.Gif.AnimatedTransparentNoRestore, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.AnimatedTransparentRestorePrevious, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.AnimatedTransparentLoop, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.AnimatedTransparentFirstFrameRestorePrev, PixelTypes.Rgba32)] + public void Decode_Animated_WithTransparency(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); + } + + [Theory] + [WithFile(TestImages.Gif.StaticNontransparent, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.StaticTransparent, PixelTypes.Rgba32)] + public void Decode_Static_No_Animation(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + image.DebugSave(provider); + image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); + } + [Theory] [WithFile(TestImages.Gif.Issues.Issue2450_A, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Issues.Issue2450_B, PixelTypes.Rgba32)] diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index d219f551b..748f505cc 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -422,12 +422,18 @@ public class GifEncoderTests [Theory] [WithFile(TestImages.Gif.Issues.Issue2866, PixelTypes.Rgba32)] - public void GifEncoder_CanDecode_Issue2866(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void GifEncoder_CanDecode_AndEncode_Issue2866(TestImageProvider provider) + where TPixel : unmanaged, IPixel { using Image image = provider.GetImage(); - // image.DebugSaveMultiFrame(provider); + // Save the image for visual inspection. provider.Utility.SaveTestOutputFile(image, "gif", new GifEncoder(), "animated"); + + // Now compare the debug output with the reference output. + // We do this because the gif encoding is lossy and encoding will lead to differences in the 10s of percent. + // From the unencoded image, we can see that the image is visually the same. + static bool Predicate(int i, int _) => i % 8 == 0; // Image has many frames, only compare a selection of them. + image.CompareDebugOutputToReferenceOutputMultiFrame(provider, ImageComparer.Exact, extension: "gif", predicate: Predicate); } } diff --git a/tests/ImageSharp.Tests/Formats/Icon/Cur/CurEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Icon/Cur/CurEncoderTests.cs index bf94e1d48..69c6317a7 100644 --- a/tests/ImageSharp.Tests/Formats/Icon/Cur/CurEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Icon/Cur/CurEncoderTests.cs @@ -4,6 +4,7 @@ using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Cur; using SixLabors.ImageSharp.Formats.Ico; +using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using static SixLabors.ImageSharp.Tests.TestImages.Cur; @@ -49,8 +50,8 @@ public class CurEncoderTests using Image encoded = Image.Load(memStream); encoded.DebugSaveMultiFrame(provider); - // Despite preservation of the palette. The process can still be lossy - encoded.CompareToOriginalMultiFrame(provider, ImageComparer.TolerantPercentage(.23f), IcoDecoder.Instance); + // Color palettes are not preserved when transcoding. + encoded.CompareToOriginalMultiFrame(provider, ImageComparer.TolerantPercentage(.05F), IcoDecoder.Instance); for (int i = 0; i < image.Frames.Count; i++) { diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 298d5b788..2a53e4de7 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -442,40 +442,42 @@ public partial class PngEncoderTests } [Theory] - [WithFile(TestImages.Gif.Leo, PixelTypes.Rgba32, 0.613F)] - [WithFile(TestImages.Gif.Issues.Issue2866, PixelTypes.Rgba32, 1.06F)] - public void Encode_AnimatedFormatTransform_FromGif(TestImageProvider provider, float percentage) + [WithFile(TestImages.Gif.Leo, PixelTypes.Rgba32)] + [WithFile(TestImages.Gif.Issues.Issue2866, PixelTypes.Rgba32)] + public void Encode_AnimatedFormatTransform_FromGif(TestImageProvider provider) where TPixel : unmanaged, IPixel { - if (TestEnvironment.RunsOnCI) + if (TestEnvironment.RunsOnCI && !TestEnvironment.IsWindows) { return; } using Image image = provider.GetImage(GifDecoder.Instance); + // Save the image for visual inspection. + provider.Utility.SaveTestOutputFile(image, "png", PngEncoder, "animated"); + + // Now compare the debug output with the reference output. + // We do this because the transcoding encoding is lossy and encoding will lead to differences. + // From the unencoded image, we can see that the image is visually the same. + static bool Predicate(int i, int _) => i % 8 == 0; // Image has many frames, only compare a selection of them. + image.CompareDebugOutputToReferenceOutputMultiFrame(provider, ImageComparer.Exact, extension: "png", encoder: PngEncoder, predicate: Predicate); + + // Now save the image and load it again to compare the metadata. using MemoryStream memStream = new(); image.Save(memStream, PngEncoder); memStream.Position = 0; - image.DebugSave(provider: provider, extension: "png", encoder: PngEncoder); - - using Image output = Image.Load(memStream); - - // TODO: Find a better way to compare. - // The image has been visually checked but the coarse cache used by the palette quantizer - // can lead to minor differences between frames. - ImageComparer.TolerantPercentage(percentage).VerifySimilarity(output, image); - + using Image encoded = Image.Load(memStream); GifMetadata gif = image.Metadata.GetGifMetadata(); - PngMetadata png = output.Metadata.GetPngMetadata(); + PngMetadata png = encoded.Metadata.GetPngMetadata(); Assert.Equal(gif.RepeatCount, png.RepeatCount); for (int i = 0; i < image.Frames.Count; i++) { GifFrameMetadata gifF = image.Frames[i].Metadata.GetGifMetadata(); - PngFrameMetadata pngF = output.Frames[i].Metadata.GetPngMetadata(); + PngFrameMetadata pngF = encoded.Frames[i].Metadata.GetPngMetadata(); Assert.Equal(gifF.FrameDelay, (int)(pngF.FrameDelay.ToDouble() * 100)); diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs index f82fa65df..af6f7eea1 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs @@ -8,6 +8,8 @@ using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; @@ -110,6 +112,63 @@ public class WebpEncoderTests } } + [Theory] + // [WithFile(AlphaBlend, PixelTypes.Rgba32)] + // [WithFile(AlphaBlend2, PixelTypes.Rgba32)] + [WithFile(AlphaBlend3, PixelTypes.Rgba32)] + // [WithFile(AlphaBlend4, PixelTypes.Rgba32)] + public void Encode_AlphaBlended(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + WebpEncoder encoder = new() + { + FileFormat = WebpFileFormatType.Lossless + }; + + QuantizerOptions options = new() + { + TransparencyThreshold = 128 / 255F + }; + + // First save as gif to gif using different quantizers with default options. + // Alpha thresholding is 64/255F. + GifEncoder gifEncoder = new() + { + Quantizer = new OctreeQuantizer(options) + }; + provider.Utility.SaveTestOutputFile(image, "gif", gifEncoder, "octree"); + + gifEncoder = new GifEncoder() + { + Quantizer = new WuQuantizer(options) + }; + provider.Utility.SaveTestOutputFile(image, "gif", gifEncoder, "wu"); + + // Now clone and quantize the image using the same quantizers without alpha thresholding and save as webp. + options = new() + { + TransparencyThreshold = 0 + }; + + using Image cloned1 = image.Clone(); + cloned1.Mutate(c => c.Quantize(new OctreeQuantizer(options))); + provider.Utility.SaveTestOutputFile(cloned1, "webp", encoder, "octree"); + + using Image cloned2 = image.Clone(); + cloned2.Mutate(c => c.Quantize(new WuQuantizer(options))); + provider.Utility.SaveTestOutputFile(cloned2, "webp", encoder, "wu"); + + // Now blend the images with a blue background and save as webp. + using Image background1 = new(image.Width, image.Height, Color.White.ToPixel()); + background1.Mutate(c => c.DrawImage(cloned1, 1)); + provider.Utility.SaveTestOutputFile(background1, "webp", encoder, "octree-blended"); + + using Image background2 = new(image.Width, image.Height, Color.White.ToPixel()); + background2.Mutate(c => c.DrawImage(cloned2, 1)); + provider.Utility.SaveTestOutputFile(background2, "webp", encoder, "wu-blended"); + } + [Theory] [WithFile(TestImages.Png.APng, PixelTypes.Rgba32)] public void Encode_AnimatedFormatTransform_FromPng(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 462d54154..abaec4997 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -508,6 +508,31 @@ public static class TestImages public const string Bit18RGBCube = "Gif/18-bit_RGB_Cube.gif"; public const string Global256NoTrans = "Gif/global-256-no-trans.gif"; + // Test images from: https://github.com/peterdn/gif-test-suite.git + // Animated gif with 4 frames, looping forever, no transparency. + public const string AnimatedLoop = "Gif/animated_loop.gif"; + + // Animated gif with 4 frames, interlaced, looping forever, no transparency. + public const string AnimatedLoopInterlaced = "Gif/animated_loop_interlaced.gif"; + + // Transparent gif with 4 frames, loops forever. + public const string AnimatedTransparentLoop = "Gif/animated_transparent_loop.gif"; + + // Transparent gif with 4 frames, loops forever, first frame restore previous. + public const string AnimatedTransparentFirstFrameRestorePrev = "Gif/animated_transparent_firstframerestoreprev_loop.gif"; + + // Transparent gif with 4 transparent frames, loops forever, no dispose + public const string AnimatedTransparentNoRestore = "Gif/animated_transparent_frame_norestore_loop.gif"; + + // Transparent gif with 4 transparent frames, loops forever, restore previous. + public const string AnimatedTransparentRestorePrevious = "Gif/animated_transparent_frame_restoreprev_loop.gif"; + + // Static gif with no animation, no transparency. + public const string StaticNontransparent = "Gif/static_nontransparent.gif"; + + // Static transparent gif with no animation. + public const string StaticTransparent = "Gif/static_transparent.gif"; + // Test images from https://github.com/robert-ancell/pygif/tree/master/test-suite public const string ZeroSize = "Gif/image-zero-size.gif"; public const string ZeroHeight = "Gif/image-zero-height.gif"; @@ -833,6 +858,11 @@ public static class TestImages public const string Issue2801 = "Webp/issues/Issue2801.webp"; public const string Issue2866 = "Webp/issues/Issue2866.webp"; } + + public const string AlphaBlend = "Webp/alpha-blend.webp"; + public const string AlphaBlend2 = "Webp/alpha-blend-2.webp"; + public const string AlphaBlend3 = "Webp/alpha-blend-3.webp"; + public const string AlphaBlend4 = "Webp/alpha-blend-4.webp"; } public static class Tiff diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 05abedbd8..263df8f3a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -107,6 +107,7 @@ public static class TestImageExtensions ITestImageProvider provider, object testOutputDetails = null, string extension = "png", + IImageEncoder encoder = null, bool appendPixelTypeToFileName = true, Func predicate = null) where TPixel : unmanaged, IPixel @@ -119,6 +120,7 @@ public static class TestImageExtensions provider.Utility.SaveTestOutputFileMultiFrame( image, extension, + encoder: encoder, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName, predicate: predicate); @@ -277,6 +279,47 @@ public static class TestImageExtensions return image; } + public static Image CompareDebugOutputToReferenceOutputMultiFrame( + this Image image, + ITestImageProvider provider, + ImageComparer comparer, + object testOutputDetails = null, + string extension = "png", + IImageEncoder encoder = null, + bool appendPixelTypeToFileName = true, + Func predicate = null) + where TPixel : unmanaged, IPixel + { + image.DebugSaveMultiFrame( + provider, + testOutputDetails, + extension, + encoder, + appendPixelTypeToFileName, + predicate: predicate); + + using (Image debugImage = GetDebugOutputImageMultiFrame( + provider, + image.Frames.Count, + testOutputDetails, + extension, + appendPixelTypeToFileName, + predicate: predicate)) + + using (Image referenceImage = GetReferenceOutputImageMultiFrame( + provider, + image.Frames.Count, + testOutputDetails, + extension, + appendPixelTypeToFileName, + predicate: predicate)) + { + comparer.VerifySimilarity(referenceImage, debugImage); + } + + return image; + } + public static Image CompareToReferenceOutputMultiFrame( this Image image, ITestImageProvider provider, @@ -375,6 +418,54 @@ public static class TestImageExtensions return result; } + public static Image GetDebugOutputImageMultiFrame( + this ITestImageProvider provider, + int frameCount, + object testOutputDetails = null, + string extension = "png", + bool appendPixelTypeToFileName = true, + Func predicate = null) + where TPixel : unmanaged, IPixel + { + (int Index, string FileName)[] frameFiles = [.. provider.Utility.GetTestOutputFileNamesMultiFrame( + frameCount, + extension, + testOutputDetails, + appendPixelTypeToFileName, + predicate: predicate)]; + + List> temporaryFrameImages = []; + + IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0].FileName); + + for (int i = 0; i < frameFiles.Length; i++) + { + string path = frameFiles[i].FileName; + if (!File.Exists(path)) + { + throw new FileNotFoundException("Reference output file missing: " + path); + } + + using FileStream stream = File.OpenRead(path); + Image tempImage = decoder.Decode(DecoderOptions.Default, stream); + temporaryFrameImages.Add(tempImage); + } + + Image firstTemp = temporaryFrameImages[0]; + + Image result = new(firstTemp.Width, firstTemp.Height); + + foreach (Image fi in temporaryFrameImages) + { + result.Frames.AddFrame(fi.Frames.RootFrame); + fi.Dispose(); + } + + // Remove the initial empty frame: + result.Frames.RemoveFrame(0); + return result; + } + public static IEnumerable GetReferenceOutputSimilarityReports( this Image image, ITestImageProvider provider, diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/00.png new file mode 100644 index 000000000..65b2c6ff7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b980fb1927a70f88bd26b039c54e4ea20a6a1ad68aacd6f1a68a46eb1997a29 +size 1180 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/01.png new file mode 100644 index 000000000..8c9e125ad --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4006374b88ff4c4ed665333608a19e693fc083ae72beb71850d0e39ad45c9943 +size 1144 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/02.png new file mode 100644 index 000000000..a2fc2ab3b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f5054e1e464c9e9fc999eec00b9949a6dc256ee062e9910b5718b6d4658661a +size 1303 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/03.png new file mode 100644 index 000000000..9d5b54c71 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49e8bcbcc5dc63fbd555f90a52b4e111cfc058f3adba2ca9c52dec966dbbae8f +size 1371 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/00.png new file mode 100644 index 000000000..65b2c6ff7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b980fb1927a70f88bd26b039c54e4ea20a6a1ad68aacd6f1a68a46eb1997a29 +size 1180 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/01.png new file mode 100644 index 000000000..8c9e125ad --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4006374b88ff4c4ed665333608a19e693fc083ae72beb71850d0e39ad45c9943 +size 1144 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/02.png new file mode 100644 index 000000000..a2fc2ab3b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f5054e1e464c9e9fc999eec00b9949a6dc256ee062e9910b5718b6d4658661a +size 1303 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/03.png new file mode 100644 index 000000000..9d5b54c71 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_Rgba32_animated_loop_interlaced.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49e8bcbcc5dc63fbd555f90a52b4e111cfc058f3adba2ca9c52dec966dbbae8f +size 1371 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/00.png new file mode 100644 index 000000000..193cde24d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b60d2066cb53d41988da37b8c521ddcb5355b995320a8413b95522a0492140 +size 687 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/01.png new file mode 100644 index 000000000..4d2d25510 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30ff7708250c5f02dc02d74238d398b319d8fc6c071178f32f82a17e3b637afd +size 542 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/02.png new file mode 100644 index 000000000..0654e49d4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d21f4576486692122b6ee719d75883849f65ddb07f632ea1c62b42651c289688 +size 591 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/03.png new file mode 100644 index 000000000..0c1090f66 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_firstframerestoreprev_loop.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88db68f2d59301b8ff9326143455a03c94cb616220f6e8e3832f13effe0c09bc +size 545 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/00.png new file mode 100644 index 000000000..193cde24d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b60d2066cb53d41988da37b8c521ddcb5355b995320a8413b95522a0492140 +size 687 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/01.png new file mode 100644 index 000000000..f289fdca3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:034b0b6b94c13fbef8c44d650daa07362f113aae6600d63230a3f96e29b16dec +size 790 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/02.png new file mode 100644 index 000000000..07537b9df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4b3684db6e3df52a9eb520d562b51b54632e897e9e39bff5ce904ae00799f2f +size 924 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/03.png new file mode 100644 index 000000000..e376be689 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_norestore_loop.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e33c564f55b653a693105612949401002014821abaecaf654c96d0f2b5d59b4 +size 962 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/00.png new file mode 100644 index 000000000..193cde24d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b60d2066cb53d41988da37b8c521ddcb5355b995320a8413b95522a0492140 +size 687 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/01.png new file mode 100644 index 000000000..f289fdca3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:034b0b6b94c13fbef8c44d650daa07362f113aae6600d63230a3f96e29b16dec +size 790 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/02.png new file mode 100644 index 000000000..27f29acbb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4f4eb12da36cd43c620aa5ad1c793bb6eb8431c61d2cc1b77c1118f35a741cc +size 876 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/03.png new file mode 100644 index 000000000..684c2fa38 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_frame_restoreprev_loop.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15bf02e06c6819d74a0a79cbfc5c86913c248a8812ff0ec613c0e747a000241b +size 789 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/00.png new file mode 100644 index 000000000..193cde24d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b60d2066cb53d41988da37b8c521ddcb5355b995320a8413b95522a0492140 +size 687 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/01.png new file mode 100644 index 000000000..7818cf380 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01f389a2e93023f3132927a9565c04c8c1f827e36111ebe682177adecc3a27ee +size 774 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/02.png new file mode 100644 index 000000000..18bc40863 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00ef57db2fef89112ac7d1808afb6803612c6a20fc589166be6d6b7007c46400 +size 946 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/03.png new file mode 100644 index 000000000..bd2ea67ae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Animated_WithTransparency_Rgba32_animated_transparent_loop.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:deafa4d4f8fd84489c061ca1042c2ad9e655fff3b6419248cfb35fa4ea40d9e6 +size 1000 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_nontransparent.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_nontransparent.png new file mode 100644 index 000000000..65b2c6ff7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_nontransparent.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b980fb1927a70f88bd26b039c54e4ea20a6a1ad68aacd6f1a68a46eb1997a29 +size 1180 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_transparent.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_transparent.png new file mode 100644 index 000000000..193cde24d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_Static_No_Animation_Rgba32_static_transparent.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b60d2066cb53d41988da37b8c521ddcb5355b995320a8413b95522a0492140 +size 687 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue2012BadMinCode_Rgba32_issue2012_drona1.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue2012BadMinCode_Rgba32_issue2012_drona1.png index 6f2fc842f..5d443b52a 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue2012BadMinCode_Rgba32_issue2012_drona1.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue2012BadMinCode_Rgba32_issue2012_drona1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ff67035f78690321c29a4e15c8de7c55bcb3260d667dbd9bced15de6b626fca1 -size 148499 +oid sha256:a0e1677baade797de1eaec390f2e475865d24de8bd344edddbb3fce200d6bcb0 +size 135418 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/00.png index 923fbc122..52f14e0f7 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/00.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/00.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:800d1ec2d7c7c99d449db1f49ef202cf18214016eae65ebc4216d6f4b1f4d328 -size 537 +oid sha256:473c5629d7a9f8b3d6c809e8ede40f8fd38e90beddf71851b352c726fc0570d6 +size 534 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/01.png index 6c2134d8b..b47f34ba0 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/01.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/01.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:94dcd97831b16165f3331e429d72d7ef546e04038cab754c7918f9cf535ff30a -size 542 +oid sha256:4b9b9f856c0347b460f824d6b027b343c65c67a29360793181c9a29a76f9002b +size 538 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/02.png index 6f50397ea..64869ca3c 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/02.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/02.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec1a589a8fae1b17a82b70a9583ea2ee012a476b1fa8fdba27fee2b7ce0403b2 -size 540 +oid sha256:74b8015c60d215808b1d663ae4af956d1454414206ba21326ad35b8952b0cab6 +size 534 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/03.png index 82061ba0a..ab52225f8 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/03.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/03.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c8751f4fafd5c56066dbb8d64a3890fc420a3bd66881a55e309ba274b6d14e4 -size 542 +oid sha256:8dacb6a468d3cdc94613d56264ddf34d3649846edf33619fc13b9522fcf982d6 +size 539 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/04.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/04.png index 8902eb824..78988aa60 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/04.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/04.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b78516c9874cb15de4c4b98ed307e8105d962fc6bfa7aa3490b2c7e13b455a2d -size 544 +oid sha256:8af74db6e01928ad54444fa122e4b87929741052c85abe9c0ffc998adffcbdfc +size 542 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/05.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/05.png index 82061ba0a..ab52225f8 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/05.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/05.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c8751f4fafd5c56066dbb8d64a3890fc420a3bd66881a55e309ba274b6d14e4 -size 542 +oid sha256:8dacb6a468d3cdc94613d56264ddf34d3649846edf33619fc13b9522fcf982d6 +size 539 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/06.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/06.png index 6f50397ea..64869ca3c 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/06.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/06.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec1a589a8fae1b17a82b70a9583ea2ee012a476b1fa8fdba27fee2b7ce0403b2 -size 540 +oid sha256:74b8015c60d215808b1d663ae4af956d1454414206ba21326ad35b8952b0cab6 +size 534 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/07.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/07.png index efba40c99..97610dbc0 100644 --- a/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/07.png +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/IssueTooLargeLzwBits_Rgba32_issue_2743.gif/07.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5016a323018f09e292165ad5392d82dcbad5e79c2b6b93aff3322dffff80b309 -size 126 +oid sha256:c816ca1e58d14361b84ba47454e4cbf4d3e4d29dfb7827756eb52ef2604f297c +size 161 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/00.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/00.gif new file mode 100644 index 000000000..8668f7102 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/00.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e738470c04121376b42937f0a72eed3f068bc32bdc788cc0d5877bc7f705f419 +size 67611 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/08.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/08.gif new file mode 100644 index 000000000..8fd66d120 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/08.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33b9244a09ed3b7bb17dfcbb694cbacc4f7de8ce6ffd7d7f7c35d424a6e8b2c5 +size 58696 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/104.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/104.gif new file mode 100644 index 000000000..90b8a081c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/104.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:380f86015751a8445eb706d99001efe96633c62dd183c22303e732d036175dff +size 86095 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/112.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/112.gif new file mode 100644 index 000000000..180c1e730 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/112.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae0f80bbc03fc35be4622df85f13f8fe7aec2d981424d9ca6dce88bd23ff2dad +size 59015 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/16.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/16.gif new file mode 100644 index 000000000..6eceee397 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/16.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:696ef2d76fe8ae8a32f0299b668b0cf537c1ffe5ac3ca4b418499f03ca134d89 +size 70345 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/24.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/24.gif new file mode 100644 index 000000000..51ef66811 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/24.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1dbd382f6f7b71f4cdffe61c01f0ab04523423576bad6195f8950ff7758792a2 +size 67153 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/32.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/32.gif new file mode 100644 index 000000000..26818c6a8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/32.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2942af218c05b29b4f5a8eb9117c8dea4dcf61b33e1ade3cfa6ba47a0d71f6c +size 68007 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/40.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/40.gif new file mode 100644 index 000000000..92f5c1fb9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/40.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45872e2361fc445d956abd5de454ad42bcdb8ade69742b032c865978e41cb477 +size 73531 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/48.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/48.gif new file mode 100644 index 000000000..5524ce8a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/48.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:432af0fd8df68724f2faa3fc90dc751ff15a7e45604e20f3737d1902c64a913e +size 72024 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/56.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/56.gif new file mode 100644 index 000000000..bfd22ffef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/56.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aab6a8c7892d8449ad8915f414689019684f99d3f011ddb82f722037b35a70c0 +size 77189 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/64.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/64.gif new file mode 100644 index 000000000..e3f17772e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/64.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b93da4e1ab6ed01c561d5b565c078ff8752f7b16b78c733b658237977b1e4689 +size 78172 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/72.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/72.gif new file mode 100644 index 000000000..cfe4a2eef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/72.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8b426203cd6b6b5f4b97a5213a8a04da66056e3b238be3407751a43b365e11b +size 71198 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/80.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/80.gif new file mode 100644 index 000000000..6c713186f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/80.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d47400e426792c550afb2797b68e41e3ce04409dde627e0f74c39f216a951f22 +size 83675 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/88.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/88.gif new file mode 100644 index 000000000..89a8e3880 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/88.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d11ae15a30005e335d2f84f2749573fc59d88d2f1c415cfea2126b47e3dac60b +size 91647 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/96.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/96.gif new file mode 100644 index 000000000..f7ef06534 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/GifEncoder_CanDecode_AndEncode_Issue2866_Rgba32_issue_2866.gif/96.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6410a7792823ad1c5d5f0fcaed388b362498f1bbd57175b70165e0ce3542662c +size 99183 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/00.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/00.png new file mode 100644 index 000000000..365816825 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0840e31b83f0f9621e2c98cb784881f88c882f7b558aef889eb2511a893af585 +size 63955 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/08.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/08.png new file mode 100644 index 000000000..eb52b1473 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c674fe70b76d6763215620680f7f24bc3113c3ee98eeb9f9e9572ccd8825c61f +size 68053 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/104.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/104.png new file mode 100644 index 000000000..ad4232e3c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/104.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e46346d886acf62b3d742d6df9ddd9226afd2a4184be045e00724cf0ab4c25b4 +size 77343 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/112.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/112.png new file mode 100644 index 000000000..5402b021f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/112.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a647f174ac31570a3e42c472fa888dadcd5117e6f8300ef35b21ed2cff5bd6c +size 65959 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/16.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/16.png new file mode 100644 index 000000000..0f7643659 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951a034bae41acdcbd202d1d8624609bf4a47edbcd94806e4993b0a610fb767e +size 74231 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/24.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/24.png new file mode 100644 index 000000000..0d680bb4c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/24.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce790490566b7d908e6372746a264b0d207e3b8f906fddf020e68e0b5effd757 +size 75693 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/32.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/32.png new file mode 100644 index 000000000..0c724b5e9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/32.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5aea5c9671a91101081287426e57c07fb56c1f072f582bd2f135705c114239f8 +size 79474 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/40.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/40.png new file mode 100644 index 000000000..587107445 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/40.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:100d85d20cf39ed4b8f70a7c3a23c5ef857899e3830a7869437eb38819dbe309 +size 77200 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/48.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/48.png new file mode 100644 index 000000000..ea2bd8207 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c48b5e76c80649d42c58043d6afaebf872b69031e12af0554847afc167379d9e +size 77420 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/56.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/56.png new file mode 100644 index 000000000..206ddc164 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/56.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e98364b6e9e913a56e95aace2ac07890e1d4f8a31e44b5195cac0779e9ed75bb +size 75433 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/64.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/64.png new file mode 100644 index 000000000..b92f711df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/64.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53a1c8c9653da218d6f49837a7d5b8623568eb629670d0026e056fb1f13ca52e +size 77402 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/72.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/72.png new file mode 100644 index 000000000..9e78a1f28 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/72.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06f1d36cede878377ef7731ac2530d3cd489fdb09308794315da7b62a48ec667 +size 73840 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/80.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/80.png new file mode 100644 index 000000000..0855f16ed --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/80.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ace97f772679993cb35dc0630d4431019a7e885cd397db98d2b0d91a6c984db +size 81863 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/88.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/88.png new file mode 100644 index 000000000..5564c3292 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/88.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a1fa4b08ec93e17cfa9906ca6f447da651f469aad3615cc5ae08f4080784c096 +size 86317 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/96.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/96.png new file mode 100644 index 000000000..41b121a15 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_issue_2866.gif/96.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9e6fd785ab0ef4e75adbf4697d7cb04873a95d01a5fb5197090e87061aa3430 +size 88729 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/00.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/00.png new file mode 100644 index 000000000..a0b3e0a5d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf499248f2cdb443d12998c45cad8fcfee04e0febb21965980815aa910bc34ab +size 23945 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/08.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/08.png new file mode 100644 index 000000000..bbe754da3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/Encode_AnimatedFormatTransform_FromGif_Rgba32_leo.gif/08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ecf0666ca8b0ef16cf0e6147aea4b76af76f62777a62ea02edcf5cf5a309d8b +size 29721 diff --git a/tests/Images/Input/Gif/animated_loop.gif b/tests/Images/Input/Gif/animated_loop.gif new file mode 100644 index 000000000..5fad702a1 --- /dev/null +++ b/tests/Images/Input/Gif/animated_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8750149c953e9e910472684158c07a2cb551c1f7e95744ab48db1a67f63f342 +size 873 diff --git a/tests/Images/Input/Gif/animated_loop_interlaced.gif b/tests/Images/Input/Gif/animated_loop_interlaced.gif new file mode 100644 index 000000000..9577a8465 --- /dev/null +++ b/tests/Images/Input/Gif/animated_loop_interlaced.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2bc2f895f03092b1c26381a32b5dd5838aacd3331e07f7e4dae55d5cbb4e149 +size 878 diff --git a/tests/Images/Input/Gif/animated_transparent_firstframerestoreprev_loop.gif b/tests/Images/Input/Gif/animated_transparent_firstframerestoreprev_loop.gif new file mode 100644 index 000000000..5012324ca --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_firstframerestoreprev_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b0cf18d386dc979fcf853d6a9adac673a2709a8751d31a94930199dededa25f +size 536 diff --git a/tests/Images/Input/Gif/animated_transparent_frame_norestore_loop.gif b/tests/Images/Input/Gif/animated_transparent_frame_norestore_loop.gif new file mode 100644 index 000000000..712f334ab --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_frame_norestore_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad7359801fa6ed89fb041de1e88faea856b1028d9f477fdc4eda774df6e5f1ce +size 685 diff --git a/tests/Images/Input/Gif/animated_transparent_frame_restorebackground_loop.gif b/tests/Images/Input/Gif/animated_transparent_frame_restorebackground_loop.gif new file mode 100644 index 000000000..b6f675dca --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_frame_restorebackground_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12254f22eeee9eac6babbfbfb34b6ae9302342454fd6677e8c7c9937656cc127 +size 685 diff --git a/tests/Images/Input/Gif/animated_transparent_frame_restoreprev_loop.gif b/tests/Images/Input/Gif/animated_transparent_frame_restoreprev_loop.gif new file mode 100644 index 000000000..be7fdf85d --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_frame_restoreprev_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0cdfba6efea653bb94ede6edd0577ba6af1f7c130307b94903dd94f0f8bbc4f9 +size 685 diff --git a/tests/Images/Input/Gif/animated_transparent_loop.gif b/tests/Images/Input/Gif/animated_transparent_loop.gif new file mode 100644 index 000000000..cb001ece8 --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3297987894ba27c2acc6a5c447c3d3a52cc169447b451409535decccc1743e55 +size 536 diff --git a/tests/Images/Input/Gif/animated_transparent_restoreprev_loop.gif b/tests/Images/Input/Gif/animated_transparent_restoreprev_loop.gif new file mode 100644 index 000000000..f51d02433 --- /dev/null +++ b/tests/Images/Input/Gif/animated_transparent_restoreprev_loop.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9418561ef2f2307456bb068ecc1a9d5aa02da5e314e7aadd722985e27503926b +size 536 diff --git a/tests/Images/Input/Gif/static_nontransparent.gif b/tests/Images/Input/Gif/static_nontransparent.gif new file mode 100644 index 000000000..17ab1e2ec --- /dev/null +++ b/tests/Images/Input/Gif/static_nontransparent.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0a5e1b2f0c5c1763eb950a1d92c5317f048875e04e88dca7f1a966552c2774c +size 678 diff --git a/tests/Images/Input/Gif/static_transparent.gif b/tests/Images/Input/Gif/static_transparent.gif new file mode 100644 index 000000000..89039a732 --- /dev/null +++ b/tests/Images/Input/Gif/static_transparent.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f73f56bbe2206bd1cd8a4625b6a4d61506214b37b61ff3e8194e2030b28abca5 +size 341 diff --git a/tests/Images/Input/Webp/alpha-blend-2.webp b/tests/Images/Input/Webp/alpha-blend-2.webp new file mode 100644 index 000000000..3ca4c77cf --- /dev/null +++ b/tests/Images/Input/Webp/alpha-blend-2.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b07a49ab8b3af82fa123faf897ec537cd26d57175b1d6301b617372c06432899 +size 1580484 diff --git a/tests/Images/Input/Webp/alpha-blend-3.webp b/tests/Images/Input/Webp/alpha-blend-3.webp new file mode 100644 index 000000000..1922f561d --- /dev/null +++ b/tests/Images/Input/Webp/alpha-blend-3.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7244a2cfb42285a196fc7846c49da65fac47e5b85f735bc07b131707c8a2d46 +size 948 diff --git a/tests/Images/Input/Webp/alpha-blend-4.webp b/tests/Images/Input/Webp/alpha-blend-4.webp new file mode 100644 index 000000000..6f4db231f --- /dev/null +++ b/tests/Images/Input/Webp/alpha-blend-4.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c8b98f188d006715bd5bc60593ff2a379078f28a7fc14a51d28ae1cfb279aac +size 2185502 diff --git a/tests/Images/Input/Webp/alpha-blend.webp b/tests/Images/Input/Webp/alpha-blend.webp new file mode 100644 index 000000000..110d2a594 --- /dev/null +++ b/tests/Images/Input/Webp/alpha-blend.webp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dc2762d1c1030fb951e1af57eaa7e66035a7b5e63bd9dc9f9bd50f0ff5c4c3a +size 1297692