processInputImage method

Future<ScanResult> processInputImage(
  1. InputImage inputImage,
  2. ScanMode mode, {
  3. String? imagePath,
})

Processes an ML Kit InputImage for the specified ScanMode.

Implementation

Future<ScanResult> processInputImage(
  InputImage inputImage,
  ScanMode mode, {
  String? imagePath,
}) async {
  initialize();
  final stopwatch = Stopwatch()..start();

  final plugin = ScannerPluginRegistry.findForMode(mode);
  if (plugin != null) {
    try {
      final pluginResult = await plugin.processInputImage(inputImage);
      if (pluginResult != null) {
        stopwatch.stop();
        return pluginResult;
      }
    } catch (_) {}
  }

  ScanResult rawResult;
  switch (mode) {
    case ScanMode.qr:
    case ScanMode.barcode:
    case ScanMode.pdf417:
    case ScanMode.multiCode:
      rawResult = await _processBarcodes(
        inputImage,
        mode,
        imagePath: imagePath,
      );
      break;

    case ScanMode.passport:
    case ScanMode.aadhaar:
    case ScanMode.pan:
    case ScanMode.drivingLicense:
    case ScanMode.vin:
    case ScanMode.ocr:
    case ScanMode.invoice:
    case ScanMode.receipt:
    case ScanMode.businessCard:
    case ScanMode.cheque:
    case ScanMode.idCard:
    case ScanMode.licensePlate:
      rawResult = await _processTextAndDocuments(
        inputImage,
        mode,
        imagePath: imagePath,
      );
      break;

    case ScanMode.document:
      rawResult = await _processDocumentScanner(
        inputImage,
        imagePath: imagePath,
      );
      break;

    case ScanMode.face:
      rawResult = await _processFaces(inputImage, mode, imagePath: imagePath);
      break;
  }

  stopwatch.stop();
  final duration = stopwatch.elapsed;

  final width = inputImage.metadata?.size.width ?? 640.0;
  final height = inputImage.metadata?.size.height ?? 480.0;
  final imgSize = Size(width, height);

  Rect? bbox = rawResult.boundingBox;
  List<Offset>? corners = rawResult.corners;
  if (bbox == null && rawResult.isValid) {
    final docCorners = DocumentScannerService.detectDocumentEdges(imgSize);
    bbox = docCorners.toBoundingBox();
    corners = docCorners.toList();
  }

  // AI Classification pass
  final classification = DocumentClassifier.classify(
    rawResult.rawValue,
    fields: rawResult.fields,
    mode: mode,
  );

  debugPrint(
    '⏱️ [UniversalScanEngine] Scan completed in ${duration.inMilliseconds} ms | Mode: ${mode.name} | Category: ${classification.category.name} | Valid: ${rawResult.isValid}',
  );

  return ScanResult(
    mode: rawResult.mode,
    rawValue: rawResult.rawValue,
    fields: rawResult.fields,
    isValid: rawResult.isValid,
    confidence: rawResult.confidence,
    timestamp: rawResult.timestamp,
    imagePath: rawResult.imagePath,
    rawBytes: rawResult.rawBytes,
    format: rawResult.format ?? rawResult.metadata['format'] as String?,
    documentCategory: classification.category.name,
    roi: rawResult.roi,
    enhancementsApplied: rawResult.enhancementsApplied,
    corners: corners,
    boundingBox: bbox,
    imageSize: imgSize,
    scanDuration: duration,
    metadata: {
      ...rawResult.metadata,
      'aiClassification': classification.toJson(),
    },
    multiResults: rawResult.multiResults,
    detectedBarcodes: rawResult.detectedBarcodes,
  );
}