Skip to content

Commit 14418c1

Browse files
Merge pull request #2034 from SixLabors/js/resize-pad
Allow pad to work for non-alpha pixel formats
2 parents 47a759e + 7ca5680 commit 14418c1

File tree

7 files changed

+54
-54
lines changed

7 files changed

+54
-54
lines changed

src/ImageSharp/Processing/Extensions/Transforms/PadExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors.
1+
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

44
namespace SixLabors.ImageSharp.Processing
@@ -34,9 +34,10 @@ public static IImageProcessingContext Pad(this IImageProcessingContext source, i
3434
Size = new Size(width, height),
3535
Mode = ResizeMode.BoxPad,
3636
Sampler = KnownResamplers.NearestNeighbor,
37+
PadColor = color
3738
};
3839

39-
return color.Equals(default) ? source.Resize(options) : source.Resize(options).BackgroundColor(color);
40+
return source.Resize(options);
4041
}
4142
}
4243
}

src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,12 @@ public ResizeProcessor(ResizeOptions options, Size sourceSize)
2121

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

24-
this.Sampler = options.Sampler;
24+
this.Options = options;
2525
this.DestinationWidth = size.Width;
2626
this.DestinationHeight = size.Height;
2727
this.DestinationRectangle = rectangle;
28-
this.Compand = options.Compand;
29-
this.PremultiplyAlpha = options.PremultiplyAlpha;
3028
}
3129

32-
/// <summary>
33-
/// Gets the sampler to perform the resize operation.
34-
/// </summary>
35-
public IResampler Sampler { get; }
36-
3730
/// <summary>
3831
/// Gets the destination width.
3932
/// </summary>
@@ -50,14 +43,9 @@ public ResizeProcessor(ResizeOptions options, Size sourceSize)
5043
public Rectangle DestinationRectangle { get; }
5144

5245
/// <summary>
53-
/// Gets a value indicating whether to compress or expand individual pixel color values on processing.
54-
/// </summary>
55-
public bool Compand { get; }
56-
57-
/// <summary>
58-
/// Gets a value indicating whether to premultiply the alpha (if it exists) during the resize operation.
46+
/// Gets the resize options.
5947
/// </summary>
60-
public bool PremultiplyAlpha { get; }
48+
public ResizeOptions Options { get; }
6149

6250
/// <inheritdoc />
6351
public override ICloningImageProcessor<TPixel> CreatePixelSpecificCloningProcessor<TPixel>(Configuration configuration, Image<TPixel> source, Rectangle sourceRectangle)

src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System;
55
using System.Runtime.CompilerServices;
66
using SixLabors.ImageSharp.Advanced;
7-
using SixLabors.ImageSharp.Formats;
87
using SixLabors.ImageSharp.Memory;
98
using SixLabors.ImageSharp.PixelFormats;
109

@@ -17,12 +16,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
1716
internal class ResizeProcessor<TPixel> : TransformProcessor<TPixel>, IResamplingTransformImageProcessor<TPixel>
1817
where TPixel : unmanaged, IPixel<TPixel>
1918
{
19+
private readonly ResizeOptions options;
2020
private readonly int destinationWidth;
2121
private readonly int destinationHeight;
2222
private readonly IResampler resampler;
2323
private readonly Rectangle destinationRectangle;
24-
private readonly bool compand;
25-
private readonly bool premultiplyAlpha;
2624
private Image<TPixel> destination;
2725

2826
public ResizeProcessor(Configuration configuration, ResizeProcessor definition, Image<TPixel> source, Rectangle sourceRectangle)
@@ -31,13 +29,12 @@ public ResizeProcessor(Configuration configuration, ResizeProcessor definition,
3129
this.destinationWidth = definition.DestinationWidth;
3230
this.destinationHeight = definition.DestinationHeight;
3331
this.destinationRectangle = definition.DestinationRectangle;
34-
this.resampler = definition.Sampler;
35-
this.premultiplyAlpha = definition.PremultiplyAlpha;
36-
this.compand = definition.Compand;
32+
this.options = definition.Options;
33+
this.resampler = definition.Options.Sampler;
3734
}
3835

3936
/// <inheritdoc/>
40-
protected override Size GetDestinationSize() => new Size(this.destinationWidth, this.destinationHeight);
37+
protected override Size GetDestinationSize() => new(this.destinationWidth, this.destinationHeight);
4138

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

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

94+
if (shouldFill)
95+
{
96+
destinationFrame.Clear(fillColor);
97+
}
98+
9499
ApplyNNResizeFrameTransform(
95100
configuration,
96101
sourceFrame,
@@ -123,6 +128,11 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
123128
ImageFrame<TPixel> sourceFrame = source.Frames[i];
124129
ImageFrame<TPixel> destinationFrame = destination.Frames[i];
125130

131+
if (shouldFill)
132+
{
133+
destinationFrame.Clear(fillColor);
134+
}
135+
126136
ApplyResizeFrameTransform(
127137
configuration,
128138
sourceFrame,

src/ImageSharp/Processing/ResizeOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,10 @@ public class ResizeOptions
5151
/// the alpha (if it exists) during the resize operation.
5252
/// </summary>
5353
public bool PremultiplyAlpha { get; set; } = true;
54+
55+
/// <summary>
56+
/// Gets or sets the color to use as a background when padding an image.
57+
/// </summary>
58+
public Color PadColor { get; set; }
5459
}
5560
}

tests/ImageSharp.Tests/Processing/Processors/Transforms/PadTest.cs

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,37 @@ public class PadTest
2020
public void ImageShouldPad<TPixel>(TestImageProvider<TPixel> provider)
2121
where TPixel : unmanaged, IPixel<TPixel>
2222
{
23-
using (Image<TPixel> image = provider.GetImage())
24-
{
25-
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50));
26-
image.DebugSave(provider);
23+
using Image<TPixel> image = provider.GetImage();
24+
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50));
25+
image.DebugSave(provider);
2726

