erode function
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;
}