/// <summary> /// Any pixel values below threshold will be changed to 0 (black). /// Any pixel values above (or equal to) threshold will be changed to 255 (white). /// </summary> /// <param name="imageBytes">Image bytes</param> /// <param name="bitmapData">Pixel depth</param> /// <param name="threshold">Threshold value</param> private static void ApplyDirect(byte[] imageBytes, BitmapData bitmapData, byte threshold) { if (bitmapData.IsColor()) { int pixelDepth = bitmapData.GetPixelDepth(); int stride = bitmapData.Stride; int width = bitmapData.GetStrideWithoutPadding(); int height = bitmapData.Height; int limit = bitmapData.GetSafeArrayLimitForImage(imageBytes); // Exclude alpha/transparency byte when averaging int thresholdByteLength = Math.Min(pixelDepth, Constants.PixelDepthRGB); int pixelSum; bool belowThreshold; // Find distribution of pixels at each level for (int y = 0; y < height; y++) { // Images may have extra bytes per row to pad for CPU addressing. // so need to ensure we traverse to the correct byte when moving between rows. int offset = y * stride; for (int x = 0; x < width; x += pixelDepth) { int i = offset + x; if (i < limit) { pixelSum = 0; // Sum each pixel component for (int j = 0; j < thresholdByteLength && i + j < imageBytes.Length; j++) { pixelSum += imageBytes[i + j]; } // Compare average to threshold belowThreshold = (pixelSum / thresholdByteLength) < threshold; // Apply threshold for (int j = 0; j < thresholdByteLength && i + j < imageBytes.Length; j++) { imageBytes[i + j] = belowThreshold ? byte.MinValue : byte.MaxValue; } } else { break; } } } } else { // Apply threshold value to image for (int i = 0; i < imageBytes.Length; i++) { imageBytes[i] = imageBytes[i] < threshold ? byte.MinValue : byte.MaxValue; } } }