hybrid static method

UBitMatrix hybrid(
  1. UGrayImage image
)

Implementation

static UBitMatrix hybrid(UGrayImage image) {
  if (image.width < 40 || image.height < 40) return global(image);
  final int subWidth = (image.width + _blockSize - 1) >> _blockShift;
  final int subHeight = (image.height + _blockSize - 1) >> _blockShift;
  final Uint8List averages = Uint8List(subWidth * subHeight);

  for (int by = 0; by < subHeight; by++) {
    int yOffset = by << _blockShift;
    if (yOffset + _blockSize > image.height) yOffset = image.height - _blockSize;
    for (int bx = 0; bx < subWidth; bx++) {
      int xOffset = bx << _blockShift;
      if (xOffset + _blockSize > image.width) xOffset = image.width - _blockSize;
      int sum = 0;
      int min = 255;
      int max = 0;
      for (int y = 0; y < _blockSize; y++) {
        final int rowStart = (yOffset + y) * image.stride + xOffset;
        for (int x = 0; x < _blockSize; x++) {
          final int pixel = image.data[rowStart + x];
          sum += pixel;
          if (pixel < min) min = pixel;
          if (pixel > max) max = pixel;
        }
      }
      int average = sum >> (_blockShift * 2);
      if (max - min <= _minDynamicRange) {
        average = min ~/ 2;
        if (by > 0 && bx > 0) {
          final int neighbours = (averages[(by - 1) * subWidth + bx] + 2 * averages[by * subWidth + bx - 1] + averages[(by - 1) * subWidth + bx - 1]) ~/ 4;
          if (min < neighbours) average = neighbours;
        }
      }
      averages[by * subWidth + bx] = average;
    }
  }

  final UBitMatrix matrix = UBitMatrix(image.width, image.height);
  for (int by = 0; by < subHeight; by++) {
    int yOffset = by << _blockShift;
    if (yOffset + _blockSize > image.height) yOffset = image.height - _blockSize;
    final int top = _clampBlock(by, subHeight);
    for (int bx = 0; bx < subWidth; bx++) {
      int xOffset = bx << _blockShift;
      if (xOffset + _blockSize > image.width) xOffset = image.width - _blockSize;
      final int leftBlock = _clampBlock(bx, subWidth);
      int sum = 0;
      for (int dy = -2; dy <= 2; dy++) {
        final int rowStart = (top + dy) * subWidth;
        sum += averages[rowStart + leftBlock - 2] +
            averages[rowStart + leftBlock - 1] +
            averages[rowStart + leftBlock] +
            averages[rowStart + leftBlock + 1] +
            averages[rowStart + leftBlock + 2];
      }
      final int threshold = sum ~/ 25;
      for (int y = 0; y < _blockSize; y++) {
        final int rowStart = (yOffset + y) * image.stride + xOffset;
        for (int x = 0; x < _blockSize; x++) {
          if (image.data[rowStart + x] <= threshold) matrix.set(xOffset + x, yOffset + y);
        }
      }
    }
  }
  return matrix;
}