dilate function

Future<Image> dilate({
  1. required Image inputImage,
  2. required int kernelSize,
})

Performs a dilation operation on the input image.

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

Parameters:

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

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

Implementation

Future<ui.Image> dilate({
  required ui.Image inputImage,
  required int kernelSize,
}) 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);

  // Create the elliptical kernel
  final List<List<bool>> kernel = _createEllipticalKernel(kernelSize);

  // Apply dilation
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      bool hasBlackPixel = false;

      for (int ky = 0; ky < kernelSize; ky++) {
        for (int kx = 0; kx < kernelSize; kx++) {
          if (kernel[ky][kx]) {
            final int px = x + kx - kernelSize ~/ 2;
            final int py = y + ky - kernelSize ~/ 2;

            if (px >= 0 && px < width && py >= 0 && py < height) {
              final int index = (py * width + px) * 4;
              // Check if there's a black pixel in the kernel area
              if (inputPixels[index] == 0) {
                hasBlackPixel = true;
                break;
              }
            }
          }
        }
        if (hasBlackPixel) {
          break;
        }
      }

      final int outputIndex = (y * width + x) * 4;
      final int pixelValue = hasBlackPixel ? 0 : 255;
      outputPixels[outputIndex] = pixelValue; // R
      outputPixels[outputIndex + 1] = pixelValue; // G
      outputPixels[outputIndex + 2] = pixelValue; // B
      outputPixels[outputIndex + 3] = 255; // Alpha channel
    }
  }

  // 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;
}