analyzeBlur static method

BlurAnalysis analyzeBlur(
  1. Uint8List imageBytes, {
  2. required int width,
  3. required int height,
})

Analyzes blur level using discrete Laplacian operator.

Implementation

static BlurAnalysis analyzeBlur(
  Uint8List imageBytes, {
  required int width,
  required int height,
}) {
  if (imageBytes.isEmpty || width <= 2 || height <= 2) {
    return const BlurAnalysis(
      severity: BlurSeverity.heavy,
      score: 1.0,
      laplacianVariance: 0.0,
    );
  }

  // Compute discrete Laplacian variance as blur metric
  double sum = 0;
  double sumSquared = 0;
  int count = 0;

  for (int y = 1; y < height - 1 && y * width < imageBytes.length; y++) {
    for (int x = 1; x < width - 1; x++) {
      final idx = y * width + x;
      if (idx + width < imageBytes.length && idx - width >= 0) {
        // Laplacian kernel: [0,-1,0; -1,4,-1; 0,-1,0]
        final laplacian = 4 * imageBytes[idx] -
            imageBytes[idx - 1] -
            imageBytes[idx + 1] -
            imageBytes[idx - width] -
            imageBytes[idx + width];
        sum += laplacian;
        sumSquared += laplacian * laplacian;
        count++;
      }
    }
  }

  if (count == 0) {
    return const BlurAnalysis(
      severity: BlurSeverity.heavy,
      score: 1.0,
      laplacianVariance: 0.0,
    );
  }

  final mean = sum / count;
  final variance = (sumSquared / count) - (mean * mean);
  final normalizedVariance = variance.abs();

  // Map variance to blur severity
  final BlurSeverity severity;
  final double blurScore;

  if (normalizedVariance > 500) {
    severity = BlurSeverity.sharp;
    blurScore = 0.0;
  } else if (normalizedVariance > 200) {
    severity = BlurSeverity.mild;
    blurScore = 0.25;
  } else if (normalizedVariance > 50) {
    severity = BlurSeverity.moderate;
    blurScore = 0.6;
  } else {
    severity = BlurSeverity.heavy;
    blurScore = 0.9;
  }

  return BlurAnalysis(
    severity: severity,
    score: blurScore,
    laplacianVariance: normalizedVariance,
  );
}