Skip to content

Commit 9fc42d7

Browse files
Merge branch 'main' into bp/extrasamples2
2 parents e0fa9d8 + 7bd0e03 commit 9fc42d7

File tree

7 files changed

+35
-29
lines changed

7 files changed

+35
-29
lines changed

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Six Labors.
22
// Licensed under the Apache License, Version 2.0.
33

4+
using System;
5+
46
namespace SixLabors.ImageSharp.Processing
57
{
68
/// <summary>
@@ -29,9 +31,11 @@ public static IImageProcessingContext Pad(this IImageProcessingContext source, i
2931
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
3032
public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height, Color color)
3133
{
34+
Size size = source.GetCurrentSize();
3235
var options = new ResizeOptions
3336
{
34-
Size = new Size(width, height),
37+
// Prevent downsizing.
38+
Size = new Size(Math.Max(width, size.Width), Math.Max(height, size.Height)),
3539
Mode = ResizeMode.BoxPad,
3640
Sampler = KnownResamplers.NearestNeighbor,
3741
PadColor = color

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ protected virtual void Dispose(bool disposing)
101101
/// Returns a <see cref="ResizeKernel"/> for an index value between 0 and DestinationSize - 1.
102102
/// </summary>
103103
[MethodImpl(InliningOptions.ShortMethod)]
104-
internal ref ResizeKernel GetKernel(int destIdx) => ref this.kernels[destIdx];
104+
internal ref ResizeKernel GetKernel(nint destIdx) => ref this.kernels[destIdx];
105105

106106
/// <summary>
107107
/// Computes the weights to apply at each pixel when resizing.

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

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ public void ApplyTransform<TResampler>(in TResampler sampler)
6161
Rectangle destinationRectangle = this.destinationRectangle;
6262
bool compand = this.options.Compand;
6363
bool premultiplyAlpha = this.options.PremultiplyAlpha;
64+
TPixel fillColor = this.options.PadColor.ToPixel<TPixel>();
6465
bool shouldFill = (this.options.Mode == ResizeMode.BoxPad || this.options.Mode == ResizeMode.Pad)
6566
&& 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
@@ -209,21 +209,18 @@ private static void ApplyResizeFrameTransform(
209209

210210
// To reintroduce parallel processing, we would launch multiple workers
211211
// for different row intervals of the image.
212-
using (var worker = new ResizeWorker<TPixel>(
212+
using var worker = new ResizeWorker<TPixel>(
213213
configuration,
214214
sourceRegion,
215215
conversionModifiers,
216216
horizontalKernelMap,
217217
verticalKernelMap,
218-
destination.Width,
219218
interest,
220-
destinationRectangle.Location))
221-
{
222-
worker.Initialize();
219+
destinationRectangle.Location);
220+
worker.Initialize();
223221

224-
var workingInterval = new RowInterval(interest.Top, interest.Bottom);
225-
worker.FillDestinationPixels(workingInterval, destination.PixelBuffer);
226-
}
222+
var workingInterval = new RowInterval(interest.Top, interest.Bottom);
223+
worker.FillDestinationPixels(workingInterval, destination.PixelBuffer);
227224
}
228225

229226
private readonly struct NNRowOperation : IRowOperation

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

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ internal sealed class ResizeWorker<TPixel> : IDisposable
3939

4040
private readonly ResizeKernelMap verticalKernelMap;
4141

42-
private readonly int destWidth;
43-
4442
private readonly Rectangle targetWorkingRect;
4543

4644
private readonly Point targetOrigin;
@@ -57,7 +55,6 @@ public ResizeWorker(
5755
PixelConversionModifiers conversionModifiers,
5856
ResizeKernelMap horizontalKernelMap,
5957
ResizeKernelMap verticalKernelMap,
60-
int destWidth,
6158
Rectangle targetWorkingRect,
6259
Point targetOrigin)
6360
{
@@ -67,7 +64,6 @@ public ResizeWorker(
6764
this.conversionModifiers = conversionModifiers;
6865
this.horizontalKernelMap = horizontalKernelMap;
6966
this.verticalKernelMap = verticalKernelMap;
70-
this.destWidth = destWidth;
7167
this.targetWorkingRect = targetWorkingRect;
7268
this.targetOrigin = targetOrigin;
7369

@@ -80,19 +76,19 @@ public ResizeWorker(
8076

8177
int numberOfWindowBands = ResizeHelper.CalculateResizeWorkerHeightInWindowBands(
8278
this.windowBandHeight,
83-
destWidth,
79+
targetWorkingRect.Width,
8480
workingBufferLimitHintInBytes);
8581

8682
this.workerHeight = Math.Min(this.sourceRectangle.Height, numberOfWindowBands * this.windowBandHeight);
8783

8884
this.transposedFirstPassBuffer = configuration.MemoryAllocator.Allocate2D<Vector4>(
8985
this.workerHeight,
90-
destWidth,
86+
targetWorkingRect.Width,
9187
preferContiguosImageBuffers: true,
9288
options: AllocationOptions.Clean);
9389

9490
this.tempRowBuffer = configuration.MemoryAllocator.Allocate<Vector4>(this.sourceRectangle.Width);
95-
this.tempColumnBuffer = configuration.MemoryAllocator.Allocate<Vector4>(destWidth);
91+
this.tempColumnBuffer = configuration.MemoryAllocator.Allocate<Vector4>(targetWorkingRect.Width);
9692

9793
this.currentWindow = new RowInterval(0, this.workerHeight);
9894
}
@@ -118,6 +114,9 @@ public void FillDestinationPixels(RowInterval rowInterval, Buffer2D<TPixel> dest
118114
// When creating transposedFirstPassBuffer, we made sure it's contiguous:
119115
Span<Vector4> transposedFirstPassBufferSpan = this.transposedFirstPassBuffer.DangerousGetSingleSpan();
120116

117+
int left = this.targetWorkingRect.Left;
118+
int right = this.targetWorkingRect.Right;
119+
int width = this.targetWorkingRect.Width;
121120
for (int y = rowInterval.Min; y < rowInterval.Max; y++)
122121
{
123122
// Ensure offsets are normalized for cropping and padding.
@@ -131,17 +130,18 @@ public void FillDestinationPixels(RowInterval rowInterval, Buffer2D<TPixel> dest
131130
ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempColSpan);
132131

133132
int top = kernel.StartIndex - this.currentWindow.Min;
133+
134134
ref Vector4 fpBase = ref transposedFirstPassBufferSpan[top];
135135

136-
for (int x = 0; x < this.destWidth; x++)
136+
for (nint x = 0; x < (right - left); x++)
137137
{
138138
ref Vector4 firstPassColumnBase = ref Unsafe.Add(ref fpBase, x * this.workerHeight);
139139

140140
// Destination color components
141141
Unsafe.Add(ref tempRowBase, x) = kernel.ConvolveCore(ref firstPassColumnBase);
142142
}
143143

144-
Span<TPixel> targetRowSpan = destination.DangerousGetRowSpan(y);
144+
Span<TPixel> targetRowSpan = destination.DangerousGetRowSpan(y).Slice(left, width);
145145

146146
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, tempColSpan, targetRowSpan, this.conversionModifiers);
147147
}
@@ -170,6 +170,9 @@ private void CalculateFirstPassValues(RowInterval calculationInterval)
170170
Span<Vector4> tempRowSpan = this.tempRowBuffer.GetSpan();
171171
Span<Vector4> transposedFirstPassBufferSpan = this.transposedFirstPassBuffer.DangerousGetSingleSpan();
172172

173+
int left = this.targetWorkingRect.Left;
174+
int right = this.targetWorkingRect.Right;
175+
int targetOriginX = this.targetOrigin.X;
173176
for (int y = calculationInterval.Min; y < calculationInterval.Max; y++)
174177
{
175178
Span<TPixel> sourceRow = this.source.DangerousGetRowSpan(y);
@@ -184,13 +187,13 @@ private void CalculateFirstPassValues(RowInterval calculationInterval)
184187
// Span<Vector4> firstPassSpan = transposedFirstPassBufferSpan.Slice(y - this.currentWindow.Min);
185188
ref Vector4 firstPassBaseRef = ref transposedFirstPassBufferSpan[y - this.currentWindow.Min];
186189

187-
for (int x = this.targetWorkingRect.Left; x < this.targetWorkingRect.Right; x++)
190+
for (nint x = left, z = 0; x < right; x++, z++)
188191
{
189-
ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - this.targetOrigin.X);
192+
ResizeKernel kernel = this.horizontalKernelMap.GetKernel(x - targetOriginX);
190193

191194
// optimization for:
192195
// firstPassSpan[x * this.workerHeight] = kernel.Convolve(tempRowSpan);
193-
Unsafe.Add(ref firstPassBaseRef, x * this.workerHeight) = kernel.Convolve(tempRowSpan);
196+
Unsafe.Add(ref firstPassBaseRef, z * this.workerHeight) = kernel.Convolve(tempRowSpan);
194197
}
195198
}
196199
}

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ public void ResizeWithBoxPadMode<TPixel>(TestImageProvider<TPixel> provider)
472472
var options = new ResizeOptions
473473
{
474474
Size = new Size(image.Width + 200, image.Height + 200),
475-
Mode = ResizeMode.BoxPad
475+
Mode = ResizeMode.BoxPad,
476+
PadColor = Color.HotPink
476477
};
477478

478479
image.Mutate(x => x.Resize(options));
@@ -580,7 +581,8 @@ public void ResizeWithPadMode<TPixel>(TestImageProvider<TPixel> provider)
580581
var options = new ResizeOptions
581582
{
582583
Size = new Size(image.Width + 200, image.Height),
583-
Mode = ResizeMode.Pad
584+
Mode = ResizeMode.Pad,
585+
PadColor = Color.Lavender
584586
};
585587

586588
image.Mutate(x => x.Resize(options));
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)