Skip to content

feat(barcode-scanner): expose enableAllPotentialBarcodes - #4188

Open
AdarshJais wants to merge 1 commit into
margelo:mainfrom
AdarshJais:feat/barcode-enable-all-potential-barcodes
Open

feat(barcode-scanner): expose enableAllPotentialBarcodes#4188
AdarshJais wants to merge 1 commit into
margelo:mainfrom
AdarshJais:feat/barcode-enable-all-potential-barcodes

Conversation

@AdarshJais

@AdarshJais AdarshJais commented Sep 9, 2026

Copy link
Copy Markdown
The gap

From JS there is currently no way to tell whether the camera is looking at something barcode-shaped at all. A frame with no Barcode and a frame containing a Barcode that MLKit could not read both return an empty array.

That makes scan failures unmeasurable. When a user reports "it just doesn't scan", there is nothing to inspect — you cannot distinguish:

  • The detector never found the symbol — low contrast, poor lighting, out of focus
  • The detector found it and could not decode it — too far away, too few pixels per module

Those need opposite corrections. More light versus more zoom. Without the distinction, any fix is a guess.

MLKit already provides this — it just isn't reachable

From Google's Android barcode-scanning guide:

Starting from bundled model 17.1.0 and unbundled model 18.2.0, you can also call enableAllPotentialBarcodes() to return all potential barcodes even if they cannot be decoded.

And from the BarcodeScannerOptions.Builder reference:

Returns all potential barcodes when enabled, even if they cannot be decoded. Barcode.getRawBytes() and Barcode.getRawValue() will return null for any undecoded barcodes, but Barcode.getBoundingBox() will return the area potentially containing a barcode. This can be used to facilitate further detection, e.g., by zooming in the camera to get a clearer image of any barcode in the returned bounding box.

The package already ships MLKit 17.3.0, so the capability is present. toMLBarcodeScannerOptions() just builds BarcodeScannerOptions.Builder().setBarcodeFormats(...).build() and nothing else, so it cannot be turned on.

API
const scanner = useBarcodeScanner({
  barcodeFormats: ['qr-code'],
  enableAllPotentialBarcodes: true,
})

Also available on useBarcodeScannerOutput / <CodeScanner />.

What it enables

Two things that are impossible today:

  1. Diagnosis. Every frame can be classified — saw nothing / saw but could not read / read. A failure becomes a measurement instead of an anecdote.
  2. Auto-zoom. A code too small to decode still reports where it is, which is exactly the use Google names in the quote above.

margelo/react-native-vision-camera#3957 and margelo/react-native-vision-camera#4142 both report "the scanner misses barcodes that are clearly visible on screen", and both were closed for lack of a reproduction. This flag is what would let a reporter produce one.

Verified against a real failing label

A QR printed directly onto kraft paper (common low-contrast delivery packaging), at 1280×720 / ~30fps:

  |   -- | -- Frames MLKit located the code on | ~13% Continuous time in view | 30.1s Successful decodes | 0

Before this flag that session produced no signal whatsoever. With it, the 13% detection rate says the problem is detection, not decoding — which points at contrast and focus rather than zoom, and would have led to the wrong fix without it.

Also verified on a deliberately masked QR: located continuously, decoded only once uncovered.

Platform support

Android only. MLKitBarcodeScanning.BarcodeScannerOptions on iOS exposes only formats — there is no equivalent. Documented with @note, matching the existing pattern on CameraExtension ("only supported on Android") and CameraDevice.supportsFocus ("On non iOS platforms this is always false").

Notes
  • Defaults to false — no behaviour change for existing users.
  • Generated Nitro files updated with bun scanner specs; the diff is purely additive (std::optional<bool> / Boolean?).
  • bun lint-kotlin and Biome both clean.
  • Docs section added to barcode-scanner.mdx.
Follow-up (not in this PR)

setZoomSuggestionOptions is the natural companion — it consumes these bounding boxes to auto-zoom. Kept separate to keep this reviewable.

The gap

@vercel

vercel Bot commented Sep 9, 2026

Copy link
Copy Markdown

@AdarshJais is attempting to deploy a commit to the Margelo Team on Vercel.

A member of the Team first needs to authorize it.

@AdarshJais

Copy link
Copy Markdown
Author

@mrousavy, could you or any of the reviewers (not sure who all are involved) please take some time to look into this PR and share your feedback? It would be really valuable.

Comment thread docs/content/docs/barcode-scanner.mdx Outdated
Comment on lines +132 to +158
### Barcodes that cannot be decoded

By default, only successfully decoded Barcodes are returned. A frame containing a
Barcode that MLKit could not read is indistinguishable from a frame containing no
Barcode at all - both give you an empty array.

Enable [`enableAllPotentialBarcodes`](/api/react-native-vision-camera-barcode-scanner/interfaces/BarcodeScannerOptions#enableallpotentialbarcodes)
to also receive the ones it located but could not read:

```ts
const scanner = useBarcodeScanner({
barcodeFormats: ['qr-code'],
enableAllPotentialBarcodes: true,
})
```

On those Barcodes, [`rawValue`](/api/react-native-vision-camera-barcode-scanner/hybrid-objects/Barcode#rawvalue)
is `undefined` while [`boundingBox`](/api/react-native-vision-camera-barcode-scanner/hybrid-objects/Barcode#boundingbox)
describes where the potential Barcode is. That tells apart two failures which need
opposite fixes - a Barcode that cannot be *seen* (lighting, contrast, focus) from one
that cannot be *read* (too far away, or too few pixels per module) - and lets you act
on the second by zooming towards the reported region.

> [!NOTE]
> This is an Android-only option. The iOS MLKit SDK exposes no equivalent, and setting
> it there has no effect.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This AI-generated docs section is bad. It will have to be re-written.

As for iOS support, why doesn't MLKit provide that?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair, rewrote it, was way too wordy for the rest of the page.

On iOS: MLKit doesn't expose it there. The iOS BarcodeScannerOptions is only formats no enableAllPotentialBarcodes, and no setZoomSuggestionOptions either, so the iOS SDK looks generally behind on options rather than this being a deliberate omission. Couldn't find anything from Google explaining why

Lemme know, If I might be missing any direction here.

MLKit can return Barcodes it located but could not decode, with rawValue
undefined and boundingBox describing the region. That option was not
reachable from JS, so a Barcode that cannot be read is indistinguishable
from no Barcode at all - both return an empty array.

Those are two different failures with opposite fixes: a Barcode that
cannot be seen (lighting, contrast, focus) versus one that cannot be read
(too far away, too few pixels per module). Surfacing the located-but-
undecoded ones separates them, and their boundingBox can drive zoom.

Android only - the iOS MLKit SDK exposes no equivalent option. Documented
as Android-only in the spec, matching CameraExtension and
CameraDevice.supportsFocus.

Defaults to false, so behaviour is unchanged for existing users. Requires
bundled model 17.1.0+; the package already ships 17.3.0.

Generated Nitro files updated with `bun scanner specs`.
@AdarshJais
AdarshJais force-pushed the feat/barcode-enable-all-potential-barcodes branch from 8efc807 to 89c1c83 Compare September 10, 2026 10:52
@AdarshJais
AdarshJais requested a review from mrousavy September 10, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants