Code Monkey home page Code Monkey logo

capacitor-document-scanner's Introduction

Capacitor Document Scanner

Npm package version npm peer dependency version

This is a Capacitor plugin that lets you scan documents using Android and iOS. You can use it to create apps that let users scan notes, homework, business cards, receipts, or anything with a rectangular shape.

iOS Android
Dollar-iOS Dollar Android

Install

npm install capacitor-document-scanner
npx cap sync

Examples

Basic Example

import { Capacitor } from '@capacitor/core'
import { DocumentScanner } from 'capacitor-document-scanner'

const scanDocument = async () => {
  // start the document scanner
  const { scannedImages } = await DocumentScanner.scanDocument()

  // get back an array with scanned image file paths
  if (scannedImages.length > 0) {
    // set the img src, so we can view the first scanned image
    const scannedImage = document.getElementById('scannedImage') as HTMLImageElement
    scannedImage.src = Capacitor.convertFileSrc(scannedImages[0])
  }
}

Here's what this example looks like with several items

Dollar.iOS.mp4
Dollar.Android.mp4
Business.Card.iOS.mp4
Business.Card.Android.mp4
Sign.iOS.mp4
Sign.Android.mp4
Notes.iOS.mp4
Notes.Android.mp4
Laptop.iOS.mp4
Laptop.Android.mp4

Limit Number of Scans

You can limit the number of scans. For example if your app lets a user scan a business card you might want them to only capture the front and back. In this case you can set maxNumDocuments to 2. This only works on Android.

import { Capacitor } from '@capacitor/core'
import { DocumentScanner } from 'capacitor-document-scanner'

const scanDocument = async () => {
  // limit the number of scans to 2
  const { scannedImages } = await DocumentScanner.scanDocument({
    maxNumDocuments: 2
  })

  // get back an array with scanned image file paths
  if (scannedImages.length > 0) {
    // set the img src, so we can view the first scanned image
    const scannedImage = document.getElementById('scannedImage') as HTMLImageElement
    scannedImage.src = Capacitor.convertFileSrc(scannedImages[0])
  }
}
Limit.Num.Scans.Android.mp4

Remove Cropper

You can automatically accept the detected document corners, and prevent the user from making adjustments. Set letUserAdjustCrop to false to skip the crop screen. This limits the max number of scans to 1. This only works on Android.

import { Capacitor } from '@capacitor/core'
import { DocumentScanner } from 'capacitor-document-scanner'

const scanDocument = async () => {
  // skip the crop screen
  const { scannedImages } = await DocumentScanner.scanDocument({
    letUserAdjustCrop: false
  })

  // get back an array with scanned image file paths
  if (scannedImages.length > 0) {
    // set the img src, so we can view the first scanned image
    const scannedImage = document.getElementById('scannedImage') as HTMLImageElement
    scannedImage.src = Capacitor.convertFileSrc(scannedImages[0])
  }
}
Remove.Cropper.Android.mp4

iOS

iOS requires the following usage description be added and filled out for your app in Info.plist:

  • NSCameraUsageDescription (Privacy - Camera Usage Description)

Read about Configuring Info.plist in the iOS Guide for more information on setting iOS permissions in Xcode

Documentation

scanDocument(...)

scanDocument(options?: ScanDocumentOptions | undefined) => Promise<ScanDocumentResponse>

Opens the camera, and starts the document scan

Param Type
options ScanDocumentOptions

Returns: Promise<ScanDocumentResponse>


Interfaces

ScanDocumentResponse

Prop Type Description
scannedImages string[] This is an array with either file paths or base64 images for the document scan.
status ScanDocumentResponseStatus The status lets you know if the document scan completes successfully, or if the user cancels before completing the document scan.

ScanDocumentOptions

