imageToBlackOnWhite function

Future<Image> imageToBlackOnWhite(
  1. Image inputImage, {
  2. double contrast = 0,
})

Converts a color image to a binary (black and white) image.

This preprocessing step simplifies the image for text recognition by converting it to a binary format where text is represented as black pixels on a white background.

The function works in three steps:

  1. Converts the color image to grayscale using weighted RGB values
  2. Applies optional contrast adjustment using the provided contrast parameter
  3. Applies adaptive thresholding to convert grayscale to binary

Parameters:

  • inputImage: The source color image to convert.
  • contrast: Optional contrast adjustment level. 0 means no adjustment, positive values increase contrast, range typically 0-100.

Returns: A Future<Image> containing the binary version of the input image.

Implementation

Future<Image> imageToBlackOnWhite(
  final Image inputImage, {
  // Adjust contrast level (0 = normal, 100 = high contrast)
  double contrast = 0,
}) async {
  final int width = inputImage.width;
  final int height = inputImage.height;
  final Uint8List pixels = await imageToUint8List(inputImage);

  // Calculate contrast factor
  final double factor = (259 * (contrast + 255)) / (255 * (259 - contrast));

  // Create a new Uint8List for the output image
  Uint8List outputPixels = Uint8List(pixels.length);
  for (int i = 0; i < pixels.length; i += 4) {
    final int r = pixels[i];
    final int g = pixels[i + 1];
    final int b = pixels[i + 2];
    // ignore: unused_local_variable
    final int a = pixels[i + 3];

    // Calculate brightness using a weighted average
    int gray = (0.299 * r + 0.587 * g + 0.114 * b).toInt();

    // Apply contrast adjustment
    gray = (factor * (gray - 128) + 128).clamp(0, 255).toInt();

    outputPixels[i] = gray;
    outputPixels[i + 1] = gray;
    outputPixels[i + 2] = gray;
    outputPixels[i + 3] = 255; // Drop alpha
  }

  // Compute threshold dynamically
  int threshold = computeAdaptiveThreshold(outputPixels, width, height);

  // Apply binary threshold
  Uint8List bwPixels = Uint8List(outputPixels.length);
  for (int i = 0; i < outputPixels.length; i += 4) {
    final int gray = outputPixels[i];
    final int newColor = (gray > threshold) ? 255 : 0;

    bwPixels[i] = newColor;
    bwPixels[i + 1] = newColor;
    bwPixels[i + 2] = newColor;
    bwPixels[i + 3] = 255; // Drop alpha
  }

  // Convert Uint8List back to Image
  return await createImageFromPixels(bwPixels, width, height);
}