The standard architecture for a document scanner is a camera client and an OCR server. The client uploads a page, the server runs recognition, the client gets text back. It is easy to build, it works on weak hardware, and it means every scanned receipt in your life passes through somebody else’s disk.
ScanLocker does it the other way round. Recognition, PDF assembly and encryption all happen on the phone. This post is about what that actually costs.
The pipeline
A page goes through four stages, all local:
- Capture and edge detection. The camera frame is analysed for a document quad, then perspective-corrected so the page is rectangular. Users can drag the four corners when detection gets it wrong.
- Clean-up. Rotation, crop and a filter pass (original, enhanced, grayscale, black and white). Nothing is destructive until export.
- Recognition. Google ML Kit’s on-device text recogniser runs over the cleaned bitmap and returns blocks, lines and words with bounding boxes.
- Assembly. The cleaned image becomes a full-page PDF image, and the recognised words are written as an invisible text layer positioned using those bounding boxes.
The result looks like a scan and behaves like text: you can search it, select it, and copy a sentence out of a photographed invoice.
Getting the invisible layer right
This is the part that separates a demo from a usable feature. Naive implementations write recognised text as one string at the top of the page, which produces PDFs that are searchable in theory and useless in practice — every highlight and selection lands in the wrong place.
The text layer has to be positioned per word, in PDF user units, with a font whose metrics roughly match the observed glyph boxes. Two practical notes:
- Normalise on the rendered page size, not the bitmap. The bitmap may be 3000 px wide and the PDF page 595 pt. Every bounding box needs the same transform, or the layer drifts by a few percent and selection feels broken.
- Do not try to preserve fonts. An approximate sans-serif at a scaled size is enough for search and selection. Embedding the “real” font would bloat the file for no practical gain.
If the layer is even slightly off, users notice immediately — text selection is the moment the feature either works or looks fake.
Language coverage and the trade-off
Recognition covers English (Latin script) and Hindi (Devanagari). ML Kit ships separate models, so the app bundles both and lets you pick one as the export default, with a per-document override.
The cost is size. ML Kit’s bundled recognition models are the largest single contributor to the APK, comfortably bigger than the rest of the app’s code. The alternative — downloading models on demand — moves the cost to first use and breaks the “works with no connection” promise, which for a privacy-first scanner is not a trade worth making. A scanner that needs a network connection before it can read a page is not really offline.
Why this matters beyond privacy
There is a compliance angle, and it is not hypothetical: a scanned passport, a medical letter or a signed contract is exactly the kind of document you should not be uploading to an OCR API whose retention policy you have not read. Local recognition makes the question moot. There is no processor, no sub-processor, and nothing to declare in a data-safety form except the camera permission itself.
It also removes a per-page cost. Cloud OCR is priced per thousand pages, which quietly makes a document scanner a subscription product. Local recognition is free at the margin, and the only cost is the download.
Encryption, and where the files live
Export produces an ordinary PDF, optionally protected with 256-bit AES. Password protection is applied before the file leaves the app’s private storage, so there is no window where a sensitive document exists unencrypted on shared storage.
Inside the app, documents live in a private folder, organised into folders and tags, indexed for full-text search. Deleting moves a document to Trash for 30 days rather than erasing it immediately, because “I deleted the wrong receipt” is a much more common failure than “someone recovered my deleted file”.
Backups are a single password-protected file you choose the destination for. Restore merges newest-wins, so an old backup cannot silently roll back newer work. No account, no sync server, no restore code to lose.
None of this is exotic engineering. It is just an unusual set of defaults: recognition, storage and encryption are boring local operations, and the only reason most scanners upload is that uploading is easier to build.