From 7d81b9e0d31ce627355370d8ffaae51eec18424b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20M=C3=BCller?= Date: Fri, 16 Feb 2018 08:12:10 +0100 Subject: [PATCH] Focus and Performance Optimization (#2) * Expand focus * Footer/Header + Focus * Rotate image at end (performance optimization) --- package-lock.json | 89 ++++++++++++++++++------------------ src/classes/picture.ts | 1 + src/pages/camera/camera.html | 4 +- src/pages/camera/camera.ts | 84 ++++++++++++++++++++++++++-------- src/pages/edit/edit.html | 2 +- src/pages/edit/edit.ts | 21 ++------- 6 files changed, 118 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 117defc..d0ae829 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ionic-multi-camera", - "version": "0.0.0", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -109,9 +109,9 @@ "dev": true }, "@types/node": { - "version": "8.5.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.7.tgz", - "integrity": "sha512-+1ZfzGIq8Y3EV7hPF7bs3i+Gi2mqYOiEGGRxGYPrn+hTYLMmzg+/5TkMkCHiRtLB38XSNvr/43aQ9+cUq4BbBg==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.8.tgz", + "integrity": "sha512-8KmlRxwbKZfjUHFIt3q8TF5S2B+/E5BaAoo/3mgc5h6FJzqxXkCK/VMetO+IRDtwtU6HUvovHMBn+XRj7SV9Qg==", "dev": true }, "abbrev": { @@ -338,13 +338,13 @@ "dev": true }, "autoprefixer": { - "version": "7.2.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.4.tgz", - "integrity": "sha512-am8jJ7Rbh1sy7FvLvNxxQScWvhv2FwLAS3bIhvrZpx9HbX5PEcc/7v6ecgpWuiu0Dwlj+p/z/1boHd8x60JFwA==", + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.5.tgz", + "integrity": "sha512-XqHfo8Ht0VU+T5P+eWEVoXza456KJ4l62BPewu3vpNf3LP9s2+zYXkXBznzYby4XeECXgG3N4i+hGvOhXErZmA==", "dev": true, "requires": { - "browserslist": "2.11.0", - "caniuse-lite": "1.0.30000789", + "browserslist": "2.11.3", + "caniuse-lite": "1.0.30000792", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "6.0.16", @@ -376,7 +376,7 @@ "dev": true, "requires": { "cache-base": "1.0.1", - "class-utils": "0.3.5", + "class-utils": "0.3.6", "component-emitter": "1.2.1", "define-property": "1.0.0", "isobject": "3.0.1", @@ -448,12 +448,12 @@ } }, "browserslist": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.0.tgz", - "integrity": "sha512-mNYp0RNeu1xueGuJFSXkU+K0nH+dBE/gcjtyhtNKfU8hwdrVIfoA7i5iFSjOmzkGdL2QaO7YX9ExiVPE7AY9JA==", + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000789", + "caniuse-lite": "1.0.30000792", "electron-to-chromium": "1.3.30" } }, @@ -497,9 +497,9 @@ } }, "caniuse-lite": { - "version": "1.0.30000789", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000789.tgz", - "integrity": "sha1-Lj2TeyZxM/Y2Ne9/RB+sZjYPyIk=", + "version": "1.0.30000792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz", + "integrity": "sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI=", "dev": true }, "caseless": { @@ -522,15 +522,14 @@ } }, "class-utils": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.5.tgz", - "integrity": "sha1-F+eTEDdQ+WJ7IXbqNM/RtWWQPIA=", + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { "arr-union": "3.1.0", "define-property": "0.2.5", "isobject": "3.0.1", - "lazy-cache": "2.0.2", "static-extend": "0.1.2" }, "dependencies": { @@ -610,7 +609,7 @@ "requires": { "ansi-regex": "2.1.1", "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-iterator": "2.0.3", "memoizee": "0.4.11", "timers-ext": "0.1.2" @@ -724,9 +723,9 @@ } }, "commander": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", - "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", "dev": true }, "component-emitter": { @@ -805,7 +804,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "dashdash": { @@ -1038,9 +1037,9 @@ } }, "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", "dev": true, "requires": { "es6-iterator": "2.0.3", @@ -1054,7 +1053,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-symbol": "3.1.1" } }, @@ -1065,7 +1064,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "es6-weak-map": { @@ -1075,7 +1074,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -1093,7 +1092,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "expand-brackets": { @@ -1204,9 +1203,9 @@ } }, "extglob": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.3.tgz", - "integrity": "sha512-AyptZexgu7qppEPq59DtN/XJGZDrLcVxSHai+4hdgMMS9EpF4GBvygcWWApno8lL9qSjVpYt7Raao28qzJX1ww==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { "array-unique": "0.3.2", @@ -1655,7 +1654,7 @@ "integrity": "sha512-QaNccpZ95AzRtTNtIPbQmPIr9RZsgrd7zlkOr7LASnQbfXTAsjJqRUhdusRoMtZW6bPhLO2qDDGu7woda0mcoA==", "dev": true, "requires": { - "autoprefixer": "7.2.4", + "autoprefixer": "7.2.5", "gulp-util": "3.0.8", "less": "2.7.3", "node-sass": "4.7.2", @@ -2484,7 +2483,7 @@ "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.38" } }, "make-iterator": { @@ -2535,7 +2534,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "es6-weak-map": "2.0.2", "event-emitter": "0.3.5", "is-promise": "2.1.0", @@ -2581,7 +2580,7 @@ "braces": "2.3.0", "define-property": "1.0.0", "extend-shallow": "2.0.1", - "extglob": "2.0.3", + "extglob": "2.0.4", "fragment-cache": "0.2.1", "kind-of": "6.0.2", "nanomatch": "1.2.7", @@ -2873,7 +2872,7 @@ "dev": true, "requires": { "chalk": "1.1.3", - "commander": "2.12.2", + "commander": "2.13.0", "is-my-json-valid": "2.17.1", "pinkie-promise": "2.0.1" } @@ -4236,7 +4235,7 @@ "integrity": "sha1-YcxHp2wavTGV8UUn+XjViulMUgQ=", "dev": true, "requires": { - "es5-ext": "0.10.37", + "es5-ext": "0.10.38", "next-tick": "1.0.0" } }, @@ -4825,9 +4824,9 @@ } }, "zone.js": { - "version": "0.8.19", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.19.tgz", - "integrity": "sha512-l9rofaOs6a4y1W8zt4pDmnCUCnYG377dG+5SZlXNWrTWYUuXFqcJZiOarhYiRVR0NI9sH/8ooPJiz4uprB/Mkg==", + "version": "0.8.20", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.20.tgz", + "integrity": "sha512-FXlA37ErSXCMy5RNBcGFgCI/Zivqzr0D19GuvDxhcYIJc7xkFp6c29DKyODJu0Zo+EMyur/WPPgcBh1EHjB9jA==", "dev": true } } diff --git a/src/classes/picture.ts b/src/classes/picture.ts index 4b3d744..886781c 100644 --- a/src/classes/picture.ts +++ b/src/classes/picture.ts @@ -4,4 +4,5 @@ export interface Picture { normalizedURL: string; fileEntry: FileEntry; base64Data: string; + imageOrientation: number; } diff --git a/src/pages/camera/camera.html b/src/pages/camera/camera.html index b0c2ce1..e93b8ca 100644 --- a/src/pages/camera/camera.html +++ b/src/pages/camera/camera.html @@ -31,11 +31,11 @@ - + - + diff --git a/src/pages/camera/camera.ts b/src/pages/camera/camera.ts index 57cf522..2fccedf 100644 --- a/src/pages/camera/camera.ts +++ b/src/pages/camera/camera.ts @@ -31,6 +31,7 @@ import { base64toBlob, rotateBase64Image } from '../../helpers/picture-mutations export class CameraComponent { @ViewChild('header') header: ElementRef; + @ViewChild('footer') footer: ElementRef; public pictures: Array = []; private callback: (data: PictureResult) => Promise; @@ -111,7 +112,16 @@ export class CameraComponent { public focus(event) { const headerHeight = this.header.nativeElement.offsetHeight; - this.cameraPreview.tapToFocus(event.offsetX, event.offsetY + headerHeight); + const footerHeight = this.footer.nativeElement.offsetHeight; + const xPoint: number = event.offsetX; + const yPoint: number = (event.offsetY - headerHeight) / (window.screen.height - headerHeight - footerHeight) * window.screen.height; + this.cameraPreview.tapToFocus(xPoint, yPoint) + .then(() => { + + }) + .catch(err => { + console.error(err); + }); } public switchCamera(): void { @@ -143,19 +153,20 @@ export class CameraComponent { } public takePicture(): void { + const imageOrientation = this.getImageOrientation(); this.cameraPreview.takePicture(this.pictureOptions) - .then(async picture => { - picture = await this.rotateImageBasedOnOrientation(picture); + .then(picture => { const fileOptions: IWriteOptions = { replace: true }; - this.file.writeFile(this.file.cacheDirectory, uuid() + '.jpeg', base64toBlob(picture, 'image/jpeg'), fileOptions) + return this.file.writeFile(this.file.cacheDirectory, uuid() + '.jpeg', base64toBlob(picture, 'image/jpeg'), fileOptions) .then(fileEntry => { const normalizedURL = normalizeURL(fileEntry.toURL()); this.pictures.push({ fileEntry, normalizedURL, - base64Data: picture + base64Data: picture, + imageOrientation }); }) .catch(err => { @@ -168,7 +179,46 @@ export class CameraComponent { } public finish(): void { - this.exit(); + const promises = []; + this.pictures.forEach(picture => { + promises.push( + new Promise((resolve, reject) => { + rotateBase64Image(picture.base64Data, picture.imageOrientation) + .then(imageData => { + picture.imageOrientation = 0; + picture.base64Data = imageData; + picture.fileEntry.createWriter(fileWriter => { + fileWriter.onwriteend = () => { + resolve(picture); + }; + fileWriter.onerror = function (e) { + reject(e); + }; + const file: Blob = base64toBlob(imageData, 'image/jpeg'); + fileWriter.truncate(file.size); + fileWriter.write(file); + }, err => { + reject(err); + }); + }) + .catch(err => { + reject(err); + }); + }) + ); + }); + + Promise.all(promises) + .then(results => { + this.callback({ + pictures: results + }); + this.doesExit = true; + this.navCtrl.pop(); + }) + .catch(err => { + this.errorHandler(err); + }); } public editPicture(picture: Picture, index: number): void { @@ -196,11 +246,13 @@ export class CameraComponent { } private startCam(): void { + const headerHeight = this.header.nativeElement.offsetHeight; + const footerHeight = this.footer.nativeElement.offsetHeight; const cameraPreviewOpts: CameraPreviewOptions = { x: 0, - y: 0, + y: headerHeight, width: window.screen.width, - height: window.screen.height, + height: window.screen.height - headerHeight - footerHeight, camera: 'rear', tapPhoto: false, previewDrag: false, @@ -237,30 +289,26 @@ export class CameraComponent { this.cameraPreview.stopCamera(); } - private rotateImageBasedOnOrientation(imageData: string): Promise { + private getImageOrientation(): number { if (this.deviceOrientation) { // If landscape if (Math.abs(this.deviceOrientation.x) > Math.abs(this.deviceOrientation.y)) { if (this.deviceOrientation.x > 0) { - return rotateBase64Image(imageData, 270); + return 270; } else { - return rotateBase64Image(imageData, 90); + return 90; } } else { // Portrait upside-down if (this.deviceOrientation.y < 0) { - return rotateBase64Image(imageData, 180); + return 180; } else { // Right-side up - return new Promise((resolve) => { - resolve(imageData); - }); + return 0; } } } else { - return new Promise((resolve) => { - resolve(imageData); - }); + return 0; } } diff --git a/src/pages/edit/edit.html b/src/pages/edit/edit.html index d5591c4..72f6efb 100644 --- a/src/pages/edit/edit.html +++ b/src/pages/edit/edit.html @@ -21,5 +21,5 @@ - + diff --git a/src/pages/edit/edit.ts b/src/pages/edit/edit.ts index a17d33d..fc2f992 100644 --- a/src/pages/edit/edit.ts +++ b/src/pages/edit/edit.ts @@ -5,9 +5,6 @@ import { NavController, NavParams } from 'ionic-angular'; // Classes import { Picture } from '../../classes/picture'; -// Helpers -import { base64toBlob, rotateBase64Image } from '../../helpers/picture-mutations'; - @Component({ selector: 'ionic-multi-edit', templateUrl: 'edit.html', @@ -42,20 +39,10 @@ export class EditComponent { } public rotateLeft(): void { - rotateBase64Image(this.picture.base64Data, 270) - .then(imageData => { - this.picture.base64Data = imageData; - this.picture.fileEntry.createWriter(fileWriter => { - const file: Blob = base64toBlob(imageData, 'image/jpeg'); - fileWriter.truncate(file.size); - fileWriter.write(file); - }, err => { - console.error(err); - }); - }) - .catch(err => { - console.error(err); - }); + this.picture.imageOrientation += 90; + if (this.picture.imageOrientation >= 360) { + this.picture.imageOrientation - 360; + } } }