Repository navigation
iOS: would you accept an opt-in capture controller that preserves original colors? #174
Description
iOS: would you accept an opt-in capture controller that preserves original colors?
The problem
On iOS the plugin uses Apple's VNDocumentCameraViewController. For document
scanning it's excellent, but for identity verification (KYC) it has three
limitations we couldn't work around from the outside:
- It applies automatic filters that wash out colors. The returned image is
processed for readability, not for fidelity. For an ID card that means shifted
tones and lost detail — some verification providers reject those images. - The filter buttons can't be removed. Users can switch to grayscale or
black & white, which silently breaks the same flows. - Multi-page capture is forced. For a single-sided ID it's confusing UX, and
the user has to tap "Save" after every shot.
Android already has an escape hatch for the first point — AndroidScannerMode.base
keeps real colors, which is exactly why we use it. iOS has no equivalent, because
the limitation lives inside Apple's controller rather than in this plugin.
What we built, and why we're asking
We maintain a fork where iOS uses a custom capture controller instead of Apple's. The
pipeline is:
- Preview with
AVCaptureSession+AVCapturePhotoOutput. - On shutter tap, capture a raw JPEG — no filters applied.
- Run
VNDetectDocumentSegmentationRequest(Vision framework, the same model Apple's
own Notes app uses) to find the document's four corners. - Apply
CIPerspectiveCorrectionwith those corners to the raw image, so the
result is cropped and deskewed with the original colors. - If detection fails, return the flat photo rather than failing the capture.
- Show a confirmation preview with Retake / Use.
It's been running in production for a while in an identity-verification flow.
We'd rather contribute this than keep a fork, but we don't want to send 500+ lines
of Swift you may not want, so we're asking first.
Questions before we write anything
-
Is this in scope? It's a second capture path, not a change to the existing one.
Our intent is that it be strictly opt-in — e.g. anIosScannerModealongside
the existingAndroidScannerMode— so current behaviour stays untouched by default. -
How would you want it shaped? Our fork is based on
1.4.0, and iOS has been
restructured since (SPM layout,CunningDocumentCropperViewController,
CroppingOverlayView,MagnifierView). We'd port onto the current architecture
and reuse what's already there rather than duplicating it — but you know better
than us where the seams should be. -
Is a framing guide overlay welcome, and if so how? Our version draws a centered
rectangle with a fixed aspect ratio plus a dimmed surround, which materially improves
capture quality for cards. In our fork the ratio is hardcoded to the ID card format we
needed. If you'd want it, we'd expose the ratio as a parameter — or we can
leave the overlay out entirely and contribute only the capture path. -
Anything you'd want us to avoid? Minimum iOS version, dependencies, testing
approach — happy to follow whatever you prefer.
If you'd rather not take this direction, that's completely fine — knowing now saves us
both time, and we'll keep maintaining our fork.
Thanks for the project, and for how actively you keep it maintained.
Activity
vicajilau commentedon Oct 21, 2026
Thanks for asking before writing the code, and for such a clear proposal. Yes, this is in scope: iOS has no equivalent to
AndroidScannerMode.base, and an opt-in path that keeps the original colors is a gap worth closing.One thing that should make the contribution much smaller than your fork: most of steps 3 to 6 of your pipeline already exist in the plugin. The gallery cropper (
CunningDocumentCropperViewController) detects the corners withVNDetectDocumentSegmentationRequest, appliesCIPerspectiveCorrection, lets the user adjust the corners, and confirms each page. When detection fails it falls back to default corners the user can drag, rather than returning the flat photo. WithIosScannerOptions(defaultFilter: IosDocumentFilter.original, showFilterBar: false)it keeps the original colors and hides the filter selector. So what is really missing is the capture.Here is the shape I would suggest:
AVCaptureSessionandAVCapturePhotoOutputthat takes an unprocessed photo and hands it to the existing cropper, instead of a separate detection, correction and Retake/Use screen. If a retake action is needed, adding it to the cropper is better than a second confirmation screen. WithnoOfPages: 1the flow ends after the first confirmed photo, which covers the single-sided ID case.IosScannerOptions. For example anIosScannerModewithvisionKitas the default and a mode for this capture path, added toIosScannerOptionsrather than as a new top-level parameter ofgetPictures.withCameraAccessinCunningDocumentScannerPlugin.swift), so please reuse it.Happy to review a draft PR early if you want feedback on the structure before polishing it.