decodeGrayscaleFrame method

List<BarcodeResult> decodeGrayscaleFrame(
  1. Uint8List gray,
  2. int width,
  3. int height, {
  4. List<BarcodeFormatFilter>? allowedFormats,
  5. bool enableMultiLineScanning = true,
  6. bool enableRotatedScanning = false,
})

Decodes barcodes from raw grayscale byte buffer.

Enhanced v3.0: scans across multiple horizontal lines, supports rotation, and implements full EAN-13, Code 128, and QR finder pattern detection.

Implementation

List<BarcodeResult> decodeGrayscaleFrame(
  Uint8List gray,
  int width,
  int height, {
  List<BarcodeFormatFilter>? allowedFormats,
  bool enableMultiLineScanning = true,
  bool enableRotatedScanning = false,
}) {
  final results = <BarcodeResult>[];
  final seenValues = <String>{};

  // Scan across multiple horizontal lines for 1D barcodes
  final scanLines = enableMultiLineScanning
      ? _generateScanLines(height)
      : [height ~/ 2];

  for (final scanY in scanLines) {
    if (scanY < 0 || scanY >= height) continue;

    final lineResults = _scan1DBarcodesAtRow(gray, width, height, scanY);
    for (final r in lineResults) {
      if (!seenValues.contains(r.rawValue)) {
        results.add(r);
        seenValues.add(r.rawValue);
      }
    }
  }

  // Scan for 2D QR Finder Patterns
  final qrResults = _scanQrFinderPatterns(gray, width, height);
  for (final r in qrResults) {
    if (!seenValues.contains(r.rawValue)) {
      results.add(r);
      seenValues.add(r.rawValue);
    }
  }

  // Optional: scan at 90° rotation for rotated barcodes
  if (enableRotatedScanning && results.isEmpty) {
    final rotated = _rotateGrayscale90(gray, width, height);
    final rotResults = _scan1DBarcodesAtRow(
      rotated,
      height,
      width, // swapped dimensions
      width ~/ 2,
    );
    results.addAll(rotResults);
  }

  // Filter by allowed formats if specified
  if (allowedFormats != null && allowedFormats.isNotEmpty) {
    final allowedNames =
        allowedFormats.map((f) => f.nameString.toUpperCase()).toSet();
    return results
        .where((r) => allowedNames.contains(r.format.toUpperCase()))
        .toList();
  }

  return results;
}