/// <summary> /// Gets (256) array of histogram values for image. /// </summary> /// <param name="imageBytes">Image bytes</param> /// <param name="pixelDepth">Pixel depth of image</param> /// <returns>256 array of histogram values</returns> public static int[] GetHistogramValues(byte[] imageBytes, int pixelDepth) { bool isColor = BitmapDataExt.IsColorPixelDepth(pixelDepth); // 0-255 int[] histogram = new int[byte.MaxValue + 1]; int limit = BitmapDataExt.GetSafeArrayLimitForImage(isColor, pixelDepth, imageBytes); byte avg; // Find number of pixels at each level. for (int i = 0; i < limit; i += pixelDepth) { if (isColor) { avg = (byte)((imageBytes[i] + imageBytes[i + 1] + imageBytes[i + 2]) / 3); } else { avg = imageBytes[i]; } // double-check within range. if (avg >= 0 && avg < histogram.Length) { histogram[avg]++; } } return(histogram); }
/// <summary> /// Histogram Equalization will enhance general contrast /// by distributing grey levels wider and more evenly. /// </summary> /// <param name="imageBytes">Image bytes</param> /// <param name="pixelDepth">Pixel depth of image</param> /// <param name="imageWidth">Image width</param> /// <param name="imageHeight">Image height</param> public static void HistogramEqualizationDirect(byte[] imageBytes, int pixelDepth, int imageWidth, int imageHeight) { int[] histogram = ImageHistogram.GetHistogramValues(imageBytes, pixelDepth); double numberOfPixels = imageWidth * imageHeight; double numberOfLevels = histogram.Length; int cumulativeFrequency = 0; int equalizedValue; // Calculate cumulative distribution for histogram for (int i = 0; i < histogram.Length; i++) { cumulativeFrequency += histogram[i]; // Calculate equalized value equalizedValue = (int)Math.Round((numberOfLevels * cumulativeFrequency) / numberOfPixels) - 1; // Ensure +ve value histogram[i] = Math.Max(0, equalizedValue); } bool isColor = BitmapDataExt.IsColorPixelDepth(pixelDepth); int limit = BitmapDataExt.GetSafeArrayLimitForImage(isColor, pixelDepth, imageBytes); // Apply distribution to image to equalize if (isColor) { // Exclude alpha/transparency byte int pixelDepthWithoutAlpha = Math.Min(pixelDepth, Constants.PixelDepthRGB); for (int i = 0, j; i < limit; i += pixelDepth) { for (j = 0; j < pixelDepthWithoutAlpha; j++) { imageBytes[i + j] = (byte)histogram[imageBytes[i + j]]; } } } else { for (int i = 0; i < limit; i++) { imageBytes[i] = (byte)histogram[imageBytes[i]]; } } }