super_qr_code_scanner 1.0.0 copy "super_qr_code_scanner: ^1.0.0" to clipboard
super_qr_code_scanner: ^1.0.0 copied to clipboard

A robust Flutter plugin for scanning QR codes from images using OpenCV and ZXing. High-performance native implementation with multi-platform support.

Super QR Code Scanner #

A robust Flutter FFI plugin for scanning QR codes from images using OpenCV and ZXing.

Zero setup required! Just add to your pubspec.yaml and start scanning.

Features #

  • Multi-platform support: Android, iOS, macOS, Linux, Windows
  • Multiple QR codes: Detect up to 50 QR codes in a single image
  • High accuracy: 6 detection strategies with image preprocessing
  • Type-safe: Strong type checking with custom exception hierarchy
  • Configurable: Adjust scanning parameters for speed vs accuracy
  • Logging: Built-in debug logging for troubleshooting
  • Validated input: Automatic validation of image paths and data
  • Memory-safe: Proper native memory management
  • Zero setup: All dependencies bundled, no external configuration needed

Installation #

Add to your pubspec.yaml:

dependencies:
  super_qr_code_scanner: ^1.0.0
  image_picker: ^1.0.7  # Optional: For picking images

Run:

flutter pub get

That's it! No additional setup required. The package includes:

  • ZXing-C++ source code (bundled)
  • OpenCV (auto-fetched from Maven for Android, CocoaPods for iOS)
  • Native C++ compilation (automatic)

Quick Start #

Basic Usage #

import 'package:super_qr_code_scanner/super_qr_code_scanner.dart';

// Initialize scanner (singleton - done once)
final scanner = SuperQRCodeScanner();

// Scan from file path
try {
  final results = scanner.scanImageFile('/path/to/image.jpg');
  
  for (final qr in results) {
    print('Format: ${qr.format}');
    print('Content: ${qr.content}');
  }
  
  if (results.isEmpty) {
    print('No QR codes found');
  }
} on InvalidParameterException catch (e) {
  print('Invalid input: ${e.message}');
} on ImageProcessingException catch (e) {
  print('Failed to process: ${e.message}');
}

Scan from Raw Bytes #

import 'dart:typed_data';

void scanFromBytes(Uint8List imageData, int width, int height) {
  final scanner = SuperQRCodeScanner();
  
  // Scan RGB image (3 channels)
  final results = scanner.scanImageBytes(
    imageData,
    width,
    height,
    3, // channels: 1=grayscale, 3=RGB, 4=RGBA
  );
  
  print('Found ${results.length} QR codes');
}

Complete Example with Image Picker #

import 'package:flutter/material.dart';
import 'package:super_qr_code_scanner/super_qr_code_scanner.dart';
import 'package:image_picker/image_picker.dart';

class QRScannerDemo extends StatefulWidget {
  @override
  State<QRScannerDemo> createState() => _QRScannerDemoState();
}

class _QRScannerDemoState extends State<QRScannerDemo> {
  final scanner = SuperQRCodeScanner();
  final picker = ImagePicker();
  List<QRCode> results = [];
  bool isScanning = false;

  @override
  void initState() {
    super.initState();
    // Optional: Configure scanner for accuracy
    scanner.updateConfig(QRScannerConfig.accurateConfig);
  }

  Future<void> pickAndScan() async {
    try {
      final XFile? image = await picker.pickImage(
        source: ImageSource.gallery,
      );
      
      if (image == null) return;

      setState(() => isScanning = true);

      // Scan in background to avoid blocking UI
      final qrCodes = await Future.microtask(
        () => scanner.scanImageFile(image.path),
      );

      setState(() {
        results = qrCodes;
        isScanning = false;
      });
    } catch (e) {
      setState(() => isScanning = false);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error: $e')),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('QR Scanner')),
      body: Column(
        children: [
          ElevatedButton(
            onPressed: isScanning ? null : pickAndScan,
            child: Text(isScanning ? 'Scanning...' : 'Pick Image'),
          ),
          
          if (results.isNotEmpty)
            Expanded(
              child: ListView.builder(
                itemCount: results.length,
                itemBuilder: (context, index) {
                  final qr = results[index];
                  return Card(
                    child: ListTile(
                      title: Text(qr.content),
                      subtitle: Text('Format: ${qr.format}'),
                    ),
                  );
                },
              ),
            )
          else
            Padding(
              padding: EdgeInsets.all(16),
              child: Text('No QR codes found'),
            ),
        ],
      ),
    );
  }
}

Configuration #

Predefined Configs #

// Fast scanning (fewer strategies, good for real-time)
scanner.updateConfig(QRScannerConfig.fastConfig);

// Balanced (default, recommended for most use cases)
scanner.updateConfig(QRScannerConfig.defaultConfig);

// Accurate (all strategies, thorough but slower)
scanner.updateConfig(QRScannerConfig.accurateConfig);

Custom Configuration #

scanner.updateConfig(QRScannerConfig(
  tryHarder: true,           // More thorough scanning
  tryRotate: true,           // Try rotating image
  tryDownscale: true,        // Try downscaling
  maxNumberOfSymbols: 50,    // Max QR codes to detect
  enableLogging: true,       // Enable debug logs
));

Debug Logging #

// Enable logging in main()
void main() {
  QRScannerLogger.setEnabled(true);
  QRScannerLogger.setLevel(LogLevel.debug);  // debug, info, warning, error
  
  runApp(MyApp());
}

