From d41ece14326d83c93edfc8b57166573953612d90 Mon Sep 17 00:00:00 2001 From: popow Date: Sat, 30 Jun 2018 15:46:22 +0200 Subject: [PATCH] added first attempt of histogram equalization --- .../HistogramEqualizationExtension.cs | 23 +++++++ .../HistogramEqualizationProcessor.cs | 64 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/ImageSharp/Processing/Contrast/HistogramEqualizationExtension.cs create mode 100644 src/ImageSharp/Processing/Contrast/HistogramEqualizationProcessor.cs diff --git a/src/ImageSharp/Processing/Contrast/HistogramEqualizationExtension.cs b/src/ImageSharp/Processing/Contrast/HistogramEqualizationExtension.cs new file mode 100644 index 0000000000..1cd29f8b43 --- /dev/null +++ b/src/ImageSharp/Processing/Contrast/HistogramEqualizationExtension.cs @@ -0,0 +1,23 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Contrast +{ + /// + /// Adds extension that allows applying an HistogramEqualization to the image. + /// + public static class HistogramEqualizationExtension + { + /// + /// Equalizes the histogram of an image to increases the global contrast. + /// + /// The pixel format. + /// The image this method extends. + /// The . + public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) + where TPixel : struct, IPixel + => source.ApplyProcessor(new HistogramEqualizationProcessor()); + } +} diff --git a/src/ImageSharp/Processing/Contrast/HistogramEqualizationProcessor.cs b/src/ImageSharp/Processing/Contrast/HistogramEqualizationProcessor.cs new file mode 100644 index 0000000000..2bacb98ce4 --- /dev/null +++ b/src/ImageSharp/Processing/Contrast/HistogramEqualizationProcessor.cs @@ -0,0 +1,64 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Contrast +{ + internal class HistogramEqualizationProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) + { + var rgb = default(Rgb24); + int numberOfPixels = source.Width * source.Height; + + // build the histogram of the grayscale levels + int luminanceLevels = 256; + int[] histogram = new int[luminanceLevels]; + for (int y = 0; y < source.Height; y++) + { + Span row = source.GetPixelRowSpan(y); + for (int x = 0; x < source.Width; x++) + { + TPixel sourcePixel = row[x]; + sourcePixel.ToRgb24(ref rgb); + + // Convert to grayscale using ITU-R Recommendation BT.709 if required + int luminance = (int)((.2126F * rgb.R) + (.7152F * rgb.G) + (.0722F * rgb.B)); + histogram[luminance]++; + } + } + + // calculate the cumulative distribution function + double[] cdf = new double[luminanceLevels]; + double sum = 0.0d; + for (int i = 0; i < histogram.Length; i++) + { + double p = (double)histogram[i] / numberOfPixels; + sum += p; + cdf[i] = sum; + } + + // apply the cdf to each pixel of the image + for (int y = 0; y < source.Height; y++) + { + Span row = source.GetPixelRowSpan(y); + for (int x = 0; x < source.Width; x++) + { + TPixel sourcePixel = row[x]; + sourcePixel.ToRgb24(ref rgb); + int luminance = (int)((.2126F * rgb.R) + (.7152F * rgb.G) + (.0722F * rgb.B)); + byte luminanceEqualized = (byte)(cdf[luminance] * luminance); + + row[x].PackFromRgba32(new Rgba32(luminanceEqualized, luminanceEqualized, luminanceEqualized)); + } + } + } + } +}