Prop Type Description Default
croppedImageQuality number Android only: The quality of the cropped image from 0 - 100. 100 is the best quality. : 100
letUserAdjustCrop boolean Android only: If true then once the user takes a photo, they get to preview the automatically detected document corners. They can then move the corners in case there needs to be an adjustment. If false then the user can't adjust the corners, and the user can only take 1 photo (maxNumDocuments can't be more than 1 in this case). : true
maxNumDocuments number Android only: The maximum number of photos an user can take (not counting photo retakes) : 24
responseType ResponseType The response comes back in this format on success. It can be the document scan image file paths or base64 images. : ResponseType.ImageFilePath

Enums

ScanDocumentResponseStatus

Members Value Description
Success 'success' The status comes back as success if the document scan completes successfully.
Cancel 'cancel' The status comes back as cancel if the user closes out of the camera before completing the document scan.

ResponseType

Members Value Description
Base64 'base64' Use this response type if you want document scan returned as base64 images.
ImageFilePath 'imageFilePath' Use this response type if you want document scan returned as inmage file paths.

License

Copyright 2022 David Marcus

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

capacitor-document-scanner's People

Contributors

d-marc1 avatar dmarcs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

capacitor-document-scanner's Issues

Upgrade to Capacitor 5?

hi! thanks for all your hard work, it's a really useful plugin, is there any plan to upgrade to capacitor 5?

web implementation?

Any chance that you will be implementing this for the web also?

Although I do not see many usecases for it.

kind regards

Option to start in manual mode.

Would it be possible to add an option to start the scanner in manual mode? In auto mode after I scan a image, it tends to keep scanning the same image over and over. I am hoping that if I can default to manual mode it will stop the users from doing that.
Amazing work by the way. Best document scanner iv seen.

New feature: crop from side and top/bottom

Top scanner !. migrated from Cordova to Capacitor partly because of issues with scanning documents.

Would it be possible to crop 2 points in parallel like in the attached example. (from Cordova document scanner)

In the example, the top and bottom were cropped by the middle touchpoint, the sides will be moved inward by the middle touchpoints to select only the white image.

crop

Android: Missing buttons after cropping when you take full display photo

Hello,
This plugin is very usefull and thank you for it. I have problem on Android. When I open document scanner on my Samsung Galaxy S20 FE, camera is set in full screen photo mode then after take photo I can not aprrove crop. Buttons are hide out of display or under photo and it is not possible to scrool down. When I set 9:16 screen photo modeeverything is ok.

Here is GIF where I took photo Full screen and after I set up 9:16 screen and took photo again: https://ibb.co/3Fy1HYY

Is it possible to set it screen strictly before run document scanner or some soloutions how to fix it? I cannot find solution.

Thank you for yor time.

Tested on: Samsung Galaxy S20 FE, Android 12

D8: Type com.websitebeaver.documentscanner.BuildConfig is defined multiple times

While running the following command:

./gradlew clean bundleRelease

I'm getting the following error:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:mergeDexRelease'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.DexMergingTaskDelegate
   > There was a failure while executing work items
      > A failure occurred while executing com.android.build.gradle.internal.tasks.DexMergingWorkAction
         > com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
           Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
           Type com.websitebeaver.documentscanner.BuildConfig is defined multiple times: /.../node_modules/.pnpm/[email protected]_@[email protected]/node_modules/capacitor-document-scanner/android/build/.transforms/0c5137feee1f7f0dd263bea070ce71e2/transformed/classes/classes.dex, /.../android/app/build/intermediates/external_libs_dex/release/mergeExtDexRelease/classes.dex

Looks like it happens in your own example folder as well

Limit scan to 1 document?

It seems to be possible for Android to set a max. So I imagine is the iOS limitation making it not possible. Or is there some kind of workaround to achieve this?

iOS 15.6.1 - Ionic 6 - Webkit Crashes sometimes in the Background

Hi -

Thanks for your great Work.

In my case, when opening the scanner, the App in the background sometimes crashes and restarts. Therefore not listening to any callbacks and the scanned input is lost. I don't know when exactly it happens. Not depending of the size of the scan.

It might be related to a webkit bug: ionic-team/capacitor#5491

Anyway, here's the log:

