/// <summary> /// Any pixel values above threshold will be changed to max value. /// (Low-pass filter) /// </summary> /// <param name="imageBytes">Image bytes (Grayscale/RGB)</param> /// <param name="pixelDepth">Pixel depth. i.e. 1 for grayscale, 3 for color</param> /// <param name="maxValue">Max value to retain</param> public static void ApplyMaxDirect(byte[] imageBytes, int pixelDepth, byte maxValue) { bool isColor = BitmapDataExt.IsColorPixelDepth(pixelDepth); // Apply threshold value to image. for (int i = 0; i < imageBytes.Length; i += pixelDepth) { if (imageBytes[i] > maxValue) { imageBytes[i] = maxValue; } if (isColor && i < imageBytes.Length - 2) { // G if (imageBytes[i + 1] > maxValue) { imageBytes[i + 1] = maxValue; } // R if (imageBytes[i + 2] > maxValue) { imageBytes[i + 2] = maxValue; } } } }
/// <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]]; } } }
/// <summary> /// Any pixel values outside the threshold will be changed to min/max. /// </summary> /// <param name="imageBytes">Image bytes (Grayscale/RGB)</param> /// <param name="pixelDepth">Depth of pixels (typically 1 for grayscale, 3 for color)</param> /// <param name="minValue">Minimum threshold value</param> /// <param name="maxValue">Maximum threshold value</param> public static void ApplyMinMaxDirect(byte[] imageBytes, int pixelDepth, byte minValue, byte maxValue) { bool isColor = BitmapDataExt.IsColorPixelDepth(pixelDepth); // Adjust image to within min/max. for (int i = 0; i < imageBytes.Length; i += pixelDepth) { // Change values outside threshold to extremes if (imageBytes[i] < minValue) { imageBytes[i] = minValue; } else if (imageBytes[i] > maxValue) { imageBytes[i] = maxValue; } // Extra bytes for color images (RGB) if (isColor && i < imageBytes.Length - 2) { // G if (imageBytes[i + 1] < minValue) { imageBytes[i + 1] = minValue; } else if (imageBytes[i + 1] > maxValue) { imageBytes[i + 1] = maxValue; } // R if (imageBytes[i + 2] < minValue) { imageBytes[i + 2] = minValue; } else if (imageBytes[i + 2] > maxValue) { imageBytes[i + 2] = maxValue; } } } }