erode function

Future<Image> erode(
  1. Image inputImage, {
  2. int kernelSize = 3,
})

Performs an erosion operation on the input image.

This function takes a ui.Image and performs an erosion operation on it. The erosion operation shrinks the black pixels (letters) against the white background.

Parameters:

  • inputImage: The source image to be eroded (black and white).
  • kernelSize: The size of the erosion kernel (must be an odd number).

Returns: A Future that resolves to a ui.Image containing the eroded image.

Implementation

Future<ui.Image> erode(
  final ui.Image inputImage, {
  final int kernelSize = 3,
}) async {
  final int width = inputImage.width;
  final int height = inputImage.height;

  // Get the pixel data from the input image
  final ByteData? byteData =
      await inputImage.toByteData(format: ui.ImageByteFormat.rawRgba);
  if (byteData == null) {
    throw Exception('Failed to get image data');
  }
  final Uint8List inputPixels = byteData.buffer.asUint8List();

  // Create a new Uint8List for the output image
  final Uint8List outputPixels = Uint8List(width * height * 4);

  // Calculate the radius of the kernel
  final int radius = kernelSize ~/ 2;

  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      // Initialize the maximum value to black (0)
      int maxValue = 0;

      // Check the kernel area
      for (int ky = -radius; ky <= radius; ky++) {
        for (int kx = -radius; kx <= radius; kx++) {
          // Calculate the index of the neighbor pixel
          int neighborX = x + kx;
          int neighborY = y + ky;

          // Ensure we stay within bounds
          if (neighborX >= 0 &&
              neighborX < width &&
              neighborY >= 0 &&
              neighborY < height) {
            // Get the pixel value (assuming binary image, check the red channel)
            int pixelIndex = (neighborY * width + neighborX) * 4; // RGBA
            int r =
                inputPixels[pixelIndex]; // Assuming grayscale, use red channel

            // Update the maximum value
            maxValue = max(maxValue, r);
          }
        }
      }

      // Set the eroded pixel value in the output image
      int outputIndex = (y * width + x) * 4;
      outputPixels[outputIndex] = maxValue; // R
      outputPixels[outputIndex + 1] = maxValue; // G
      outputPixels[outputIndex + 2] = maxValue; // B
      outputPixels[outputIndex + 3] = 255; // A (fully opaque)
    }
  }

  // Create a new ui.Image from the output pixels
  final ui.ImmutableBuffer buffer =
      await ui.ImmutableBuffer.fromUint8List(outputPixels);
  final ui.ImageDescriptor descriptor = ui.ImageDescriptor.raw(
    buffer,
    width: width,
    height: height,
    pixelFormat: ui.PixelFormat.rgba8888,
  );
  final ui.Codec codec = await descriptor.instantiateCodec();
  final ui.FrameInfo frameInfo = await codec.getNextFrame();
  return frameInfo.image;
}