⚡️  [log] - start scan
⚡️  To Native ->  DocumentScanner scanDocument 67361918
2022-09-09 14:14:59.176340+0200 App[16404:767529] [XPC] Handle connection with error: Connection interrupted
2022-09-09 14:14:59.176974+0200 App[16404:766008] [Process] 0x113001230 - [PID=16415] WebProcessProxy::didClose: (web process 0 crash)
2022-09-09 14:14:59.177008+0200 App[16404:766008] [Process] 0x113001230 - [PID=16415] WebProcessProxy::processDidTerminateOrFailedToLaunch: reason=4
2022-09-09 14:14:59.177119+0200 App[16404:766008] [ProcessSuspension] 0x111018120 - ProcessAssertion: Failed to acquire RBS Background assertion 'ConnectionTerminationWatchdog' for process because PID 0 is invalid
2022-09-09 14:14:59.177285+0200 App[16404:767530] [ProcessSuspension] 0x111018120 - ProcessAssertion::acquireSync Failed to acquire RBS assertion 'ConnectionTerminationWatchdog' for process with PID=0, error: (null)
2022-09-09 14:14:59.179592+0200 App[16404:766008] [Process] 0x10301d018 - [pageProxyID=7, webPageID=8, PID=16415] WebPageProxy::processDidTerminate: (pid 16415), reason 4
2022-09-09 14:14:59.198168+0200 App[16404:766008] [Loading] 0x10301d018 - [pageProxyID=7, webPageID=8, PID=16415] WebPageProxy::dispatchProcessDidTerminate: reason=Crash
⚡️  [log] - onscript loading complete

Maybe somebody can point me in the right direction for a fix.

Best,
hofer

Webkit Crashes on first time load

I am using
Ionic Angular - 6
Capacitor - 4

When opening camera, the plugin crashes the first time with following error

java.lang.UnsatisfiedLinkError: No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_1(java.lang.String) (tried Java_org_opencv_imgcodecs_Imgcodecs_imread_11 and Java_org_opencv_imgcodecs_Imgcodecs_imread_11__Ljava_lang_String_2)
at org.opencv.imgcodecs.Imgcodecs.imread_1(Native Method)
at org.opencv.imgcodecs.Imgcodecs.imread(Imgcodecs.java:114)
at com.websitebeaver.documentscanner.utils.ImageUtil.getImageFromFilePath(ImageUtil.kt:32)
at com.websitebeaver.documentscanner.DocumentScannerActivity$cameraUtil$1.invoke(DocumentScannerActivity.kt:81)
at com.websitebeaver.documentscanner.DocumentScannerActivity$cameraUtil$1.invoke(DocumentScannerActivity.kt:68)
at com.websitebeaver.documentscanner.utils.CameraUtil.startForResult$lambda-0(CameraUtil.kt:41)
at com.websitebeaver.documentscanner.utils.CameraUtil.$r8$lambda$QtmUm3JcXlX2aa1YkJnrPoMUzS8(Unknown Source:0)
at com.websitebeaver.documentscanner.utils.CameraUtil$$ExternalSyntheticLambda0.onActivityResult(Unknown Source:4)
at androidx.activity.result.ActivityResultRegistry.doDispatch(ActivityResultRegistry.java:409)
at androidx.activity.result.ActivityResultRegistry.dispatchResult(ActivityResultRegistry.java:366)
at androidx.activity.ComponentActivity.onActivityResult(ComponentActivity.java:712)
at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:140)
at android.app.Activity.dispatchActivityResult(Activity.java:8551)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5455)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4904)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4950)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54)
at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2291)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:210)
at android.os.Looper.loop(Looper.java:299)
at android.app.ActivityThread.main(ActivityThread.java:8319)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)

Multi-language support

Hi @dmarcs,
We love this component and would love it even more if there was support for other languages.
How can we make this happen? We'd be open for submitting a pull request, but I'd like to hear your thoughts on how you would like this implemented first.
Thanks,
Marvin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.