// Or via config
scanner.updateConfig(
  QRScannerConfig(enableLogging: true)
);

Exception Handling #

The plugin provides specific exception types:

Exception Description
QRScannerException Base exception class
LibraryLoadException Failed to load native library
ImageProcessingException Failed to process image
InvalidParameterException Invalid input parameters
try {
  final results = scanner.scanImageFile(imagePath);
  // Process results
} on LibraryLoadException catch (e) {
  // Native library failed to load
  print('Library error: ${e.message}');
  print('Details: ${e.details}');
} on InvalidParameterException catch (e) {
  // Invalid image path, format, or parameters
  print('Invalid input: ${e.message}');
} on ImageProcessingException catch (e) {
  // Image processing failed
  print('Processing error: ${e.message}');
} on QRScannerException catch (e) {
  // Generic scanner error
  print('Scanner error: ${e.message}');
}

Models #

QRCode #

class QRCode {
  final String content;         // The decoded QR code content
  final String format;          // Format type (e.g., "QRCode")
  final QRCodePosition? position; // Optional position data
}

QRCodePosition #

class QRCodePosition {
  final int x;
  final int y;
  final int width;
  final int height;
}Supported Image Formats

The plugin automatically validates input:

- **File formats**: JPG, JPEG, PNG, BMP, WEBP, TIFF, TIF
- **Max file size**: 50MB
- **Max dimensions**: 10000x10000 pixels
- **Color modes**: Grayscale (1 channel), RGB (3 channels), RGBA (4 channels)
- **Path validation**: Checks file exists and is readable
- **Data validation**: Verifies raw image data size matches dimensionsg, bmp, webp, tiff, tif
- Image dimensions (max 10000x10000)
- Raw image data size matches dimensions
- Valid channel count (1, 3, or 4)

## API Reference

### Methods

#### `scanImageFile(String imagePath)`
Scans QR codes from an image file.

**Returns:** `List<QRCode>` - Found QR codes (empty if none)

**Throws:** `InvalidParameterException`, `ImageProcessingException`

#### `scanImageBytes(List<int> imageData, int width, int height, int channels)`
Scans QR codes from raw image data.

**Parameters:**
- `imageData`: Raw pixel data
- `width`: Image width in pixels
- `height`: Image height in pixels
- `channels`: 1 (grayscale), 3 (RGB), or 4 (RGBA)

**Returns:** `List<QRCode>` - Found QR codes (empty if none)

#### `updateConfig(QRScannerConfig config)`
Updates scanner configuration.

### Models

#### `QRCode`
```dart
class QRCode {
  final String content;  // QR code text content
  final String format;   // Format (e.g., "QR_CODE")
}Platform Setup

### Android
- **Min SDK**: 21 (Android 5.0)
- **Permissions**: Add to `AndroidManifest.xml` if using camera:
  ```xml
  <uses-permission android:name="android.permission.CAMERA" />

iOS #

  • Min Version: iOS 12.0
  • Permissions: Add to Info.plist if using camera:
    <key>NSCameraUsageDescription</key>
    <string>We need camera access to scan QR codes</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>We need photo library access to select images</string>
    

Dependencies (Automatic) #

The package is completely self-contained:

Android:

  • Op"No QR codes found"
  • Ensure image has good quality and lighting
  • Try accurateConfig for difficult images
  • Check image isn't too blurry or small

"Invalid image path" #

  • Use absolute paths
  • Verify file exists and is readable
  • Check supported formats

Build errors on Android #

  • Clean build: flutter clean && flutter pub get
  • Check NDK is installed in Android Studio

Build errors on iOS #

  • Run cd ios && pod install
  • Clean Xcode build folder

Library not found error #

// Enable logging to see detailed error messages
QRScannerLogger.setEnabled(true);
QRScannerLogger.setLevel(LogLevel.debug);
```t
4. **Adaptive threshold**: Otsu and adaptive thresholding
5. **Inverted**: Scan inverted grayscale image
6. **Sharpened**: Apply sharpening kernel

## Requirements

### No setup required!

The package is completely self-contained. Dependencies are automatically handled:

**Android:**
- Min SDK: 21 (Android 5.0)
- OpenCV: Automatically fetched from Maven Central
- ZXing: Bundled with package

**iOS:**
- iOS 12.0+
- OpenCV: Automatically installed via CocoaPods
- ZXing: Bundled with package

**First build may take 5-10 minutes** as dependencies are downloaded and compiled. Subsequent builds are fast.

## Example App

See the [example app](example/) for a complete working implementation with image picker.

## Troubleshooting

### Library not found error

```dart
// Enable logging to see detailed error messages
QRScannerLogger.setEnabled(true);
QRScannerLogger.setLevel(LogLevel.debug);

No QR codes detected #

  • Ensure image quality is good
  • Try accurateConfig for difficult images
  • Check that QR code is clearly visible
  • Verify supported format (standard QR codes only)

Memory issues #

  • Reduce image size before scanning
  • Ensure proper disposal of resources
  • Check that file size is within limits (50MB)

License #

See LICENSE file for details.

1
likes
0
points
65
downloads

Publisher

unverified uploader

Weekly Downloads

A robust Flutter plugin for scanning QR codes from images using OpenCV and ZXing. High-performance native implementation with multi-platform support.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

ffi, flutter

More

Packages that depend on super_qr_code_scanner

Packages that implement super_qr_code_scanner