Browse Source

use ParallelHelper in BinaryThresholdProcessor and OilPaintingProcessor

af/merge-core
Anton Firszov 8 years ago
parent
commit
141073fd34
  1. 43
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  2. 110
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs

43
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
@ -56,7 +56,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
public TPixel LowerColor { get; set; }
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
float threshold = this.Threshold * 255F;
TPixel upper = this.UpperColor;
@ -70,25 +73,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
ParallelFor.WithConfiguration(
startY,
endY,
var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY);
ParallelHelper.IterateRows(
workingRect,
configuration,
y =>
rows =>
{
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
for (int y = rows.Min; y < rows.Max; y++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly
? rgba.A
: (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
color = luminance >= threshold ? upper : lower;
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly
? rgba.A
: (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
color = luminance >= threshold ? upper : lower;
}
}
});
}

110
src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs

@ -3,11 +3,11 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Effects
@ -49,7 +49,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
public int BrushSize { get; }
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
if (this.BrushSize <= 0 || this.BrushSize > source.Height || this.BrushSize > source.Width)
{
@ -70,69 +73,74 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
source.CopyTo(targetPixels);
ParallelFor.WithConfiguration(
startY,
maxY,
var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY);
ParallelHelper.IterateRows(
workingRect,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
for (int x = startX; x < endX; x++)
rows =>
{
int maxIntensity = 0;
int maxIndex = 0;
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
int[] intensityBin = new int[levels];
float[] redBin = new float[levels];
float[] blueBin = new float[levels];
float[] greenBin = new float[levels];
for (int x = startX; x < endX; x++)
{
int maxIntensity = 0;
int maxIndex = 0;
for (int fy = 0; fy <= radius; fy++)
{
int fyr = fy - radius;
int offsetY = y + fyr;
int[] intensityBin = new int[levels];
float[] redBin = new float[levels];
float[] blueBin = new float[levels];
float[] greenBin = new float[levels];
offsetY = offsetY.Clamp(0, maxY);
for (int fy = 0; fy <= radius; fy++)
{
int fyr = fy - radius;
int offsetY = y + fyr;
Span<TPixel> sourceOffsetRow = source.GetPixelRowSpan(offsetY);
offsetY = offsetY.Clamp(0, maxY);
for (int fx = 0; fx <= radius; fx++)
{
int fxr = fx - radius;
int offsetX = x + fxr;
offsetX = offsetX.Clamp(0, maxX);
Span<TPixel> sourceOffsetRow = source.GetPixelRowSpan(offsetY);
var vector = sourceOffsetRow[offsetX].ToVector4();
for (int fx = 0; fx <= radius; fx++)
{
int fxr = fx - radius;
int offsetX = x + fxr;
offsetX = offsetX.Clamp(0, maxX);
float sourceRed = vector.X;
float sourceBlue = vector.Z;
float sourceGreen = vector.Y;
var vector = sourceOffsetRow[offsetX].ToVector4();
int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1));
float sourceRed = vector.X;
float sourceBlue = vector.Z;
float sourceGreen = vector.Y;
intensityBin[currentIntensity]++;
blueBin[currentIntensity] += sourceBlue;
greenBin[currentIntensity] += sourceGreen;
redBin[currentIntensity] += sourceRed;
int currentIntensity = (int)MathF.Round(
(sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1));
if (intensityBin[currentIntensity] > maxIntensity)
{
maxIntensity = intensityBin[currentIntensity];
maxIndex = currentIntensity;
}
}
intensityBin[currentIntensity]++;
blueBin[currentIntensity] += sourceBlue;
greenBin[currentIntensity] += sourceGreen;
redBin[currentIntensity] += sourceRed;
float red = MathF.Abs(redBin[maxIndex] / maxIntensity);
float green = MathF.Abs(greenBin[maxIndex] / maxIntensity);
float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity);
if (intensityBin[currentIntensity] > maxIntensity)
{
maxIntensity = intensityBin[currentIntensity];
maxIndex = currentIntensity;
}
}
ref TPixel pixel = ref targetRow[x];
pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
float red = MathF.Abs(redBin[maxIndex] / maxIntensity);
float green = MathF.Abs(greenBin[maxIndex] / maxIntensity);
float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity);
ref TPixel pixel = ref targetRow[x];
pixel.PackFromVector4(
new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
}
}
}
}
});
});
Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}

Loading…
Cancel
Save