Browse Source

Optimize Resize

pull/221/head
James Jackson-South 9 years ago
parent
commit
e8b11042f3
  1. 5
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
  2. 4
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  3. 66
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

5
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs

@ -1,3 +1,8 @@
// <copyright file="ResamplingWeightedProcessor.Weights.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Processing.Processors namespace ImageSharp.Processing.Processors
{ {
using System; using System;

4
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs

@ -6,9 +6,7 @@
namespace ImageSharp.Processing.Processors namespace ImageSharp.Processing.Processors
{ {
using System; using System;
using System.Buffers;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ImageSharp.PixelFormats; using ImageSharp.PixelFormats;
@ -90,7 +88,7 @@ namespace ImageSharp.Processing.Processors
IResampler sampler = this.Sampler; IResampler sampler = this.Sampler;
float radius = MathF.Ceiling(scale * sampler.Radius); float radius = MathF.Ceiling(scale * sampler.Radius);
WeightsBuffer result = new WeightsBuffer(sourceSize, destinationSize); var result = new WeightsBuffer(sourceSize, destinationSize);
for (int i = 0; i < destinationSize; i++) for (int i = 0; i < destinationSize; i++)
{ {

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

@ -73,26 +73,24 @@ namespace ImageSharp.Processing.Processors
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
using (PixelAccessor<TPixel> targetPixels = new PixelAccessor<TPixel>(width, height)) using (var targetPixels = new PixelAccessor<TPixel>(width, height))
{ {
using (PixelAccessor<TPixel> sourcePixels = source.Lock()) Parallel.For(
{ minY,
Parallel.For( maxY,
minY, this.ParallelOptions,
maxY, y =>
this.ParallelOptions, {
y => // Y coordinates of source points
{ Span<TPixel> sourceRow = source.GetRowSpan((int)(((y - startY) * heightFactor) + sourceY));
// Y coordinates of source points Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
int originY = (int)(((y - startY) * heightFactor) + sourceY);
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
// X coordinates of source points // X coordinates of source points
targetPixels[x, y] = sourcePixels[(int)(((x - startX) * widthFactor) + sourceX), originY]; targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)];
} }
}); });
}
// Break out now. // Break out now.
source.SwapPixelsBuffers(targetPixels); source.SwapPixelsBuffers(targetPixels);
@ -106,10 +104,9 @@ namespace ImageSharp.Processing.Processors
// are the upper and lower bounds of the source rectangle. // are the upper and lower bounds of the source rectangle.
// TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed! // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed!
using (PixelAccessor<TPixel> targetPixels = new PixelAccessor<TPixel>(width, height)) using (var targetPixels = new PixelAccessor<TPixel>(width, height))
{ {
using (PixelAccessor<TPixel> sourcePixels = source.Lock()) using (var firstPassPixels = new Buffer2D<Vector4>(width, source.Height))
using (Buffer2D<Vector4> firstPassPixels = new Buffer2D<Vector4>(width, source.Height))
{ {
firstPassPixels.Clear(); firstPassPixels.Clear();
@ -120,21 +117,18 @@ namespace ImageSharp.Processing.Processors
y => y =>
{ {
// TODO: Without Parallel.For() this buffer object could be reused: // TODO: Without Parallel.For() this buffer object could be reused:
using (Buffer<Vector4> tempRowBuffer = new Buffer<Vector4>(sourcePixels.Width)) using (var tempRowBuffer = new Buffer<Vector4>(source.Width))
{ {
Span<TPixel> sourceRow = sourcePixels.GetRowSpan(y); Span<Vector4> firstPassRow = firstPassPixels.GetRowSpan(y);
Span<TPixel> sourceRow = source.GetRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4( PixelOperations<TPixel>.Instance.ToVector4(sourceRow, tempRowBuffer, sourceRow.Length);
sourceRow,
tempRowBuffer,
sourceRow.Length);
if (this.Compand) if (this.Compand)
{ {
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX); firstPassRow[x] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX);
} }
} }
else else
@ -142,7 +136,7 @@ namespace ImageSharp.Processing.Processors
for (int x = minX; x < maxX; x++) for (int x = minX; x < maxX; x++)
{ {
WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX); firstPassRow[x] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX);
} }
} }
} }
@ -157,6 +151,7 @@ namespace ImageSharp.Processing.Processors
{ {
// Ensure offsets are normalised for cropping and padding. // Ensure offsets are normalised for cropping and padding.
WeightsWindow window = this.VerticalWeights.Weights[y - startY]; WeightsWindow window = this.VerticalWeights.Weights[y - startY];
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
if (this.Compand) if (this.Compand)
{ {
@ -165,9 +160,9 @@ namespace ImageSharp.Processing.Processors
// Destination color components // Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY);
destination = destination.Compress(); destination = destination.Compress();
TPixel d = default(TPixel);
d.PackFromVector4(destination); ref TPixel pixel = ref targetRow[x];
targetPixels[x, y] = d; pixel.PackFromVector4(destination);
} }
} }
else else
@ -177,9 +172,8 @@ namespace ImageSharp.Processing.Processors
// Destination color components // Destination color components
Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY);
TPixel d = default(TPixel); ref TPixel pixel = ref targetRow[x];
d.PackFromVector4(destination); pixel.PackFromVector4(destination);
targetPixels[x, y] = d;
} }
} }
}); });

Loading…
Cancel
Save