로메오의 블로그

[IONIC] Document Scanner 본문

Frontend/angular

[IONIC] Document Scanner

romeoh 2020. 5. 14. 09:52
반응형

ionic 차례

 

프로젝트 생성

$ ionic start first-project
$ ionic cordova platform add android
$ ionic cordova platform add ios

 

Camera 설치

$ ionic cordova plugin add cordova-plugin-camera
$ yarn add @ionic-native/camera

 

Document Scanner 설치

$ ionic cordova plugin add cordova-plugin-document-scanner
$ yarn add @ionic-native/document-scanner

 

File 설치

$ ionic cordova plugin add cordova-plugin-file
$ yarn add @ionic-native/file

 

File Openner 설치

$ ionic cordova plugin add cordova-plugin-file-opener2
$ yarn add @ionic-native/file-opener

 

jspdf 설치

$ yarn add jspdf

 

ImagePicker 설치 

$ ionic cordova plugin add cordova-plugin-telerik-imagepicker
$ yarn add @ionic-native/image-picker

 

Android Support Library Release 설치 

ImagePicker 사용을 위해 Android Support Library 버전을 27.+ 로 업그레이드 합니다.

$ cordova plugin add cordova-android-support-gradle-release

 

ImageResizer 설치

$ ionic cordova plugin add info.protonet.imageresizer
$ yarn add @ionic-native/image-resizer

 

Base64ToGallery 설치

$ ionic cordova plugin add cordova-base64-to-gallery
$ yarn add @ionic-native/base64-to-gallery

 

Base64 설치

$ ionic cordova plugin add com-badrit-base64
$ yarn add @ionic-native/base64

 

 

 

app module 추가

app.module.ts

...
import { DocumentScanner } from '@ionic-native/document-scanner/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { File } from '@ionic-native/file/ngx';
import { ImagePicker } from '@ionic-native/image-picker/ngx';
import { ImageResizer } from '@ionic-native/image-resizer/ngx';
import { Base64ToGallery } from '@ionic-native/base64-to-gallery/ngx';
import { Base64 } from '@ionic-native/base64/ngx';

@NgModule({
  ...
  providers: [
    ...
    DocumentScanner,
    File,
    FileOpener,
    ImagePicker,
    ImageResizer,
    Base64ToGallery,
    Base64,
  ],
  ...
})
...
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { DocumentScanner } from '@ionic-native/document-scanner/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { File } from '@ionic-native/file/ngx';
import { ImagePicker } from '@ionic-native/image-picker/ngx';
import { ImageResizer } from '@ionic-native/image-resizer/ngx';
import { Base64ToGallery } from '@ionic-native/base64-to-gallery/ngx';
import { Base64 } from '@ionic-native/base64/ngx';


@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    AppRoutingModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    DocumentScanner,
    File,
    FileOpener,
    ImagePicker,
    ImageResizer,
    Base64ToGallery,
    Base64,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

 

화면처리

/src/app/folder/foler.page.html

<ion-header [translucent]="true">
    <ion-toolbar>
        <ion-buttons slot="start">
            <ion-menu-button></ion-menu-button>
        </ion-buttons>
        <ion-title>{{ doc }}</ion-title>
    </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
    <ion-header collapse="condense">
        <ion-toolbar>
            <ion-title size="large">{{ doc }}</ion-title>
        </ion-toolbar>
    </ion-header>

    <div id="container">
        <ion-item>
            <ion-button (click)="scanDoc()" expand="block" fill="clear" shape="round">
                Scan DOC
            </ion-button>
        </ion-item>
        <ion-item>
            <ion-button (click)="imagePick()" expand="block" fill="clear" shape="round">
                Pick Images
            </ion-button>
        </ion-item>
        <ion-item>
            <ion-button (click)="makePdf()" expand="block" fill="clear" shape="round">
                Make a PDF
            </ion-button>
        </ion-item>
    </div>

    <ion-grid>
        <ion-row>
            <ion-col>
                <!-- More Pinterest floating gallery style -->
                <div class="images">
                    <div class="one-image" *ngFor="let img of imageResponse">
                        <img class="selected-img" src="{{img}}" alt="" srcset="">
                    </div>
                </div>
            </ion-col>
        </ion-row>
    </ion-grid>
</ion-content>

 

 

/src/app/folder/foler.page.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { DocumentScanner, DocumentScannerOptions } from '@ionic-native/document-scanner/ngx';
import * as jsPDF from 'jspdf';
import { File, IWriteOptions } from '@ionic-native/file/ngx';
import { FileOpener } from '@ionic-native/file-opener/ngx';
import { ImagePicker } from '@ionic-native/image-picker/ngx';

@Component({
    selector: 'app-folder',
    templateUrl: './folder.page.html',
    styleUrls: ['./folder.page.scss'],
})
export class FolderPage implements OnInit {
    imageResponse: any;
    doc: string;

    constructor(
        private activatedRoute: ActivatedRoute,
        private documentScanner: DocumentScanner,
        private file: File,
        private fileOpener: FileOpener,
        private imagePicker: ImagePicker
    ) {
        this.doc = this.activatedRoute.snapshot.paramMap.get('id');
    }

    ngOnInit() {
    }

    taskDate() {

        var d = new Date();
        var month = '' + (d.getMonth() + 1);
        var day = '' + d.getDate();
        var year = d.getFullYear();

        if (month.length < 2) month = '0' + month;
        if (day.length < 2) day = '0' + day;

        return [year, month, day].join('-');
    }

