{"analyzedAt":"2022-07-07T07:37:17.361Z","collected":{"metadata":{"name":"ocr-photo-v2","scope":"unscoped","version":"0.4.0","description":"Document scanning component for Angular. Scan different types of ID documentation to obtain the following outputs: - Fake documentation validation - Data extraction - Photo capture","date":"2021-12-13T10:14:25.801Z","publisher":{"username":"jay_white","email":"jblancofd86@gmail.com"},"maintainers":[{"username":"jay_white","email":"jblancofd86@gmail.com"}],"links":{"npm":"https://www.npmjs.com/package/ocr-photo-v2"},"dependencies":{"tslib":"^2.0.0"},"peerDependencies":{"@angular/common":"^10.1.6","@angular/core":"^10.1.6"},"releases":[{"from":"2022-06-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":0},{"from":"2022-04-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2022-01-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1},{"from":"2021-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":21},{"from":"2020-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":24}],"readme":"# OcrPhoto by TalentoMOBILE\n\nDocument scanning component for Angular.\nScan different types of ID documentation to obtain the following outputs:\n- Fake documentation validation\n- Data extraction\n- Photo capture \n\nTo contact TalentoMobile: soporte@talentomobile.com\n\n\n## INSTALATION\n-------\n\n```\nnpm install ocr-photo-V2\n```\n\n## COMPONENT INPUTS\n-----------\n\n| INPUT  |   |\n|---|---|\n| [env] | Setting the environment. dev, pre, pro as parameters.   |\n| [token] | Validation token. | \n| [docType] | Type of document to be analyze.  | \n\n## COMPONENT OUTPUTS\n-----------\n| INPUT  |   |\n|---|---|\n| (photoTaken) |  Receive the auto photo taken  |\n| (photoMessage) | Receive the message to guide the user fot the automatic photo taken | \n| (error)| Receive any possible error.  | \n\n###  MESSAGE TYPES\n\n  SHOW_DOCUMENT \n  HOLD_DOCUMENT \n  CENTER_DOCUMENT \n  BRING_DOCUMENT_CLOSER \n\n###  ERROR TYPES\n\n  DEVICES_NOT_FOUND_ERROR\n  TRACK_START_ERROR\n  CONSTRAINT_NOT_SATISFIED_ERROR\n  PERMISSION_DENIED_ERROR\n  TYPE_ERROR\n  GENERIC_ERROR\n\n## METHODS ACCESSIBLE FROM TS\n-----------\n\n| OUTPUT  |   | input  | output  |\n|---|---|---|---|\n| takeframe() | Capture Photo manually  |    |  Blob image |  \n| sendFront() | Send the front capture to be analyze. |  Blob image  | FRONT_RESPONSE  |\n| sendBackPhoto() | Send the back capture to be analyze.  |  Blob image   | BACK_RESPONSE |\n| stopVideo() | Close the camera ones the whole capture have finished |   |\n| reset() | Refresh teh photo taken to take a new photo  |   |\n| compressImg() | Compress the image file  | Blob image | Blob image |\n\n###  FRONT_RESPONSE\nThis response will be optimize and resented in the Back response as a global response for the whole process\n\n```json\n  {\n    \"data\":{\n      \"country\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"date_of_birth\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"doc_expire_date\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"doc_number\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"doc_type\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"name\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"nationality\":{\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"opt_cli\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"opt_laser_grab\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"opt_number_can\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"opt_support_number\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"sex\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"surname1\": {\n        \"value\": \"string\", \"confidence\": 0\n        },\n      \"surname2\": {\n        \"value\": \"string\", \"confidence\": 0\n        }\n    },\n    \"docType\": \"string\",\n    \"frontVal\":{\n      \"document_aspect_ratio\": \"boolean\",\n      \"document_aspect_ratio_value\": \"number\",\n      \"document_backwhite_check\": \"boolean\",\n      \"document_typography\": \"boolean\"\n    },\n    \"uuid\": \"string\"\n  }\n\n```\n\n\n###  BACK_RESPONSE\n\n```json\n{ \n  \"result\":\n    {\n        \"doc_type\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"doc_number\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"personal_number\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"doc_expire_date\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"issue_date\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"surname1\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"surname2\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"name\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"sex\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"date_of_birth\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"nationality\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"nationality_code\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"country_expedition\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"country\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"address\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"mrz\": {\n          \"value\": \"string\",\n          \"confidence\": 0\n        },\n        \"mrz_data\": {\n          \"doc_type\": \"string\",\n          \"serial_number\": \"string\",\n          \"nation_code\": \"string\",\n          \"reserve_number\": \"string\",\n          \"date_of_birth\": \"string\",\n          \"doc_expire_date\": \"string\",\n          \"sex\": \"string\",\n          \"nationality_code\": \"string\",\n          \"name\": \"string\",\n          \"surname1\": \"string\",\n          \"surname2\": \"string\",\n          \"checkdigits\": {}\n        },\n        \"validationChecks\": { \n          \"sidesMatch\": \"boolean\",     // ambos lados pertenecen al mismo documento\n          \"validMRZ\": \"boolean\",     // Validación algorítmica del mrz\n          \"expired\": \"boolean\",     // valida si los documentos están vencidos\n          \"legalAge\": \"boolean\",     // valida si el titular del documento es mayor de edad por ley\n          \"quality\": \"boolean\",     // valida que los campos hayan sido capturados. 3 campos vacios o mas  y la fallta del doc_number y mrz deverán un false.\n          \"front\":{\n            \"face_photo\": \"boolean\", // Verifica que hay foto de la cara en el documento\n            \"document_aspect_ratio\" : \"boolena\", // Verifica la proporción de las mediciones (alt x anch)\n            \"document_aspect_ratio_value\": \"number\", // Valor de las proporciones (alt x anch)\n            \"document_backwhite_check\": \"boolean\" // Verifica que el documento esta en blanco y negro\n          },\n          \"back\":{\n            \"char_distance\" : \"boolean\", // Verifica la distancia entre caracteres\n            \"char_distance_value\" : \"number\", // Valor de distancia entre caracteres\n            \"document_aspect_ratio\": \"boolean\", // Verifica la proporción de las mediciones (alt x anch)\n            \"document_aspect_ratio_value\": \"number\", // Valor de las proporciones (alt x anch)\n            \"document_backwhite_check\": \"boolean\", // Verifica que el documento esta en blanco y negro\n            \"mrz_aspect_ratio\": \"boolean\", // Verifica la proporción de las mediciones (alt x anch) del mrz\n            \"mrz_aspect_ratio_value\": \"number\", // Valor de las proporciones (alt x anch) del mrz\n            \"mrz_characters_count_value\": \"number\", // Cantidad de caracteres encontrados en el mrz\n            \"mrz_typography\": \"number\" // Porcentaje de valided en similitud con la fuente ocrb\n          }\n        },\n        \"opt_data\": {},\n        \"global_confidence\": \"boolean\" // Media de todos los confidence obtenidos\n    }\n  },\n  \"error\":{\n    \"code\": \"string\",\n    \"message\": \"string\"\n  }\n}\n```\n\n\n## USAGE EXAMPLE\n--------\n###  app.module.ts (Import in your app module)\n\n\n\n\n```ts\nimport {BrowserModule} from '@angular/platform-browser';\nimport {NgModule} from '@angular/core';\n \nimport {AppComponent} from './app.component';\nimport {OcrPhotoModule} from 'ocr-photo';\n \n@NgModule({\n  declarations: [AppComponent],\n  imports: [BrowserModule],\n  providers: [OcrPhotoModule],\n  bootstrap: [AppComponent]\n})\nexport class AppModule {}\n```\n\n### app.component.ts\n\n```ts\nimport { ChangeDetectorRef, Component, OnInit } from '@angular/core';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { CaptureFrameService } from 'ocr-photo';\n\nenum MessageType {\n  SHOW_DOCUMENT = 'Muestra tu documento de identidad',\n  HOLD_DOCUMENT = 'No muevas el documento',\n  CENTER_DOCUMENT = 'Centra el documento entre los márgenes',\n  BRING_DOCUMENT_CLOSER = 'Acerca el documento ajustándolo a los márgenes'\n}\n\nenum ErrorOcr {\n  DEVICES_NOT_FOUND_ERROR = '',\n  TRACK_START_ERROR = '',\n  CONSTRAINT_NOT_SATISFIED_ERROR = '',\n  PERMISSION_DENIED_ERROR = '',\n  TYPE_ERROR = '',\n  GENERIC_ERROR = '',\n}\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.scss']\n})\nexport class AppComponent implements OnInit {\n\n  public imageTaken: string;\n  public imageToShow\n  public processID : string;\n  public frontFinish = false;\n  public loading = false;\n  public error = false; // Show error \n\n  public photoMessage = '';\n\n  constructor(\n    private captureFrameService:CaptureFrameService,\n    private cdRef:ChangeDetectorRef,\n    private sanitizer: DomSanitizer){}\n\n  ngOnInit() {\n    return null;\n  }\n\n  // TAKE A PHOTO MANUALY AND RETRIVE THE CAPTURE IN BASE64. (we save the photo in a variable )\n  async flashFoto(){\n    this.imageTaken = await this.captureFrameService.takeFrame() as any\n    let objectURL = URL.createObjectURL(this.imageTaken);\n    this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);\n    console.log(this.imageTaken);\n  }\n\n  // SENDING THE PHOTO (FRONT) TO BE ANALYSE. The response can be the end response in case is a ONE-SIDE-DOCUMENT otherwise we will capture the uuid to continue with\n  sendFrontPhoto(){\n    this.loading = true;\n    this.cdRef.detectChanges();\n    this.captureFrameService.sendFront(this.imageTaken).then((res:any) => {\n      console.log(res);\n      if (res.uuid) this.processID = res.uuid\n      this.frontFinish = true;\n      this.imageTaken = '';\n      this.loading = false;\n      this.error = false;\n      this.cdRef.detectChanges();\n    }).catch((err)=>{\n      this.loading = false;\n      this.error = err;\n      this.imageTaken = '';\n      this.cdRef.detectChanges();\n      console.warn(err)\n    })\n  }\n\n  // SENDING THE PHOTO (BACK) TO BE ANALYSE. OBTAINING THE END RESPONSE WITH THE RESULTS\n  sendBackPhoto(){\n    this.loading = true;\n    this.cdRef.detectChanges();\n    this.captureFrameService.sendBack(this.imageTaken, this.processID).then((res) => {\n      console.log(res);\n      this.loading = false;\n      this.error = false;\n      this.cdRef.detectChanges();\n    }).catch((err)=> {\n      this.loading = false;\n      this.error = err;\n      this.imageTaken = '';\n      this.cdRef.detectChanges();\n      console.warn(err)\n    })\n  }\n\n  // CAPTURE THE PHOTO FROM EVENT\n  photoTaken(event){\n    console.log('CAPTURING PHOTO', event);\n    this.imageTaken = event;\n    let objectURL = URL.createObjectURL(this.imageTaken);\n    this.imageToShow = this.sanitizer.bypassSecurityTrustUrl(objectURL);\n    this.cdRef.detectChanges();\n  }\n\n\n  handleError(error){\n    console.log('ERROR');\n    console.log(error);\n  }\n\n  //CAPTURE THE MESSAGE FROM EVENT\n  public changeMessage(event){\n    this.photoMessage = MessageType[event];;\n    this.cdRef.detectChanges();\n  }\n\n    // IMAGE RESIDE BLOB OUTPUT\n  async onChangeFile(event){\n    const file = event.target.files[0];\n\n    const newBlobImg = await new Promise((resolve, reject) => {\n      let reader = new FileReader();\n      reader.onload = async (e:any) => {\n         let blob = new Blob([new Uint8Array(e.target.result)], {type: file.type });\n         const newBlob = await this.captureFrameService.compressImg(blob)\n         resolve(newBlob)\n      };\n      reader.readAsArrayBuffer(file);\n    })\n    console.log(newBlobImg);\n  }\n\n\n}\n\n```\n\n### app.component.html\n\n\n```html\n<div class=\"main_container\">\n  <div>{{frontFinish ? 'Mostrar trasera' : 'Mostrar delantera'}}</div>\n\n  <div class=\"video_box\">\n    <!-- // FOR THE COMPONENT TO WORK ALL THE THREE PARAMETERS MUST BE PASSED CORRECTLY -->\n    <tm-ocr-photo\n      #taken\n      [env]=\"'local'\"\n      (photoTaken)=\"photoTaken($event)\"\n      (photoMessage)=\"changeMessage($event)\"\n      [token]=\"'c23...'\"\n      (error)=\"handleError($event)\"\n      [docType]=\"'ESP_DNI3'\">\n    </tm-ocr-photo>\n  </div>\n\n  <div>{{photoMessage}}</div>\n\n  <button (click)=\"flashFoto()\" style=\"margin-bottom:20px\">Capturar imagen</button>\n\n  <div *ngIf=\"imageTaken\" class=\"photoShow\">\n    <img [src]=\"imageToShow\" alt=\"\">\n    <button *ngIf=\"!frontFinish\" (click)=\"taken.reset(); sendFrontPhoto()\">Confirmar Front</button>\n    <button *ngIf=\"frontFinish\" (click)=\"sendBackPhoto()\">Confirmar Back</button>\n  </div>\n  <div>{{error ? 'Calidad insuficiente' + error : ''}}</div>\n</div>\n\n<div *ngIf=\"loading\" class=\"spinner_box\">\n  <div class=\"lds-ring\"><div></div><div></div><div></div><div></div></div>\n</div>\n\n```\n\n### app.component.scss\n\n```css\n.main_container{\n  margin: 40px;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  .video_box{\n    width: 350px;\n    height: auto;\n  }\n\n  .photoShow{\n    width: 250px;\n    height: 250px;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    img{\n      width: 100%;\n    }\n  }\n}\n\nbutton{\n  margin-top: 20px;\n  cursor: pointer;\n  border-radius: 12px;\n  font-size: 14px;\n  font-weight: 500;\n  line-height: 25px;\n  letter-spacing: 0.5px;\n  width: 100%;\n  max-width: 200px;\n  height: 40px;\n  border: none;\n  background-color: #005db4d8 !important;\n  color: white;\n  &:focus{\n    outline: none;\n  }\n  transition: all 200ms ;\n}\n\n\n////////SPINNER///\n\n.lds-ring {\n  display: inline-block;\n  position: relative;\n  width: 80px;\n  height: 80px;\n}\n.lds-ring div {\n  box-sizing: border-box;\n  display: block;\n  position: absolute;\n  width: 64px;\n  height: 64px;\n  margin: 8px;\n  border: 8px solid #005db4d8;\n  border-radius: 50%;\n  animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n  border-color: #005db4d8 transparent transparent transparent;\n}\n.lds-ring div:nth-child(1) {\n  animation-delay: -0.45s;\n}\n.lds-ring div:nth-child(2) {\n  animation-delay: -0.3s;\n}\n.lds-ring div:nth-child(3) {\n  animation-delay: -0.15s;\n}\n@keyframes lds-ring {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(360deg);\n  }\n}\n\n.spinner_box{\n\n  width: 100%;\n  height: 100%;\n  background: rgba(10, 10, 10, 0.2);;\n  right: 0;\n  top: 0;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  position: fixed;\n}\n```"},"npm":{"downloads":[{"from":"2022-07-06T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":37},{"from":"2022-06-30T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":118},{"from":"2022-06-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":311},{"from":"2022-04-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":902},{"from":"2022-01-08T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":1536},{"from":"2021-07-07T00:00:00.000Z","to":"2022-07-07T00:00:00.000Z","count":2874}],"starsCount":0},"source":{"files":{"readmeSize":14026,"testsSize":0}}},"evaluation":{"quality":{"carefulness":0.19,"tests":0,"health":1,"branding":0},"popularity":{"communityInterest":0,"downloadsCount":300.6666666666667,"downloadsAcceleration":0.7880136986301371,"dependentsCount":0},"maintenance":{"releasesFrequency":0.8891267123287672,"commitsFrequency":0,"openIssues":0,"issuesDistribution":0}},"score":{"final":0.21725443946743164,"detail":{"quality":0.32061221484759234,"popularity":0.012583166704249384,"maintenance":0.3333333333333333}}}