floodFill function
Performs a highly optimized flood fill algorithm on a binary image matrix.
Uses direct array access and efficient data structures (8-connected).
Returns a list of Point objects representing all connected points found.
Implementation
List<Point<int>> floodFill(
final Artifact binaryPixels,
final Artifact visited,
final int startX,
final int startY,
) {
final int width = binaryPixels.cols;
final int height = binaryPixels.rows;
// Early bounds check
if (startX < 0 || startX >= width || startY < 0 || startY >= height) {
return const [];
}
// Early check for valid starting pixel
if (!binaryPixels.cellGet(startX, startY)) {
return const [];
}
// Direct access to the underlying arrays
final Uint8List pixelData = binaryPixels.matrix;
final Uint8List visitedData = visited.matrix;
// Pre-allocate with estimated capacity to reduce reallocations
final List<Point<int>> connectedPoints = <Point<int>>[];
final Queue<int> queue = Queue<int>();
// Calculate initial index
final int startIndex = startY * width + startX;
// Mark start point as visited and add to queue
visitedData[startIndex] = _pixelOnValue;
queue.add(startIndex);
connectedPoints.add(Point(startX, startY));
// Direction offsets for adjacent pixels (including diagonals)
const List<int> rowOffsets = [-1, -1, -1, 0, 0, 1, 1, 1];
const List<int> colOffsets = [-1, 0, 1, -1, 1, -1, 0, 1];
while (queue.isNotEmpty) {
final int currentIndex = queue.removeFirst();
final int x = currentIndex % width;
final int y = currentIndex ~/ width;
// Check all eight directions (including diagonals)
for (int i = 0; i < rowOffsets.length; i++) {
final int nx = x + colOffsets[i];
final int ny = y + rowOffsets[i];
// Skip out-of-bounds
if (nx < 0 || nx >= width || ny < 0 || ny >= height) {
continue;
}
final int neighborIndex = ny * width + nx;
// Check if neighbor is valid and not visited
if (pixelData[neighborIndex] == _pixelOnValue &&
visitedData[neighborIndex] == _pixelOffValue) {
visitedData[neighborIndex] = _pixelOnValue;
queue.add(neighborIndex);
connectedPoints.add(Point(nx, ny));
}
}
}
return connectedPoints;
}