    // https://github.com/DrPradipBhatt/docscan/blob/master/src/app/docview/docview.page.ts
    scanDoc() {
        let opts: DocumentScannerOptions = {};
        this.documentScanner
            .scanDoc(opts)
            .then((res: string) => {
                debugger
                console.log(res);
                var uuid = "" + Math.round(new Date().getTime() / 1000);
                var docname = this.taskDate() + "_" + uuid;
                let n = res.lastIndexOf("/");
                let oldpath = res.substr(0, n);
                let oldfile = res.substr(n + 1);
                let newpath = this.file.documentsDirectory + this.doc;
                let newfile = "doc_" + docname + '.jpg';

                //let pdfOutput = doc.output();
                let buffer = new ArrayBuffer(1);
                const directory = this.file.documentsDirectory;
                let options: IWriteOptions = { replace: true };

                this.file.checkFile(directory, newfile).then((success) => {
                    this.file.writeFile(directory, newfile, buffer, options)
                        .then((success) => {
                            console.log("File created Succesfully" + JSON.stringify(success));
                            // this.fileOpener.open(this.file.dataDirectory + fileName, 'application/pdf')
                            //     .then(() => console.log('File is opened'))
                            //     .catch(e => console.log('Error opening file', e));
                        })
                        .catch((error) => {
                            console.log(error);
                        });
                }).catch((error) => {
                    console.log(error)
                })
            })
    }


    imagePick() {
        this.imageResponse = [];

        const options = {
            width: 960,
            height: 1280,
            outputType: 1
        };
        this.imagePicker.getPictures(options)
            .then((results) => {
                for (var i = 0; i < results.length; i++) {
                    this.imageResponse.push('data:image/jpeg;base64,' + results[i]);
                }
            }, (err) => {
                console.error(err);
            });
    }

    makePdf() {
        var doc = new jsPDF('p', "mm", "a4");
        doc.deletePage(1);

        let images = document.getElementsByClassName('selected-img');
        for (var i = 0; i < images.length; i++) {
            let imgObj = images[i] as HTMLImageElement;
            let imgWidth = Math.floor(imgObj.naturalWidth * 0.264583);
            let imgHeight = Math.floor(imgObj.naturalHeight * 0.264583);

            let newWidth = imgWidth;
            let newHeight = imgHeight;

            doc.addPage('a4', imgWidth < imgHeight ? 'p' : 'l');

            var pageWidth = doc.internal.pageSize.getWidth();
            var pageHeight = doc.internal.pageSize.getHeight();

            if (imgWidth > pageWidth || imgHeight > pageHeight) {


                if (imgWidth > imgHeight) {
                    newHeight = imgHeight * (pageWidth / imgWidth);
                    newWidth = pageWidth;
                } else {
                    newWidth = imgWidth * (pageHeight / imgHeight);
                    newHeight = pageHeight;
                }
            }

            console.log("[IMG] W:", imgWidth, "H:", imgHeight);
            console.log("[NEW] W:", newWidth, "H:", newHeight);

            doc.addImage(this.imageResponse[i], 'PNG', (pageWidth - newWidth) / 2, (pageHeight - newHeight) / 2, newWidth, newHeight);
        }

        let pdfOutput = doc.output();
        let buffer = new ArrayBuffer(pdfOutput.length);
        let array = new Uint8Array(buffer);
        for (var i = 0; i < pdfOutput.length; i++) {
            array[i] = pdfOutput.charCodeAt(i);
        }

        const directory = this.file.dataDirectory;
        const fileName = "export.pdf";
        let options: IWriteOptions = { replace: true };

        this.file.checkFile(directory, fileName).then((success) => {
            //Writing File to Device
            this.file.writeFile(directory, fileName, buffer, options)
                .then((success) => {
                    console.log("File created Succesfully" + JSON.stringify(success));
                    this.fileOpener.open(this.file.dataDirectory + fileName, 'application/pdf')
                        .then(() => console.log('File is opened'))
                        .catch(e => console.log('Error opening file', e));
                })
                .catch((error) => {
                    console.log(error);
                });
        })
            .catch((error) => {
                //Writing File to Device
                this.file.writeFile(directory, fileName, buffer)
                    .then((success) => {
                        console.log("File created Succesfully" + JSON.stringify(success));
                        this.fileOpener.open(this.file.dataDirectory + fileName, 'application/pdf')
                            .then(() => console.log('File is opened'))
                            .catch(e => console.log('Error opening file', e));
                    })
                    .catch((error) => {
                        console.log("Cannot Create File " + JSON.stringify(error));
                    });
            });
    }

}

 

/src/app/folder/foler.page.scss

ion-menu-button {
  color: var(--ion-color-primary);
}

#container {
  text-align: center;
}

#container strong {
  font-size: 20px;
  line-height: 26px;
}

#container p {
  font-size: 16px;
  line-height: 22px;
  color: #8c8c8c;
  margin: 0;
}

#container a {
  text-decoration: none;
}

 

빌드하기

$ ionic cordova build ios && ionic cordova run ios --device

메인화면

 

 

 

ScanDoc - 문서 촬영 화면

 

 

 

사진 선택 화면

 

 

사진 불러오기 화면

 

 

사진을 PDF로 만든 화면

 

반응형

'Frontend > angular' 카테고리의 다른 글

[IONIC] 파일 업로드 - to Spring  (0) 2020.05.29
[IONIC] navigation 파라미터 넘기기  (0) 2020.05.26
[IONIC] Firebase Firestore 연결  (0) 2020.02.13
[IONIC] Firebase Login  (1) 2020.02.12
[IONIC] Firebase hosting 으로 배포하기  (0) 2020.02.07
Comments