dilateArtifact function

Artifact dilateArtifact({
  1. required Artifact matrixImage,
  2. required int kernelSize,
})

Applies dilation morphological operation to a binary image.

Dilation expands the white regions in a binary image, which helps connect nearby text elements and fill small gaps in characters.

matrixImage is the source binary image to dilate. kernelSize determines the size of the dilation kernel. Returns a new Artifact containing the dilated image.

Implementation

Artifact dilateArtifact({
  required final Artifact matrixImage,
  required int kernelSize,
}) {
  final Artifact result = Artifact(matrixImage.cols, matrixImage.rows);
  final int halfKernel = kernelSize ~/ 2;
  final int width = matrixImage.cols;
  final int height = matrixImage.rows;

  // Pre-compute row boundaries for each y position to avoid repeated calculations
  final List<int> minKYs = List<int>.filled(height, 0);
  final List<int> maxKYs = List<int>.filled(height, 0);
  for (int y = 0; y < height; y++) {
    minKYs[y] = max(0, y - halfKernel);
    maxKYs[y] = min(height - 1, y + halfKernel);
  }

  // Pre-compute column boundaries for each x position
  final List<int> minKXs = List<int>.filled(width, 0);
  final List<int> maxKXs = List<int>.filled(width, 0);
  for (int x = 0; x < width; x++) {
    minKXs[x] = max(0, x - halfKernel);
    maxKXs[x] = min(width - 1, x + halfKernel);
  }

  // Process the image
  // For large images, process in chunks
  // First pass: find all pixels that are set in the original image
  // and mark their kernel areas in the result
  for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
      if (matrixImage.cellGet(x, y)) {
        // This pixel is set, so dilate it by setting all pixels in its kernel area
        for (int ky = minKYs[y]; ky <= maxKYs[y]; ky++) {
          for (int kx = minKXs[x]; kx <= maxKXs[x]; kx++) {
            result.cellSet(kx, ky, true);
          }
        }
      }
    }
  }

  return result;
}