# Pixelnetica — full content for AI agents
> Aggregated plain-text content from the Pixelnetica site: every FAQ, the SharpScan tutorials, and the Document Scanning SDK guide pages, concatenated for one-shot retrieval. Text is stripped of HTML markup; the canonical pages (indexed in /llms.txt) remain authoritative. This file can be large.
----------------------------------------------------------------------
# Frequently Asked Questions
## Is DSSDK Compatible with Other Platforms?
_Product: DSSDK · Category: all_
Yes. Pixelnetica™ Document Scanning SDK is also available natively for Android, iOS, and Xamarin, allowing flexible integration and consistent performance across multiple platforms.
## What is Pixelnetica™ Document Scanning SDK for .NET MAUI?
_Product: DSSDK · Category: all_
Pixelnetica™ Document Scanning SDK (DSSDK) for .NET MAUI adds document scanning and image enhancement to your mobile applications.
It captures documents and improves OCR accuracy and document management on both Android and iOS, from one shared codebase.
## How Does Pixelnetica™ DSSDK Enhance .NET MAUI Apps?
_Product: DSSDK · Category: all_
Pixelnetica™ DSSDK provides advanced document scanning through:
Intelligent Real-Time Feedback: Guides users in capturing clear scans by correcting common issues such as inaccurate framing, poor lighting, and camera shake.
Automatic Document Recognition and Correction: Quickly detects document boundaries, accurately corrects perspective distortion, and optimizes scan clarity.
Sophisticated Image Processing: Enhances images automatically, adjusting brightness, contrast, noise reduction, and compressing file sizes for optimal quality and efficient storage.
## How Easy Is DSSDK Integration with .NET MAUI?
_Product: DSSDK · Category: all_
Integrating DSSDK into your .NET MAUI applications is straightforward and quick. Integration guidance, API documentation, and sample applications are available online to speed up your work.
Discover our Complete .NET MAUI DSSDK Documentation and our ready-to-use GitHub Example Projects.
For assistance, please feel free to contact us.
## Is there a free .NET MAUI Document Scanner SDK?
_Product: DSSDK · Category: all_
While free SDKs like OpenCV, OpenCVSharp, and other basic imaging APIs offer essential features, they typically lack professional-grade capabilities such as customizable UI components, real-time scanning guidance, distortion correction, and image optimization.
DSSDK provides these capabilities, which matter for enterprise-level document scanning.
## What platforms does DSSDK support besides Android?
_Product: DSSDK · Category: all_
In addition to Android, Pixelnetica™ Document Scanning SDK available for native Apple iOS and cross-platform frameworks such as .NET MAUI and Xamarin.
## How to achieve perfect document scans in my Android App?
_Product: DSSDK · Category: all_
To achieve the highest quality scans in your Android application, choose an SDK specifically designed to handle the unique challenges of scanning paper documents on mobile devices. Key features include:
Advanced assistive technology to reduce common user errors during scanning:
Real-time detection of document borders in the camera viewfinder, preventing poorly positioned captures.
Automatic measurement of the effective document area, maximizing capture quality.
Correction and reduction of geometric distortions to maintain optimal image quality.
Touch-free automatic document capture that takes a photo when all quality criteria are met.
Specialized document processing:
Optimized image processing for readability, OCR accuracy, and efficient storage.
Advanced geometric distortion correction to preserve image clarity.
Wide support for document formats and advanced compression:
Supports standard formats like PDF, TIFF, JPEG, PNG, and text files.
A PDF engine with customizable compression levels, from lossless to extreme optimization.
## How quickly can I integrate document scanning into my Android app?
_Product: DSSDK · Category: all_
Integration is quick and straightforward thanks to ready-to-use UI components for document capturing, manual editing, and OCR correction.
Refer to our Documentation and sample application source code.
For assistance, please feel free to contact us.
## How Pixelnetica™ Document Scanning SDK Differs from Traditional Imaging SDKs?
_Product: DSSDK · Category: features_
Traditional imaging software development kits (SDKs) primarily target general photo manipulations, such as format conversions, simple rotations, brightness and contrast adjustments, and basic binarization. While these functions are sufficient for standard image processing, they fall short when handling mobile-captured photographs of paper documents. Such images often require higher-quality reproduction for applications like Optical Character Recognition (OCR), document archiving, digital documentation, and more.
Photographs taken with mobile device cameras typically suffer from various issues, including distortions due to camera angles, inconsistent lighting conditions, shadows, glare, motion blur from shaking hands, out-of-focus shots, and user errors such as improper document positioning within the camera’s viewfinder. These factors significantly degrade image quality, affecting the effectiveness of OCR and other document-based tasks.
Pixelnetica™ Document Scanning SDK addresses these specific challenges by providing advanced preprocessing features optimized for documents captured with mobile devices:
Efficient Multi-language Text Recognition: Accurately recognizes text in over 100 languages, with full on-device processing.
Flexible Document Sharing: Easily share documents as “sandwiched” PDFs (containing both the scanned image and selectable text) or as plain TXT files for - straightforward text extraction.
Smart Crop Technology: Precisely detects and crops document boundaries.
Automatic Distortion Correction: Corrects 2D geometric and 3D perspective distortions automatically.
Automatic Orientation Detection and Rotation: Automatically detects and corrects document orientation.
Enhanced Noise Reduction: Reduces digital noise to significantly improve image clarity.
Brightness and Contrast Normalization: Mitigates shadows and glare, enhancing document readability.
Adaptive Binarization: Optimized specifically for OCR, preserving maximum text detail.
Adaptive Color Processing Profiles: Automatically adjusts color processing based on document content, ensuring optimal readability.
Secure On-Device Processing: Fully automated processing compliant with GDPR and CCPA, ensuring secure handling of sensitive data.
Ready-to-use UI Components: A set of customizable UI components for common document scanning flows, which cuts development time and cost.
By leveraging these advanced preprocessing features, Pixelnetica™ Document Scanning SDK produces images that match the high-quality standard of traditional flatbed scanners, significantly enhancing OCR accuracy and the efficiency of paperless workflows.
## What is an Android Document Scanner SDK?
_Product: DSSDK · Category: all_
Pixelnetica™Android Document Scanner SDK (DSSDK) is a software development kit that lets developers add document scanning to their Android applications.
It supports functionalities like automatic capture, precise cropping, real-time edge detection, image enhancement, and Optical Character Recognition (OCR) for over 100 languages.
## How to get perfect document scan with iPhone or iPad?
_Product: iOS · Category: SharpScan_
We made SharpScan to be able to correct as much scanning problems as possible, but following the simple rules below you can be sure that you’ll get perfectly scanned documents:
Important Good lighting is a key factor
Make sure that document is well lit.
Avoid strong shadows as well as glares (especially with glossy documents).
Use the flash with matt originals.
Document should be flat (not curved or folded).
Background should be uniform and contrast to original to make sure that Smart Crop (auto cropping) will work well.
Use Stabilization switched ON in SmarCamera Settings during shooting especially in low light conditions.
Make sure that document fits camera viewfinder (window).
Hold device parallel (as much as possible) and centered to original document.
## What is Pixelnetica™ Document Scanning SDK for iOS
_Product: DSSDK · Category: all_
Pixelnetica™ Document Scanning SDK (DSSDK) for Apple iOS is a commercial library that adds document scanning to an iOS app: live camera edge detection with automatic capture, perspective correction and image enhancement, on-device OCR in 100+ languages, and export to PDF, TIFF, JPEG, and PNG (including searchable, layered PDFs).
It ships through Swift Package Manager as binary frameworks and offers both ready-to-use UI screens (camera, crop/page editor, OCR editor, language picker) and a lower-level engine API for fully custom workflows. All processing runs on the device.
## How to compress document to smallest possible size with SharpScan for Android?
_Product: Android · Category: SharpScan_
Use Black and White processing profile .
In most cases Black-and-White documents are ~20 smaller than Gray or Color.
If document colors are crucial use the lowest acceptable Jpeg quality (in Setting menu, Export section).
## How to change several documents/pages in batch with ShapScan for Android?
_Product: Android · Category: SharpScan_
When you have a lot of multi-page documents scanned sometimes you need to process them in batch.
Currently in batch mode you can:
change color profile,
rotate document (clockwise, counterclockwise or upside-down),
redetect document boundaries.
To process documents/pages in batch mode please follow the steps below:
Select documents (or several pages inside document) by long tapping on first one or selecting Select pages from action menu and tap on each target page (document).
Use Select All icon for quick selection of multiple items).
Tap on action menu and select Batch Process icon
On Bach processor screen select options you want to change — e.g. “Change color profile”, “Rotate”, etc.
Tap on OK. You’ll see the progress on documents (page) icons.
## Is there a free Android Document Scanner SDK?
_Product: DSSDK · Category: all_
While free solutions like OpenCV exist, they primarily focus on general image manipulation or basic scanning features rather than specialized document processing.
Typically, they offer limited UI components, lacking critical features such as real-time document quality assessment, distortion correction, or adaptive OCR optimization.
In contrast, Pixelnetica™ DSSDK provides ready-to-use UI elements: camera integration, manual document editing, and a text recognition editor, plus active user guidance and dedicated support.
Additionally, Pixelnetica™ offers dedicated support and regular updates, ensuring smooth integration and ongoing reliability.
## I've change compression ratio but document size doesn’t changed.
_Product: Android · Category: SharpScan_
New compression setting will be applied during document reprocessing (modification). To recompress document (not altering cropping and profile settings) do the following.
Open desired page.
Tap on action menu and select Change color option .
Tap on any other color profile (e.g. Original) than tap on desired profile.
Tap on done Back button (or on device). New compression level will be applied, document size will change.
Do not be afraid to change compression level over and over again. Each time document will be compressed from original, so there will be no compression errors accumulation.
To recompress several pages or documents use batch processing — read about this in “How to change several documents/pages at once” article (see above).
## What is “Strong Shadows” option?
_Product: Android · Category: SharpScan_
Use this option with any processing preset (except Original) if original image contain strong shadows. In most cases it could help reveal a lot of additional information.
Shadows processing will work more effectively, if processed document was cropped accurately without any additional dark fragments from background.
## When I need to use “stabilization”?
_Product: Android · Category: SharpScan_
We recommend always use this option especially in low-lit conditions.
There are very few shooting problems we can’t (currently) correct. And one of them is defocusing. Usually it happens due to camera tremor during shooting and especially critical in low-lit conditions.
To mitigate this, we implement stabilization feature to our camera. It works very simple – camera waits until trembling will be reduced to appropriate level and only after that makes a shot.
When tremor detected stabilization icon will change to tremor icon until shaking stops.
To reduce camera tremor, try to hold hand still as much as possible or use any kind of support (stand or tripod).
## Why some documents been cropped automatically and some not?
_Product: Android · Category: SharpScan_
If shooting conditions was not good, or in some cases when document or background have complicated content, “Smart Crop” function could offer to manually correct document boundaries.
Follow our “recommendations for perfect scanning” (see above) to make sure that you’ll get best possible results in full auto mode.
## What is “Smart Crop” in SharpScan and how to use it?
_Product: Android · Category: SharpScan_
Smart Crop is our proprietary artificial intelligence technology allowing to automatically detect document boundaries and cut it out from background with high precision.
This mean that in most cases you don’t need to manually adjust document boundaries – this will be done in full auto.
In case when SmarpCrop will not detect document properly it will offer to manually correct document boundaries.
## How to copy or move page into other document?
_Product: Android · Category: SharpScan_
In SharpScan you can easily copy or move any page(pages) to any existing document.
The method described below works not only with pages of single document but with whole documents (selected on Documents screen). The difference is that in case of coping (moving) applied to the document all pages of selected documents will be copied (moved).
Open document which contains pages you want to copy (or move).
To select pages, you want to copy tap on first page and hold about 2 sec (long tap). You’ll be switched to select mode.
You can also enter it by tapping action menu and choosing Select pages option.
Tap on the page(s) you want to copy to select them.
You can use Select all to select all pages in document.
Tap on action menu and select Copy&Move option.
On Copy or Move dialogue select the action you want to apply to previously selected pages — copy or move them by tapping on switch below the headline.
Select document from list or tap on New Document to create new document from selected pages. Selected pages will be copied and appended to the selected document.
## What color processing profile should I use?
_Product: Android · Category: SharpScan_
This is highly depending on your future documents usage. Anyway, feel free to experiments since you can always revert document to original state.
Below our general recommendations about processing profiles usage.
B&W (Black and White).
Use it when you care about document size and text only. It produces clear tiny black and white documents with favour to the text area and disregard images and photos. Could be useful when you need to send rather big documents over low quality connection (like cellular network). Also take into account that image will have lossless compression.
Gray.
Near the same as B&W but optimized for human eye readability. Using lossy Jpeg compression (level could be set in settings).
Color.
Use Color processing profile when you care about document color information. Better fits for documents with color charts, photos, magazines etc. Using lossy Jpeg compression (level could be set in settings).
Original.
Use it only if anything else fits your needs. Doesn’t process documents at all (only crop). Using lossy Jpeg compression (level could be set in settings)
## What is the Pixelnetica™ Document Scanner SDK licensing model?
_Product: DSSDK · Category: licensing_
The Document Scanner SDK is provided through a straightforward, fixed annual subscription. This flat-fee model gives you unlimited access—no hidden costs based on the number of users, scans, or devices.
## What document types can Android DSSDK generate?
_Product: DSSDK · Category: all_
DSSDK supports most common file formats including PDF, TIFF, JPEG, PNG, and plain text files.
It also offers advanced PDF generation of layered PDF documents (also known as “sandwiched PDFs”), which greatly enhances indexing and usability by allowing users to search and copy text directly from scanned documents.
Document Scanning SDK provides layered searchable PDFs and customizable compression options. Lossless compression preserves every detail—ideal for healthcare, finance, legal, and archival purposes. While advanced compression significantly reduces file sizes, making documents easier to store, share, and manage.
DSSDK’s compression algorithms produce smaller files without compromising legibility or OCR accuracy.
Our support team can also help you tune compression settings for your application, for efficient storage and faster sharing.
## How to scan document in color or grayscale with SharpScan for Android?
_Product: Android · Category: SharpScan_
First of all — feel free to change document color mode as much as you want. Since SharpScan edit all documents in nondestructive mode you can always revert to original image.
You can change document color in two ways:
Manually
Open page you want to reprocess.
Tap on action menu and select Change color profile option
Tap on color desired profile icon on bottom toolbar (could one of ,
, , ). Choose strong Shadow option for documents with strong shadows on it.
Tap on Back button on top menu or on your device.
For more information on color profiles please read “What color processing profile should I use” article (see below).
Used color profile will be set as new default and will be used on next scan (until you change it again).
In batch mode
Please read about in “How to change several documents/pages at once” article (see below).
## How to rename documents in SharpScan for Android?
_Product: Android · Category: SharpScan_
There two main ways to rename document in SharpScan.
First – the quick one
Open document you want to rename.
Tap on its name on top toolbar.
On opened dialogue edit existing or enter new name and tap on OK button.
Second
Open document you want to rename by tapping on its thumbnail.
Tap on action menu on top toolbar.
Tap on document property icon .
Edit document name and tap on OK. Document name will be changed.
## How to get perfect document scan with Android smartphone or tablet?
_Product: Android · Category: SharpScan_
SharpScan are able to correct lots of scanning problems, but following the simple rules below you can be sure that you’ll always get perfectly scanned documents:
Important Good lighting is a key factor
Make sure that document is well lit. Avoid strong shadows and glares (especially glossy original). Use the flash with matt originals.
Switch the Torch on in camera especially in low lit environment.
Use Stabilization in camera during shooting. This will prevent appearing out of focus scans.
Document should be flat - not curved or folded.
Background should be uniform and contrast to original to make sure that document boundaries will be detected properly and Smart Crop (automatic document cropping and correction) will work well.
Make sure that document fully fits camera viewfinder (window).
Hold device parallel (as much as possible) and centered to original document.
Of course Smart Camera will assist you as much as possible but following these rules will guarantee best results.
## Does DSSDK Support Other Platforms?
_Product: DSSDK · Category: all_
Yes. Pixelnetica™ Document Scanning SDK is available for native Android, Apple iOS as well as cross-platform frameworks like .NET MAUI .
## What File Formats Are Supported by Xamarin DSSDK?
_Product: DSSDK · Category: all_
DSSDK supports a wide range of common document formats, including PDF, TIFF, JPEG, and PNG. It also provides customizable PDF generation, allowing users to choose from archival-quality lossless compression to highly efficient, space-saving formats optimized for sharing and OCR performance.
## Is there a free Xamarin Document Scanner SDK?
_Product: DSSDK · Category: all_
Open-source solutions such as OpenCV, Apple’s Vision Kit, ML Kit, CameraX API provide free options for basic document scanning on mobile OS.
However, these solutions often lack advanced features such as customizable UI components and intelligent real-time user guidance.
Pixelnetica™ DSSDK provides advanced capabilities that are critical for professional applications. These features include intelligent user guidance, customizable interfaces, automatic distortion correction, enhanced OCR, and file optimization, well beyond basic free options.
## How Easy Is It to Integrate DSSDK into My Xamarin App?
_Product: DSSDK · Category: all_
DSSDK integrates into Xamarin projects with thorough documentation, full API details, and sample apps for Xamarin.Forms, Xamarin.Android, and Xamarin.iOS. Developers can start immediately with our readily accessible GitHub resources:
Explore our DSSDK Documentation and the sample applications source codes.
Xamarin.Forms demo app source code
Xamarin.Android demo app source code
Xamarin.iOS demo app source code
For assistance, please feel free to contact us.
## How can DSSDK improve scanning quality in My Xamarin App?
_Product: DSSDK · Category: all_
DSSDK significantly enhances document scanning in your Xamarin app through:
Real-Time Intelligent Guidance: Automatically assists users in achieving optimal scans by helping avoid common errors such as poor framing, improper lighting, and shaky captures.
Automatic Document Detection: Instantly detects document boundaries and corrects perspective, improving scanning precision.
Advanced Image Enhancement: Applies sophisticated processing techniques for maximum readability, optimal OCR accuracy, and reduced file sizes for efficient storage.
## What will happen to DSSDK Xamarin after Microsoft support ends?
_Product: DSSDK · Category: all_
Microsoft officially ended support for Xamarin.Forms and other Xamarin SDKs as of May 1, 2024. While existing Xamarin apps will continue to run, they no longer receive official updates, including security patches and technical support.
“Xamarin.Forms has evolved into .NET Multi-platform App UI (MAUI) and existing Xamarin.Forms projects should be migrated to .NET MAUI.
…
For more information about upgrading Xamarin projects to .NET, see the Upgrade from Xamarin to .NET & .NET MAUI documentation.”
To maintain the sustainability of your applications, we highly recommend migrating to .NET MAUI, Microsoft’s next-generation platform for mobile apps. Pixelnetica™ provides a DSSDK solution for .NET MAUI with ongoing updates and full compatibility with future .NET releases.
Explore DSSDK for .NET MAUI
## What is Pixelnetica™ Document Scanning SDK for Xamarin & Xamarin.Forms?
_Product: DSSDK · Category: all_
Pixelnetica™ Document Scanning SDK (DSSDK) for Xamarin.Forms, Xamarin.Android, and Xamarin.iOS enhances your mobile apps by providing sophisticated document capture features.
It improves image quality and OCR accuracy and simplifies mobile document management.
## What is Pixelnetica™ Document Scanner SDK?
_Product: DSSDK · Category: overview_
The Pixelnetica Document Scanner Software Development Kit (DSSDK) is a toolkit that turns any smartphone or tablet into a document scanner. Using computer vision, it produces high-quality scans optimized for automated processing.
Key features include:
Automatic document capture with interactive user guidance.
Automatic orientation detection, rotation, cropping, and advanced color conversion (binarization).
Optical Character Recognition (OCR) support for over 100 languages.
Exporting capabilities in various formats including images, text, or layered PDF with sophisticated compression techniques.
These functions come as ready-to-use UI components. DSSDK runs entirely offline, so document data stays on the device.
## What File Formats Are Supported by .NET MAUI DSSDK?
_Product: DSSDK · Category: all_
DSSDK supports popular formats including PDF, TIFF (G4), PNG, and JPEG. It also offers advanced PDF compression, significantly reducing document file sizes for easy sharing and improved OCR processing.
## How to OCR (recognize) text on document?
_Product: iOS · Category: SharpScan_
OCR feature allows you to transform image taken from camera into editable text. You can test how OCR (optical character recognition) feature works in SharpScan before purchase it. To do this please follow the steps below.
Open document and page you want to OCR.
Tap on Txt icon on bottom toolbar. Text layer screen will open.
Tap on Recognize button.
On Language selection screen select desired language for recognition. If there were no any language selected before you’ll need to download at least one.
Tap on All languages.
Tap on language you need.
After chosen language download will be finished and you’ll be able to select it. Just tap on it. Select mark will appear.
Tap on Select button on top toolbar. Selected language symbol will be displayed on bottom toolbar.
Tap on Recognize button. When recognition process will be finished you’ll be able to see the results. Pages with text layer will have an additional text icon.
You can recognize any amount of documents on any available languages and see results for free. To share resulted text (as text file or via "Copy-and-Paste") you'll need an additional in-app purchase (will be offered after sharing trial or from SharpScan Settings).
## Does DSSDK comply with GDPR and other privacy & security regulations?
_Product: DSSDK · Category: features_
Yes. All image processing happens on the device, so no images or sensitive data are sent to external servers.
This guarantees full compliance with major data privacy regulations including GDPR, CCPA,CPRA, etc.
Your users’ data stays private, secure, and fully under your application’s control, providing peace of mind and minimizing compliance risks.
## How can I improve text recognition (OCR) quality for mobile document images?
_Product: DSSDK · Category: features_
Digitizing documents with traditional scanners typically results in clear, evenly-lit, and well-aligned images, benefiting from high-speed scanning and duplexing capabilities. These qualities play a crucial role in ensuring OCR accuracy by minimizing errors and enhancing text extraction reliability.
In contrast, images captured using mobile cameras often encounter challenges like shaky hands, poor lighting, shadows, glare, and various geometric distortions. These factors significantly impact the quality of Optical Character Recognition (OCR), leading to increased error rates or making OCR processing impossible.
To achieve the best OCR results from mobile-captured documents, consider these key image preprocessing steps, each building upon the previous to minimize errors and enhance text recognition more effectively:
Geometric distortions correction: 2D and 3D perspective distortions (e.g., trapezoidal) should be identified and corrected for accurate text extraction and fewer OCR errors.
Image Alignment and Rotation: Automatically correct random angles for proper text orientation.
Noise Reduction: Digital noise caused by camera sensors should be detected and minimized.
Shadows and Glare Elimination: Properly mitigate shadows, glare, and background artifacts.
Document Background Cleaning: Remove unwanted background textures, color cast, etc. to enhance text clarity and readability.
Adaptive Binarization: Convert images into optimized black-and-white or grayscale formats, preserving maximum detail for OCR accuracy.
Pixelnetica™ Document Scanning SDK incorporates all these advanced preprocessing capabilities, including distortion correction, noise reduction, shadow elimination, background cleaning, and adaptive binarization, delivering exceptional OCR-ready results directly on mobile devices. Optimized for use with smartphones, tablets, and document cameras, Document Scanning SDK offers broad cross-platform compatibility and reliable performance, with clarity and legibility comparable to traditional scanners, ready to drop into your mobile applications. Additionally, the SDK offers ready-to-use, critically important UI components that significantly reduce development effort and enhance user experience, including Smart Camera integration, manual document boundaries adjustment, rotation correction, OCR results correction, and language management. The toolkit also supports text recognition in over 100 languages, processed entirely on-device.
## Is there a free Apple iOS Document Scanner SDK?
_Product: DSSDK · Category: all_
Yes — Apple’s VisionKit (VNDocumentCameraViewController) is a free, built-in document camera on iOS, and OpenCV is a free open-source option. (Google’s free ML Kit Document Scanner is Android-only — there is no iOS build.)
These cover basic capture, but they leave the hard parts to you: VisionKit has no built-in OCR or searchable-PDF output, no control over the output format or the enhancement profile (black-and-white / grayscale / color), a fixed non-customizable UI, and no auto-capture tuning — you build and maintain those yourself, and you cannot patch the system component when an OS update changes its behavior.
Pixelnetica™ DSSDK is a commercial SDK that provides all of that out of the box — ready-to-use customizable screens, automatic capture with real-time guidance, perspective correction, on-device OCR with searchable PDF, and selectable compression — with support. A free trial is available.
## What makes Pixelnetica™ Document Scanner SDK's pricing unique?
_Product: DSSDK · Category: licensing_
Unlike many competitors, DSSDK’s pricing is entirely flat. There are no usage tiers, no extra charges, and no hidden fees, allowing unlimited users, devices, and scans across any type of application—commercial, private, or public.
## Why do I need mobile document scanner software?
_Product: DSSDK · Category: overview_
Today, almost every user carries a camera-enabled mobile device, such as a smartphone or tablet. Mobile document scanning software uses these devices to deliver scans comparable to traditional hardware scanners. Mobile scanning software is always readily available, eliminating the expense and inconvenience of purchasing dedicated scanning hardware. Furthermore, data captured this way can be fed into corporate back-end systems, improving workflow.
## Do I need separate licenses for multiple applications?
_Product: DSSDK · Category: trial_
For all supported platforms and frameworks (native Android & iOS, .NET, and Xamarin), a Document Scanning SDK (DSSDK) license is required for each application on each operating system (e.g., iOS, Android).
Bulk discounts are available for second and subsequent application licenses by request.
White-label products do not require a separate license.
DSSDK standard license is available for a royalty-free flat annual fee and includes no limitations on the number of users, installations, or scans. It can be used in any type of application—public, private, or commercial.
Support Maintenance and Upgrade Assurance (SMUA) is included with the standard license and is valid for the same duration. It offers the following benefits:
Priority Support – via email, during business hours (Central European Time).
Maintenance – includes free minor version updates and bug fixes (e.g. from v2.1 to v2.2).
Upgrade Assurance – guarantees free major version upgrades (e.g. from v2.x to v3.x).
Custom licensing schemes, including irrevocable perpetual licenses, are available upon request.
Licenses for development or staging product versions are provided free of charge.
Feel free to contact us to find the optimal licensing scheme for your specific use case.
## How to restore SharpScan access to Photo album?
_Product: iOS · Category: SharpScan_
After SharpScan installed on device he will ask permission to access Photos (to be able to load document from Photo library).
If you do not grant access first time you still able to change this in future.
To restore SharpScan access to Photo library please follow these simple steps:
Open your device global Settings (grey gear icon on home screen).
Go to Privacy - Photos.
Find “SharpScan” in application list. Switch it on.
Now SharpScan will be able to access your Photos.
## How to restore SharpScan access to device Camera?
_Product: iOS · Category: SharpScan_
After SharpScan installed on device he will ask permission to access Camera (to be able to utilise device Camera).If you do not grant access first time you still able to change this in future.
To restore SharpScan access to device Camera please follow these simple steps:
Open your device global “Settings” (grey gear icon on home screen).
Go to Privacy - Camera section.
Find SharpScan icon in the list. Switch it on.
Now SharpScan will be able to access your Camera.
## Why my documents almost always rotated wrong side?
_Product: iOS · Category: SharpScan_
If you found that almost all your document (and document preview in camera viewfinder) wrongly turned 90° usually this means that access to device Motion sensor was not provided.
To grant access to device Motion Sensor please follow these simple steps:
Open your device global Settings (grey gear icon on home screen).
Scroll down the application list and find SharpScan. Tap on its icon.
Check that all items are switched ON (Album, Camera, Mobile Data).
Open Location section and make sure that it set to Always.
Reboot your device and start SharpScan again.
## How to change document sharing format?
_Product: iOS · Category: SharpScan_
By default, document sharing format set to PDF (as most supported over all known computer platforms and mobile devices). SharpScan also supports other document sharing formats — Images and Text.
If you’d like to change your document sharing format, please follow these simple steps:
Open document you’d like to share.
Tap on sharing icon .
On opened Sharing screen tap on Document Format (first item in list) and choose preferred document format from the list. Your choice will be remembered and used by default for the next sharing. You can always change it later.
Share you document through your favorite service by tapping on it in the list.
## How to rename documents in SharpScan?
_Product: iOS · Category: SharpScan_
There two main ways to rename document in SharpScan.
First (most simple)
Open document you want to rename.
Tap on its name on top toolbar.
On opened dialogue edit existing or enter new name and tap on OK button.
Second
Open document you what to rename by tapping on its thumbnail.
Tap on document property icon on bottom menu bar. Document Property screen will open. On this screen you can not only rename document but also change it paper size.
Tap on document Name field. It should become editable. Enter an appropriate document name.
Tap on Save. Document name will be changed.
## How to scan or rescan document as color, gray or original?
_Product: iOS · Category: SharpScan_
First of all — feel free to change document color mode as much as you want. Since SharpScan edit all documents in nondestructive mode you can always revert to original image.
You can change document color in two ways:
Manually
Open the page you want to reprocess (rescan).
Tap on color profile icon on bottom toolbar ( one of , ,, )
Tap color profile icon again and choose new color from list. Image will be reprocessed.
For more information on color profiles please read “What color processing profile should I use” article (see below).
Tap on OK.
Used color profile will be set as new default and will be used on next scan (until you change it again).
In batch mode
Please read about in “How to change several documents/pages at once” article (see below).
You can watch our document manual adjustments video tutorial where color changing process well covered.
## What color mode should I use for document scan?
_Product: iOS · Category: SharpScan_
This is highly depending on your future documents usage. Anyway, feel free to experiments since you can always revert document to original state.
Below our general recommendations about processing profiles usage.
B&W (Black and White).
Use it when you care about document size and text only. It produces clear tiny black and white documents with favour to the text area and disregard images and photos. Could be useful when you need to send rather big documents over low quality connection (like cellular network). Also take into account that image will have lossless compression.
Gray.
Near the same as B&W but optimized for human eye readability. Using lossy Jpeg compression (level could be set in settings).
Color.
Use Color processing profile when you care about document color information. Better fits for documents with color charts, photos, magazines etc. Using lossy ÏJpeg compression (level could be set in settings).
Original.
Use it only if anything else fits your needs. Doesn’t process documents at all (only crop). Using lossy Jpeg compression (level could be set in settings).
Please watch our document manual adjustments video tutorial where color changing process well covered.
## How to turn “Smart Camera” off?
_Product: iOS · Category: SharpScan_
Smart Camera is aimed to provide full auto mode shooting and reduce unintentional shooting errors. But sometimes this leads to some inconvenience especially in bad lighting conditions.
If you have problems complaining Smart Camera interactive demands border or simply in a rush you can:
Just ignore the messages and tap on camera button or document preview in camera viewfinder. In this case camera will take a shot not waiting when document will be found and handshaking sensor will be ignored.
If you completely don’t like new scanning method you can easily switch it off by tapping on radar icon (it will change to
) or adjust it more precisely in SharpScan Settings — Smart Camera section.
## How to copy page to another document?
_Product: iOS · Category: SharpScan_
In SharpScan you can easily copy or move any page(pages) to any existing document. Just follow the steps below.
Make sure that you have a «destination» document where you want your pages to be copied (moved). If you don’t have it just create new one from Camera or Album .
Open document which contains page you want to copy.
Tap on Select menu and select the page(s) you want to copy.
Tap on Folder icon (bottom menu bar).
Select desired action: Copy or Move.
Select the «destination» document (from step 1) for your pages.
Tap on Done. Pages will be copied or moved to selected document.
## What is “Smart Crop” and how to use it?
_Product: iOS · Category: SharpScan_
“Smart Crop” is our proprietary artificial intelligence technology allowing to automatically detect document boundaries and cut it out from background with high precision.
This means that in most cases you don’t need manually adjust document boundaries – this will be done in full auto.
## Why some documents was not cropped automatically?
_Product: iOS · Category: SharpScan_
If shooting conditions was not good, or in some cases when document or background have complicated content, “Smart Crop” function could offer to manually correct document boundaries.
Follow our recommendations for perfect scanning (see above) to make sure that you’ll get the best possible results in full auto mode.
## When I need to use “stabilization”?
_Product: iOS · Category: SharpScan_
We recommend using this option in low-lit conditions.
There are very few shooting problems we can’t (currently) correct. And one of them is defocusing. Usually it happens due to camera tremor during shooting and especially critical in low-lit conditions.
To mitigate this, we implement “stabilization” feature to our camera. It works very simple – camera waits until trembling will be reduced to appropriate level and only after that makes a shot.
To reduce camera tremor, try to hold hand still as much as possible or use any kind of support (stand or tripod).
## What is “Shadows” option?
_Product: iOS · Category: SharpScan_
Use this option with any processing preset (except Original) if original image contain strong shadows. In most cases it could help reveal a lot of additional information.
“Shadows” processing will work more effectively, if processed document was cropped accurately without any additional dark fragments from background.
Please avoid use this option on documents without strong shadows since it could lead to loose some details on dark areas.
## I've change compression ratio but document size doesn’t changed.
_Product: iOS · Category: SharpScan_
New compression setting will be applied during document reprocessing (modification). To recompress document (not altering cropping and profile settings) do the following.
Open desired page.
Tap on color profile icon (could one of ,
, , ).
Tap on Done button. New compression level will be applied, document size will be changed.
Do not be afraid to change compression level over and over again. Each time document will be compressed from original so there will be no compression errors accumulation. To recompress several pages or documents use batch processing.
## How to edit several documents/pages at batch?
_Product: iOS · Category: SharpScan_
When you have a lot of multipage documents scanned sometimes you need to process them in batch. Currently in batch mode you can: change color profile, rotate document clockwise or counterclockwise, redetect document boundaries.
To process documents/pages in batch mode please follow the steps below.
Select documents (or pages inside document) by tapping on Select button and taping on appropriate items. Use Select All icon for quick selection of multiple items.
Tap on Batch processor icon .
On Bach processor screen select options you want to change — e.g. Color profile, Rotation, Boundary redetection.
Tap on OK. You’ll see the progress on documents (page) icons.
You can also watch our “batch processing video tutorial”.
## How to compress document to smallest possible size?
_Product: iOS · Category: SharpScan_
Consider using Black and White processing profile .
In most cases it 10-20 times (depend on document content) smaller than Gray or Color.
If document colors are crucial use the lowest acceptable Jpeg quality (in Setting menu, Export section).
## How to share the original “untouched” image?
_Product: iOS · Category: SharpScan_
If you need to share the “original” image (which comes from camera and not affected by SharpScan in any way) you can do it by following several simple steps.
Open desired page.
Tap on Crop icon.
Tap on Select all icon. Image cropping boundaries will be extended to all visible area.
Tap on Processing profile icon (could be one of ).
Choose original image processing profile by tapping the Original icon.
Tap on Done button.
Tap on Share icon. Choose Share as: Image.
Tap on Done button. Original image will be shared.
## How to set up “Permissions Password” for document?
_Product: iOS · Category: SharpScan_
For the sake of simplicity in Document property you can set up only the “Open Password”. In this case the “Permissions password” will also be set.
It equals to “open password” plus “js” (lower case).
For example, if you set the open password to 123 your permission password will be the 123js .
## How to automatically upload all documents to cloud?
_Product: iOS · Category: SharpScan_
“AutoUpload” feature allows you fully automatically upload your documents to your favorite cloud sharing service in background. To set up your documents to AutoUpload jus follow the steps below.
Open SharpScan Settings by tapping on Gear icon on Documents screen.
Tap on Upload Accounts.
Tap on your favorite cloud service and enter an appropriate credentials (login and password).
Tap on AutoUpload option.
Switch AutoUpload ON for chosen cloud service.
By default, all uploads will go to the root folder od selected service. You can change it by tapping on service name below the list. In opened screen browse to desired folder (or crate new one) and tap on Select.
Now all you new and changed documents will be automatically upload to the selected folder of your favorite cloud service.
All existing document created before `AutoUpload` been switched on will not be automatically uploaded (at least until you'll change/edit them). You'll need to share them manually.
Documents will be shared as `PDF`. To share documents as `Image` (or `Text`) please do this manually.
## What are the small cloud icons appearing sometimes near document name?
_Product: iOS · Category: SharpScan_
These icons appear when AutoUpload option is switch on and shows the actual status of document uploading.
There could be two icons:
Grey — shows that document in the queue for PDF preparation.
Blue — shows that document is uploading to sharing service. When upload will be done icons will disappear.
## How Easy Is It to Integrate DSSDK into My iOS App?
_Product: DSSDK · Category: all_
Integration is through Swift Package Manager: add the package, import the module, and present a ready-to-use screen — a working scanner takes a few minutes. The ready-to-use UI components are customizable, and a lower-level engine API is available when you need a fully custom flow.
A complete iOS sample application and full API documentation are provided. Explore the DSSDK documentation and the sample application source code.
For assistance, contact us.
## What determines the pricing for Document Scanner SDK?
_Product: DSSDK · Category: licensing_
Pricing is determined solely by the number of distinct applications in which the SDK is integrated. Factors like the number of users, devices, or scans are not considered in our pricing structure.
## What is the difference between the free Trial and full Commercial license?
_Product: DSSDK · Category: trial_
There is only one key difference between the trial and commercial licenses: the free trial license works only with a demo application ID (the package ID for Android or the bundle ID for iOS).
If a different App ID is used, watermarks will appear on the processed images.
This arrangement is typically sufficient for testing in our demo apps (provided with source code) and for initial integration into your own project.
To view results without watermarks in your own app, you can temporarily change your App ID to the demo App ID. In most cases, that’s enough for testing and demonstrations.
If you think the trial will not be enough (e.g., for demonstration to your stakeholders or clients), feel free to contact us for a temporary full license.
Once you’re ready to go live, simply replace the trial license with the commercial license issued for your own App ID.
## What should be considered when choosing document scanning software?
_Product: DSSDK · Category: overview_
Choosing the right document scanning software should primarily focus on generating high-quality scans compatible with your corporate systems. Key considerations include:
Quality: The software should reliably produce crisp, clear, and legible scans, even under challenging lighting conditions or when dealing with poor-quality originals.
Compatibility: Check that the software integrates with your existing development platforms, frameworks, and tools.
Features: Beyond basic scanning capabilities, consider advanced features for your specific needs, such as customized document formats, adaptive color profiles (color, grayscale, black-and-white), and export options including JPEG, PNG, TIFF, and advanced PDF formats with text layers.
Security: With increasing regulatory requirements (GDPR, CCPA), software must securely handle data. DSSDK, for instance, does all processing on-device and offline, which maintains compliance with strict security standards.
Pricing: Transparent, predictable, and scalable pricing models are essential. DSSDK offers a royalty-free licensing model with a fixed annual fee, unlimited usage, and no user, installation, or scan limitations.
## How can I integrate Pixelnetica™ Document Scanner SDK into my product?
_Product: DSSDK · Category: overview_
Integrating DSSDK into your product is straightforward thanks to its ready-to-use UI components, such as the interactive camera interface for automatic document capture and intuitive manual editing tools for precise cropping and rotation adjustments. For integration details, refer to our documentation and explore the sample application source code.
For further assistance or queries, please don’t hesitate to contact us directly.
## How Can DSSDK Improve Scanning Quality in My iOS App?
_Product: DSSDK · Category: all_
DSSDK improves scan quality with real-time capture guidance, automatic border detection and perspective correction, document-specific image processing, and flexible output and compression — turning a handheld phone photo into a clean, readable scan. In detail:
Intelligent Real-Time Assistance
Real-time guidance helps users avoid common errors such as poor framing, improper lighting, or shaky camera handling.
Automatic document border detection and perspective correction.
Automatic capture mode that activates only when images meet predefined quality standards.
Automatic assessment of effective document area coverage, maximizing captured image quality.
Specialized Image Processing
Purpose-built algorithms improve readability and OCR accuracy, and shrink image size for efficient storage and quick sharing.
Advanced distortion correction for high document quality.
Flexible Output and Compression Options
Extensive support for standard file formats including PDF, TIFF, JPEG, PNG, and more.
Advanced customizable PDF compression from lossless archival quality to highly optimized, space-efficient documents.
## Where can I get document scanning software?
_Product: DSSDK · Category: overview_
While many free and open-source solutions exist, these often lack scanning quality and complete functionality, and need extra development for UI elements and format support. Investing in a professional solution like Pixelnetica Document Scanner SDK significantly reduces development time and ongoing support efforts by providing ready-made UI components, full documentation, and ready-to-use OCR features, eliminating the need for extensive custom coding.
Explore our Document Scanner solution, see it in our demo application, or try it in your application today.
## Which platforms are supported by Pixelnetica™ Document Scanner SDK?
_Product: DSSDK · Category: overview_
Pixelnetica Document Scanner SDK currently supports the following platforms:
Android
Apple iOS
.NET MAUI
Xamarin
A free demo application (complete with source code) and trial are available to get you started immediately.
## What is a White-label product and what license is required?
_Product: DSSDK · Category: trial_
In mobile application development, a White-label product refers to an application that shares the same functionality and purpose as the main product, but includes minor customizations such as branding, color schemes, localization, etc.
For example, it could be the same product used by a different subsidiary, region, or sub-brand within the same organization.
Such a White-label product does not require a separate license and is fully covered under the license of the main product — effectively provided free of charge.
For more details and personalized licensing advice, please contact us.
## Is the Pixelnetica™ Document Scanner SDK license royalty-free?
_Product: DSSDK · Category: licensing_
Yes, DSSDK’s licensing is royalty-free. Pay one annual fee, and use it without incurring additional costs per scan, installation, or user.
## What is the primary Document Scanner SDK licensing model?
_Product: DSSDK · Category: licensing_
The main licensing option is a fixed annual fee covering one application on a single operating system. For customized licensing solutions such as irrevocable perpetual licenses, please contact our team.
## Are there discounts for multiple licenses?
_Product: DSSDK · Category: trial_
Yes, we offer competitive discounts for multiple licenses, including multiple OS and multiple applications.
For custom pricing, Contact us directly.
## What File Formats Are Supported by iOS DSSDK?
_Product: DSSDK · Category: all_
DSSDK exports PDF, TIFF, JPEG, PNG, and plain text.
It also generates layered, searchable PDFs (“sandwiched PDFs”) that embed a hidden text layer behind the page image for indexing, search, and text extraction.
Customizable compression lets you choose between highly optimized files for easy sharing and lossless files for archival — and black-and-white pages are always stored losslessly regardless of the setting.
## Can I try DSSDK before purchasing?
_Product: DSSDK · Category: features_
Yes.
You can download our free demo application, which includes full SDK functionality (with watermarked outputs), documentation, and sample source code.
Free trial license without watermarking available upon request.
## How transparent is Pixelnetica™ DSSDK licensing?
_Product: DSSDK · Category: licensing_
Our Standard license includes all available features by default, eliminating the hassle of comparing different packages or navigating complex pricing structures.
## Does DSSDK Support Other Platforms?
_Product: DSSDK · Category: all_
Yes. DSSDK is available for native Android, and for the cross-platform frameworks .NET MAUI and Xamarin.
Each platform (iOS & Android) is licensed separately.
## Does DSSDK send my scanned documents anywhere, or is it fully on-device?
_Product: DSSDK · Category: all_
All document processing and OCR run entirely on the device — no images, page data, or recognized text are sent to any server. The SDK contains no analytics or telemetry. The only network request it can make is the optional download of OCR language packs from a location you configure, which transfers model files only, never user or document data.
DSSDK also ships an Apple privacy manifest (PrivacyInfo.xcprivacy) declaring no tracking and no data collection, so it accounts for itself in your app’s App Store privacy report and you do not need to add anything on the SDK’s behalf.
## What does 'flat licensing' mean for Pixelnetica™ DSSDK?
_Product: DSSDK · Category: licensing_
DSSDK employs a flat licensing structure, meaning your fee remains consistent regardless of the volume of scans, number of users, or devices. Visually, this flat model is illustrated on a pricing chart as a constant, horizontal line. Unlike tiered pricing models, which rise incrementally as usage or users increase, our flat pricing stays level, clearly emphasizing predictability and ease of budgeting for your organization.
## How does the Pixelnetica™ Document Scanning SDK work in Commercial Applications?
_Product: DSSDK · Category: features_
The Document Scanning SDK (DSSDK) from Pixelnetica™ makes it easier to add scanning to commercial mobile apps, improving speed, accuracy, and efficiency. Businesses can rapidly digitize paper documents like invoices, contracts, proof of delivery, questionnaires, etc. reducing processing time and manual errors.
Most features of the Document Scanning SDK are showcased in Pixelnetica™ SharpScan, a full-featured mobile scanner for capturing and managing multi-page documents. Please note that the source code for SharpScan is not available.
Additionally, DSSDK powers our EasyScan application, which is designed to handle one multi-page document at a time. EasyScan’s source code is readily available for Android and Apple iOS and supports modern development frameworks like .NET MAUI and Xamarin, enabling rapid integration and significantly reducing your application development time. This makes implementation quick across multiple platforms.
Get SharpScan
Apple App Store
Google Play store
Get EasyScan
Apple Appstore
Google Play store
## Can I use DSSDK from SwiftUI?
_Product: DSSDK · Category: all_
Yes. The ready-to-use screens are provided as SwiftUI views, so you present them directly from a SwiftUI app. The core engine API is Objective-C and is called from Swift through the generated interface (the SDK is imported as a Swift module). The included EasyScanner sample app is a SwiftUI app and shows both the screens and the engine API in use.
## Does Pixelnetica™ DSSDK track or collect scan data?
_Product: DSSDK · Category: licensing_
Absolutely not. DSSDK processes all data completely offline and directly on users’ devices. We do not collect, monitor, or access your usage or scans, ensuring full privacy and compliance with GDPR and CCPA.
## What's the difference between Demo, Trial, and Commercial licenses?
_Product: DSSDK · Category: licensing_
Demo License: Bundled with our demo application source code. Includes all features but adds a watermark to processed images.
Trial License: Available upon request, fully featured, watermark-free for a limited time, and tied to our demo application ID.
Commercial License: Fully featured, watermark-free, and tied specifically to your application ID.
## How much does DSSDK add to my app's size?
_Product: DSSDK · Category: all_
The device frameworks add roughly 16 MB before App Store thinning: the core framework is about 15 MB and the ready-to-use UI framework about 1.3 MB. Linkers dead-strip unused code and the App Store thins the download further, so the real impact on your users’ download is typically smaller.
OCR language packs are downloaded on demand at runtime, not bundled, so they do not add to your app binary.
## How many licenses are needed for cross-platform applications?
_Product: DSSDK · Category: licensing_
Each DSSDK license covers one application on a single operating system (e.g., Android, iOS). Cross-platform frameworks like .NET MAUI require a separate license for each operating system. However, internal testing, staging environments, or white-label variations don’t require additional licenses and are covered by the same commercial license. Bulk discounts are available—please contact us.
## Does the DSSDK license need an internet connection to activate?
_Product: DSSDK · Category: all_
No. The license key is validated entirely on the device — the SDK verifies it cryptographically against an embedded public key, with no activation server and no network call. This means DSSDK works in fully offline and air-gapped deployments, and your users never wait on a license check.
## Are updates and new features included in the Standard license?
_Product: DSSDK · Category: licensing_
Yes, your Standard license includes all minor and major updates, new features, and enhancements during the subscription period at no extra charge.
## Which iOS versions and Apple platforms does DSSDK support?
_Product: DSSDK · Category: all_
DSSDK targets iOS 16.3 or later on iPhone and iPad, built with Xcode 15+ (Swift tools 5.9). It ships as Swift Package Manager binary frameworks with device (arm64) and simulator (arm64 + x86_64) slices, so it builds and runs on both Apple-silicon and Intel simulators.
It is an iOS SDK — Mac Catalyst, visionOS, and macOS are not currently supported. For other platforms, see the Android, .NET MAUI, and Xamarin editions.
## What support options does Pixelnetica™ DSSDK include?
_Product: DSSDK · Category: licensing_
Your DSSDK subscription includes priority email support available during standard business hours (Central European Time).
## Is custom licensing available?
_Product: DSSDK · Category: licensing_
Yes, custom licensing options, including perpetual licenses, are available upon request. Please contact our team for further details.
## What payment methods are accepted?
_Product: DSSDK · Category: licensing_
We support a wide range of payment methods, including credit cards, purchase orders (PO), and specific local payment options via our payment processing partner. You can also make direct payments via bank wire transfer.
## Can I pay DSSDK directly?
_Product: DSSDK · Category: licensing_
Certainly! We accept direct bank wire transfers. Please contact us with your company name, address, contact person’s name, and position so we can promptly issue an accurate invoice.
----------------------------------------------------------------------
# SharpScan tutorials
## How to scan paper document with iPhone or iPad camera
To scan any paper document on the go with SharpScan please follow these simple steps.
Scan documents with device Camera
Tap on Camera button.
Point camera to document. Follow interactive tips to position camera properly. When all condition will be met SharpScan automatically take a shot.
You can also simply tap on camera button or any part of viewfinder (in this case focus will be taken on this point exactly) to enforce the shot.
Document will be scanned, cropped and process with currently chosen color automatically. If SharpScan will not be able to properly detect document borders it will offer manual correction option.
Add documents from Album
You can also add document from device Photos by tapping on Album button.
Selectin appropriate photo or several ones.
Tap on Done
Document will be processed and adjusted the way as it will be scanned with device camera.
## How to edit and adjust scanned document
First of all — feel free to edit document boundaries as much as you want. SharpScan edit all documents in nondestructive mode you can always revert to original image and edit it again and again.
To manually adjust document please follow the steps below.
Open document which you want to edit
Tap on Crop icon.
Adjust document boundaries by “tap-and-move” document corners. Try to tap not exactly on corner by slightly nearby. This corner will be zoom for your convenience.
Rotate document to appropriate angle (if needed).
Change document color (if needed). It will be remembered and applied as default in the next scan.
Adjust Shadows option.
Tap on Done button to apply changes.
Change document name.Tap on document property icon . Document Property screen will open. On this screen you can not only rename document but also change its paper size (will be used for PDF creation).
Recognise document text by tapping on OCR button.
Select language form the list. It will be downloaded if necessary.
Tap on Select button.
Tap on Recognise button.
When recognition process will be finished tap on Done button to save results. Pages with text layer available will have an additional text icon.
## How to share scanned documents
There two main ways to share documents in SharpScan - Automatically upload and Manually.
Automatically upload document with “AutoUpload”
You can use AutoUpload feature to fully automatically upload your documents to favorite cloud sharing service in background.
Open Settings by tapping on Gear icon.
Choose Upload Accounts.
Tap on your favorite cloud service and enter an appropriate credentials (login and password).
Tap on AutoUpload option.
Switch AutoUpload ON for chosen cloud service.
By default, all uploads will go to the root folder of selected service. You can change it by tapping on service name below the list. In opened screen browse to desired folder (or crate new one) and tap on Select.
Now all you new and changed documents will be automatically upload to the selected folder of your favorite cloud service.
Important.
All existing document created before AutoUpload been switched on will not be automatically uploaded (at least until you’ll change/edit them). You’ll need to share them manually.
Documents will be shared as PDF. To share documents as Image (or text) please do this manually.
Manual document sharing
To manually share any document
Open document.
Tap on Share icon
Select document format: Image, PDF, Text (if was recognised).
Pick cloud or system provided service to upload document to.
Document will be uploaded.
Multiple document sharing
To share several documents at once please do the following.
Select documents by tapping on Select button and taping on appropriate items. Use Select All icon for quick selection of multiple items.
Tap on Share icon.
Choose document format and service as described above.
All selected documents will be uploaded to chosen service.
Share selected page or several pages
Sometime it is useful to share not whole document but only several pages of it.
To do this please follow the steps below.
Open document which page you want to share.
Select pages by tapping on Select button and taping on appropriate items. Use Select All icon for quick selection of multiple items.
Tap on Share icon.
Choose document format and service as described above.
All selected pages will be uploaded to chosen service.
## How to speed up your work with useful gestures
You can use several convenient gestures to speed up you work with SharpScan.
Swipe right-to-left to Delete list element (document or page).
Two-Finger Pinch to Zoom pages In and Out.
Double Tap on any page to Zoom 1:1 In and Out.
## How to edit multiple documents in batch
Sometimes it may be convenient to edit several multi page documents or just several pages in one document in batch. In batch mode you can: change color profile, rotate document clockwise or counterclockwise, redetect document boundaries.
To process documents/pages in batch mode please follow the steps below.
Select documents (or pages inside document) by tapping on Select button and taping on appropriate items.
Use Select All icon for quick selection of multiple items.
Tap on Batch processor icon.
On Bach processor screen select options you want to change — e.g. Color profile, Rotation, Boundary Redetection.
Tap on OK. You’ll see the progress on documents (page) icons.
----------------------------------------------------------------------
# Documentation — Document Scanning SDK guides
## Add to a project
https://www.pixelnetica.com/docs/document-scanner-sdk/android/add-to-android-project.html
The SDK is distributed as Maven artifacts. There are two repositories to choose from, and the recommended one needs no account and no token. The demo application source code is a working project already set up this way — a useful reference while you follow the steps below.
1. Recommended: specify the repository in the project
Add the Pixelnetica repository to the project-level Gradle script. It is anonymous: no credentials, no account, nothing to request.
repositories {
maven {
// Pixelnetica Document Scanning SDK
url = uri("https://maven.pixelnetica.com/")
}
}
That is the whole prerequisite. If you are migrating from the GitHub Packages route, you can delete the token and the credentials block along with it.
2. Choose the modules and add the dependencies
The SDK is split into modules, so an application adds only what it uses:
Module
What it provides
When you need it
scanning
The core library: document detection, cropping, colour processing, OCR, and export to image files and searchable PDF.
Always — every integration starts here.
camera
A ready-made camera activity with live document detection and automatic capture.
When you want a working scanner screen without building your own camera UI.
design
Ready-made UI components: the crop editor, the OCR language manager, and the recognized-text editor.
When you use the ready-made screens rather than building your own.
A fourth artifact, support, is a utility library the modules above depend on; Gradle resolves it automatically, and you do not add it yourself.
For the minimal setup, add scanning to the “dependencies” section of the module-level build.gradle.kts file:
dependencies {
implementation("com.pixelnetica.sdk:scanning:3.2.0")
.....
}
Dependencies can also be managed through a Version Catalog:
Add the following information to the gradle/libs.versions.toml file.
[versions]
.....
pixelnetica="3.2.0"
[libraries]
.....
pixelnetica-camera = { module = "com.pixelnetica.sdk:camera", version.ref = "pixelnetica"}
pixelnetica-design = { module = "com.pixelnetica.sdk:design", version.ref = "pixelnetica"}
pixelnetica-scanning = { module = "com.pixelnetica.sdk:scanning", version.ref = "pixelnetica"}
Update the build.gradle.kts module file adding the following information.
dependencies {
.....
implementation(libs.pixelnetica.scanning)
implementation(libs.pixelnetica.design)
implementation(libs.pixelnetica.camera)
}
3. Which versions are where
https://maven.pixelnetica.com/ serves 3.0.0, 3.0.1, 3.1.1, 3.1.2 and 3.1.3, and every release from 3.2.0 onwards.
Two exceptions are worth stating plainly rather than leaving you to discover them:
3.1.0 is not there. It was only ever published for support, so it was never a resolvable set, and it stays where it is.
-SNAPSHOT versions are not there either. They remain on GitHub Packages.
Everything ever published to GitHub Packages stays on GitHub Packages and is never removed, so a project pinned to any of it keeps working. The 2.x series remains at its own legacy host and is unaffected by any of this.
4. Verifying the artifacts
Every file published from 3.2.0 onwards is signed, and carries .md5, .sha1, .sha256 and .sha512 checksums alongside the signature.
The public key is at https://maven.pixelnetica.com/KEYS. Its fingerprint is:
59C6 C9B1 371D F73B E3E3 D278 EB30 ADAA ED5B 88C0
To check a downloaded file by hand:
curl -O https://maven.pixelnetica.com/KEYS
gpg --import KEYS
gpg --verify scanning-3.1.3.aar.asc scanning-3.1.3.aar
If you use Gradle’s dependency verification with verify-signatures, the same key is published on keys.openpgp.org. Add it to your gradle/verification-metadata.xml so Gradle knows where to look:
Gradle queries a set of well-known key servers by default, and this key is on more than one of them — but which servers Gradle consults is a Gradle detail that can change, so naming the server in your own configuration is the reliable form rather than relying on the default.
5. The GitHub Packages route: still supported and sunsetting
[!NOTE]
GitHub Packages is deprecated but active. It will continue to receive new releases for at least two more versions, and the final version to be published there will be named here when it is decided. Nothing already published is ever removed, so existing projects keep resolving from it indefinitely. New projects should use https://maven.pixelnetica.com/ above.
This route needs a GitHub account and an access token. GitHub requires authentication for every Maven package download — even for public packages like ours. This is GitHub’s platform rule, not a Pixelnetica restriction: any GitHub account can download the SDK, there is nothing to request from us, and the token does no more than tell GitHub who is downloading.
Create the token in GitHub under Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic), and grant it the read:packages scope only — it needs no repository access and no other permissions. GitHub’s token documentation covers managing and revoking tokens.
[!IMPORTANT]
The token must be a classic one. GitHub Packages does not accept GitHub’s newer fine-grained tokens — a fine-grained token looks valid but every download fails with 401 Unauthorized.
Two more things worth deciding when you create it:
Expiration. GitHub suggests an expiry date; when it passes, dependency resolution stops with a 401 that looks like a configuration mistake (see Troubleshooting). Pick a date you will remember — or note where the token is used so the renewal is a one-line change.
Storage. Treat the token like a password: keep it in local.properties (as the demo application does) or in ~/.gradle/gradle.properties, never in a file you commit. On a build server, use the CI system’s secret store.
Then declare the repository, supplying the credentials from local.properties so they stay out of version control:
repositories {
maven {
// Reference to Scanning SDK library
url = uri("https://maven.pkg.github.com/Pixelnetica/artifacts")
credentials {
username = ""
password = ""
}
}
}
The module dependencies are the same either way — section 2 above applies unchanged.
Please use the most recent DSSDK version if you have an active SMUA (Support Maintenance and Upgrade Assurance) or active Standard subscription. If you are not sure, feel free to contact Pixelnetica DSSDK Support. Take into consideration that from time to time DSSDK can be changed.
6. Third-party notices
Each SDK library bundles assets/third-party-notices.txt, listing the open-source components inside the SDK and reproducing the licence text each one requires. Android merges library assets into your app, so the file is already in your APK once you depend on the SDK — you do not need to copy it anywhere. Most of those licences ask that their notice reach the people who receive the software, which for a mobile app usually means an acknowledgements or open-source-licences screen; reading the file out of your assets is the simplest way to fill one.
The OCR language packs are distributed separately from the SDK artifacts and carry their own notice inside that download.
For more details please check:
Document scanning SDK page,
DSSDK Version History,
Documentation,
demo application source code.
## Application Size and Packaging
https://www.pixelnetica.com/docs/document-scanner-sdk/android/app-size.html
The SDK’s processing engine is native code, compiled separately for each processor architecture — that is where its size comes from, and it is the first thing to know when planning your application’s download size. The numbers below are measured from the release artifacts, so you can budget before integrating rather than discover the size in your first build.
What the Modules Weigh
Artifact
Size
What is inside
scanning
~45 MB in your Gradle cache
The engine as native libraries for all four ABIs, plus the Kotlin API
design
~1.1 MB
The ready-made UI components
camera
~0.4 MB
The Smart Camera activity
support
~0.3 MB
Shared utilities (arrives transitively)
The scanning artifact’s bulk never reaches a user in full: a device needs the engine for its own architecture only. Per architecture, the engine (libscanning.so) weighs:
ABI
Engine size
Who runs it
arm64-v8a
~17 MB
Practically every current Android phone and tablet
armeabi-v7a
~12 MB
Older 32-bit devices
x86_64
~45 MB
Emulators; Chromebooks in x86 mode
x86
~31 MB
Legacy 32-bit emulator images
The x86 builds compile larger than the ARM ones — that is a property of the compiled engine, not packaging overhead, and all four libraries ship stripped. In practice the number that reaches your users is the arm64 one.
Keep the Download Small
Publish an App Bundle. With the .aab format, Google Play delivers each device only its own ABI’s library — your users download the ~17 MB arm64 engine, not all four. This needs no configuration; it is how App Bundles behave.
Or split APKs by ABI. If you distribute APKs directly, let Gradle build one per architecture:
android {
splits {
abi {
isEnable = true
reset()
include("arm64-v8a", "armeabi-v7a")
isUniversalApk = false
}
}
}
Trim ABIs you do not ship. A release build has no reason to carry emulator architectures:
android {
defaultConfig {
ndk {
abiFilters += listOf("arm64-v8a", "armeabi-v7a")
}
}
}
Keep x86_64 in debug builds if your team develops on emulators older than the arm64 images.
What the Optional Assets Add
Text recognition needs language data, and its size is per language — you choose what to bundle or download (see Setup OCR Languages):
A typical language file is in the 1–4 MB range: German is about 1.5 MB, Simplified Chinese about 2.5 MB, English about 4 MB.
The document orientation detector’s data (osd.pxl) is about 11 MB. Bundle it if you use orientation detection; skip it if you do not.
Searchable-PDF export needs TrueType fonts covering your languages, which the SDK does not provide; the demo’s Noto fonts are a few MB per script.
Applications that support many languages usually bundle one or two and let users download the rest — the language manager implements exactly that flow.
Shrinking and ProGuard
The SDK ships its own consumer ProGuard rules inside each artifact, so R8 and minification work without any -keep rules on your side. The rules travel with the library; you do not copy anything into your configuration.
## Smart Camera
https://www.pixelnetica.com/docs/document-scanner-sdk/android/camera.html
The camera library provides a ready-made camera activity: it watches the live preview for a document, guides the user with an on-screen frame and hints, captures automatically when the shot is good, and hands the captured pages back to your code as a list of image URIs. You launch it with one call and receive results through the standard Activity Result APIs — no camera code of your own.
Include into the Project
Add the dependency to your module-level build script:
dependencies {
implementation("com.pixelnetica.sdk:camera:3.2.0")
// Other dependencies
}
Or, if you use the Version Catalog:
dependencies {
implementation(libs.pixelnetica.camera)
// Other dependencies
}
Usage
Register the CameraContract in your Activity, Fragment, or Composable:
In an Activity or Fragment
private val cameraRequest = registerForActivityResult(CameraContract()) { uriList ->
// Handle the result
}
In a Composable
val cameraLauncher = rememberLauncherForActivityResult(
contract = CameraContract()
) { uriList ->
// Handle the result
}
The camera screen is a regular activity behind an ActivityResultContract, so hosting it in a Compose application needs nothing special — the launcher above is the complete integration.
Launching the Camera Activity
cameraLauncher.launch(CameraContract.CameraParams())
Configuring the Launch
CameraParams controls how the camera screen behaves for this launch. Every field has a working default, so CameraParams() is a complete configuration:
outputDir — the directory where captured pages are written. Left null, the activity uses its own storage.
tmpPrefix — the file-name prefix for the image files it creates.
authority — the authority of a FileProvider your application declares. With it set, results come back as content:// URIs your app can grant to other apps; left null, they arrive as plain file:// URIs, which other apps cannot open. Set it if the captured pages will be shared onward.
singleShot — true to close the camera after the first captured page instead of letting the user capture several.
shotOnTap — whether a tap on the preview captures a page (true by default).
autoShotMode — the conditions for automatic capture, combined from FrameObserver.Observation flags. The default captures when a stable document outline has been found (CUTOUT_READY) and the device is held steady (DEVICE_READY).
Receiving the Results
The callback receives a List — one URI per captured page, in capture order. With singleShot the list holds at most one entry. If the user leaves the camera without capturing (the back button, or a cancelled launch), the list is empty; there is no error to handle. Whether the URIs are content:// or file:// follows the authority parameter above.
What the User Sees
The camera screen guides the user with a coloured frame around the detected document:
No frame — the camera is still searching for a document.
Yellow — a document is detected and being framed; the user should hold steady.
Green — automatic capture is imminent; the conditions in autoShotMode are met.
Red — shown briefly while the shot is being taken.
The colours follow the same convention as the iOS SDK’s smart camera, so users of an application shipping on both platforms get the same signals. Short hint texts in the on-screen console (“Looking for document” and similar) accompany the frame.
Testing Against the Camera Screen
The camera screen is the SDK’s own UI, so an automated UI test cannot address its controls the way it would address yours. One control carries a supported contract for that purpose: the shutter button publishes the content description Take photo, and its enabled state is the SDK’s readiness signal.
val shutter = device.wait(Until.findObject(By.desc("Take photo")), 15_000)
check(shutter != null && shutter.isEnabled) { "the camera is not ready to capture" }
shutter.click()
Two things this lets a test do that it otherwise cannot. It can wait for readiness rather than guess at it — the camera takes a moment to bind, and a shot requested before then is discarded rather than queued, so a test that taps too early sees nothing happen and no error. And it can address the control without depending on the SDK’s internal view tree, whose resource identifiers carry no compatibility promise.
What the enabled state means precisely: the camera is bound and a shot will be accepted. It does not promise the preview is already delivering frames, nor that a document has been detected. A test that needs those should wait on what it actually needs.
The content description is also the control’s accessibility label, so it is what a screen reader announces.
Permissions and Hardware
The library’s manifest declares the camera permission, and manifest merging carries it into your application — you declare nothing. At runtime the camera screen requests the permission itself the first time it opens.
The library also marks the android.hardware.camera feature as required, which means app stores hide an application that includes the camera module from devices without a camera. If your application must remain installable on such devices, override the requirement in your own manifest and launch the camera only after checking availability.
Detection quality follows the camera stream: an autofocus rear camera is expected, and a sharp, well-lit preview finds document edges faster. If the device has no usable back camera, or the camera fails to start, the screen stays up, reports “Camera is not available” in its console, and returns the standard cancelled result when the user leaves.
Recipe: Capture a Single Page
For flows that need exactly one page — attaching one document to a form, for example — configure the launch to close after the first capture:
cameraLauncher.launch(
CameraContract.CameraParams(
singleShot = true,
)
)
The result list then holds one URI after a capture, or none if the user backed out.
## Colour Profiles and Refine Features
https://www.pixelnetica.com/docs/document-scanner-sdk/android/color-profiles.html
When the SDK refines a page, the colour profile decides what the result looks like: an office document reduced to crisp black and white, a photo kept in colour but cleaned of the phone camera’s cast, or the page exactly as shot. Picking the right profile is the single biggest lever on both legibility and file size, and this page shows the choices on a real document so you can pick by eye.
The Profiles, Compared
Each slider below starts from the same phone photo — skewed, unevenly lit, background visible — and wipes to what one profile makes of it after the refine pipeline crops and straightens the page. Drag the handle to compare.
Black and white (Bitonal) — the document scanning profile for text: pure black-and-white output with maximum legibility and the smallest files.
Grayscale (Monochrome) — keeps the page’s tones in shades of grey, for documents where shading matters but colour does not.
Colour (Colored) — cleans the page while keeping its colours: lighting evened out, the paper reading as paper instead of a grey photo.
The before side of each slider is the photo exactly as shot, so the wipe also shows the geometric correction — the crop and straightening — alongside the colour treatment.
Choosing a Profile
Bitonal reduces the page to pure black and white. The right default for text documents: maximum legibility, and by far the smallest files — bitonal pages compress losslessly in PDF export. Photographs and colour-coded content do not survive it.
Monochrome keeps tone in shades of grey. Use it when the page has meaningful shading — stamps, pencil, photographs on a text page — but colour itself carries no information.
Colored cleans the page while keeping its colours: lighting is evened out and the paper reads as paper, not as a grey photo. Use it when colour matters — forms with coloured fields, illustrated pages, receipts with coloured logos.
Original leaves the pixels’ colours untouched. Use it when the image must stay exactly as captured, for archival or when your own processing follows.
In code, the profile is one entry in the refine call (the workflow guide shows the full pipeline):
picture.refine(
listOf(
RefineFeature.Rectify.WithCutout(cutout),
RefineFeature.Profile(RefineFeature.Profile.Type.Colored),
)
)
The Other Refine Features
The profile is one of several independent features a refine call can carry — pass at most one of each kind, and the kinds you leave out stay unchanged:
Rectify — how to crop: to a known outline (WithCutout), to automatically detected corners (AutoDetect), or not at all (SkipCutout).
Display — which way up to leave the page; Display.Normal rotates it upright.
Shadows — even out shadows and uneven lighting across the page before the profile applies. Worth enabling for photos taken in room light.
KeepColor — keep the page’s existing colour hint instead of letting processing set it; an advanced option most applications never touch.
See the RefineFeature reference for the exact contracts.
The Same Choice in the Demo
The easyScan demo application exposes exactly these options in its page menu:
The menu’s names map to the API like this: Original, Black & White, Gray, and Color are the Original, Bitonal, Monochrome, and Colored profile types, and Strong Shadows toggles the Shadows feature on top of whichever profile is chosen.
## Design Library
https://www.pixelnetica.com/docs/document-scanner-sdk/android/design.html
The design library contains a set of ready-to-use UI controls.
Include in the project
Put into your module-level build script:
dependencies {
implementation("com.pixelnetica.sdk:design:3.2.0")
.....
}
Or, if you use a Version Catalog:
dependencies {
implementation(libs.pixelnetica.design)
.....
}
Usage with XML-View graphic system
Set up the application
To add these controls to your application, follow these steps:
Inherit an activity that contains these controls from AppCompatActivity (or a derived class).
Inherit your application (or activity) theme from Theme.ScanningSdk (see the remark below if it is not possible).
Define the following colors in your theme and change their color values as desired:
If it is not possible to inherit your theme directly from Theme.ScanningSdk, you can define a theme inherited from Theme.ScanningSdk and reference your main theme as shown below:
Using CropFragment with XML Views
This component can be used to display images, manually edit document boundaries, and rotate images using XML Views.
Perform the following:
Insert the fragment into your layout. For example:
Prepare a class that derives from CropHandler. The easiest way is to derive your ViewModel from CropHandler. Implement CropHandler methods and properties:
val picture: Flow
Provides a flow with pictures to show or null to show nothing. The orientation of the picture is ignored. See below.
val orientation: Flow
Provides a flow with the current orientation of the picture.
val cutout: Flow
Provides a flow with the current cutout or null to show nothing.
fun onPictureReady(pictureReady: Boolean)
This callback is called when the picture is shown on the screen.
fun onCutoutChanged(cutout: ScanCutout?)
This callback is called when the current cutout changes — whether the user moved a corner or the host supplied a new outline. You need to update the CropHandler.cutout flow.
Attach your CropHandler to the CropFragment by calling CropFragment.setHandler. For example:
// We suppose that viewModel derives CropHandler.
// We set the tag in XML.
(findFragmentByTag("com.pixelnetica.design.crop.CropFragment") as CropFragment).setHandler(viewModel)
Using CropPicture with Jetpack Compose
This component can be used to display images, manually edit document boundaries, and rotate images using Jetpack Compose.
The CropPicture composable takes the same data the CropHandler flows provide in the XML-View setup above — the picture, its orientation, and the current cutout — plus the two callbacks: picture-ready and cutout-changed. Supply state from your view model, update it in onCutoutChanged, and the component handles the editing gestures. See the CropPicture reference for the exact signature and parameter contracts.
Set up the LanguageManager
This section explains how to configure the initial language source (e.g., a server). This setup is required for language-related UI components (LangFragment/LanguagesSelector and ReadFragment/RecognizedText).
Prerequisites: The Document Scanning SDK (DSSDK) doesn’t provide a remote server. You need to manage the server yourself and place the language files provided by the DSSDK. More details on how to set up languages on own server.
Store the URL to your language server as urlToServer.
Before using a language list UI, you need to set up the LanguageManager. You can access the manager by calling:
val languageManager = LanguageManager.getInstance(context)
The language-source functions below are suspending functions — call them from a coroutine.
Next, you need to specify at least one language source:
Load the language list from a remote server urlToServer:
languageManager.requestServer(urlToServer, 1)
Load a language list from application assets. This is useful for the most popular languages, such as English. You can store the language file in the assets of your application:
languageManager.requestAssets(pathToAsset, 2)
The second parameter lets us control the sources is “source code”:
Delete all language archives with specified codes. The method can be used when you want to change the language server, and you need to delete archives that came from the old server:
languageManager.deleteArchives(code)
Keep archives only with specified codes and delete the rest:
languageManager.ensureArchives(codes)
Clean up removed languages to install the predefined (marked with -->) languages again:
languageManager.deleteRemoved()
When you have set up the Language Repository, you can use it with ScanDetector and ScanReader:
Use the detector path when you create an instance of ScanDetector:
launch {
// The path is null until the orientation detector file is installed
val detectorPath = LanguageManager
.getInstance(context)
.detectorPath
.first() ?: return@launch
// The detector holds native memory: use { } releases it when done
ScanDetector(detectorPath).use { orientationDetector ->
picture.detectOrientation(orientationDetector)
}
}
Use the LanguageStore (directory plus a set of selected languages) when you create an instance of ScanReader:
launch {
val languageStore = LanguageManager
.getInstance(context)
.languageStore
.first()
// The reader holds native memory too: use { } releases it after recognition
ScanReader(languageStore.directory, languageStore.languages).use { scanReader ->
picture.read(scanReader)
}
}
Using the LangFragment with XML Views
This component can be used to manage and edit language lists using XML Views.
Perform the following:
Insert the fragment in your layout. For example:
Set up the desired behavior:
Get access to the fragment:
// We have set the tag in XML.
languageFragment = findFragmentByTag("com.pixelnetica.design.lang.ui.LangFragment") as LangFragment
You can specify an “exclusive” mode: hide the language list when a user expands archives:
languageFragment.setExclusive(false)
You can show or hide the archive list from the code:
languageFragment.showArchives(true)
Using the LanguagesSelector with Jetpack Compose
This component can be used to manage and edit language lists using Jetpack Compose.
The LanguagesSelector composable renders the language list on its own — it reads the LanguageManager you configured above, so it needs no state from your code. Two optional flags adjust it: exclusiveMode hides the language list while the user has the archive list expanded (only the user can collapse or expand it — there is no API for that), and showInstalled starts with the installed-languages view. See the LanguagesSelector reference for the exact signature.
Using the ReadFragment with XML Views
This component enables users to edit recognition results using XML Views.
Insert the fragment into your layout. For example:
Prepare a class that derives from ReadHandler. The easiest way is to derive your ViewModel from ReadHandler. Implement ReadHandler methods and properties:
val picture: Flow
Provides a flow with pictures to show or null to show nothing.
val lookupRect: Flow
Provides the recognition item rectangle or null when recognition is done. You can get this value from com.pixelnetica.scanning.ScanReader.ProgressCallback.onProgress.
val lookupProgress: Flow
Provides the recognition state: -1 while the image is being analyzed, then 0 to 100 as words are recognized. The engine’s first pass is stretched to fill the range, so progress can appear to slow near the end — treat it as an indicator, not a timer. You can get this value from com.pixelnetica.scanning.ScanReader.ProgressCallback.onProgress.
val originalText: Flow
Provides the recognition result. This value is used to restore text after user editing.
val modifiedText: Flow
Provides text modified by the user.
fun onCancel()
Called when the user presses the X button during recognition.
fun onConfirmRestore(confirmRestore: ConfirmRestore)
Called when a user wants to restore the text back to the original. You can show a question box to the user.
fun onPictureReady(pictureReady: Boolean)
Called when the picture is shown on the display.
fun onModifiedTextChanged(modifiedText: ScanText)
Called when the user edits the recognized text. You need to store this text in your application and return it back through the modifiedText flow.
Attach your ReadHandler to the ReadFragment by calling ReadFragment.setHandler(). For example:
// We suppose that viewModel derives ReadHandler.
// We have set the tag in XML.
(findFragmentByTag("com.pixelnetica.design.read.ReadFragment") as ReadFragment).setHandler(viewModel)
Using the RecognizedText with Jetpack Compose
This component enables users to edit recognition results using Jetpack Compose.
The RecognizedText composable mirrors the ReadHandler surface described in the section above: you supply the picture, the recognition progress and lookup rectangle, and the original and modified texts, and you receive the same callbacks — cancellation, restore confirmation, and text edits — as composable parameters. It adds a slot for the message shown while there is no recognized text yet. See the RecognizedText reference for the exact signature and parameter contracts.
## Version history
https://www.pixelnetica.com/docs/document-scanner-sdk/android/dssdk-android-changelog.html
All notable changes to the Document Scanning SDK for Android are recorded here, so you can see what changed before updating.
3.2.0
Added
Runtime version reporting: ScanningSdkLibrary.versionInfo returns the release version, build number, and source revision of the SDK build an application embeds — for About screens, logging, and support requests.
Deterministic native-memory release: every SDK object backed by native memory (ScanPicture, ScanReader, ScanText, ScanCutout, ScanDetector, FrameObserver, ScanLayout, the ImageWriter family) now implements AutoCloseable. Call close() — or use Kotlin’s use { } / Java’s try-with-resources — to free a page’s memory the moment you are done with it. For the scan types closing is optional (the garbage-collector fallback remains, so existing code runs unchanged) and idempotent, and it keeps native memory flat in multi-page loops. The writers are the exception: an ImageWriter must be closed to finish its output file — and close() now also releases its native memory, including when finishing fails.
Changed
The SDK is now distributed from https://maven.pixelnetica.com/, which needs no account and no access token — add the repository and the dependencies, and that is the whole setup. Every file it serves is signed, with the public key at https://maven.pixelnetica.com/KEYS. The releases 3.0.0, 3.0.1, 3.1.1, 3.1.2 and 3.1.3 are available there alongside this one; 3.1.0, which only ever existed for support, and the -SNAPSHOT versions are not. See Add to a project.
GitHub Packages is deprecated but active. It will keep receiving new releases for at least two more versions, and the final version published there will be named in the release that cuts it. Nothing already published is ever removed, so a project pinned to any existing version keeps resolving from it for as long as GitHub serves it; there is no date and no deadline. New projects should use https://maven.pixelnetica.com/.
The demo application no longer requests the advertising-ID permission, and no longer collects an advertising identifier. It showed no ads and had no advertising code; the permission arrived from Firebase Analytics and is now removed explicitly. Push messaging is removed with it — the demo asked for notification permission and never sent a notification — so it also stops requesting POST_NOTIFICATIONS and the three permissions that came with the messaging and background-work libraries.
The demo’s analytics and crash reporting now sit behind small vendor-agnostic seams. AppAnalytics and AppDiagnostics define typed events and a reporting sink with no-op defaults, so the sample builds and behaves identically with no provider wired in — point them at your own analytics or crash reporter without touching the rest of the app. Crash reports carry the build identity that produced them, and warnings and errors the app logs become non-fatal reports rather than staying in the device log.
The demo application’s source code now includes a full-featured demo license key — processed results are no longer watermarked. The key is bound to the demo application’s ID; a free trial license bound to your own application ID is available on request.
The camera viewfinder’s frame colours now match the iOS SDK’s smart camera: yellow while a document is being framed, green when automatic capture is imminent — previously the meanings were inverted. No API changes.
The camera’s shutter button is now disabled until the camera is ready to capture, instead of looking available while a tap is silently discarded. It also carries the accessibility label Take photo, which doubles as the supported way for an automated UI test to address the control and read its readiness — see the camera guide.
The API reference is now generated from the SDK sources and covers the whole supported surface: every public type, function, and parameter carries a description, wrong statements are corrected, deprecated API is documented and marked, and key pages carry code samples compiled against the SDK. The documentation set is rewritten and expanded alongside — new guides cover integration paths, native memory, colour profiles, application size, privacy, and troubleshooting.
Visible versions follow one convention shared with the iOS SDK: plain MAJOR.MINOR.PATCH strings, with build numbers derived from source-control history and recorded in each build together with its source commit.
A failed OCR-language download shows a short localized message naming the cause — translated into all 14 supported locales — instead of raw technical text, with the technical details behind the failed row’s warning icon.
A ScanReader.ProgressCallback that throws during recognition now has a verified contract: recognition is cancelled, the original exception reaches the ScanPicture.read() caller unchanged, and the SDK remains fully usable.
The language-selector and recognized-text composables no longer repeat internal side-effect work on every recomposition.
Archive and ArchiveFailure in com.pixelnetica.design.lang.data gained a trailing failureKind parameter, with the new Archive.FailureKind enum. They are :design implementation detail rather than API to program against, but they are visible in the bytecode: Kotlin sources recompile unchanged, while binaries compiled against an older :design need a recompile.
The support library’s shared-cache and cursor helpers are now safe for concurrent use.
Hardened against malformed input across the engine: image loading, embedded document metadata, and license keys — including empty or corrupt key files — are rejected cleanly instead of risking crashes.
The crop surface can now be driven from a UI test: CropCutoutCornersKey publishes where the corner handles are currently drawn, in the coordinate space of the node carrying it, so a test can locate a real handle and drag it. Handle placement depends on the page, the outline and the current zoom, so previously there was nothing for a test to aim at and crop editing could only be checked by hand. The key is read-only and takes no part in gesture handling or drawing.
Fixed
A license key with a stray space or line break around it is no longer rejected. Reading a key from a file or a resource usually brings a trailing newline with it, and an otherwise valid key was refused because of a character you cannot see. Leading and trailing whitespace is now ignored. Whitespace inside a key is still an error, because it is not part of the key.
Saving pages to a PDF no longer crashes the application when the file cannot be created. If the destination folder is missing, storage is full, or the application has lost permission to write there, the write reports the failure as before — but closing the writer afterwards used to end the process, so an application that handled the error correctly still disappeared a moment later, with nothing saved and nothing shown to the user. Closing a writer whose output was never created is now safe, and so is closing one twice, so a failed export stays an ordinary error you can catch and report. Writing another page after a writer is closed is now refused with an exception instead of quietly starting a second document over the file just produced.
Rapid shutter presses no longer break the camera session. Previously two quick presses could leave the camera screen’s back button permanently dead, with the captured photos never handed to the application; the shot bookkeeping could also lose or double-count a capture when the screen was left and re-entered, or recreated by the system. A press while a capture is in flight is now ignored, every accepted capture is delivered exactly once, and a capture interrupted by a screen recreation is retaken automatically — the session always completes and the back button always returns the pages.
The shutter honours the between-shots countdown. After every capture the camera pauses briefly before the next one — the countdown shown in the viewfinder — but shutter presses used to bypass it and took a photo per press. During the countdown the shutter is now disabled and presses (including the volume key and tap-to-capture) do nothing; document detection stays quiet as well, even if it is toggled or the app returns to the foreground mid-countdown, and everything re-enables the moment the countdown ends.
Live camera frames are now assembled correctly before document detection sees them. Each frame plane is read through the geometry the camera reports for it, so rows carrying padding are no longer copied verbatim and colour information is emitted in the order the frame format defines — previously all three planes were concatenated as-is, which produced a malformed frame on every device tested.
The SDK no longer crashes on arm64 Android emulators, so development on Apple-Silicon Macs works end to end; real devices are verified unchanged image-for-image.
The demo application no longer stops working when a page’s image file goes missing. A page is stored as a database record plus image files on disk, and on a real device those can drift apart — a storage cleaner, a restore, or an interrupted save. When they did, the demo closed the moment it tried to show that page, and because the mismatch is permanent it closed again on every launch, leaving the application unusable until its data was cleared. Such a page now appears in the page list as a failed page explaining that its image is no longer on the device, and it can be deleted like any other. Opening it, cropping it or reading its text explains the same thing instead of waiting for an image that is never going to load, and exporting a document that would have to leave the page out says so rather than quietly producing a document without it. The housekeeping that removes unreferenced image files could also cause the mismatch itself, by deleting a page’s files moments after they were written; it now checks against the current store and no longer runs while a page is being saved. The sample’s page repository carries notes explaining the pattern, since an application that stores pages the same way faces the same drift.
The demo application keeps an edit made in the crop screen — a rotation as well as a reshaped outline — when you leave the screen. The save had been tied to the screen being redrawn one last time as the back stack unwound, which is not something the platform promises, so an edit could be dropped without any warning. It now runs as the screen goes away. The sample’s crop screen carries a note explaining the distinction, since the same pattern is easy to reproduce in an integrating application.
The demo application no longer closes when you share pages. The share dialog’s strip of page previews sized itself from those previews as they loaded, and they load in the background — so when the first one arrived at the moment the strip was being laid out, the strip was measured against a number of pages it did not yet have, and the application closed. It depended on timing rather than on which pages you picked, so any share could hit it. The strip now reserves one cell per selected page the moment it opens and fills each cell as its preview arrives, showing the document icon until then. The sample’s share dialog carries a note explaining why the number of cells is kept out of the loading state, since any list that sizes itself from data arriving in the background can fail the same way.
Text recognition handles full-resolution photos (12-50 MP) directly — no caller-side resize and no out-of-memory crash, with recognized text positions still reported in the original image’s coordinates — and a single malformed character no longer discards a page’s recognized text.
OCR language downloading no longer installs broken files: HTTP error pages, interrupted writes, and storage failures mark the download as failed and preserve both the installed languages and the previously fetched catalogue, devices without a usable Cronet provider fall back to the bundled network engine, and progress reporting copes with unusual server headers.
Editing recognized text no longer crashes when a deletion or keyboard edit overlaps a highlighted range.
FrameObserver.observe() validates frame buffers against the supplied geometry and format, accepts ARGB32 frames as documented, and a native failure during construction surfaces as a catchable exception instead of terminating the process.
Image and PDF export fail with catchable errors instead of crashing or producing blank pages: unwritable output paths, failed page encodes, multi-page file naming, and receipt-style paper sizes are all fixed, and an abandoned TIFF write no longer leaks its native file handle.
Document detection and refine are hardened: extreme-aspect and oversized images return a clean no-document result, the evaluation-watermark path no longer risks memory corruption, and invalid resize or profile arguments throw the documented exceptions.
The camera screen stays up on devices without a usable back camera (reporting “Camera is not available” and returning the standard cancelled result), and its console no longer crashes during rotation or drops the last hint of a sequence.
Reading a ScanText or ScanCutout from a malformed Parcel fails with a descriptive exception, and ScanCutout.describeContents() follows the Parcelable contract.
The support library’s flow and lifecycle helpers honour their documented contracts: runLatest cancels superseded work, a failed Singleton retries its creation on the next call while a failed SingletonAsync reports the failure on its state flow and rethrows the original cause, drag reordering accepts unmodifiable lists, and view-lifecycle waits survive view recreation.
3.1.3
Fixed
Rotating the device into a 180-degree orientation while the camera screen was open crashed the application with “Invalid rotation value 2”. The rotation-animation helper in the support library accepted only three of the four device orientations — ROTATION_180 was absent from its accepted set — and rejected the fourth as invalid. All four orientations are now accepted.
3.1.2
Changed
The camera module no longer uses the deprecated AndroidX LocalBroadcastManager; its internal screen-to-screen notifications now go through the support library instead.
Fixed
The camera, viewfinder, and OCR language screens now observe their state with lifecycle awareness, so a screen that is no longer visible stops receiving updates instead of continuing to be driven while stopped.
The cancel button on the OCR waiting panel no longer takes its color from the surrounding layout. It now carries its own publicly themable style attribute, px_progress_cancel, which applications can override alongside the other px_* attributes of the SDK theme.
3.1.1
Added
Full compatibility with modern Android devices featuring a 16KB memory page size.
Changed
Improved UI component support for Jetpack Compose; hybrid solutions are now deprecated.
Raised the minimum supported API level to 23.
Demo app and documentation updated for the latest DSSDK version.
General fixes and performance improvements.
3.0.1
Added
Optical Character Recognition (OCR) option with support for over 100 languages.
Runs entirely on-device, ensuring privacy and offline access by avoiding cloud processing.
Handles multi-language documents in one process, with support for right-to-left (RTL) languages.
Includes manual correction tools to improve accuracy.
Export results as layered PDFs or plain text (TXT) files.
Smart orientation detection that automatically adjusts the orientation of scanned documents based on their content.
PDF composing engine.
Implements cutting-edge image compression techniques, delivering highly efficient file size reduction.
Reduces file size by up to 90% for color and gray-scale images and 50% for black-and-white images, which helps save storage space, improve archiving, and enable faster sharing in low-bandwidth areas.
Offers flexible compression levels, from “Lossless” preservation to “Extreme” optimization for color and gray-scale images.
Supports the generation of layered PDF documents (aka. sandwiched PDF document), embedding searchable text above image layers to facilitate indexing, searching, and copying of text content.
Key UI components are now modular and ready to integrate, including:
Smart Camera module.
OCR Language Management Interface.
OCR results editor.
Document border correction editor.
Changed
EasyScan demo app:
Features multipage scanning, editing, storing, and sharing capabilities.
Includes a smart camera with multipage scanning and user guidance features.
Built with Kotlin for a modern and efficient design.
The API has been redesigned for better memory consumption, simplicity, and ease of integration, making it more accessible for developers working with diverse systems.
2.3.2
Update: Color profile improvements for better text documents processing.
2.3.1
New: Online DSSDK library distribution.##
No need to update library manually anymore, it will be updated automatically through project level Gradle script. Please check “How to add Pixelnetica™ DSSDK to Android project” documentation section for more details.
Update: License protection and key format.
2.3
Update: license protection and key format now supporting subscription based licensing.
Document corners support classes: corners regulation, average and stable detection.
2.2
New: license protection system.
Now we are using license keys as a protection method (as an addition to package ID bound). This also means that from now on no need to change demo library file with commercial one, but only to change license key on lib initialization.
2.1
Effective Document area (the area document occupies in the viewfinder) and trapezoid distortion control:
• automatic with ImageProcessing.detectDocumentCorners() additional parameters
• using DocumentCutout class
Custom corners validation moved to DocumentCutout specialized class
No more need to call ImageWriter.destroy()
2.0
New: document border detection algorithm with improved accuracy and speed.
Custom corners validation using ImageProcessing.validateDocumentCorners() method
New ability to write resulted document in various formats (Jpeg, Png, Tiff G4, PDF) with com.pixelnetica.imagesdk.ImageWriter subsystem.
No need to configure ProGuard anymore. From now on it configured internally.
Demo application update with new features implemented.
Some API changes.
Documentation update.
1.3.4
Added PDF support.
Documentation update.
Minor demo application update.
1.3.3
Added multipage TIFF support.
New advanced camera in demo application now supports Smart Shot and handshaking detection.
Demo application minor updates
Note: Demo application writes same page three times to Tiff file to demonstrate multipage possibilities.
1.3.2
Minor documentation update.
Demo application minor updates
Demo application also provided as ready-to-install APK file (cropDemo.apk).
1.3.1
This is minor update — fixed some discrepancies in documentation.
1.3
Sample application been updated.
Added camera with live document boundary detection.
SDK libs now provided in .aar format. Please check how to import them into your project in readme file.
New way of SDK initialization. Find details and sample code in readme_first file.
Eclipse version not supported anymore. If you’ll need sample application for Eclipse please request previous SDK demo version.
## Get started
https://www.pixelnetica.com/docs/document-scanner-sdk/android/get-started.html
Two things happen before any document is scanned: the SDK is initialized with your license key, and — if your application recognizes text — the OCR language files are put where the SDK can find them. This page covers both. The demo application shows a complete working setup.
Initialization
The SDK should be initialized only once. There’s no need to pass the Application object to every SDK call — ScanningSdkLibrary keeps it. Overriding Application.onCreate() is recommended.
class DemoApp : Application() {
override fun onCreate() {
super.onCreate()
// Initialize Image SDK
// Assume the license key is stored in assets
ScanningSdkLibrary.load(this)
}
}
Supply the License Key
load() accepts the key three ways. Pick one; whichever you choose, an absent or wrong key never crashes the SDK — see what happens without a valid key below.
Option 1 — a key file in your assets. The simplest route, and the one the demo application ships with. The SDK has a fixed lookup location — assets/pixelnetica/scanning/ — so place your key file there:
src/main/
assets/
pixelnetica/
scanning/
license.key
and initialize with the one-argument call from the sample above: ScanningSdkLibrary.load(this). The SDK tries these file names in order and uses the first one that exists: .key, , licence.key, license.key, licence, license, key. The call returns true when a non-empty key was read from the assets (a missing — or empty — file returns false); it does not tell you whether the key is valid — ScanningSdkLibrary.isLicenceValid() checks that.
Option 2 — a key string from your own source. Use this when the key does not live in assets — it arrives from your backend, sits in encrypted storage, or is injected as a build-time constant kept out of version control:
ScanningSdkLibrary.load(this, licenseKey)
Option 3 — a string resource. Keep the key in your string resources and pass the resource id:
ScanningSdkLibrary.load(this, R.string.scanning_license)
For most applications, option 1 is the right default: it matches how license keys are delivered, needs no code beyond the one-argument load(), and the demo application shows it working end to end. Option 2 exists for keys managed outside the build — including on your own server, which simplifies license updates (the application does not need an update) at the cost of making scanning depend on internet and server availability.
What happens without a valid key
The SDK does not crash when the key is missing or wrong — it starts in the unlicensed state and works normally, except that processed images carry a watermark. A malformed or empty key is rejected cleanly as invalid and produces the same unlicensed state, and so does a valid key bound to a different application ID — the demo application’s key, for example, licenses only the demo application. See the demo license key for how to obtain a free trial key bound to your own application ID.
Check the SDK Version at Runtime
ScanningSdkLibrary.versionInfo (from Java, ScanningSdkLibrary.getVersionInfo()) reports the exact SDK build your application embeds: the release version (name), the build number (build), and the source revision it was built from (gitHash). Use it on About screens, in logs, and in support requests, where knowing the exact build saves a round trip.
val version = ScanningSdkLibrary.versionInfo
Log.i("MyApp", "Scanning SDK $version") // prints e.g. "3.2.0 (1234) [a1b2c3d]"
Setup OCR Languages
DSSDK supports more than 100 languages for text recognition and extraction. To enable this functionality, you must set up the appropriate language files in your application.
Getting Language Files
Language files are available in a single archive from our server.
Download Language Archive, unzip it, and make its contents accessible to your application. Language files can either be placed on a remote server or bundled with your application as described below.
[!WARNING]
In the DSSDK demo application (EasyScan), language files are hosted on our server for development purposes. However, this location may change without prior notice.
For reliable and uninterrupted service, do not use the hosted files in production. Instead, store the language files on a remote private server or bundle them with your application.
Setting Up Languages in Your Application
There are two approaches to configure and use language files for text recognition (OCR):
Using the Pixelnetica UI Control to Manage Language Files
This setup process is detailed in the relevant documentation. This method is employed in the DSSDK demo application (EasyScan), allowing users to download any available language from the server. It is a practical solution for applications requiring support for multiple languages and regions.
However, if your application requires a restricted, predefined set of languages or a fully customized UI, you should consider the manual approach described below.
Managing Language Files Manually
Create a directory accessible by your application. This directory will be referred to as languagesDir.
Use the function ScanningSdkLibrary.unpackLanguageFile(languageFile, languagesDir) to unpack the desired language files into the languagesDir. Store the names of the unpacked files in a list, referred to as languageNames.
The languageFile can either be downloaded from a remote server or bundled with your application.
Unpack the file osd.pxl to enable the document orientation detector. This file is what ScanDetector uses to detect and correct a document’s orientation, which improves recognition accuracy and text readability. We recommend bundling osd.pxl with your application, so orientation detection works from the very first launch. It is also the largest single language file (about 11 MB — see application size), so if a minimal download matters more to you, take the demo application’s approach as the trade-off between size and user convenience: mark the file for automatic installation on your language server, and the language manager downloads it on first run — a smaller app, at the price of a first session that may start without orientation detection.
## Choosing an Integration Path
https://www.pixelnetica.com/docs/document-scanner-sdk/android/integration-paths.html
The SDK offers two kinds of building blocks: ready-made screens you launch, and a processing pipeline you call. Most integrations use one of three combinations. This page describes what each path gives you, what it costs, and when to move from one to another — worth deciding before you write code, because the path determines which modules you add and which guides apply to you.
Path 1: Ready-Made Screens
Add the camera and design modules and assemble scanning from finished parts: the Smart Camera activity captures pages with live document detection and automatic shot, the crop editor lets users adjust the detected outline, the language manager handles OCR language downloads, and the recognized-text editor lets users fix recognition results. Your code launches screens and receives results; the core pipeline still does the processing between them.
Choose this when you want a working scanner in days, your UI requirements fit what the screens provide, and a consistent, tested scanning flow matters more than a custom look. The screens follow your application’s theme (see theming), but their layout and flow are fixed.
Path 2: The Core Pipeline with Your Own UI
Add only the scanning module and build every screen yourself. The pipeline takes any image URI — from your camera code, the system photo picker, or a file — and gives you document detection, cropping, colour profiles, text recognition, and export to images or searchable PDF. You decide what the user sees at every step.
Choose this when your product has its own design language, you need a flow the ready-made screens do not offer (batch capture with review, say, or scanning inside a chat), or you are adding scanning to an application whose UI framework the components do not match. Expect to build and test the camera experience yourself — live detection feedback is the part users notice most.
Path 3: Mix the Two
The paths combine freely because everything exchanges the same types. A common mix: launch the Smart Camera for capture — it is the hardest screen to build well — then run your own processing and review UI on the URIs it returns. Or build your own capture and hand pages to the ready-made crop editor.
Choose this when one screen’s polish matters and the rest must be yours.
Switching Later
Starting on the ready-made path does not lock you in. The screens sit on the same public pipeline, so replacing one screen with your own is an incremental change, not a rewrite. The usual direction is path 1 first to ship, then path 3 as the product’s own design takes over — replacing screens one at a time while capture and processing keep working.
Where to Go Next
Path 1: Add the modules, then the Smart Camera and Design library articles.
Path 2: Add the scanning module, then the Workflow guide.
Either way: Get started covers initialization and OCR languages, and the API reference specifies every type these guides mention.
## Overview
https://www.pixelnetica.com/docs/document-scanner-sdk/android/introduction.html
Introduction
Pixelnetica’s Document Scanning SDK (DSSDK) adds document scanning to Android applications: it finds a document in a photo, crops and straightens it, cleans up the colours, recognizes the text on it, and saves the result as an image or a searchable PDF.
The SDK is built for photos taken with a phone camera. Its processing pipeline corrects the problems such photos actually have — skewed perspective, uneven lighting, shadows, and the wrong orientation — and its ready-to-use UI components (a smart camera screen, a crop editor, an OCR text editor, and a language manager) shorten the path from an empty project to a working scanner.
Text recognition and extraction (OCR) runs on the device in more than 100 languages, so applications that capture data from documents do not need a network connection or a cloud service.
System Requirements
Pixelnetica DSSDK is compatible with Android devices that meet the following specifications:
Android Version: Google Android API Level 23 or higher.
For detailed information on API level support for different Android versions, refer to the Android Developers site.
Supported Architectures (ABI): armeabi-v7a, arm64-v8a, x86, and x86_64.
Learn more about Android ABI.
Offline Operation: No internet connection is required.
All processing runs locally on the user’s device, and the SDK transmits nothing to any server. The privacy and data handling article states the complete network behaviour — and how to verify it yourself.
What’s New in DSSDK Version 3.2.0
Deterministic memory release. Every SDK object backed by native memory now implements AutoCloseable: call close() — or use Kotlin’s use { } — to free a page’s memory the moment you are done with it, instead of waiting for the garbage collector. Existing code keeps working unchanged.
Runtime version reporting. ScanningSdkLibrary.versionInfo returns the release version, build number, and source revision of the SDK build your application embeds — useful for About screens and support requests.
Full-resolution text recognition. OCR on a full-resolution photo no longer needs a caller-side resize; the SDK manages memory for the recognition step internally.
Camera frame colours aligned with iOS. The viewfinder frame is now yellow while a document is being framed and green when automatic capture is imminent, matching the iOS SDK’s smart camera.
Android emulator support. The SDK no longer crashes on arm64 Android emulators, so development on Apple-Silicon Macs works end to end.
Stability fixes across the SDK — image export, OCR language downloads, camera edge cases, and hardening against malformed input.
A full-featured demo key. The demo application’s source code now includes a demo license key that works without watermarking, bound to the demo application’s ID — matching the iOS SDK’s distribution.
For the complete list, see the Versions history.
The Demo License Key
The demo application’s source code includes a full-featured demo license key: the SDK runs without watermarks, and every feature behaves exactly as it does under a commercial license. The key carries one restriction — it is bound to the demo application’s ID. In any other application it does not license the SDK, which then runs in the unlicensed state and watermarks its output.
To evaluate the SDK in your own application without watermarks, a Free Trial license bound to your own application ID is available upon request →.
## Migration Notes
https://www.pixelnetica.com/docs/document-scanner-sdk/android/migration-notes.html
Whatever version you are coming from, this page tells you what an update means for your code. Sections run newest first: find the version you are updating from and read every section above it. Most updates need no code changes — and each section says so when that is the case. (For the full list of what changed in each release, see the [version history](./dssdk-android-changelog.html).)
## Updating to 3.2.0
Version 3.2.0 keeps the 3.x API — existing code compiles and runs unchanged. Three things are worth knowing when you update:
- Every SDK object backed by native memory now implements `AutoCloseable`. Closing is optional (the garbage-collector fallback remains), but loops over many pages stay flat on memory when each page is closed as it finishes — see the [native memory guide](./native-memory.html).
- The Smart Camera's frame colours changed meaning: yellow now shows while a document is being framed and green when automatic capture is imminent — previously the two were inverted. If your user guides or help screens describe the colours, update them; the states are listed in the [Smart Camera article](./camera.html#what-the-user-sees).
- `ScanningSdkLibrary.versionInfo` is new: it reports the SDK version, build number, and source revision at runtime, for About screens and support requests.
## Migrating from Version 2.x
Version 3 replaced the version 2.x API: the `com.pixelnetica.imagesdk` package (the Document Imaging SDK) is gone, and its classes have direct successors in `com.pixelnetica.scanning`. The table below maps each 2.x name to its replacement in the current API — after the switch, the guides and the sections above apply to you like to any 3.x integrator.
For reference, see how it is implemented in the [DSSDK Sample application](https://github.com/Pixelnetica/android-pdf-ocr-document-scanner).
| DSSDK Version 2.x | DSSDK Version 3 |
| --- | --- |
| `MetaImage` | `ScanPicture` |
| `ImageProcessing.detectDocumentCorners` | `ScanPicture.detectCutout` |
| `Corners` | `ScanCutout` |
| `DocumentCutout` | `ScanCutout` |
| `ImageProcessing.correctDocument` | `ScanPicture.refine()` with a list of `RefineFeature.*` |
| `ImageProcessing.imageWithoutRotation` | `ScanPicture.refine()` with a list of `RefineFeature.*` |
| `ImageProcessing.imageBWBinarization` | `ScanPicture.refine()` with `RefineFeature.Profile.Type.Bitonal` |
| `ImageProcessing.imageGrayBinarization` | `ScanPicture.refine()` with `RefineFeature.Profile.Type.Monochrome` |
| `ImageProcessing.imageColorBinarization` | `ScanPicture.refine()` with `RefineFeature.Profile.Type.Colored` |
| `ImageWriter(type)` | `ImageWriterPdf`, `ImageWriterTiff`, or `ImageWriterPng` |
## Native Memory and Object Lifetime
https://www.pixelnetica.com/docs/document-scanner-sdk/android/native-memory.html
The SDK's engine keeps images and recognition state in native memory, outside the Java heap — which is why a [`ScanPicture`](/docs/document-scanner-sdk/android/api/scanning/com.pixelnetica.scanning/-scan-picture/index.html) holding a 12-megapixel page does not strain your heap, and also why the garbage collector alone is a poor manager for it: the collector sees a small Java object and feels no pressure, while megabytes sit allocated behind it. Since version 3.2.0 you can release that memory deterministically. This page is the contract.
## Which Objects Hold Native Memory
`ScanPicture`, `ScanReader`, `ScanText`, `ScanCutout`, `ScanDetector`, `FrameObserver`, `ScanLayout`, and the `ImageWriter` family (`ImageWriterPdf`, `ImageWriterTiff`, `ImageWriterPng`) are all backed by native memory, and every one of them implements `AutoCloseable`. As a rule of thumb: if the [API reference](/docs/document-scanner-sdk/android/api/index.html) shows a type inheriting from [`ScanningSdkLibrary.Instance`](/docs/document-scanner-sdk/android/api/scanning/com.pixelnetica.scanning/-scanning-sdk-library/-instance/index.html), it holds a native handle.
## The Contract
**Closing is optional for the scan types.** An unclosed instance is still released by the garbage collector eventually, so existing code keeps working unchanged. The one exception is the writers: an `ImageWriter` must be closed to finish rendering its output file.
**`close()` is idempotent.** A second call is a harmless no-op.
**A closed object refuses native work.** After `close()`, an otherwise-valid operation that needs the instance's native state — whether the object is the receiver or an argument — throws a catchable `ScanningSdkException`. Plain Java-side access stays safe.
**You own what the SDK returns.** Any instance the SDK hands you may be closed by you.
## The Patterns
Scope an object to a block with Kotlin's `use { }` — it closes at the end of the block, on the happy path and on exceptions alike:
```kotlin
ScanPicture(context, uri).use { page ->
page.detectCutout().use { cutout ->
page.refine(
listOf(
RefineFeature.Rectify.WithCutout(cutout),
RefineFeature.Profile(RefineFeature.Profile.Type.Bitonal),
),
)
}
}
```
Note that the detected cutout is a native-handle object in its own right — anything the SDK returns is yours to close, so it gets its own `use { }`. From Java, the same contract is try-with-resources:
```java
try (ScanPicture page = new ScanPicture(context, uri);
ScanCutout cutout = page.detectCutout()) {
// process the page
}
```
Where a block does not fit — an object living in a view model, say — call `close()` at the natural end of its life, such as `onCleared()`.
## Why Loops Are the Point
One page's native memory rarely matters. Loops are where the contract earns its place: a batch that scans, recognizes, or exports many pages accumulates every page's native memory until the collector runs — unless each page is released as it finishes:
```kotlin
pageUris.forEach { uri ->
ScanPicture(context, uri).use { page ->
// detect, refine, export this page
}
}
```
With `use { }` per page, the batch's native footprint stays flat at roughly one page regardless of length. The demo application processes its batches exactly this way.
## Threads
Two rules cover the SDK's native handles:
1. **Confine an instance to one thread** unless its own reference page says otherwise. Most types hold native state with no locking of their own, so concurrent use is undefined. `FrameObserver` is the documented exception — see [its reference page](/docs/document-scanner-sdk/android/api/scanning/com.pixelnetica.scanning/-frame-observer/index.html) for what it supports.
2. **Never close an instance while another thread is inside a call using it.** This is the same discipline as `android.graphics.Bitmap.recycle()`: finish the work, then close.
## One Trap Worth Knowing
An SDK object records the license state in force when it is *constructed*, permanently. Construct one before `ScanningSdkLibrary.load()` and it stays bound to the unlicensed state — its output watermarked — no matter what loads afterwards, and nothing throws to warn you. Initialize the SDK in `Application.onCreate()` (see [Get started](./get-started.html#initialization)) and the trap never fires.
## Privacy and Data Handling
https://www.pixelnetica.com/docs/document-scanner-sdk/android/privacy.html
Documents are sensitive by nature — IDs, contracts, medical papers — so an SDK that touches them owes its integrators exact answers: where processing happens, what goes over the network, and where files end up. This page gives those answers in the form a privacy or procurement review needs.
## Processing Happens on the Device
Every processing step — document detection, cropping, colour processing, text recognition, PDF composition — runs in the SDK's engine on the user's device. No image, no recognized text, and no document metadata is ever transmitted anywhere by the SDK. There is no cloud component, no telemetry, and no analytics: the `scanning`, `camera`, and `support` libraries contain no networking code at all.
License validation is also local: the key is checked on the device, with no activation call.
## The Complete Network Behaviour
Exactly one SDK feature can use the network — downloading OCR language files, in the `design` library's [language manager](/docs/document-scanner-sdk/android/api/design/com.pixelnetica.design.lang/-language-manager/index.html) — and it talks only to servers your application chooses:
- `LanguageManager.requestServer(url, …)` downloads language lists and language files from the URL **you** supply. The SDK ships no server address of its own; production applications host the files themselves (see [Get started](./get-started.html#setup-ocr-languages)).
- `LanguageManager.requestAssets(…)` reads languages bundled inside your application, with no network at all.
The downloads carry no document data in either direction — they fetch recognition data files, nothing more. Skip the language manager (bundle your languages, or skip OCR) and the SDK performs no network activity whatsoever. That claim is verifiable from outside: run your application behind a proxy and observe the traffic.
## Where Files Are Written
The SDK writes only where your application points it, in three places:
- **Captured pages** from the [Smart Camera](./camera.html) go to the `outputDir` you pass in `CameraParams` — or, left unset, to the activity's own location in your application's private storage. The URIs come back to your code, and the files are yours to keep or delete.
- **Language files** go to the directory your application designates (directly, or through the language manager's storage in your application's private files).
- **Exported results** — images, PDFs, text — go to the paths your code passes the writers.
Nothing is written to shared or public storage unless your application chooses such a path, and the SDK never deletes or uploads user documents on its own. Files in your application's private storage are removed by Android with the app's uninstall, like the rest of your app's data.
## What This Means for Your Disclosures
For a data-safety form or privacy policy, the SDK itself contributes no data collection, no data sharing, and no third-party endpoints. The one network flow — language downloads — targets infrastructure you control and transfers no user content, so its disclosure (if any) is about your server, not about a third party. Your application's own handling of the scanned documents remains, as always, yours to declare.
## Troubleshooting
https://www.pixelnetica.com/docs/document-scanner-sdk/android/troubleshooting.html
The problems integrators actually hit, with their causes and fixes — from the first Gradle sync to release builds. Each section starts from the symptom you see. If yours is not here, the [contacting support](#contacting-support) section says what to include so one message is enough.
## Gradle Cannot Resolve the SDK
**Symptoms:** `Could not resolve com.pixelnetica.sdk:scanning`, `401 Unauthorized`, or `Received status code 401 from server` during sync.
> [!NOTE]
> **A `401` can only happen on the GitHub Packages route.** `https://maven.pixelnetica.com/` is anonymous and sends no credentials, so it has nothing to reject. If you are seeing a `401`, your build is still resolving from GitHub Packages — which remains supported, and the rest of this section applies.
**Likely cause:** GitHub Packages requires authentication for every download, even though the packages themselves are not secret. The repository declaration is missing, the token is absent or expired, the token lacks the `read:packages` permission — or it is one of GitHub's newer *fine-grained* tokens, which GitHub Packages does not accept.
**Fix, if you want to stay on GitHub Packages:** work through [the GitHub Packages route](./add-to-android-project.html#5-the-github-packages-route-still-supported-and-sunsetting). The `maven` block must point at `https://maven.pkg.github.com/Pixelnetica/artifacts`, and the credentials must be a GitHub user name plus a **classic** token with `read:packages`. Keep credentials in `local.properties` (as the demo application does), not in the build script. A `401` after it once worked usually means the token expired.
**Fix, if you would rather not deal with tokens at all:** switch the repository declaration to `https://maven.pixelnetica.com/` and delete the `credentials` block — see [Add to a project](./add-to-android-project.html#1-recommended-specify-the-repository-in-the-project). Every 3.x release except `3.1.0` and the `-SNAPSHOT` versions resolves from there; those two stay on GitHub Packages, which keeps serving everything it already has.
**A resolution failure that is *not* a `401`** — no status code, or a `404` — usually means the version you asked for is one of the exceptions above. Check [which versions are where](./add-to-android-project.html#3-which-versions-are-where).
## Manifest Merger Fails on minSdk
**Symptoms:** `uses-sdk:minSdkVersion XX cannot be smaller than version 23 declared in library [com.pixelnetica.sdk:scanning]`.
**Likely cause:** Your application's `minSdk` is below the SDK's floor of API level 23 (Android 6.0).
**Fix:** Raise `minSdk` to 23 or higher. There is no override that keeps a lower floor working — the SDK's native layer needs API 23.
## The App Crashes with UnsatisfiedLinkError
**Symptoms:** `java.lang.UnsatisfiedLinkError: ... couldn't find "libscanning.so"` at start-up or on the first SDK call.
**Likely cause:** The APK that reached the device does not contain the engine for its architecture — usually an `abiFilters` or `splits` configuration that excludes the device's ABI, or a universal APK built with every ABI stripped.
**Fix:** The SDK ships `armeabi-v7a`, `arm64-v8a`, `x86`, and `x86_64`. Make sure your packaging keeps the ABIs your users run — see [Application size and packaging](./app-size.html) for the recommended App Bundle and splits setup. Check what actually landed in the artifact with Android Studio's APK Analyzer (the `lib/` folder).
## The First Processed Image Crashes an Emulator
**Symptoms:** On an arm64 emulator (the default on Apple-Silicon Macs), the app dies with an illegal-instruction error (`SIGILL`) the first time an image is processed. Real devices are unaffected.
**Likely cause:** SDK versions before 3.2.0 trusted a processor capability the emulator falsely advertises.
**Fix:** Update to SDK 3.2.0 or later, where emulators work end to end. There is no workaround for older versions on arm64 emulators — test those on a physical device.
## Every Output Image Carries a Watermark
**Symptoms:** Scanning works, but processed pages have a watermark across them.
**Likely cause:** The SDK is running unlicensed: the license key is missing, malformed, not found where `load()` expects it, or bound to a different application ID — the demo application's key, for example, licenses only the demo application. A subtler variant: an SDK object created *before* `ScanningSdkLibrary.load()` stays bound to the unlicensed state for its whole life, even after a valid key loads — nothing throws when this happens.
**Fix:** Check the key setup against [Get started](./get-started.html#initialization), and make sure `load()` runs in `Application.onCreate()` before anything constructs an SDK object. For evaluating in your own application without watermarks, [request a free trial key](/products/document-scanning-sdk/sdk-support.html) bound to your application ID.
## The Camera Screen Says "Camera is not available"
**Symptoms:** The Smart Camera opens but shows "Camera is not available" in its console and captures nothing.
**Likely cause:** The device (or emulator configuration) has no usable back camera, or camera initialization failed.
**Fix:** On emulators, set the AVD's back camera to a webcam or the emulated scene. On devices, this state is the screen's controlled failure mode: it ignores capture input and returns the standard cancelled result when the user leaves — your result callback receives an empty list, and no special handling is needed. See [Smart Camera](./camera.html#permissions-and-hardware).
## OCR Language Downloads Fail
**Symptoms:** Languages in the language manager show "download failed", "server error", or "downloads unavailable on this device".
**Likely cause:** The language server URL your application configured is unreachable or returns an error page; the device is out of storage; or, on devices without a usable network stack provider, the downloader's fallback also failed.
**Fix:** The row's warning icon opens the technical error details. Check that the server URL passed to `requestServer()` serves the language files (see [Get started](./get-started.html#setup-ocr-languages) — production apps must host the files themselves), and that storage is not full. A failed download never corrupts the installed languages: the previous catalogue and files stay usable.
## Contacting Support
If a problem survives this page, [write to support](/products/document-scanning-sdk/sdk-support.html) with:
1. The exact SDK build — the string from `ScanningSdkLibrary.versionInfo` (see [Get started](./get-started.html#check-the-sdk-version-at-runtime)).
2. Device model and Android version (or emulator image), and whether a physical device reproduces it.
3. Steps that reproduce the problem, and whether it happens every time.
4. The relevant `adb logcat` output around the failure.
That set usually makes one round trip enough.
## Workflow Guide
https://www.pixelnetica.com/docs/document-scanner-sdk/android/workflow-guide.html
This guide walks through the standard workflow for processing a document photo with the Pixelnetica Document Scanning SDK (DSSDK): open an image, detect the document in it, correct its orientation, refine it, recognize its text, and save the result as a searchable PDF. The pipeline needs no camera of its own — the input is any image URI, whether it came from the [Smart Camera](./camera.html), the system photo picker, or a file. Each step is a short snippet you can adapt; the [sample application source code](https://github.com/Pixelnetica/android-pdf-ocr-document-scanner) shows the same pipeline in a complete application.
A document photo
camera · picker · file
→
↓
1 · Open and detect
ScanPicture · detectCutout()
→
↓
2 · Correct orientation
detectOrientation(ScanDetector)
→
↓
3 · Refine the page
refine(RefineFeature…)
↓
↓
→
4 · Recognize text
read(ScanReader)
→
↓
5 · Export
ImageWriterPdf · ImageWriterTiff · ImageWriterPng
→
↓
Searchable PDF
or PNG · TIFF images
Every stage links to its step below. Steps 2 and 4 are optional — skip orientation detection or recognition if your application does not need them — and the [Release the Page](#release-the-page) section closes the loop on the native memory the pipeline holds.
## Step 1: Open an Image and Detect Document Bounds
**Prerequisites**: An `imageUri` obtained from the Image Picker, Gallery, or other local storage sources.
> [!WARNING]
> Do not use an internet URL!
```kotlin
// Create and configure ScanPicture
val picture = ScanPicture(context, imageUri)
picture.shadows = true // Even out shadows and uneven lighting
// Detect document corners
val cutout = picture.detectCutout()
if (!cutout.isDefined) {
// In cases where document borders cannot be determined,
// consider displaying a warning to the user.
}
```
A [`ScanPicture`](/docs/document-scanner-sdk/android/api/scanning/com.pixelnetica.scanning/-scan-picture/index.html) holds its image in native memory, outside the Java heap — and so does the cutout it just returned. You can release that memory the moment you are done by calling `close()`; because this guide keeps both objects across several steps, it closes them together in the [last step](#release-the-page). The other native-handle objects the guide creates, the detector and the reader, live inside a single step each, so they are scoped with `use { }` and released as soon as their step completes. The [native memory guide](./native-memory.html) explains the contract in full.
## Step 2: Automatically Detect Picture Orientation
**Prerequisites**: A language directory path (`languagesDir`) as described in the [Setup OCR Languages](./get-started.html#setup-ocr-languages) section.
```kotlin
// The detector holds native memory: use { } releases it
// as soon as orientation detection is done
ScanDetector(languagesDir).use { orientationDetector ->
picture.detectOrientation(orientationDetector)
}
```
## Step 3: Process the Image
Execute the `refine` pipeline to crop the page to its detected outline, apply the desired colour profile, and rotate it upright for display. Pass a list holding at most one [`RefineFeature`](/docs/document-scanner-sdk/android/api/scanning/com.pixelnetica.scanning/-refine-feature/index.html) of each kind; kinds you leave out stay unchanged. The [colour profiles guide](./color-profiles.html) shows what each profile is for and how the results look.
```kotlin
picture.refine(
listOf(
RefineFeature.Rectify.WithCutout(cutout), // Crop and straighten to the detected outline
RefineFeature.Profile(RefineFeature.Profile.Type.Bitonal), // Black-and-white (bitonal) processing
RefineFeature.Display.Normal, // Rotate the page upright for display
)
)
// Obtain the processed image
val bitmap: Bitmap = picture.createBitmap()
```
When no document outline is available, pass `RefineFeature.Rectify.SkipCutout` to leave the page uncropped, or `RefineFeature.Rectify.AutoDetect` to let the SDK find the corners without asking the user.
## Step 4: Recognize Text in the Image
**Prerequisites**: A language directory path (`languagesDir`) and a list of languages (`languageNames`), as described in the [Setup OCR Languages](./get-started.html#setting-up-languages-in-your-application) section.
```kotlin
// The reader holds native memory too: use { } releases it after recognition
ScanReader(languagesDir, languageNames).use { scanReader ->
picture.read(scanReader)
}
// Retrieve the recognized text
val text: String = picture.scanText.toString()
```
Pass the picture at full resolution — no caller-side resize is needed. The SDK manages memory for the recognition step internally, and recognized text positions are reported in the original image's coordinates. If a device does run out of memory, `read()` fails with a catchable `ScanningSdkException` instead of crashing, and the reader stays usable for the next page.
## Step 5: Save Results as a Searchable PDF
**Prerequisites**:
- `picture` from the [Process the Image](#step-3-process-the-image) section.
- TrueType font files supporting the necessary languages.
> [!IMPORTANT]
> To create and save a layered (sandwiched) PDF file with embedded searchable text above image layers, a set of **TrueType** font files (`.ttf`) must be stored in an accessible directory.
> DSSDK does not provide fonts. The demo application includes several royalty-free [Google fonts](https://fonts.google.com/noto). Additionally, any other fonts that support the necessary languages can be used.
1. Define a list, e.g., `fontList`, containing the font files.
2. Set the desired image compression using predefined values:
```kotlin
val imageCompression = ImageWriterPdf.ImageCompression.Medium
```
Alternatively, specify the image compression ratio manually:
```kotlin
val imageCompression = ImageWriterPdf.ImageCompression(60.0F)
```
DSSDK provides five compression presets for images in PDFs: `Lossless`, `Low`, `Medium`, `High`, and `Extreme`.
**Note**: Compression levels apply only to color and grayscale images. Black-and-white (bitonal) images always use highly efficient lossless compression.
```kotlin
// Obtain an ImageWriterPdf instance
ImageWriterPdf(fileName).use { writer ->
writer.setFontFiles(fontList)
writer.setImageCompression(imageCompression)
writer.write(picture)
}
```
## Release the Page
When the page's work is finished, release the native memory of both objects the guide kept — the cutout from step 1 and the page itself:
```kotlin
cutout.close()
picture.close()
```
Closing is optional — if you skip it, the garbage collector releases the memory eventually, and existing code keeps working unchanged. It matters in loops: an application that scans or recognizes many pages in a row keeps its native memory flat by closing each page as it finishes, instead of accumulating pages until the collector runs. `close()` is safe to call twice, and an operation that needs a closed page's native state throws a catchable `ScanningSdkException`. The [native memory guide](./native-memory.html) covers the details.
## Performance Notes
Numbers measured with release builds on a mid-range reference phone, so you can set expectations before profiling your own integration:
- Document detection takes about 43 ms.
- Refining a page costs 161–220 ms per colour profile.
- Recognizing a full-resolution page takes about 55 seconds and peaks at about 57 MB of native memory.
- PDF export is the memory-hungriest step, peaking at about 113 MB.
Debug builds are several times slower than these figures — profile with a release build before drawing conclusions.
## Camera capture
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/camera-capture.html
Capturing a document means showing a camera preview, detecting the page’s edges in real time, and taking the shot when the framing is good. DSSDK offers this as a ready-to-use screen, or as an engine you drive from your own camera UI.
Ready-to-use: the camera screen
The fastest path is PxUiCameraScreen (presented via the SwiftUI PxUiCameraScreenView). It runs the live preview, edge-detection overlay, optional auto-shot, and torch control for you, and returns the captured page plus its detected corners.
import DocScanningSDK_UI
PxUiCameraScreenView(configuration: PxUiCameraScreenConfiguration()) { result in
switch result {
case .success(let image, let cutout):
// `image` = the captured page; `cutout` = the detected document quad.
break
case .cancelled, .failure:
break
@unknown default:
break
}
}
Configure behaviour (edge detection, auto-shot, torch) through PxUiCameraScreenConfiguration, and re-localise the on-screen guidance through the strings table. See Quick Start for the full presentation.
Engine: drive detection yourself
If you build your own camera UI, feed each preview frame to a PxFrameObserver and use what it reports to draw your overlay:
observe(_:) (or observe(_:roi:)) takes a frame and returns status flags describing the current detection (for example whether a stable document quad is defined).
checkedFullness and checkedDistortion tell you whether the document fills enough of the frame and how skewed it is — the signals behind “move closer” / “hold steady” guidance.
When the quad is stable, capture a full-resolution still and pass it on to cropping.
The full PxFrameObserver surface (flags, averaging, region of interest) is in the API reference.
Tips
Live capture needs a real device; add NSCameraUsageDescription to Info.plist.
Detection runs on a downscaled working image, so a high-resolution preview does not improve detection — capture the full-resolution still only when you take the shot.
See also
Edge detection & cropping — refine the corners after capture.
Process an existing image — the no-camera path (and how to test on the Simulator).
## Version history
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/changelog.html
All notable changes to the Document Scanning SDK for iOS are recorded here, so you can see what changed before updating.
3.0.3
Fixed
The camera screen now follows the host app’s interface orientation. In apps locked to a single orientation (for example, portrait-only), physically rotating the device no longer rotates and stretches the camera preview against the on-screen controls — the viewfinder stays upright and correctly proportioned, and captured images always match what the viewfinder showed. Apps that support rotation behave exactly as before.
3.0.2
Fixed
The camera no longer reports a spurious “camera-init-failed” error right after a successful automatic capture. With AutoShot on and a document detected the moment the camera opened, a successful capture could be immediately followed by an unexpected failure callback for the same shot. The camera screen now delivers exactly one result per capture — a success, a failure, or a cancellation.
3.0.1
Fixed
The camera shutter no longer stalls on iPads when the live document detector is on. On some iPad models the still capture could hang for a long time after you tapped the shutter, because continuous document detection kept the camera’s processing queue busy and starved the capture. Detection now pauses while a photo is being taken, so the shutter responds promptly.
The camera screen’s torch button now reflects the real state of the torch. Previously the torch icon could show as on while the light stayed off (for example, when the system briefly refused the torch), and it did not update when iOS turned the torch off on its own. The icon now follows the actual torch state and self-corrects after a system-initiated shutoff, so the control and the light always agree.
Changed
On large iPads the live camera preview now streams at a moderate resolution instead of the sensor’s full video resolution, and document detection runs on a downscaled frame. This lowers CPU use, heat, and battery drain while scanning. The resolution of the captured photo is unchanged.
The camera screen’s torch button now appears only on devices that have a torch. On hardware without a rear torch (for example, some iPads) the button is hidden instead of being shown as a control that does nothing.
The bundled EasyScanner sample app is now localized into German, Spanish, French, Italian, Simplified Chinese, and Japanese — including the ready-made SDK-UI screens (camera, page editor, language picker), which it localizes from its own app bundle to show how you can localize those screens in your app. The frameworks themselves continue to ship their strings in English.
3.0.0
A full rewrite of the Document Scanning SDK for iOS. If you are upgrading from 2.x, read the migration guide first — the API surface has changed.
Added
Swift Package Manager distribution. Add https://github.com/Pixelnetica/DocScanningSDK-iOS as a package dependency; the SDK ships as two binary frameworks: DocScanningSDK (core scanning, image processing, and document export) and DocScanningSDK-UI (ready-made screens).
On-device OCR with support for over 100 languages. Recognition runs entirely on the device — no cloud processing — and handles multi-language documents in a single pass, including right-to-left (RTL) scripts. Recognised text exports as plain text or as a searchable PDF.
Offline text-orientation detection (OSD). Automatically corrects page orientation from document content, and works on a fresh install with no network download.
PDF composing engine with advanced image compression — up to 90% smaller files for colour and greyscale pages and 50% for black-and-white, with selectable compression levels from “Lossless” to “Extreme”. It produces layered (“sandwiched”) PDFs, embedding a searchable text layer above the page image for indexing, search, and copy.
Batteries-included UI screens in DocScanningSDK-UI, each adoptable in a single line: a smart document camera with live border detection, automatic capture, and interactive quality guidance (trapezoid-distortion and effective-document-area indicators); an OCR results editor with manual correction; an OCR language picker with search; and a page/border editor.
A bundled, browsable API reference and a refreshed documentation set, including a 2.x → 3.x migration guide.
Third-party attribution notices bundled with the framework.
An Apple privacy manifest (PrivacyInfo.xcprivacy) in each framework, declaring on-device processing with no tracking and no data collection. This lets your app’s App Store submission account for the SDK automatically.
Changed
Rebuilt on a new Objective-C API surface. Existing 2.x integrations need code changes; see the migration guide.
The minimum supported iOS version is now 16.3.
2.5.2
Added compatibility with iOS 15 and Xcode 13.
Fixed Camera UI on iOS 15.
Minor bug fixes and demo improvements.
2.5.1
Added compatibility with Xcode 12 and above.
Minor bug fixes and demo improvements.
2.4.1
Fixed: Pure black or white images processing.
2.4
Added compatibility with Apple iOS 13.
2.3.4
Added additional license key initialization method - from license.txt file.
Application Bundle ID changed to conform Apple App Store requirements.
Demo application published at App Store as EasyScan: PDF Doc Scanner.
Demo application source code available on GitHub.
Added license debug info.
Demo application UI updates.
2.3.3
Added build-phase script to safely and conveniently strip unnecessary architecture slices from framework.
Demo application UI compatibility with iPhoneX series improved.
Minor demo application UI updates and fixes.
2.3.2
Added demo application camera compatibility with iPhoneX series models.
Fixed problem with invalid document corners error in case of “stretched parallelogram” document borders shape.
Fixed several memory leaks issues.
Changed PxMetaImage::image property from retain to assign.
Changed method names from createXXX to newXXX for the ARC compatibilty. Specifically, this change affected the following methods:
newWithType: (PxImageWriter)
new: (PxMetaImage)
new: (PxMetaImage) withMetadata:
new: (PxMetaImage) withPath:
new: (PxMetaImage) withURL:
Minor bug fixes and performance improvements.
2.3.1
Added compatibility with Apple iOS 12.
2.3
DSSDK now available as an Embedded Framework.
Changed PxDocCutout class.
Added PxAutoShotDetector class - a more convenient helper to detect when document corners are stable and it is safe to make a camera shot.
2.2
New license protection and key format now supporting subscription based licensing.
Minor bug fixing and improvements in demo application and documentation.
2.1
Added Effective Document area (the area document occupies in the viewfinder) and Trapezoid Distortion control into demo application camera.
Minor bug fixing and improvements in demo application.
Minor Documentation update.
2.0
Added new protocol PxImageWriter (and related enum) for document writing in various formants.
Added GLImageSDK::detectDocumentCorners2:correctDocument:corners, with more precise document corner detection algorithm.
GLImageSDK::correctDocument:corners now can corrects user changed document corners.
Added class DocumentCutout for document corners check and correction.
Added class-factory PxImageWriterFactory.
Added new protocol PxMetaImage (and related enum), representing Image and related EXIF metadata.
Added class-factory PxMetaImageFactory.
Added class PxException for developer mistakes indication (e.g. wrong enum value or unsupported method call, etc.).
Added VertexDrawingFilter.
Documentation update:
New documentation format - now in convenient html.
Content update.
Demo Application update:
Resulted document could be written as: PDF, PNG, TIFF (G4 compressed) and Jpg files.
Simulate multi-page output (writes same page three time in row) to demonstrate how to create multi-page documents.
Resulted document now could be shared through standard iOS dialogue.
1.3.1
Fixed bug with torch in demo application.
1.3
Demo application Smart Camera and AutoShot support.
Demo application camera UI update.
Demo application image rotation support.
SDK lib now supports multiple bundle ids.
1.2.3
Fixed bug in imageWithoutRotation method.
1.2.2
Increased compatibility with iOS 8x versions.
1.2
*Added Bitcode support.
Library became universal and includes support (slices) for devices as well as simulator in single file.
Live document border detection support added.
Demo application updated:
Added ability to scan documents from camera.
Smart Camera with live document border detection in viewfinder.
Added “Settings” section with ability to change color processing profile as well SmartCrop feature switching.
See also
Installation & SwiftPM integration · Migrating from 2.x to 3.x
## Core engine (DocScanningSDK)
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/core-api.html
This is the map of the DocScanningSDK core engine API. The full generated reference (every class, method, and type) is published alongside these pages; this page orients you in it. The core API is Objective-C and is callable from both Objective-C and Swift.
Setup & licensing
Type
Purpose
PxSDK
Global SDK info — version, build.
PxLicense
Apply and inspect the license. See Licensing.
PxException / PxCatchExceptions
Convert engine exceptions into NSError (PxCatchExceptions.do { … }).
Image & processing
Type
Purpose
PxPicture
The image and its processing — create from camera/import, then detect, refine, and extractImage.
PxRefineFeatures
A builder describing the processing to apply (rectify, perspective, colour profile); pass it to PxPicture’s refine.
PxCutout
The detected document quad (four corners).
PxFrameObserver
Live edge detection over camera frames (for custom camera UIs).
PxColorProfile, PxColorHint, PxOrientation
Processing options and image orientation.
Value types
Basic value types — PxPointF/I/D, PxRectF/I/D, PxMatrixF/I.
OCR
Type
Purpose
PxTextReader / PxTextDetector
Run text recognition over a PxPicture.
PxTextResult
The recognised text and its PxTextAttribute elements (blocks, lines, words, symbols).
PxLanguageDownloader
Download OCR language packs on demand.
PxBundledOcrData
The bundled offline orientation/script-detection data.
Export
Type
Purpose
PxImageWriter
Write PDF / TIFF / JPEG / PNG, including searchable PDFs. See Export.
PxPaper
Paper size and dimensions for PDF output.
See also
The ready-to-use UI layer: API reference — ready-to-use UI.
Task guides under Core concepts walk these types stage by stage.
## Customising the UI
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/customizing-the-ui.html
The ready-to-use screens ship with built-in English text. You can override any of it — to change wording or to localise into other languages — without touching the screens themselves.
How overriding works
Each piece of on-screen text is looked up by key in a strings table named PxUiStrings. The SDK checks your app’s main bundle first, and falls back to its own built-in default when you have not provided a value. So to override a string, you simply add a PxUiStrings.strings file to your app and define the keys you want to change — no API call required.
Add a file named PxUiStrings.strings to your app target.
Define any of the keys below with your own text.
Leave out the keys you are happy with — the SDK’s defaults apply.
/* PxUiStrings.strings (in your app) */
"camera-label-searching" = "Point the camera at a document";
"image-editor-title" = "Adjust edges";
Localising
Localisation uses the standard iOS mechanism: provide PxUiStrings.strings inside each language’s .lproj folder in your app (for example de.lproj/PxUiStrings.strings). iOS picks the right table for the user’s language, and the SDK resolves the keys from it.
The keys
Key
Where it appears
camera-init-failed
Shown when the camera cannot start
camera-label-searching
Camera guidance: looking for a document
camera-label-too-far
Camera guidance: move closer
camera-label-too-distored
Camera guidance: reduce the viewing angle
camera-label-capturing
Camera guidance: capturing
camera-label-manual-focus
Camera guidance: tap-to-focus prompt
image-editor-title
Title of the crop / page editor
editor-banner-no-document-detected
Editor banner when no document was detected
ocr-languages
OCR language picker: title
ocr-select-languages-desc
OCR language picker: description
ocr-avaiable-languages
OCR language picker: available-languages section
ocr-no-languages-installed
OCR language picker: empty state
ocr-search-languages
OCR language picker: search field
[!NOTE]
The key names are matched exactly as written above (including their existing spelling) — copy them verbatim.
Per-screen behaviour
Text is cross-cutting; other behaviour is set per screen through that screen’s configuration object — PxUiCameraScreenConfiguration, PxUiPageCropScreenConfiguration, PxUiOcrEditorScreenConfiguration, and PxUiLanguagePickerScreenConfiguration. Each is documented in its screen’s guide.
Deeper visual theming (custom colours, fonts, icons) is not available for the ready-to-use screens in this release; build on the core engine if you need a bespoke look.
See also
Camera capture · Edge detection & cropping · OCR languages · Core engine vs ready-to-use UI
## Edge detection & cropping
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/edge-detection-and-cropping.html
After a page is captured or imported, you crop to the document and correct its perspective so an angled photo becomes a flat, rectangular page. The detected corners are a PxCutout; cropping applies that cutout to a PxPicture.
Ready-to-use: the crop editor
PxUiPageCropScreen (SwiftUI PxUiPageCropScreenView) shows the page with draggable corner handles and rotation, so the user can fine-tune the auto-detected edges. It takes a PxPicture and its cutout and returns the adjusted result.
import DocScanningSDK_UI
// The camera screen returns a UIImage and a cutout; wrap the image in a PxPicture.
let picture = PxPicture(image)
PxUiPageCropScreenView(picture: picture, cutout: cutout) { result in
switch result {
case .finished(let image, let cutout):
// The user-adjusted page and corners.
break
case .cancelled:
break
@unknown default:
break
}
}
This is the natural next step after the camera screen: wrap the UIImage it returns in a PxPicture and pass that with the cutout.
Engine: crop and correct in code
With the core engine you describe the processing on a PxRefineFeatures builder, then apply it to the picture:
import DocScanningSDK
let picture = PxPicture(image) // from capture or import
let features = PxRefineFeatures()
features.rectify(with: cutout) // crop + perspective-correct
picture.refine(features) // apply the processing (resets the builder)
let corrected = picture.extractImage() // the flattened page
PxRefineFeatures also offers rectifyAutodetectCutout() (detect the edges and crop in one call) and rectifyWithoutCutout() (process the whole image). A PxCutout exposes the corners through getPoints(_:) / setPoints(_:_:) and reports isDefined / isValid, so you can validate or adjust corners before cropping.
Each instruction method returns the builder, so you can chain steps — for example a colour profile (see Image enhancement).
Tips
A cutout from the camera screen is already in the captured image’s coordinate space — pass both straight to the editor or to rectify(with:).
Check cutout.isValid before cropping; an undefined or degenerate quad means detection did not find a confident document.
See also
Camera capture & live detection · Image enhancement · The processing pipeline
## Engine vs ready-to-use UI
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/engine-vs-ready-to-use-ui.html
DSSDK gives you the same capabilities at two levels. Picking the right one is the most important early decision, so this page lays out what each offers and when to reach for it.
The two levels
Ready-to-use UI (DocScanningSDK-UI) — screen-level components you present like any other view controller or SwiftUI view. The SDK owns the user interface and the interaction; you provide a configuration and receive a result. The screens are:
PxUiCameraScreen — the camera scanner with live edge detection and auto-shot.
PxUiPageCropScreen — a crop/borders editor for adjusting the detected corners and rotation.
PxUiOcrEditorScreen — an editor for reviewing and correcting recognised text.
PxUiLanguagePickerScreen — a picker for choosing OCR languages.
Each screen takes a *Configuration object and can be re-localised through a strings table, but its layout and behaviour are fixed by the SDK.
Core engine (DocScanningSDK) — the underlying capabilities with no UI: live detection (PxFrameObserver), the image and its processing (PxPicture), document corners (PxCutout), text recognition (PxTextReader), and export (PxImageWriter). You drive these from your own UI, or headlessly with no UI at all.
Because the UI product includes the core engine, you can mix the two: present a ready-to-use screen and then post-process its result with the engine.
Decision rubric
If you want to…
Use
Ship a working scanner quickly with a standard, well-tested UX
Ready-to-use screens
Adjust the wording/localisation of the standard screens
Ready-to-use screens + their *Configuration and the strings table
Build a fully custom camera, editor, or results UI
Core engine
Process images with no UI at all (e.g. batch a folder of imported images)
Core engine
Use the standard camera but your own results/export flow
Ready-to-use camera + core engine for the rest
The guiding principle: start with the ready-to-use screens for a fast, reliable result, and drop down to the core engine only where you genuinely need custom UI or headless processing. You do not have to choose globally — mix per feature.
What ready-to-use does not (yet) do
The screens are configurable and localisable, but they are not deeply re-themable (custom colours, fonts, and icons) in this release. If your design requires a bespoke look, build that screen on the core engine.
See also
The document processing pipeline — the stages both levels share.
Camera capture & live detection — the ready-to-use screen and the PxFrameObserver engine path.
Customising the ready-to-use UI — strings and localisation.
## Export (PDF, TIFF, JPEG, PNG)
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/export.html
Once a page is cropped, enhanced, and (optionally) recognised, you write it to a file with PxImageWriter. The same API produces single images, multi-page PDFs, and searchable PDFs with an embedded invisible text layer.
Output formats
PxImageWriter_Type selects the format: PxImageWriter_Type_JPEG, PxImageWriter_Type_PNG, PxImageWriter_Type_PNG_EXT, PxImageWriter_Type_TIFF, and PxImageWriter_Type_PDF. PNG, TIFF, and PDF are licensed features.
Write a page
Create a writer for the format, open an output path, write the picture, and close. Engine calls can raise exceptions, so wrap them with PxCatchExceptions:
import DocScanningSDK
let writer = PxImageWriter.new(PxImageWriter_Type_PDF)
var writtenPath: String?
try PxCatchExceptions.do {
writer.open(outputPath)
writtenPath = writer.write(picture) // write throws PxException for license-gated formats
}
writer.close()
Searchable PDF
To embed the OCR result as an invisible, selectable text layer behind the image, pass the page’s PxTextResult to write(_:with:) — the text layer is hidden by default:
let writer = PxImageWriter.new(PxImageWriter_Type_PDF)
var writtenPath: String?
try PxCatchExceptions.do {
writer.open(outputPath)
writtenPath = writer.write(picture, with: picture.scanResult)
}
writer.close()
Use setFonts(_:) to supply the fonts for the embedded text layer. See OCR & text recognition for producing the PxTextResult.
Multi-page PDFs
For a multi-page document, open the writer once, write each page, then close — every write call appends a page:
let writer = PxImageWriter.new(PxImageWriter_Type_PDF)
try PxCatchExceptions.do {
writer.open(outputPath)
for page in pages { _ = writer.write(page, with: page.scanResult) }
}
writer.close()
Compression
PDF (and TIFF) output is compressed per page. Call setCompressionLevel(_:) before writing, passing one of the PxImageWriter_CompressionLevel presets — or any custom rate >= 1. Higher means a smaller file at lower quality:
let writer = PxImageWriter.new(PxImageWriter_Type_PDF)
writer.setCompressionLevel(Float(PxImageWriter_CompressionLevel_Medium.rawValue))
Preset
Use when
PxImageWriter_CompressionLevel_Lossless
Archival quality — no quality loss, largest files.
PxImageWriter_CompressionLevel_Low
Default. Balanced size and quality for everyday documents.
PxImageWriter_CompressionLevel_Medium
Noticeably smaller, for sharing or upload, with slight quality loss.
PxImageWriter_CompressionLevel_High
Aggressive size reduction when storage or bandwidth is tight.
PxImageWriter_CompressionLevel_Extreme
Smallest files, most visible quality loss.
The level tunes the lossy compression of colour and greyscale pages only. Black-and-white pages are always stored losslessly, whatever the level — see Image enhancement. If you never call setCompressionLevel(_:), the writer uses Low.
[!NOTE]
Viewing the PDFs. To keep files small, the SDK uses modern PDF image compression — JBIG2 for black-and-white pages and JPEG 2000 for colour and greyscale. Both are part of the PDF standard and render correctly in current mainstream viewers, including Apple’s built-in Preview and Quick Look on recent macOS and iOS, and the previews in Google Docs and Google Drive. Some older or lightweight third-party readers don’t fully implement these codecs, though, and may show such a page blank or render it slowly. If you need a viewer that fully supports both across the board, Adobe Acrobat and Adobe Reader do.
More controls
Paper size & orientation: configure the PDF page geometry with the writer’s paper-configuration API (see PxPaper and the API reference).
Footer: add a footer with text (and an optional URL) via the writer’s footer configuration.
Tips
Always close() the writer — for PDFs this finalises the file.
Confirm the format’s feature is enabled on your license before exporting (PNG / TIFF / PDF are gated).
See also
OCR & text recognition · Image enhancement · Licensing
## Image enhancement
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/image-enhancement.html
Enhancement turns a raw photo into a clean “scanned” look: sharpened text, flattened lighting, and a colour mode that suits the document. In DSSDK this is a colour profile applied while the page is processed.
In the ready-to-use flow this happens inside the crop editor. With the engine you choose the profile yourself.
Colour profiles
PxColorProfile selects the output style:
Profile
Output
Best for
PxColorProfile_BW
High-contrast bilevel (black & white)
Text documents — crispest text, smallest files.
PxColorProfile_Gray
Greyscale
Documents with shading, or photos you want neutral.
PxColorProfile_Color
Content-aware colour
Receipts, forms, ID cards — anything where colour matters.
PxColorProfile_None
The source image, unprocessed
Photos, or OCR on pages with complex shadows and highlights.
Black & white binarises the page to pure black-on-white. It gives the sharpest text and the smallest output, and when you save to PDF or TIFF the bilevel page is stored with lossless compression (JBIG2 in PDF, CCITT Group 4 in TIFF) — so the text stays crisp no matter how hard you compress the colour pages around it.
Greyscale keeps the page’s tones instead of collapsing them to pure black-and-white. Like black & white it flattens uneven lighting and sharpens text, but it preserves shading and soft edges — a good middle ground for pages with pencil marks, faint stamps, or photos that hard binarisation would crush, when full colour isn’t needed. File size sits between black & white and colour.
Colour is content-aware: the SDK analyses the captured page and flattens uneven lighting while preserving the original colours, turning a photographed receipt or form into something that reads like a flatbed scan.
None does no colour processing at all — you get the source image (cropped and dewarped if you rectified it, otherwise untouched). Reach for it when binarisation would lose information: ordinary photos, or OCR on pages with complex shadows and highlights where the recogniser does better with the original tones.
Applying a profile
Build a PxRefineFeatures, set the colour profile on it, then apply it with picture.refine(_:):
import DocScanningSDK
let features = PxRefineFeatures()
features.use(PxColorProfile_BW, forPic: picture) // choose the colour mode
picture.refine(features) // apply it (resets the builder)
let enhanced = picture.extractImage() // the processed page
Related controls on PxRefineFeatures (each returns the builder, so they chain):
overrideStrongShadows(_:) — handle documents with strong shadows.
normalizeOrientation() — straighten the page orientation.
ignoreColorHint() — ignore the capture-time colour hint when deciding processing.
Tips
Default to PxColorProfile_BW for text — it gives the sharpest, smallest result. Switch to Color only when the document’s colour carries meaning.
Let users pick the profile and re-process — the colour mode is a per-page choice, not a global setting.
See also
Edge detection & cropping — produces the PxRefineFeatures you enhance.
Export — write the enhanced page to a file.
## Import an existing image
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/import-existing-image.html
Not every document comes from the live camera. You can feed an existing photo — picked from the library, received as a file, or held in memory — into the same pipeline. This is also how you exercise detection, cropping, enhancement, OCR, and export on the Simulator, which has no camera.
Create a PxPicture from your source
PxPicture initialises from whatever you have:
import DocScanningSDK
let picture = PxPicture(image) // a UIImage (e.g. from PHPicker)
// or:
let fromFile = PxPicture(fromPath: filePath) // a file-system path
let fromURL = PxPicture(fromNSURL: fileURL) // a file URL
let fromData = PxPicture(fromData: imageData) // raw image bytes
There is also an initialiser that takes a UIImage plus a metadata dictionary, when you want to carry capture metadata through.
Run the pipeline
From there it is the same flow as a camera capture. To detect and crop in one step:
let features = PxRefineFeatures()
features.rectifyAutodetectCutout() // find edges + crop + correct
picture.refine(features) // apply the processing
let corrected = picture.extractImage() // the flattened page
Then enhance (colour profiles), recognise text (OCR), and export exactly as you would for a captured page. If you want the user to confirm the detected edges, hand the picture and its cutout to the crop editor.
Tips
This path runs on the Simulator — useful for developing and testing the non-camera stages without a device.
Add the appropriate photo-library usage description to Info.plist if you import from the user’s library.
See also
Camera capture & live detection — the live path.
Edge detection & cropping · The processing pipeline
## Installation (Swift Package Manager)
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html
DSSDK is distributed exclusively through Swift Package Manager as binary xcframeworks. There is no CocoaPods, Carthage, or manual-framework option. This page covers adding the package, choosing a product, and maintaining the dependency over time.
The package URL is:
https://github.com/Pixelnetica/DocScanningSDK-iOS
Add the package in Xcode
In Xcode, choose File ▸ Add Package Dependencies…
Paste the package URL above into the search field.
For the dependency rule, choose Up to Next Major Version starting from 3.0.0. This picks up bug-fix and feature releases automatically while protecting you from breaking changes.
Choose the product(s) to add to your app target (see Choosing a product) and finish.
Add the package in Package.swift
If your app is itself a Swift package, add the dependency and the product you need:
dependencies: [
.package(
url: "https://github.com/Pixelnetica/DocScanningSDK-iOS",
from: "3.0.0"
)
],
targets: [
.target(
name: "MyApp",
dependencies: [
.product(name: "DocScanningSDK-UI", package: "DocScanningSDK-iOS")
]
)
]
Choosing a product
The package vends two products:
Product
Contains
Use when
DocScanningSDK-UI
The ready-to-use screens and the core engine
You want the batteries-included scanner / editor screens (most apps).
DocScanningSDK
The core engine only (no UI)
You are building a fully custom UI on top of the engine.
DocScanningSDK-UI already includes the core engine, so adding the UI product alone is enough: you can import DocScanningSDK and call the core API without adding the DocScanningSDK product separately.
Adding both products is also valid. Because they share the same core binary, the engine is linked only once — there is no duplication and no increase in app size. The EasyScanner sample app is set up this way on purpose: it imports DocScanningSDK directly in one screen, so it declares an explicit dependency on the core product it uses, rather than relying on the UI product to re-export it. Either setup is correct — adding only DocScanningSDK-UI is simply the smaller one.
Updating and pinning
Update to a new release: in Xcode, File ▸ Packages ▸ Update to Latest Package Versions, or run swift package update. With the Up to Next Major rule, this moves you to the newest 3.x.
Pin an exact version: the resolved versions are recorded in your Package.resolved file. Commit it so every machine and CI run builds against the same SDK build. To lock to one release, set the dependency rule to Exact Version.
Review before adopting: check the Changelog before updating across feature releases.
Troubleshooting
Checksum mismatch. SwiftPM caches binary artifacts by checksum. After an SDK update, reset the package caches (File ▸ Packages ▸ Reset Package Caches) and resolve again.
Resolution fails / version not found. Confirm the package URL and that your dependency rule allows the version you expect; then resolve again.
More in Troubleshooting.
Next steps
Quick Start — present the scanner.
Licensing, trial & evaluation — apply your license.
System requirements & device support.
## Introduction
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/introduction.html
The Pixelnetica Document Scanning SDK (DSSDK) turns photos of paper documents into clean, deskewed pages that look like they came from a flatbed scanner — and, optionally, into searchable PDFs.
Everything runs on the device: capture, detection, image processing, and text recognition need no network connection.
If you are building an app that scans receipts, contracts, IDs, whiteboards, or any paper document with the camera, DSSDK gives you the whole pipeline rather than a single piece of it.
What you can build
Capture with live guidance — a camera screen that detects the document’s edges in real time and can shoot automatically when the framing is good.
Detect and crop — find the document’s four corners and correct perspective, so a photo taken at an angle becomes a flat, rectangular page.
Enhance — apply scan-style colour profiles (black-and-white, greyscale, colour) that sharpen text and flatten uneven lighting.
Recognise text (OCR) — extract text from a page and export a searchable PDF with an invisible text layer.
Export — write the result as PDF, TIFF, JPEG, or PNG, including multi-page PDFs.
Two products: ready-to-use UI, or the core engine
DSSDK ships as two Swift Package products. Most apps start with the first:
DocScanningSDK-UI — batteries-included screens you present in a few lines: a camera scanner, a crop/borders editor, an OCR results editor, and a language picker. The SDK owns the UI; you handle the result.
DocScanningSDK — the core engine (image processing, detection, OCR, export) with no UI. Use it directly when you want to build a fully custom scanning experience.
A good rule of thumb: start with the ready-to-use screens for a working scanner fast, and drop down to the core engine only where you need custom UI. See Core engine vs ready-to-use UI.
Why DSSDK
One-line screens. A complete capture → crop → OCR flow you present like any other view controller or SwiftUI view.
Offline OCR out of the box. Orientation and script detection work on first launch with no download; additional language packs are fetched on demand.
Real searchable PDFs. Export a PDF with an embedded, invisible OCR text layer — not just an image in a PDF wrapper.
Modern integration. Distributed exclusively via Swift Package Manager as binary xcframeworks.
Requirements
iOS 16.3 or later.
Swift or Objective-C. The core API is Objective-C; the ready-to-use UI is Swift.
What’s new in version 3.0.3
The camera screen now follows the host app’s interface orientation. In orientation-locked apps (portrait-only is the common case), the viewfinder stays upright and correctly proportioned no matter how the device is physically held, and captured images always match the viewfinder.
For earlier releases and the full detail of every version, see the Version history.
Next steps
Quick Start — a working scanner in about five minutes.
Installation & SwiftPM integration — add the package and keep it up to date.
Licensing, trial & evaluation — apply a license and understand evaluation mode.
## Licensing & trial
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/licensing.html
DSSDK is a commercial SDK. A license key unlocks full output (no watermark) and the licensed features. This page covers getting a key, applying it, and checking it at runtime.
Getting a trial key
A free trial key is available from Pixelnetica — visit the Document Scanning SDK product page to request one. A license key is bound to a specific app bundle identifier, so request the trial for the bundle ID you build with.
Applying the license
Call PxLicense.initialize(withKey:) once, as early as possible in the app lifecycle (for example at launch). It returns a PxLicenseStatus. Passing nil deactivates any current license and runs in evaluation mode.
import DocScanningSDK
let status = PxLicense.initialize(withKey: myLicenseKey)
switch status {
case PxLicenseStatus_Active:
break // Full functionality, no watermark.
default:
// Evaluation mode — see below.
break
}
Evaluation mode
If no active license is applied — no key, an invalid key, or an expired one — the SDK still works, but processed results are watermarked. This lets you evaluate the full pipeline before purchasing. Apply a valid key to remove the watermark.
Checking the status at runtime
PxLicense.initialize(withKey:) returns the current status, and PxLicense.info() exposes details about the active license. Useful members:
Member
Meaning
status
The current PxLicenseStatus.
appId
The bundle identifier the license is bound to.
clientName
The license owner.
validTs
UNIX timestamp the license is valid until (0xfffffff = unlimited).
validSubscriptionTs
UNIX timestamp the update subscription is valid until.
features
Bitmask of licensed features (see below).
The PxLicenseStatus values cover the common failure cases — no key, a malformed key, a key bound to a different app (AppID_Mismatch) or platform, an expired license, and an expired update subscription — so you can show the user a precise message.
Feature gating
Some outputs are gated by license features (PxLicenseFeature): PNG export, TIFF export, PDF export, and OCR. The features bitmask on the active license tells you which are permitted; a full-featured license enables all of them.
Tips
Apply the license before you use any SDK functionality.
The license is tied to your bundle identifier — an AppID_Mismatch status usually means the key was issued for a different bundle ID.
Check the status at runtime rather than assuming success, and surface a clear message when it is not active.
Next steps
Quick Start — present the scanner.
Export — PDF, TIFF, JPEG, and PNG output.
Troubleshooting.
## Migrating 2.x to 3.x
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/migration-2x-to-3x.html
The 3.x release changes how the SDK is distributed and adds a ready-to-use UI layer. The core capabilities are the same; the main work is swapping the integration method.
## What changed
- **Distribution is now Swift Package Manager only.** The 2.x SDK was integrated by dragging `DocScanningSDK.framework` into the project and adding it to *Embedded Binaries*. That manual step — and the CocoaPods option — are gone. 3.x is consumed as binary `xcframework`s through SwiftPM.
- **New ready-to-use UI.** 3.x adds the `DocScanningSDK-UI` product: complete camera, crop-editor, OCR-editor, and language-picker screens that did not exist in 2.x.
- **Minimum iOS raised to 16.3.**
## Migration steps
1. **Remove the old framework.** Delete the embedded `DocScanningSDK.framework` reference and its *Embedded Binaries* / *Frameworks, Libraries, and Embedded Content* entry.
2. **Add the package.** Follow [Installation & SwiftPM integration](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html). Choose `DocScanningSDK-UI` if you want the new screens (it includes the core engine), or `DocScanningSDK` for the engine alone.
3. **Update imports.** Import the module — `import DocScanningSDK` (and `import DocScanningSDK_UI` if you use the screens) — rather than the old umbrella-header `#import`.
4. **Re-apply your license.** License application is unchanged in spirit — call `PxLicense.initialize(withKey:)` early; see [Licensing](/docs/document-scanner-sdk/apple-ios/licensing.html).
5. **Rebuild and resolve.** Build against the current headers and fix any references the compiler flags against the [current API reference](/docs/document-scanner-sdk/apple-ios/core-api.html).
6. **Adopt the ready-to-use screens (optional).** If you previously built your own camera/editor UI, you can now replace it with the [ready-to-use screens](/docs/document-scanner-sdk/apple-ios/engine-vs-ready-to-use-ui.html) — or keep your custom UI on the core engine.
## Tips
- Raise your deployment target to iOS 16.3 before adding the package.
- Commit `Package.resolved` so your team and CI build against the same SDK version.
## See also
- [Installation & SwiftPM integration](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html) · [Changelog](/docs/document-scanner-sdk/apple-ios/changelog.html) · [Troubleshooting](/docs/document-scanner-sdk/apple-ios/troubleshooting.html)
## OCR languages
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/ocr-languages.html
OCR needs language data. DSSDK ships orientation/script detection data in the framework so it works on first launch with no network, and downloads recognition languages on demand.
## Bundled offline data (OSD)
Orientation and script detection (OSD) data is bundled and decrypted on first use — no download, no network. Ask for its directory:
```swift
import DocScanningSDK
// Synchronous:
let osdDir = try PxBundledOcrData.osdDirectory()
// or asynchronous:
PxBundledOcrData.osdDirectory { dir, error in /* ... */ }
```
This is what lets the SDK detect a page's orientation and script offline, before any language pack is installed.
## Hosting the language files
DSSDK recognises 100+ languages. Their recognition data ships as a single archive that you download once and make available to your app:
[**Download the language archive**](/products/OCR/dssdk-ocr-lang-pack.zip), unzip it, and either host the files on a server your app can reach or bundle them in the app. The SDK downloads each language from a **base URL** you provide — the location the unzipped files live under.
> [!WARNING]
> **Host the files yourself for production.** For development convenience, the SDK's default base URL — and the EasyScanner sample app — point at a Pixelnetica-hosted location (`PxUiLanguagePickerScreenConfiguration.defaultBaseURL`). That location is for evaluation only and may change without notice, so do not depend on it in a shipping app. Put the language files on your own server (or bundle them) and point the SDK at that location, as shown below.
## Downloading language packs
Recognition languages (English, German, …) are downloaded on demand with `PxLanguageDownloader`. You give it a language code, a base URL, an output directory, and a delegate that receives progress and completion:
```swift
let downloader = PxLanguageDownloader(
"eng", from: baseURL, withOutDir: languagesDir, andDelegate: self)
downloader.start() // downloader.cancel() to abort
```
The delegate (`PxLanguageDownloaderDelegate`) reports `onLanguageDownloadProgress(_:progress:)` and `onLanguageDownloadFinished(_:error:)`. The output directory is the folder you later pass to [`PxTextReader`](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) as its language data.
## Ready-to-use: the language picker
`PxUiLanguagePickerScreen` (SwiftUI `PxUiLanguagePickerScreenView`) presents the installed and available languages, handles search, and returns the user's selection. It pairs with the [OCR editor](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html), which can present it to change languages and re-recognise. Its on-screen text is re-localisable through the [strings table](/docs/document-scanner-sdk/apple-ios/customizing-the-ui.html).
You tell the picker where to download from and where to store the files through its configuration. EasyScanner builds this in `OCRLanguagePickerSupport.swift`; point `baseURL` at the location where you host the language files:
```swift
PxUiLanguagePickerScreenConfiguration(
outputDirectory: ocrLanguagesDirectory(), // where downloaded files are stored
baseURL: "https://your-server.example.com/ocr-languages", // your hosted language files
selectionStore: OCRLanguageSelectionStore())
```
The sample passes `PxUiLanguagePickerScreenConfiguration.defaultBaseURL` (the Pixelnetica evaluation server) — replace it with your own URL for production. If you drive downloads yourself instead of using the picker, pass the same URL as the `from:` argument of `PxLanguageDownloader` (shown above).
## Tips
- OSD data is always available; recognition languages must be downloaded before first use of that language.
- Pass several languages to `PxTextReader` at once by joining codes with `+` (for example `"eng+fra"`).
## See also
- [OCR & text recognition](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) · [Customising the ready-to-use UI](/docs/document-scanner-sdk/apple-ios/customizing-the-ui.html)
## OCR & text recognition
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html
Optical character recognition (OCR) extracts the text from a processed page. The recognised text — with its layout and per-element positions — is what later lets you export a **searchable PDF**.
## Recognise text with the engine
A `PxTextReader` is created with the path to the OCR language data and the language(s) to use, then run against a `PxPicture`. The result lands on the picture's `scanResult`:
```swift
import DocScanningSDK
let reader = PxTextReader(traineddataDirectory, languages: "eng")
reader.scanText(picture)
if let result = picture.scanResult, result.status == PxScanStatus_Recognized {
let text = result.text // the recognised text
let languages = result.languages // languages actually used
}
```
- **Language data.** `traineddataDirectory` is a folder of OCR language files. The bundled offline data and on-demand language packs are covered in [OCR languages](/docs/document-scanner-sdk/apple-ios/ocr-languages.html); pass multiple languages joined with `+` (for example `"eng+deu"`).
- **Result detail.** `PxTextResult` exposes the full text plus `PxTextAttribute` elements (blocks, lines, words, symbols) you can walk for positions and confidence.
## Report progress and allow cancel
Long scans should be cancellable and show progress. Assign a `progressCallback` (a `PxTextReaderProgressCallback`) before scanning — it receives per-page progress and can cancel an in-flight scan.
## Ready-to-use: the OCR editor
`PxUiOcrEditorScreen` (SwiftUI `PxUiOcrEditorScreenView`) presents the recognised text over the page for the user to review and correct. It takes a `PxUiOcrEditorScreenConfiguration` and a `PxUiOcrEditorSession` (built from the page image and its `PxTextResult`), and calls back with the edited text. Combine it with the [language picker](/docs/document-scanner-sdk/apple-ios/ocr-languages.html).
## Tips
- Check `result.status` — `PxScanStatus_Recognized` means success; `PxScanStatus_NotFound` or `PxScanStatus_Cancelled` need handling.
- OCR is a licensed feature; confirm the OCR feature is enabled on your [license](/docs/document-scanner-sdk/apple-ios/licensing.html).
## See also
- [OCR languages — download, offline OSD & picker](/docs/document-scanner-sdk/apple-ios/ocr-languages.html) · [Export](/docs/document-scanner-sdk/apple-ios/export.html) (searchable PDF) · [The processing pipeline](/docs/document-scanner-sdk/apple-ios/processing-pipeline.html)
## Processing pipeline
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/processing-pipeline.html
Whichever level you work at, a document moves through the same stages. Understanding them makes the rest of the documentation easy to navigate, because each task guide covers one stage.
```
acquire ─▶ detect ─▶ crop / correct ─▶ enhance ─▶ recognise text ─▶ export
(camera (find (perspective (colour (OCR, optional) (PDF / TIFF /
or import) corners) correction) profile) JPEG / PNG)
```
## The stages
| Stage | What happens | Core engine | Ready-to-use screen |
| --- | --- | --- | --- |
| **Acquire** | Capture with the camera, or import an existing photo | `PxFrameObserver` (live frames) / `PxPicture` (import) | `PxUiCameraScreen` |
| **Detect** | Find the document's four corners (the *cutout*) | `PxCutout` | (part of the camera screen) |
| **Crop / correct** | Use the cutout to crop and flatten perspective into a rectangular page | `PxRefineFeatures` → `PxPicture.refine` | `PxUiPageCropScreen` |
| **Enhance** | Apply a scan-style colour profile (B&W / greyscale / colour) | `PxRefineFeatures` (`use…forPic:`) + `PxColorProfile` | (part of the crop editor) |
| **Recognise text** | Optional OCR; produce text with positions | `PxTextReader` → `PxTextResult` | `PxUiOcrEditorScreen` |
| **Export** | Write the page as PDF, TIFF, JPEG, or PNG — including a **searchable PDF** with an invisible OCR text layer | `PxImageWriter` (+ `PxPaper`) | (no dedicated screen) |
## How the two levels map onto it
- The **ready-to-use screens** package several stages into one presentation: the camera screen handles acquire + detect; the crop editor handles crop + enhance; the OCR editor handles recognise-text review.
- The **core engine** exposes each stage as an API you call in sequence, so a fully custom flow assembles the same stages itself.
- **Export is always the engine.** There is no ready-to-use export screen — you write the final file with `PxImageWriter` after the user is happy with the page.
A typical app uses the camera screen to acquire and detect, the crop editor to let the user fine-tune, optionally the OCR editor, and then calls the engine to export.
## See also
- [Core engine vs ready-to-use UI](/docs/document-scanner-sdk/apple-ios/engine-vs-ready-to-use-ui.html) — choosing your level.
- Per-stage guides: [Camera capture](/docs/document-scanner-sdk/apple-ios/camera-capture.html) · [Edge detection & cropping](/docs/document-scanner-sdk/apple-ios/edge-detection-and-cropping.html) · [Image enhancement](/docs/document-scanner-sdk/apple-ios/image-enhancement.html) · [OCR & text recognition](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) · [Export](/docs/document-scanner-sdk/apple-ios/export.html).
## Quick start
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/quick-start.html
This guide gets you from an empty project to a working document scanner using the ready-to-use camera screen. It takes about five minutes.
## Before you begin
1. **Add the package.** Add `DocScanningSDK-UI` to your app — see [Installation & SwiftPM integration](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html). (The UI product includes the core engine, so you only need this one.)
2. **Have a license key.** Without an active license the SDK still runs, but results are watermarked. See [Licensing, trial & evaluation](/docs/document-scanner-sdk/apple-ios/licensing.html) to get a trial key.
3. **Allow camera access.** Add an `NSCameraUsageDescription` string to your app's `Info.plist` — iOS requires it before the camera can start, and the scanner will fail without it.
## 1. Initialize the license at launch
Apply your license once, as early as possible — for example when the app starts. Passing `nil` runs the SDK in evaluation mode.
```swift
import DocScanningSDK
let status = PxLicense.initialize(withKey: myLicenseKey)
if status != PxLicenseStatus_Active {
// Evaluation mode: results will be watermarked.
}
```
## 2. Present the camera scanner
`PxUiCameraScreenView` is a SwiftUI view that runs the full capture experience — live edge detection, optional auto-shot, and a torch control — and calls you back with the result.
```swift
import SwiftUI
import DocScanningSDK_UI
struct ScanButton: View {
@State private var showCamera = false
var body: some View {
Button("Scan") { showCamera = true }
.fullScreenCover(isPresented: $showCamera) {
PxUiCameraScreenView(configuration: PxUiCameraScreenConfiguration()) { result in
showCamera = false
switch result {
case .success(let image, let cutout):
// `image` is the captured page; `cutout` is the detected
// document quad. Hand them to the crop editor or process
// them with the core engine.
break
case .cancelled:
break
case .failure(let error):
print((error as NSError).localizedDescription)
@unknown default:
break
}
}
.ignoresSafeArea()
}
}
}
```
That is a complete scanner. The screen returns a captured `image` and the detected document corners (`cutout`).
## Where to go next
- Let the user fine-tune the crop: [Edge detection & cropping](/docs/document-scanner-sdk/apple-ios/edge-detection-and-cropping.html).
- Recognise text and export a searchable PDF: [OCR & text recognition](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) and [Export](/docs/document-scanner-sdk/apple-ios/export.html).
- Build a custom camera UI instead of the ready-to-use screen: [Camera capture & live detection](/docs/document-scanner-sdk/apple-ios/camera-capture.html).
## Tips
- Test camera capture on a real device — the Simulator has no camera, though you can still [import an existing image](/docs/document-scanner-sdk/apple-ios/import-existing-image.html).
- If the scanner closes immediately, check that `NSCameraUsageDescription` is present in `Info.plist`.
## Sample app — EasyScanner
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/sample-app-guide.html
**EasyScanner** is a complete, runnable Swift app that demonstrates the SDK from capture to export. It is the best starting point for seeing how the pieces fit together in a real project, and a reference you can copy patterns from.
## What it demonstrates
- Presenting the ready-to-use [camera scanner](/docs/document-scanner-sdk/apple-ios/camera-capture.html) and handling its result.
- The [crop / page editor](/docs/document-scanner-sdk/apple-ios/edge-detection-and-cropping.html) for adjusting detected edges.
- [Image enhancement](/docs/document-scanner-sdk/apple-ios/image-enhancement.html) with selectable colour profiles.
- [OCR](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) and the OCR results editor, with the [language picker](/docs/document-scanner-sdk/apple-ios/ocr-languages.html).
- [Exporting](/docs/document-scanner-sdk/apple-ios/export.html) to PDF (including searchable PDF) and sharing the result.
- Applying a [license](/docs/document-scanner-sdk/apple-ios/licensing.html) at launch, and reading the license status.
It also shows practical app concerns the SDK leaves to you — persisting the user's settings (compression level, fonts) and wiring the screens into a SwiftUI app.
## Building and running
EasyScanner consumes the SDK the same way your app will — through the Swift Package. Open the project, let Xcode resolve the package, and run.
- **Run on a real device** to use the camera scanner; on the Simulator, use the import flow.
- **Apply a license** to remove the evaluation watermark — see [Licensing](/docs/document-scanner-sdk/apple-ios/licensing.html).
The full source is provided so you can read, run, and adapt it. Use it alongside the task guides: each guide's snippets mirror how EasyScanner calls the same APIs.
## See also
- [Quick Start](/docs/document-scanner-sdk/apple-ios/quick-start.html) · [The processing pipeline](/docs/document-scanner-sdk/apple-ios/processing-pipeline.html)
## System requirements
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/system-requirements.html
## Platform
- **iOS 16.3 or later.** This is a hard minimum — the SDK does not load on earlier versions.
- **Swift or Objective-C.** The core engine (`DocScanningSDK`) exposes an Objective-C API usable from both. The ready-to-use UI (`DocScanningSDK-UI`) is Swift.
- **Xcode 15 or later**, with Swift Package Manager (the package manifest targets `swift-tools-version: 5.9`). SwiftPM is the only supported integration channel — see [Installation](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html).
## Architectures
The SDK ships as binary `xcframework`s with slices for:
- **arm64** — physical iPhone and iPad devices.
- **arm64 / x86_64 simulator** — Apple-silicon and Intel Macs running the iOS Simulator.
## Device vs Simulator
- **Live camera capture requires a real device** — the Simulator has no camera, so the camera scanner cannot run there.
- On the Simulator you can still exercise the rest of the pipeline by [importing an existing image](/docs/document-scanner-sdk/apple-ios/import-existing-image.html) (from Photos or a file) and running detection, cropping, enhancement, OCR, and export.
## Permissions
- **Camera:** add `NSCameraUsageDescription` to your `Info.plist` to use the camera scanner. iOS requires it before the camera can start.
- **Photo library:** if you import images from the user's photo library, add the relevant photo-library usage description as well.
## Next steps
- [Installation & SwiftPM integration](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html).
- [Quick Start](/docs/document-scanner-sdk/apple-ios/quick-start.html).
## Troubleshooting
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/troubleshooting.html
Common developer issues and how to resolve them. For product, pricing, and general questions, see the [FAQ](/products/document-scanning-sdk/ios-faq.html).
## Installation
**The package won't resolve, or I get a checksum mismatch.**
SwiftPM caches binary artifacts by checksum. After an SDK update, reset the package caches (**File ▸ Packages ▸ Reset Package Caches**) and resolve again. Confirm the package URL and that your version rule allows the release you expect. See [Installation](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html).
**After updating the SDK, the compiler can't find a type that clearly exists.**
This is usually a stale module cache. Clean the build folder (**Product ▸ Clean Build Folder**) and rebuild.
**The package resolves, but the build fails to link ("Undefined symbols").**
A binary-framework link failure after resolution usually means a missing system dependency. Confirm your target links the frameworks the SDK relies on and builds for a supported slice (arm64 device, or arm64/x86_64 simulator); then clean and rebuild.
## Distribution & code signing
**The app builds in Debug but fails to archive, or is rejected at upload.**
Binary xcframeworks must be embedded with **Embed & Sign** so Xcode re-signs them with your identity. Confirm the SDK frameworks are set to *Embed & Sign* (not *Do Not Embed*) in your target's *Frameworks, Libraries, and Embedded Content*. A launch-time "invalid code signature" crash points to the same setting.
**How do I symbolicate a crash that points inside the SDK?**
The xcframeworks ship with bundled dSYMs. Keep the dSYM for the SDK version you shipped, and symbolicate the crash report against it as you would your own (Xcode's Organizer, or `atos`/`symbolicatecrash` with the matching UUID).
## Licensing
**Results come out watermarked.**
No active license is applied, so the SDK is in evaluation mode. Apply a valid key — see [Licensing](/docs/document-scanner-sdk/apple-ios/licensing.html).
**`PxLicense.initialize(withKey:)` returns `AppID_Mismatch`.**
The key was issued for a different bundle identifier. License keys are bound to one bundle ID; request a key for the bundle ID you build with.
**The key looks correct but is still rejected.**
License keys must be passed verbatim. A key that picked up stray whitespace, line breaks, or truncation when copied will fail validation — re-copy it intact. (Validation is fully on-device; no network is involved.)
**The license was working and now reports expired.**
Check `status` and `validTs` on the active license. An expired license falls back to evaluation (watermarked) behaviour.
## Camera
**The camera screen opens and immediately closes, or fails to start.**
Add an `NSCameraUsageDescription` string to your `Info.plist` — iOS blocks the camera without it.
**The preview is black even though permission was granted.**
The camera may be restricted (Screen Time / parental controls) or already in use by another app or capture session. Check `AVCaptureDevice.authorizationStatus` for `.restricted`, and make sure no other session holds the camera when you present the scanner.
**Opening and closing the camera in quick succession crashes or hangs.**
Let the camera screen finish tearing down its capture session before presenting it again, rather than dismissing and re-presenting back-to-back.
**I can't test scanning on the Simulator.**
The Simulator has no camera. Use [Process an existing image](/docs/document-scanner-sdk/apple-ios/import-existing-image.html) to exercise detection, cropping, enhancement, OCR, and export there.
## OCR
**OCR returns no text or an error for a language.**
The recognition language pack must be downloaded before first use — see [OCR languages](/docs/document-scanner-sdk/apple-ios/ocr-languages.html). Orientation/script detection (OSD) is bundled and needs no download.
**OCR results are poor or inaccurate.**
Recognition quality depends on the input. Make sure the right language(s) are selected (a wrong or missing language pack produces garbled text), and feed the recogniser a cropped, de-skewed, adequately-resolved page — run OCR on the enhanced/rectified image, not a raw low-resolution photo.
**Which formats and OCR require a license feature?**
PNG, TIFF, and PDF export and OCR are licensed features. Check the active license's `features` mask — see [Licensing](/docs/document-scanner-sdk/apple-ios/licensing.html).
## Export & PDF
**My searchable PDF doesn't seem searchable.**
The text layer is embedded but hidden behind the page image (that is what makes it searchable rather than visible). If a viewer shows no selectable text or renders the page blank, it is usually the viewer, not the file — some lightweight or older readers don't fully implement the modern image codecs the SDK uses (JBIG2, JPEG 2000). Open it in a fully standards-compliant viewer (Adobe Acrobat/Reader, or a current mainstream viewer). See [Export ▸ Viewing the PDFs](/docs/document-scanner-sdk/apple-ios/export.html#compression).
## Performance & memory
**Memory spikes or the app is terminated when scanning many pages or exporting a large PDF/TIFF.**
Process and release pages incrementally rather than holding every full-resolution page in memory at once, and write multi-page documents page-by-page through the open writer. Run OCR and enhancement off the main thread so a large job doesn't block the UI.
## Engine
**A processing or export call throws.**
Core-engine calls can raise exceptions. Wrap them with `PxCatchExceptions` and handle the thrown `NSError`, as shown in [Export](/docs/document-scanner-sdk/apple-ios/export.html).
## See also
- [Installation](/docs/document-scanner-sdk/apple-ios/installation-swiftpm.html) · [Licensing](/docs/document-scanner-sdk/apple-ios/licensing.html) · [Migrating from 2.x to 3.x](/docs/document-scanner-sdk/apple-ios/migration-2x-to-3x.html)
## Ready-to-use UI (DocScanningSDK-UI)
https://www.pixelnetica.com/docs/document-scanner-sdk/apple-ios/ui-api.html
This is the map of the `DocScanningSDK-UI` ready-to-use screen API. The [full generated reference](api/docscanningsdk_ui/) is published alongside these pages. This layer is Swift; each screen ships as a UIKit controller and a SwiftUI wrapper, with a configuration object and a result/delegate.
## The screens
| Screen (SwiftUI wrapper) | Configuration | Result / delegate | Guide |
| --- | --- | --- | --- |
| [`PxUiCameraScreen`](api/docscanningsdk_ui/pxuicamerascreen/) ([`PxUiCameraScreenView`](api/docscanningsdk_ui/pxuicamerascreenview/)) | [`PxUiCameraScreenConfiguration`](api/docscanningsdk_ui/pxuicamerascreenconfiguration/) | [`PxUiCameraScreenResult`](api/docscanningsdk_ui/pxuicamerascreenresult/) / [`PxUiCameraScreenDelegate`](api/docscanningsdk_ui/pxuicamerascreendelegate/) | [Camera capture](/docs/document-scanner-sdk/apple-ios/camera-capture.html) |
| [`PxUiPageCropScreen`](api/docscanningsdk_ui/pxuipagecropscreen/) ([`PxUiPageCropScreenView`](api/docscanningsdk_ui/pxuipagecropscreenview/)) | [`PxUiPageCropScreenConfiguration`](api/docscanningsdk_ui/pxuipagecropscreenconfiguration/) | [`PxUiPageCropScreenResult`](api/docscanningsdk_ui/pxuipagecropscreenresult/) / [`PxUiPageCropScreenDelegate`](api/docscanningsdk_ui/pxuipagecropscreendelegate/) | [Edge detection & cropping](/docs/document-scanner-sdk/apple-ios/edge-detection-and-cropping.html) |
| [`PxUiOcrEditorScreen`](api/docscanningsdk_ui/pxuiocreditorscreen/) ([`PxUiOcrEditorScreenView`](api/docscanningsdk_ui/pxuiocreditorscreenview/)) | [`PxUiOcrEditorScreenConfiguration`](api/docscanningsdk_ui/pxuiocreditorscreenconfiguration/) | [`PxUiOcrEditorScreenResult`](api/docscanningsdk_ui/pxuiocreditorscreenresult/) / [`PxUiOcrEditorScreenDelegate`](api/docscanningsdk_ui/pxuiocreditorscreendelegate/) | [OCR & text recognition](/docs/document-scanner-sdk/apple-ios/ocr-text-recognition.html) |
| [`PxUiLanguagePickerScreen`](api/docscanningsdk_ui/pxuilanguagepickerscreen/) ([`PxUiLanguagePickerScreenView`](api/docscanningsdk_ui/pxuilanguagepickerscreenview/)) | [`PxUiLanguagePickerScreenConfiguration`](api/docscanningsdk_ui/pxuilanguagepickerscreenconfiguration/) | [`PxUiLanguagePickerScreenResult`](api/docscanningsdk_ui/pxuilanguagepickerscreenresult/) / [`PxUiLanguagePickerScreenDelegate`](api/docscanningsdk_ui/pxuilanguagepickerscreendelegate/) | [OCR languages](/docs/document-scanner-sdk/apple-ios/ocr-languages.html) |
Each SwiftUI wrapper takes the inputs its screen needs — a configuration, plus a picture and cutout for the crop editor, or a `PxUiOcrEditorSession` for the OCR editor — and calls back with the result; the UIKit controller uses the matching delegate. The language picker additionally exposes [`PxUiLanguagePickerSelection`](api/docscanningsdk_ui/pxuilanguagepickerselection/) and a [`PxUiLanguagePickerSelectionStore`](api/docscanningsdk_ui/pxuilanguagepickerselectionstore/) for persisting the selection.
## Customisation
On-screen text is overridable and localisable through the strings table — see [Customising the ready-to-use UI](/docs/document-scanner-sdk/apple-ios/customizing-the-ui.html). Per-screen behaviour is set through each screen's `*Configuration`.
## See also
- The underlying engine: [API reference — core engine](/docs/document-scanner-sdk/apple-ios/core-api.html).
- [Core engine vs ready-to-use UI](/docs/document-scanner-sdk/apple-ios/engine-vs-ready-to-use-ui.html) — choosing your level.
## Get Started
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/get-started.html
Installation
The Pixelnetica Document Scanning SDK for .NET MAUI is distributed as a NuGet package. To install the Pixelnetica.DocScanSDK.Maui package in Visual Studio:
Open your solution in Visual Studio.
Select the target project and go to Project → Manage NuGet Packages.
Ensure nuget.org is set as the package source and search for Pixelnetica.DocScanSDK.Maui.
Click Install to add the DSSDK package to your project.
After installation, the SDK is referenced in your project and ready to use.
Permissions
Android Permissions
Add the following entries to your app’s AndroidManifest.xml file:
Require OpenGL ES 2.0 support:
Enable large heap and hardware acceleration in the tag:
Request camera and flashlight access:
iOS Permissions
To allow document scanning from the camera and photo library, add the following keys to your app’s Info.plist file:
NSCameraUsageDescription
This app requires access to the camera to take document photos.
NSPhotoLibraryUsageDescription
This app requires access to the photo library to load documents.
Initialization
Initialize DSSDK before using it. Initialization must be performed only once per application lifetime.
Pass your license key as a parameter to UsePixelnetica(). The license key can be loaded from a variable, a file, or another storage mechanism. If UsePixelnetica() is called without parameters, the SDK will attempt to locate the license key in the default locations of the main application project:
Resources/Raw/Android_License.key — Android license key
Resources/Raw/iOS_License.key — iOS license key
For both files, set the Build Action to MauiAsset.
It is recommended to embed the license key directly in the application code. This approach ensures maximum availability and security; however, it reduces flexibility, as any license update will require recompilation of the application.
SDK initialization requires a call to UsePixelnetica inside the CreateMauiApp method. The following example shows how to add UsePixelnetica to an existing CreateMauiApp implementation:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UsePixelnetica() // or .UsePixelnetica(LicenseKeyString)
.UseMauiCommunityToolkit()
Alternatively, the license key can be stored on an external server and retrieved at runtime during SDK initialization. Be aware that this approach introduces a dependency on server availability: users without network access will not be able to use the SDK.
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp()
.UsePixelnetica(DeviceInfo.Current.Platform == DevicePlatform.Android ? AndroidKey : iOSKey) // AndroidKey and iOSKey are string values containing the Android and iOS licenses
.UseMauiCommunityToolkit()
## ImageSdk Modules
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/imagesdk-modules.html
Processing
The Processing module handles document detection, correction, and binarization.
⚠️ Important: All methods of this module (including creation) must be called from the same thread.
Module Creation
ImageProcessing sdk = new ImageProcessing();
Resource Management
We recommend utilizing the using statement to ensure proper disposal of resources:
using (ImageProcessing ip = new ImageProcessing())
{
// your processing code here
}
Loading Image Metadata with MetaImage
The most convenient way to load metadata is by using a ContentResolver and an image Uri:
string imageUri = ... // basic Uri
MetaImage sourceImage = MetaImage.FromStream(stream, imageUri);
There are multiple methods available to create a MetaImage.
Document Detection
Corners corners = sdk.DetectDocumentCorners(sourceImage);
After detection, you can allow users to confirm or adjust the detected document boundaries.
Document Cropping and Correction
This step aligns the document image, applies perspective correction, and crops it according to the detected or user-adjusted boundaries.
MetaImage croppedImage = sdk.CorrectDocument(sourceImage, corners);
Image Processing and Binarization
Use this set of methods depending on the desired output format: black-and-white for OCR and archival, grayscale for compact storage, enhanced color for readability, or orientation correction when only alignment is needed.
The SDK provides four image processing methods:
// Binarize to **Black and White** image
targetImage = sdk.ImageBWBinarization(croppedImage);
// Convert to **Grayscale** image
targetImage = sdk.ImageGrayBinarization(croppedImage);
// Convert to a **Color** image with content-aware enhancements such as noise removal, background cleaning, and improved contrast and color balance
targetImage = sdk.ImageColorBinarization(croppedImage);
// Rotate to the correct orientation while keeping **Original** colors
targetImage = sdk.ImageOriginal(croppedImage);
## ImageWriter Module
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/imagewriter-module.html
The ImageWriter module provides functionality for saving processed images or scanned pages into various output formats, such as JPEG, PNG, PDF, or TIFF.
Creation
We recommend using using statements to ensure writer instances are automatically disposed of after use.
using (ImageWriter writer = new ImageWriter(ImageWriter.EImageFileType.Pdf))
{
...
}
The module supports the following writer types:
Writer Type
Description
ImageSdkLibrary.ImageWriterJpeg
Writes color JPEG images.
ImageSdkLibrary.ImageWriterPng
Writes color PNG images.
ImageSdkLibrary.ImageWriterWebM
Writes WebM images.
ImageSdkLibrary.ImageWriterPngExt
Writes 1-bit black-and-white PNG images.
ImageSdkLibrary.ImageWriterPdf
Writes PDF documents.
ImageSdkLibrary.ImageWriterTiff
Writes 1-bit black-and-white TIFF-G4 compressed images (most compact black-and-white format).
Writing Images
To write one or multiple images (or document pages), specify the output file path:
writer.Open(filePath);
You can also configure additional optional parameters specific to the writer type (e.g., JPEG compression quality or PDF page size):
writer.Configure(key, value);
To write a single image or page:
writer.Write(image);
For multipage documents, call Write() multiple times for each page.
Further Reference
For more details, please refer to the .NET MAUI demo application source code on GitHub.
## Overview
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/introduction.html
Introduction
Pixelnetica’s Document Scanning SDK (DSSDK) (DSSDK) provides developers with an intelligent and efficient toolkit for integrating advanced image processing features into their .NET MAUI applications. These features are specifically optimized for document photos captured with mobile devices or document cameras.
The SDK streamlines paperless workflows by preprocessing document images to enhance visual quality and legibility, making them easier to use with Optical Character Recognition (OCR) programs and systems.
For more details about the main features and benefits of DSSDK, see the full list of features on the Pixelnetica website.
Prerequisites
Latest Microsoft Visual Studio with .NET MAUI
For Android projects: Android SDK
For iOS projects: a macOS system with the latest Xcode installed
Supported Platforms
Android: Google Android 5.1 (API Level 22) and higher
iOS: Apple iOS 12.2 and above
Demo Applications
To demonstrate the key features of the Document Scanning SDK for .NET MAUI and their use in real applications, we provide demo applications with full source code:
DSSDK Demo Application for .NET MAUI →
Licensing
The Document Scanning SDK (DSSDK) is a commercial product and requires a license for each application on each platform (e.g., iOS, Android).
Licensing options, pricing plans, discounts, and purchase details are available on the Pixelnetica website.
Demo and Trial Licenses
⚠️ The demo application source code is provided “as is”, without warranties, and may be used in commercial products only with a valid DSSDK license. DSSDK .NET MAUI demo applications include Demo License Keys, which function like commercial licenses but watermark the output. These keys can also be used in other applications for development and testing purposes only, where all generated documents will include watermarks.
To evaluate DSSDK without watermarks, a free trial license is available on request.
🚫 Demo and trial licenses are strictly limited to development and staging purposes. Distribution, marketing, or publishing to application stores (including but not limited to the App Store and Google Play) using demo or trial licenses is strictly prohibited.
## Manual Crop Component
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/manual-crop.html
The **Manual Crop** component allows users to edit document boundaries, rotate, and crop images directly within the app.
This component can be integrated into the application interface as a `View`.
* Class: `ImageSdkWrapper.Forms.PxlCropImageView`
Key methods:
* `TakeToolBar` – retrieves the toolbar, so buttons can be flexibly placed in the UI.
* `UiSetMetaImage` – sets the picture and parameters obtained from a scanner or file.
Usage examples can be found in the [.NET MAUI demo application](https://github.com/Pixelnetica/net-maui-pdf-ocr-document-scanner "Document Scanner SDK .NET MAUI Demo application source code") under `MainPage.cs`.
## Customization Properties
### Document boundary colors
* `Color NonActiveEdgeColor`
* `Color EdgeActiveColor`
* `Color EdgeMoveColor`
* `Color EdgeInvalidColor`
### Corner colors
* `Color CornerActiveColor`
* `Color CornerMoveColor`
* `Color CornerInvalidColor`
### Zoom and touch settings
* `double ZoomInMovingMode` – zooms in when a corner is touched.
* `double TouchRadius` – defines the touch detection radius.
### Toolbar appearance
* `Color ToolBarBackgroundColor`
* `double ToolBarHeight`
* `Thickness ToolBarPadding`
* `double ToolBarButtonsSpace`
### Safe area padding
* `Thickness SafeAreaPadding`
### Toolbar buttons
* `ImageButton MenuButton`
* `ImageButton RotateLeftButton`
* `ImageButton RotateRightButton`
* `ImageButton SelectButton`
* `ImageButton CloseButton`
### Events
* `event EventHandler ActiveChanged;` – triggered when the component enters or exits edit mode.
* `event EventHandler OnMenu;` – triggered when the user taps the menu button.
## Smart Camera Component
https://www.pixelnetica.com/docs/document-scanner-sdk/net-maui/smart-camera.html
The **Smart Camera** component enables document scanning using the device camera with built-in guidance for better capture quality.
This component can be integrated into the application interface as a `View`.
* Class: `ImageSdkWrapper.Forms.PxlScannerView`
Events:
* `PictureReceiver` – returns a scanned image or error.
* `CloseClicked` – triggered if the user cancels scanning.
Usage examples are provided in the demo app, under `CameraMainPage.xaml.cs`.
```csharp
p.PictureReceiver = MyPictureReceiver;
void MyPictureReceiver(MetaImage img, string errorTextOrNull)
{
if (img == null)
{
Console.WriteLine(errorTextOrNull);
}
else
{
// Handle scanned image
}
}
```
## Smart Camera Detectors
The Smart Camera includes three detectors that interactively analyze the viewfinder to prevent common mistakes:
* `ShakeDetection` – avoids blurred images caused by device shaking.
* `DocumentArea` – ensures the document occupies a sufficient portion of the frame.
* `TrapezoidDistortion` – detects and warns about perspective distortion.
These detectors can be disabled (e.g., to improve scanning speed):
```csharp
ImageSdkWrapper.Forms.Camera.Settings.DocumentArea = false;
```
## Customization Properties
### Bottom toolbar
* `Color PanelBackgroundColor`
* `Thickness PanelPadding`
* `Thickness CloseButtonPadding`
* `double ButtonsSize`
* `double CloseButtonsSize`
### Safe area padding
* `Thickness SafeAreaPadding` – recommended for devices with non-standard screen shapes.
### Shutter button
* `double ShotButtonSize`
* `Color ShotButtonBorderColor`
### Camera status display
* `double StateTextVerticalDiv`
* `Color StateBackgroundColor`
* `Color StateTextColor`
* `Thickness StateTextPadding`
* `double StateTextFontSize`
### Localization
Camera messages can be localized by editing static strings in the demo app (`CameraMainPage.xaml.cs`):
* `Msg.shot_busy = "Camera busy";`
* `Msg.shot_not_stable = "Camera is shaking";`
* `Msg.looking_for_document = "Looking for document";`
* `Msg.small_area = "Move camera closer to document";`
* `Msg.distorted = "Hold camera parallel to document";`
* `Msg.unstable = "Don't move camera";`