文档扫描与图像处理

React Native扫描图书ISBN码

国际标准书号(ISBN)是一种商业图书的数字标识符。我们可以在书的背面找到它。一个EAN-13格式的条码通常会被打印着,以供机器进行扫描。

在本文中,我们将构建一个React Native应用,使用Dynamsoft Barcode Reader扫描ISBN并使用Google Book API获取图书信息。

演示视频:

创建新的React Native项目

使用特定版本创建新的React Native项目:

npx @react-native-community/cli init ISBNScanner --version 0.75.2

添加Dynamsoft Barcode Reader

安装Dynamsoft Capture Vision(内含Dynamsoft Barcode Reader):

npm install dynamsoft-capture-vision-react-native

设置许可证

App.tsx添加以下代码以在应用启动时设置许可证。可以在此处申请许可证

useEffect(()=>{
  LicenseManager.initLicense('LICENSE-KEY')
  .then(()=>{/*Init license successfully.*/})
  .catch(error => console.error('Init License failed.', error));
},[]);

请求相机权限

  1. 将以下行添加到Info.plist来声明iOS端相机的用途。

    <key>NSCameraUsageDescription</key>
    <string>For barcode scanning</string>
    
  2. 应用启动后,请求相机权限。

    useEffect(()=>{
      CameraEnhancer.requestCameraPermission();
    },[]);
    

编写ISBN扫描组件

  1. 使用以下模板在components/BarcodeScanner.tsx下创建新文件:

    import React, {useEffect, useRef} from 'react';
    import {DecodedBarcodesResult} from 'dynamsoft-capture-vision-react-native';
    import { StyleSheet } from 'react-native';
    
    export interface ScannerProps{
      onScanned?: (result:DecodedBarcodesResult) => void;
    }
    
    export function BarcodeScanner(props:ScannerProps) {
      return (
        <></>
      );
    }
    const styles = StyleSheet.create({
      container: {
        flex:1,
      },
    });
    
  2. 添加一个CameraView组件。

    export function BarcodeScanner(props:ScannerProps) {
       const cameraView = useRef<CameraView>(null);
       return (
         <CameraView style={styles.container} ref={cameraView} />
       );
    }
    
  3. 获取Camera实例以打开相机,并在CameraView组件中显示视频流。

    export function BarcodeScanner(props:ScannerProps) {
      const cameraView = useRef<CameraView>(null);
      const camera = CameraEnhancer.getInstance();
      useEffect(() => {
        camera.setCameraView(cameraView.current!!);
        camera.open();
        return () => {
          //close the camera when the component is going to be unmounted
          camera.close();
        };
      }, [camera, cameraView, props]);
    
      return (
        <CameraView style={styles.container} ref={cameraView} />
      );
    }
    
  4. 获取Capture Vision Router的实例,以调用Barcode Reader从视频流读取条形码。

    export function BarcodeScanner(props:ScannerProps) {
      const router = CaptureVisionRouter.getInstance();
      useEffect(() => {
        //...
        router.initSettings(dotcodeTemplate);
        router.setInput(camera);
        let resultReceiver = router.addResultReceiver({
          onDecodedBarcodesReceived: (result: DecodedBarcodesResult) =>  {
            console.log('scanned');
            if (props.onScanned) {
              props.onScanned(result);
            }
          },
        });
    
        router.startCapturing(EnumPresetTemplate.PT_READ_SINGLE_BARCODE);
    
        return () => {
          //...
          router.removeResultReceiver(resultReceiver!);
        };
      }, [camera, router, cameraView, props]);
    }
    
  5. 将条形码格式指定为EAN-13,避免错误地读取其它格式的条码。

    let settings: SimplifiedCaptureVisionSettings = {
      barcodeSettings: {
        barcodeFormatIds:  EnumBarcodeFormat.BF_EAN_13,
      }
    };
    await router.updateSettings(settings,EnumPresetTemplate.PT_READ_SINGLE_BARCODE);
    

使用ISBN扫描组件

更新App.tsx以使用ISBN扫描组件扫描并显示结果。

import React, { useEffect } from 'react';
import {
  Button,
  SafeAreaView,
  StyleSheet,
  Text,
  View,
} from 'react-native';
import { BarcodeScanner } from './components/BarcodeScanner';
import { CameraEnhancer, DecodedBarcodesResult, LicenseManager } from 'dynamsoft-capture-vision-react-native';

function App(): React.JSX.Element {
  const [isScanning, setIsScanning] = React.useState(false);
  const [barcodeText, setBarcodeText] = React.useState('');
  useEffect(()=>{
    LicenseManager.initLicense('LICENSE-KEY')
    .then(()=>{/*Init license successfully.*/})
    .catch(error => console.error('Init License failed.', error));
    CameraEnhancer.requestCameraPermission();
  },[]);

  const toggleScanning = () => {
    setIsScanning(!isScanning);
  };

  const onScanned = (result:DecodedBarcodesResult) => {
    if (result.items && result.items.length > 0) {
      console.log(result.items[0].text);
      toggleScanning();
      setBarcodeText(result.items[0].text);
    }
  };

  return (
    <SafeAreaView style={styles.container}>
      {isScanning &&
      <>
        <BarcodeScanner
          onScanned={onScanned}
        />
        <View style={styles.controls}>
          <Button title="Stop Scanning" onPress={toggleScanning}/>
        </View>
      </>}
      {!isScanning &&
        <View style={styles.home}>
          <Text>DotCode Scanner</Text>
          <Button title="Start Scanning" onPress={toggleScanning}/>
          {barcodeText &&
            <Text>{'Result: ' + barcodeText}</Text>
          }
        </View>
      }
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex:1,
  },
  home:{
    alignItems:'center',
  },
  controls:{
    position:'absolute',
    width:'100%',
    alignItems:'center',
    bottom:10,
  },
  button:{
    width: '50%',
  },
});

export default App;

通过Google Book API获取图书信息

我们可以更进一步,检索图书信息,如作者、标题、出版商和封面图片。

const response = await fetch(
  'https://www.googleapis.com/books/v1/volumes?q=isbn:'+ISBN,
);
const json = await response.json();
const bookItem = json.items[0];
const title = bookItem.volumeInfo.title;
const publisher = bookItem.volumeInfo.publisher;
const authors = bookItem.volumeInfo.authors.join(",");
const imageLink = bookItem.volumeInfo.imageLinks.thumbnail;

源代码

获取源代码来自己试用一下吧:

https://github.com/tony-xlh/react-native-isbn-scanner