juliansteenbakker / mobile_scanner

A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS.
BSD 3-Clause "New" or "Revised" License
899 stars 517 forks source link

Large QR codes fail with analyze from file #1217

Open lwisne opened 1 month ago

lwisne commented 1 month ago

We are seeing some unexpected behavior in our app, and the behavior is reproducible by running the current example app and using "Analyze image from file"

To reproduce: 1) run the example app on iOS or Android 2) Choose "Analyze image from file" 3) both qr_small and qr_med are recognized. qr_large does not give a code. They are all the same code at different zooms.

All three of these files work if the example app is run on Mac OS.

What to do to help mitigate this issue?

qr_small qr_med qr_large

navaronbracke commented 1 month ago

Hmm, this sounds like a bug in MLKit? On MacOS we use the Vision API from Apple. When I tested the implementation of analyzeImage() (which I only recently added for MacOS) I found that it produced better results compared to iOS (it would find qr codes in images that clearly had one, where MLKit would fail to detect it)

We do plan on using the Vision API on iOS too, but that will take a bit of refactoring.

FuadAghjayev commented 1 month ago

Hmm, this sounds like a bug in MLKit? On MacOS we use the Vision API from Apple. When I tested the implementation of analyzeImage() (which I only recently added for MacOS) I found that it produced better results compared to iOS (it would find qr codes in images that clearly had one, where MLKit would fail to detect it)

We do plan on using the Vision API on iOS too, but that will take a bit of refactoring.

analyzeImage() dont work for me, qr from gallery not scanned help me pls

lpl-code-github commented 3 days ago

Hmm, this sounds like a bug in MLKit? On MacOS we use the Vision API from Apple. When I tested the implementation of analyzeImage() (which I only recently added for MacOS) I found that it produced better results compared to iOS (it would find qr codes in images that clearly had one, where MLKit would fail to detect it) We do plan on using the Vision API on iOS too, but that will take a bit of refactoring.

analyzeImage() dont work for me, qr from gallery not scanned help me pls

I have encountered the same problem as you. Your question gave me some inspiration. I suspect that the QR code will detach from its analysis area when it becomes too large, so the analyzeImage method did not provide any results. I wrote a method to add margins to images:

/// Add a white edge to an image
  static Future<File?> addPaddingAndSaveToFile(String filePath) async {
    // 读取这个路径下的图片 Read images from this path
    Uint8List bytes;
    try {
      bytes = await File(filePath).readAsBytes();
    } catch (e) {
      return null;
    }

    // 解码图片 Decoding images
    ui.Codec codec = await ui.instantiateImageCodec(bytes);
    ui.FrameInfo frameInfo = await codec.getNextFrame();
    ui.Image image = frameInfo.image;

    // 创建一个新的画布 Create a new canvas
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(
        recorder,
        Rect.fromPoints(const Offset(0.0, 0.0),
            Offset(image.width.toDouble() + 50, image.height.toDouble() + 50)));

    // 绘制图片 Draw a picture
    canvas.drawImage(image, const Offset(25, 25), Paint());

    // 将生成的图像保存到文件 Save the generated image to a file
    ui.Picture picture = recorder.endRecording();
    final img = await picture.toImage(
        (image.width + 50).toInt(), (image.height + 50).toInt());
    final byteData = await img.toByteData(format: ui.ImageByteFormat.png);
    Uint8List pngBytes = byteData!.buffer.asUint8List();

    File newFile = File(filePath.replaceAll('.png', '_with_padding.png'));

    await newFile.writeAsBytes(pngBytes);

    return newFile;
  }

Then I used an image picker to read the album:

final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      //Add blank edges to the original image (This is my newly added pre logic)
      File? editedImageFile = await Utils.addPaddingAndSaveToFile(pickedFile.path);

      if (editedImageFile != null) {
        MyToast.showLoading();
        final capture = await scannerController.analyzeImage(editedImageFile.path);
        MyToast.dismissLoading();

        if (capture != null) {
          await _handleBarcodeByGallery(capture);
        } else {
          MyToast.showFailure("QR code picture is error");
        }
      } else {
        MyToast.showFailure("QR code picture is error");
      }
    }