Skip to content

Commit 8f19e5e

Browse files
committed
Moving sliding window from left to right instead of from top to bottom
1 parent f2930c7 commit 8f19e5e

File tree

1 file changed

+49
-46
lines changed

1 file changed

+49
-46
lines changed

src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistEqualizationSWProcessor.cs

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -51,43 +51,44 @@ protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle source
5151
Span<TPixel> pixels = source.GetPixelSpan();
5252

5353
var parallelOptions = new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism };
54-
int tileWidth = source.Width / this.Tiles;
55-
int pixeInTile = tileWidth * tileWidth;
56-
int halfTileWith = tileWidth / 2;
54+
int tileHeight = source.Height / this.Tiles;
55+
int pixeInTile = tileHeight * tileHeight;
56+
int halfTileHeight = tileHeight / 2;
57+
int halfTileWidth = halfTileHeight;
5758
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Width, source.Height))
5859
{
5960
Parallel.For(
6061
0,
61-
source.Width,
62+
source.Height,
6263
parallelOptions,
63-
x =>
64+
y =>
6465
{
6566
using (IMemoryOwner<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
6667
using (IMemoryOwner<int> histogramBufferCopy = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
6768
using (IMemoryOwner<int> cdfBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
68-
using (IMemoryOwner<TPixel> pixelRowBuffer = memoryAllocator.Allocate<TPixel>(tileWidth, AllocationOptions.Clean))
69+
using (IMemoryOwner<TPixel> pixelColumnBuffer = memoryAllocator.Allocate<TPixel>(tileHeight, AllocationOptions.Clean))
6970
{
7071
Span<int> histogram = histogramBuffer.GetSpan();
7172
ref int histogramBase = ref MemoryMarshal.GetReference(histogram);
7273
Span<int> histogramCopy = histogramBufferCopy.GetSpan();
7374
ref int histogramCopyBase = ref MemoryMarshal.GetReference(histogramCopy);
7475
ref int cdfBase = ref MemoryMarshal.GetReference(cdfBuffer.GetSpan());
7576

76-
Span<TPixel> pixelRow = pixelRowBuffer.GetSpan();
77+
Span<TPixel> pixelColumn = pixelColumnBuffer.GetSpan();
7778
int maxHistIdx = 0;
7879

7980
// Build the histogram of grayscale values for the current tile.
80-
for (int dy = -halfTileWith; dy < halfTileWith; dy++)
81+
for (int dx = -halfTileWidth; dx < halfTileWidth; dx++)
8182
{
82-
Span<TPixel> rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, dy, tileWidth);
83-
int maxIdx = this.AddPixelsToHistogram(rowSpan, histogram, this.LuminanceLevels);
83+
Span<TPixel> columnSpan = this.GetPixelColumn(source, pixelColumn, dx, y - halfTileHeight, tileHeight);
84+
int maxIdx = this.AddPixelsToHistogram(columnSpan, histogram, this.LuminanceLevels);
8485
if (maxIdx > maxHistIdx)
8586
{
8687
maxHistIdx = maxIdx;
8788
}
8889
}
8990

90-
for (int y = 0; y < source.Height; y++)
91+
for (int x = 0; x < source.Width; x++)
9192
{
9293
if (this.ClipHistogramEnabled)
9394
{
@@ -103,18 +104,18 @@ protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle source
103104

104105
float numberOfPixelsMinusCdfMin = pixeInTile - cdfMin;
105106

106-
// Map the current pixel to the new equalized value
107+
// Map the current pixel to the new equalized value.
107108
int luminance = GetLuminance(source[x, y], this.LuminanceLevels);
108109
float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / numberOfPixelsMinusCdfMin;
109110
targetPixels[x, y].FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, source[x, y].ToVector4().W));
110111

111-
// Remove top most row from the histogram, mirroring rows which exceeds the borders.
112-
Span<TPixel> rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, y - halfTileWith, tileWidth);
113-
maxHistIdx = this.RemovePixelsFromHistogram(rowSpan, histogram, this.LuminanceLevels, maxHistIdx);
112+
// Remove left most column from the histogram, mirroring columns which exceeds the borders of the image.
113+
Span<TPixel> columnSpan = this.GetPixelColumn(source, pixelColumn, x - halfTileWidth, y - halfTileHeight, tileHeight);
114+
maxHistIdx = this.RemovePixelsFromHistogram(columnSpan, histogram, this.LuminanceLevels, maxHistIdx);
114115

115-
// Add new bottom row to the histogram, mirroring rows which exceeds the borders.
116-
rowSpan = this.GetPixelRow(source, pixelRow, x - halfTileWith, y + halfTileWith, tileWidth);
117-
int maxIdx = this.AddPixelsToHistogram(rowSpan, histogram, this.LuminanceLevels);
116+
// Add new right column to the histogram, mirroring columns which exceeds the borders of the image.
117+
columnSpan = this.GetPixelColumn(source, pixelColumn, x + halfTileWidth, y - halfTileHeight, tileHeight);
118+
int maxIdx = this.AddPixelsToHistogram(columnSpan, histogram, this.LuminanceLevels);
118119
if (maxIdx > maxHistIdx)
119120
{
120121
maxHistIdx = maxIdx;
@@ -128,62 +129,64 @@ protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle source
128129
}
129130

130131
/// <summary>
131-
/// Get the a pixel row at a given position with a length of the tile width. Mirrors pixels which exceeds the edges.
132+
/// 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.
132133
/// </summary>
133134
/// <param name="source">The source image.</param>
134-
/// <param name="rowPixels">Pre-allocated pixel row span of the size of a tile width.</param>
135+
/// <param name="columnPixels">Pre-allocated pixel row span of the size of a tile height.</param>
135136
/// <param name="x">The x position.</param>
136137
/// <param name="y">The y position.</param>
137-
/// <param name="tileWidth">The width in pixels of a tile.</param>
138+
/// <param name="tileHeight">The height in pixels of a tile.</param>
138139
/// <returns>A pixel row of the length of the tile width.</returns>
139-
private Span<TPixel> GetPixelRow(ImageFrame<TPixel> source, Span<TPixel> rowPixels, int x, int y, int tileWidth)
140+
private Span<TPixel> GetPixelColumn(ImageFrame<TPixel> source, Span<TPixel> columnPixels, int x, int y, int tileHeight)
140141
{
141-
if (y < 0)
142+
if (x < 0)
142143
{
143-
y = Math.Abs(y);
144+
x = Math.Abs(x);
144145
}
145-
else if (y >= source.Height)
146+
else if (x >= source.Width)
146147
{
147-
int diff = y - source.Height;
148-
y = source.Height - diff - 1;
148+
int diff = x - source.Width;
149+
x = source.Width - diff - 1;
149150
}
150151

151-
// Special cases for the left and the right border where GetPixelRowSpan can not be used
152-
if (x < 0)
152+
int idx = 0;
153+
columnPixels.Clear();
154+
if (y < 0)
153155
{
154-
rowPixels.Clear();
155-
int idx = 0;
156-
for (int dx = x; dx < x + tileWidth; dx++)
156+
columnPixels.Clear();
157+
for (int dy = y; dy < y + tileHeight; dy++)
157158
{
158-
rowPixels[idx] = source[Math.Abs(dx), y];
159+
columnPixels[idx] = source[x, Math.Abs(dy)];
159160
idx++;
160161
}
161-
162-
return rowPixels;
163162
}
164-
else if (x + tileWidth > source.Width)
163+
else if (y + tileHeight > source.Height)
165164
{
166-
rowPixels.Clear();
167-
int idx = 0;
168-
for (int dx = x; dx < x + tileWidth; dx++)
165+
for (int dy = y; dy < y + tileHeight; dy++)
169166
{
170-
if (dx >= source.Width)
167+
if (dy >= source.Height)
171168
{
172-
int diff = dx - source.Width;
173-
rowPixels[idx] = source[dx - diff - 1, y];
169+
int diff = dy - source.Height;
170+
columnPixels[idx] = source[x, dy - diff - 1];
174171
}
175172
else
176173
{
177-
rowPixels[idx] = source[dx, y];
174+
columnPixels[idx] = source[x, dy];
178175
}
179176

180177
idx++;
181178
}
182-
183-
return rowPixels;
179+
}
180+
else
181+
{
182+
for (int dy = y; dy < y + tileHeight; dy++)
183+
{
184+
columnPixels[idx] = source[x, dy];
185+
idx++;
186+
}
184187
}
185188

186-
return source.GetPixelRowSpan(y).Slice(start: x, length: tileWidth);
189+
return columnPixels;
187190
}
188191

189192
/// <summary>

0 commit comments

Comments
 (0)