Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Processing
Expand Down Expand Up @@ -34,9 +34,10 @@ public static IImageProcessingContext Pad(this IImageProcessingContext source, i
Size = new Size(width, height),
Mode = ResizeMode.BoxPad,
Sampler = KnownResamplers.NearestNeighbor,
PadColor = color
};

return color.Equals(default) ? source.Resize(options) : source.Resize(options).BackgroundColor(color);
return source.Resize(options);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,12 @@ public ResizeProcessor(ResizeOptions options, Size sourceSize)

(Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options);

this.Sampler = options.Sampler;
this.Options = options;
this.DestinationWidth = size.Width;
this.DestinationHeight = size.Height;
this.DestinationRectangle = rectangle;
this.Compand = options.Compand;
this.PremultiplyAlpha = options.PremultiplyAlpha;
}

/// <summary>
/// Gets the sampler to perform the resize operation.
/// </summary>
public IResampler Sampler { get; }

/// <summary>
/// Gets the destination width.
/// </summary>
Expand All @@ -50,14 +43,9 @@ public ResizeProcessor(ResizeOptions options, Size sourceSize)
public Rectangle DestinationRectangle { get; }

/// <summary>
/// Gets a value indicating whether to compress or expand individual pixel color values on processing.
/// </summary>
public bool Compand { get; }

/// <summary>
/// Gets a value indicating whether to premultiply the alpha (if it exists) during the resize operation.
/// Gets the resize options.
/// </summary>
public bool PremultiplyAlpha { get; }
public ResizeOptions Options { get; }

/// <inheritdoc />
public override ICloningImageProcessor<TPixel> CreatePixelSpecificCloningProcessor<TPixel>(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;

Expand All @@ -17,12 +16,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
internal class ResizeProcessor<TPixel> : TransformProcessor<TPixel>, IResamplingTransformImageProcessor<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
{
private readonly ResizeOptions options;
private readonly int destinationWidth;
private readonly int destinationHeight;
private readonly IResampler resampler;
private readonly Rectangle destinationRectangle;
private readonly bool compand;
private readonly bool premultiplyAlpha;
private Image<TPixel> destination;

public ResizeProcessor(Configuration configuration, ResizeProcessor definition, Image<TPixel> source, Rectangle sourceRectangle)
Expand All @@ -31,13 +29,12 @@ public ResizeProcessor(Configuration configuration, ResizeProcessor definition,
this.destinationWidth = definition.DestinationWidth;
this.destinationHeight = definition.DestinationHeight;
this.destinationRectangle = definition.DestinationRectangle;
this.resampler = definition.Sampler;
this.premultiplyAlpha = definition.PremultiplyAlpha;
this.compand = definition.Compand;
this.options = definition.Options;
this.resampler = definition.Options.Sampler;
}

/// <inheritdoc/>
protected override Size GetDestinationSize() => new Size(this.destinationWidth, this.destinationHeight);
protected override Size GetDestinationSize() => new(this.destinationWidth, this.destinationHeight);

/// <inheritdoc/>
protected override void BeforeImageApply(Image<TPixel> destination)
Expand All @@ -62,8 +59,11 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
Image<TPixel> destination = this.destination;
Rectangle sourceRectangle = this.SourceRectangle;
Rectangle destinationRectangle = this.destinationRectangle;
bool compand = this.compand;
bool premultiplyAlpha = this.premultiplyAlpha;
bool compand = this.options.Compand;
bool premultiplyAlpha = this.options.PremultiplyAlpha;
bool shouldFill = (this.options.Mode == ResizeMode.BoxPad || this.options.Mode == ResizeMode.Pad)
&& this.options.PadColor != default;
TPixel fillColor = this.options.PadColor.ToPixel<TPixel>();

// Handle resize dimensions identical to the original
if (source.Width == destination.Width
Expand Down Expand Up @@ -91,6 +91,11 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
ImageFrame<TPixel> sourceFrame = source.Frames[i];
ImageFrame<TPixel> destinationFrame = destination.Frames[i];

if (shouldFill)
{
destinationFrame.Clear(fillColor);
}

ApplyNNResizeFrameTransform(
configuration,
sourceFrame,
Expand Down Expand Up @@ -123,6 +128,11 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
ImageFrame<TPixel> sourceFrame = source.Frames[i];
ImageFrame<TPixel> destinationFrame = destination.Frames[i];

if (shouldFill)
{
destinationFrame.Clear(fillColor);
}

ApplyResizeFrameTransform(
configuration,
sourceFrame,
Expand Down
5 changes: 5 additions & 0 deletions src/ImageSharp/Processing/ResizeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,10 @@ public class ResizeOptions
/// the alpha (if it exists) during the resize operation.
/// </summary>
public bool PremultiplyAlpha { get; set; } = true;

/// <summary>
/// Gets or sets the color to use as a background when padding an image.
/// </summary>
public Color PadColor { get; set; }
}
}
40 changes: 18 additions & 22 deletions tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,41 +20,37 @@ public class PadTest
public void ImageShouldPad<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50));
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50));
image.DebugSave(provider);

// Check pixels are empty
for (int y = 0; y < 25; y++)
// Check pixels are empty
for (int y = 0; y < 25; y++)
{
for (int x = 0; x < 25; x++)
{
for (int x = 0; x < 25; x++)
{
Assert.Equal(default, image[x, y]);
}
Assert.Equal(default, image[x, y]);
}
}
}

[Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)]
public void ImageShouldPadWithBackgroundColor<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
var color = Color.Red;
Color color = Color.Red;
TPixel expected = color.ToPixel<TPixel>();
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50, color));
image.DebugSave(provider);
using Image<TPixel> image = provider.GetImage();
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50, color));
image.DebugSave(provider);

// Check pixels are filled
for (int y = 0; y < 25; y++)
// Check pixels are filled
for (int y = 0; y < 25; y++)
{
for (int x = 0; x < 25; x++)
{
for (int x = 0; x < 25; x++)
{
Assert.Equal(expected, image[x, y]);
}
Assert.Equal(expected, image[x, y]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public void PadWidthHeightResizeProcessorWithCorrectOptionsSet()

Assert.Equal(width, resizeProcessor.DestinationWidth);
Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
}
}
}
10 changes: 5 additions & 5 deletions tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void ResizeWidthAndHeightAndSampler()

Assert.Equal(width, resizeProcessor.DestinationWidth);
Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
}

[Fact]
Expand All @@ -52,8 +52,8 @@ public void ResizeWidthAndHeightAndSamplerAndCompand()

Assert.Equal(width, resizeProcessor.DestinationWidth);
Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(compand, resizeProcessor.Compand);
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
Assert.Equal(compand, resizeProcessor.Options.Compand);
}

[Fact]
Expand All @@ -78,8 +78,8 @@ public void ResizeWithOptions()

Assert.Equal(width, resizeProcessor.DestinationWidth);
Assert.Equal(height, resizeProcessor.DestinationHeight);
Assert.Equal(sampler, resizeProcessor.Sampler);
Assert.Equal(compand, resizeProcessor.Compand);
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
Assert.Equal(compand, resizeProcessor.Options.Compand);

// Ensure options are not altered.
Assert.Equal(width, resizeOptions.Size.Width);
Expand Down