From 8f19e5edd23f13fd1ddf93b4e795f82e7f1334bb Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Fri, 25 Jan 2019 18:29:49 +0100 Subject: [PATCH] Moving sliding window from left to right instead of from top to bottom --- .../AdaptiveHistEqualizationSWProcessor.cs | 95 ++++++++++--------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs index 8c86e58c7..0e2f29b80 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs @@ -51,21 +51,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization Span pixels = source.GetPixelSpan(); var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism }; - int tileWidth = source.Width / this.Tiles; - int pixeInTile = tileWidth * tileWidth; - int halfTileWith = tileWidth / 2; + int tileHeight = source.Height / this.Tiles; + int pixeInTile = tileHeight * tileHeight; + int halfTileHeight = tileHeight / 2; + int halfTileWidth = halfTileHeight; using (Buffer2D targetPixels = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height)) { Parallel.For( 0, - source.Width, + source.Height, parallelOptions, - x => + y => { using (IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) using (IMemoryOwner histogramBufferCopy = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) using (IMemoryOwner cdfBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean)) - using (IMemoryOwner pixelRowBuffer = memoryAllocator.Allocate(tileWidth, AllocationOptions.Clean)) + using (IMemoryOwner pixelColumnBuffer = memoryAllocator.Allocate(tileHeight, AllocationOptions.Clean)) { Span histogram = histogramBuffer.GetSpan(); ref int histogramBase = ref MemoryMarshal.GetReference(histogram); @@ -73,21 +74,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization ref int histogramCopyBase = ref MemoryMarshal.GetReference(histogramCopy); ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan()); - Span pixelRow = pixelRowBuffer.GetSpan(); + Span pixelColumn = pixelColumnBuffer.GetSpan(); int maxHistIdx = 0; // Build the histogram of grayscale values for the current tile. - for (int dy = -halfTileWith; dy < halfTileWith; dy++) + for (int dx = -halfTileWidth; dx < halfTileWidth; dx++) { - Span rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, dy, tileWidth); - int maxIdx = this.AddPixelsToHistogram(rowSpan, histogram, this.LuminanceLevels); + Span columnSpan = this.GetPixelColumn(source, pixelColumn, dx, y - halfTileHeight, tileHeight); + int maxIdx = this.AddPixelsToHistogram(columnSpan, histogram, this.LuminanceLevels); if (maxIdx > maxHistIdx) { maxHistIdx = maxIdx; } } - for (int y = 0; y < source.Height; y++) + for (int x = 0; x < source.Width; x++) { if (this.ClipHistogramEnabled) { @@ -103,18 +104,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization float numberOfPixelsMinusCdfMin = pixeInTile - cdfMin; - // Map the current pixel to the new equalized value + // Map the current pixel to the new equalized value. int luminance = GetLuminance(source[x, y], this.LuminanceLevels); float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin; targetPixels[x, y].FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, source[x, y].ToVector4().W)); - // Remove top most row from the histogram, mirroring rows which exceeds the borders. - Span rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, y - halfTileWith, tileWidth); - maxHistIdx = this.RemovePixelsFromHistogram(rowSpan, histogram, this.LuminanceLevels, maxHistIdx); + // Remove left most column from the histogram, mirroring columns which exceeds the borders of the image. + Span columnSpan = this.GetPixelColumn(source, pixelColumn, x - halfTileWidth, y - halfTileHeight, tileHeight); + maxHistIdx = this.RemovePixelsFromHistogram(columnSpan, histogram, this.LuminanceLevels, maxHistIdx); - // Add new bottom row to the histogram, mirroring rows which exceeds the borders. - rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, y + halfTileWith, tileWidth); - int maxIdx = this.AddPixelsToHistogram(rowSpan, histogram, this.LuminanceLevels); + // Add new right column to the histogram, mirroring columns which exceeds the borders of the image. + columnSpan = this.GetPixelColumn(source, pixelColumn, x + halfTileWidth, y - halfTileHeight, tileHeight); + int maxIdx = this.AddPixelsToHistogram(columnSpan, histogram, this.LuminanceLevels); if (maxIdx > maxHistIdx) { maxHistIdx = maxIdx; @@ -128,62 +129,64 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// - /// Get the a pixel row at a given position with a length of the tile width. Mirrors pixels which exceeds the edges. + /// Get the a pixel column at a given position with the size of the tile height. Mirrors pixels which exceeds the edges of the image. /// /// The source image. - /// Pre-allocated pixel row span of the size of a tile width. + /// Pre-allocated pixel row span of the size of a tile height. /// The x position. /// The y position. - /// The width in pixels of a tile. + /// The height in pixels of a tile. /// A pixel row of the length of the tile width. - private Span GetPixelRow(ImageFrame source, Span rowPixels, int x, int y, int tileWidth) + private Span GetPixelColumn(ImageFrame source, Span columnPixels, int x, int y, int tileHeight) { - if (y < 0) + if (x < 0) { - y = Math.Abs(y); + x = Math.Abs(x); } - else if (y >= source.Height) + else if (x >= source.Width) { - int diff = y - source.Height; - y = source.Height - diff - 1; + int diff = x - source.Width; + x = source.Width - diff - 1; } - // Special cases for the left and the right border where GetPixelRowSpan can not be used - if (x < 0) + int idx = 0; + columnPixels.Clear(); + if (y < 0) { - rowPixels.Clear(); - int idx = 0; - for (int dx = x; dx < x + tileWidth; dx++) + columnPixels.Clear(); + for (int dy = y; dy < y + tileHeight; dy++) { - rowPixels[idx] = source[Math.Abs(dx), y]; + columnPixels[idx] = source[x, Math.Abs(dy)]; idx++; } - - return rowPixels; } - else if (x + tileWidth > source.Width) + else if (y + tileHeight > source.Height) { - rowPixels.Clear(); - int idx = 0; - for (int dx = x; dx < x + tileWidth; dx++) + for (int dy = y; dy < y + tileHeight; dy++) { - if (dx >= source.Width) + if (dy >= source.Height) { - int diff = dx - source.Width; - rowPixels[idx] = source[dx - diff - 1, y]; + int diff = dy - source.Height; + columnPixels[idx] = source[x, dy - diff - 1]; } else { - rowPixels[idx] = source[dx, y]; + columnPixels[idx] = source[x, dy]; } idx++; } - - return rowPixels; + } + else + { + for (int dy = y; dy < y + tileHeight; dy++) + { + columnPixels[idx] = source[x, dy]; + idx++; + } } - return source.GetPixelRowSpan(y).Slice(start: x, length: tileWidth); + return columnPixels; } ///