mirror of https://github.com/SixLabors/ImageSharp
9 changed files with 168 additions and 68 deletions
@ -0,0 +1,111 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Formats; |
||||
|
using SixLabors.ImageSharp.Formats.Gif; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Issues; |
||||
|
|
||||
|
// https://github.com/SixLabors/ImageSharp.Drawing/discussions/396
|
||||
|
public class Issue_396 |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithFile(TestImages.Png.Issue396Dragon, PixelTypes.Rgba32)] |
||||
|
public void GeneratesGifForInspection<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : unmanaged, IPixel<TPixel> |
||||
|
{ |
||||
|
Image<Rgba32>[] handImages = |
||||
|
[ |
||||
|
Image.Load<Rgba32>(TestFile.Create(TestImages.Png.Issue396Hand1).Bytes), |
||||
|
Image.Load<Rgba32>(TestFile.Create(TestImages.Png.Issue396Hand2).Bytes) |
||||
|
]; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
using Image<TPixel> inputImage = provider.GetImage(); |
||||
|
using Image<Rgba32> outputImage = new(handImages[0].Width, handImages[0].Height); |
||||
|
|
||||
|
const float scaleFactor = 0.6F; |
||||
|
const float squashStepFactor = 0.22F; |
||||
|
|
||||
|
for (int i = 0; i < handImages.Length; i++) |
||||
|
{ |
||||
|
using Image<Rgba32> frameImage = new(handImages[i].Width, handImages[i].Height); |
||||
|
float squashFactorY = 1 - (i * squashStepFactor); |
||||
|
|
||||
|
frameImage.ProcessPixelRows(accessor => |
||||
|
{ |
||||
|
Rgba32 gray = Color.Gray.ToPixel<Rgba32>(); |
||||
|
|
||||
|
for (int y = 0; y < accessor.Height; y++) |
||||
|
{ |
||||
|
accessor.GetRowSpan(y).Fill(gray); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
Rectangle targetRect = new( |
||||
|
(int)((frameImage.Width - (frameImage.Width * scaleFactor)) / 2), |
||||
|
(int)(frameImage.Height * (((1 - scaleFactor) / 2) + (scaleFactor * (1 - squashFactorY)))), |
||||
|
(int)(frameImage.Width * scaleFactor), |
||||
|
(int)(frameImage.Height * scaleFactor * squashFactorY)); |
||||
|
|
||||
|
using Image<Rgba32> dragonFrame = inputImage.CloneAs<Rgba32>(); |
||||
|
dragonFrame.Mutate(context => context.Resize(targetRect.Size)); |
||||
|
|
||||
|
frameImage.Mutate(context => |
||||
|
{ |
||||
|
context.DrawImage(dragonFrame, targetRect.Location, 1F); |
||||
|
context.DrawImage(handImages[i], Point.Empty, 1F); |
||||
|
}); |
||||
|
|
||||
|
ImageFrame<Rgba32> outputFrame = outputImage.Frames.AddFrame(frameImage.Frames.RootFrame); |
||||
|
GifFrameMetadata gifFrameMetadata = outputFrame.Metadata.GetGifMetadata(); |
||||
|
gifFrameMetadata.FrameDelay = 40; |
||||
|
gifFrameMetadata.DisposalMode = FrameDisposalMode.RestoreToBackground; |
||||
|
} |
||||
|
|
||||
|
for (int i = handImages.Length - 1; i > 0; i--) |
||||
|
{ |
||||
|
outputImage.Frames.AddFrame(outputImage.Frames[i]); |
||||
|
} |
||||
|
|
||||
|
outputImage.Frames.RemoveFrame(0); |
||||
|
GifMetadata gifMetadata = outputImage.Metadata.GetGifMetadata(); |
||||
|
gifMetadata.RepeatCount = 0; |
||||
|
|
||||
|
Assert.Equal((handImages.Length * 2) - 1, outputImage.Frames.Count); |
||||
|
foreach (ImageFrame<Rgba32> frame in outputImage.Frames) |
||||
|
{ |
||||
|
Assert.Equal(FrameDisposalMode.RestoreToBackground, frame.Metadata.GetGifMetadata().DisposalMode); |
||||
|
} |
||||
|
|
||||
|
outputImage.DebugSaveMultiFrame(provider, "Issue396-source-frames", appendPixelTypeToFileName: false); |
||||
|
provider.Utility.SaveTestOutputFile( |
||||
|
outputImage, |
||||
|
"gif", |
||||
|
new GifEncoder(), |
||||
|
"Issue396-encoded", |
||||
|
appendPixelTypeToFileName: false, |
||||
|
appendSourceFileOrDescription: false); |
||||
|
|
||||
|
// Save and decode the GIF so the encoder's optimized frame diffs can be inspected separately.
|
||||
|
using MemoryStream gifStream = new(); |
||||
|
outputImage.SaveAsGif(gifStream); |
||||
|
gifStream.Position = 0; |
||||
|
|
||||
|
using Image<Rgba32> decodedImage = Image.Load<Rgba32>(gifStream); |
||||
|
decodedImage.DebugSaveMultiFrame(provider, "Issue396-decoded-frames", appendPixelTypeToFileName: false); |
||||
|
|
||||
|
Assert.Equal(outputImage.Frames.Count, decodedImage.Frames.Count); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
foreach (Image<Rgba32> handImage in handImages) |
||||
|
{ |
||||
|
handImage.Dispose(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
version https://git-lfs.github.com/spec/v1 |
||||
|
oid sha256:203aca58e0aa19cbb7ab0820ef55005af830bf4c9bfd1dd4d9967c7e1bc1d51a |
||||
|
size 494160 |
||||
@ -0,0 +1,3 @@ |
|||||
|
version https://git-lfs.github.com/spec/v1 |
||||
|
oid sha256:4ab791784ac46f9e50a63bd255f39ff8af236a922aab3510a29b473bd93bffd5 |
||||
|
size 16295 |
||||
@ -0,0 +1,3 @@ |
|||||
|
version https://git-lfs.github.com/spec/v1 |
||||
|
oid sha256:dbf54bcef6730b68b18770105a15448f984aaca6910693d4e65106a526af58d8 |
||||
|
size 17756 |
||||
Loading…
Reference in new issue