28-
// Check pixels are empty
29-
for (int y = 0; y < 25; y++)
27+
// Check pixels are empty
28+
for (int y = 0; y < 25; y++)
29+
{
30+
for (int x = 0; x < 25; x++)
3031
{
31-
for (int x = 0; x < 25; x++)
32-
{
33-
Assert.Equal(default, image[x, y]);
34-
}
32+
Assert.Equal(default, image[x, y]);
3533
}
3634
}
3735
}
3836

3937
[Theory]
40-
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
38+
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)]
4139
public void ImageShouldPadWithBackgroundColor<TPixel>(TestImageProvider<TPixel> provider)
4240
where TPixel : unmanaged, IPixel<TPixel>
4341
{
44-
var color = Color.Red;
42+
Color color = Color.Red;
4543
TPixel expected = color.ToPixel<TPixel>();
46-
using (Image<TPixel> image = provider.GetImage())
47-
{
48-
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50, color));
49-
image.DebugSave(provider);
44+
using Image<TPixel> image = provider.GetImage();
45+
image.Mutate(x => x.Pad(image.Width + 50, image.Height + 50, color));
46+
image.DebugSave(provider);
5047

51-
// Check pixels are filled
52-
for (int y = 0; y < 25; y++)
48+
// Check pixels are filled
49+
for (int y = 0; y < 25; y++)
50+
{
51+
for (int x = 0; x < 25; x++)
5352
{
54-
for (int x = 0; x < 25; x++)
55-
{
56-
Assert.Equal(expected, image[x, y]);
57-
}
53+
Assert.Equal(expected, image[x, y]);
5854
}
5955
}
6056
}

tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public void PadWidthHeightResizeProcessorWithCorrectOptionsSet()
2323

2424
Assert.Equal(width, resizeProcessor.DestinationWidth);
2525
Assert.Equal(height, resizeProcessor.DestinationHeight);
26-
Assert.Equal(sampler, resizeProcessor.Sampler);
26+
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
2727
}
2828
}
2929
}

tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void ResizeWidthAndHeightAndSampler()
3535

3636
Assert.Equal(width, resizeProcessor.DestinationWidth);
3737
Assert.Equal(height, resizeProcessor.DestinationHeight);
38-
Assert.Equal(sampler, resizeProcessor.Sampler);
38+
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
3939
}
4040

4141
[Fact]
@@ -52,8 +52,8 @@ public void ResizeWidthAndHeightAndSamplerAndCompand()
5252

5353
Assert.Equal(width, resizeProcessor.DestinationWidth);
5454
Assert.Equal(height, resizeProcessor.DestinationHeight);
55-
Assert.Equal(sampler, resizeProcessor.Sampler);
56-
Assert.Equal(compand, resizeProcessor.Compand);
55+
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
56+
Assert.Equal(compand, resizeProcessor.Options.Compand);
5757
}
5858

5959
[Fact]
@@ -78,8 +78,8 @@ public void ResizeWithOptions()
7878

7979
Assert.Equal(width, resizeProcessor.DestinationWidth);
8080
Assert.Equal(height, resizeProcessor.DestinationHeight);
81-
Assert.Equal(sampler, resizeProcessor.Sampler);
82-
Assert.Equal(compand, resizeProcessor.Compand);
81+
Assert.Equal(sampler, resizeProcessor.Options.Sampler);
82+
Assert.Equal(compand, resizeProcessor.Options.Compand);
8383

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

0 commit comments

Comments
 (0)