@ekyc_qoobiss/qbs-ect-cmp 3.6.25 → 3.6.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/i18n/en.json +100 -0
  2. package/dist/i18n/ro.json +100 -0
  3. package/dist/i18n/ru.json +100 -0
  4. package/dist/{collection/helpers/Cameras.js → qbs-ect-cmp/Cameras-dfbebc29.js} +9 -6
  5. package/dist/{collection/models/CaptureFlow.js → qbs-ect-cmp/CaptureFlow-db5d90a4.js} +6 -4
  6. package/dist/{collection/libs/IDML5Detector/IDPose.js → qbs-ect-cmp/IDPose-181bcb25.js} +4 -2
  7. package/dist/{collection/models/IDevice.js → qbs-ect-cmp/IDevice-15ecfdeb.js} +6 -4
  8. package/dist/qbs-ect-cmp/ML5-657ef934.js +1370 -0
  9. package/dist/qbs-ect-cmp/Stream-b867a2be.js +3104 -0
  10. package/dist/qbs-ect-cmp/_commonjsHelpers-321aa363.js +44 -0
  11. package/dist/qbs-ect-cmp/agreement-check.entry.js +41 -0
  12. package/dist/qbs-ect-cmp/agreement-info.entry.js +66 -0
  13. package/dist/qbs-ect-cmp/app-globals-0f993ce5.js +3 -0
  14. package/dist/qbs-ect-cmp/base-component-2e490fd9.js +502 -0
  15. package/dist/qbs-ect-cmp/camera-comp.entry.js +103 -0
  16. package/dist/qbs-ect-cmp/camera-error.entry.js +59 -0
  17. package/dist/qbs-ect-cmp/capture-error.entry.js +53 -0
  18. package/dist/qbs-ect-cmp/css-shim-b7d3d95f.js +4 -0
  19. package/dist/qbs-ect-cmp/dom-64053c71.js +73 -0
  20. package/dist/qbs-ect-cmp/end-redirect.entry.js +25 -0
  21. package/dist/qbs-ect-cmp/error-end.entry.js +19 -0
  22. package/dist/qbs-ect-cmp/how-to-info.entry.js +52 -0
  23. package/dist/{collection/components/common/id-back-capture/id-back-capture.js → qbs-ect-cmp/id-back-capture.entry.js} +30 -100
  24. package/dist/{collection/components/common/id-capture/id-capture.js → qbs-ect-cmp/id-capture.entry.js} +28 -98
  25. package/dist/{collection/components/common/id-tilt/id-tilt.js → qbs-ect-cmp/id-tilt.entry.js} +28 -98
  26. package/dist/qbs-ect-cmp/identification-component.entry.js +909 -0
  27. package/dist/qbs-ect-cmp/index-78a05b9e.js +3371 -0
  28. package/dist/qbs-ect-cmp/index.esm.js +1 -0
  29. package/dist/qbs-ect-cmp/landing-validation.entry.js +90 -0
  30. package/dist/{esm → qbs-ect-cmp}/loader-dots.entry.js +1 -1
  31. package/dist/qbs-ect-cmp/mobile-redirect.entry.js +2984 -0
  32. package/dist/{collection/components/flow/process-id/process-id.js → qbs-ect-cmp/process-id.entry.js} +32 -100
  33. package/dist/qbs-ect-cmp/qbs-ect-cmp.css +320 -1
  34. package/dist/qbs-ect-cmp/qbs-ect-cmp.esm.js +148 -1
  35. package/dist/{esm → qbs-ect-cmp}/random-actions.entry.js +6 -3
  36. package/dist/{collection/components/common/selfie-capture/selfie-capture.js → qbs-ect-cmp/selfie-capture.entry.js} +28 -99
  37. package/dist/{collection/components/common/selfie-tilt/selfie-tilt.js → qbs-ect-cmp/selfie-tilt.entry.js} +29 -99
  38. package/dist/qbs-ect-cmp/shadow-css-98135883.js +387 -0
  39. package/dist/qbs-ect-cmp/sms-code-validation.entry.js +106 -0
  40. package/dist/{esm/store-fdeed827.js → qbs-ect-cmp/textValues-6bcc85dd.js} +51 -147
  41. package/dist/{collection/components/flow/user-liveness/user-liveness.js → qbs-ect-cmp/user-liveness.entry.js} +30 -91
  42. package/dist/{collection/utils/utils.js → qbs-ect-cmp/utils-8225f0b7.js} +10 -8
  43. package/dist/types/components/base-component.d.ts +2 -0
  44. package/dist/types/components/common/agreement-check/agreement-check.d.ts +1 -0
  45. package/dist/types/components/common/random-actions/random-actions.d.ts +2 -0
  46. package/dist/types/components/flow/end-redirect/end-redirect.d.ts +1 -0
  47. package/dist/types/components/identification-component/identification-component.d.ts +1 -0
  48. package/dist/types/components.d.ts +2 -0
  49. package/dist/types/helpers/TranslationUtils.d.ts +9 -0
  50. package/dist/types/helpers/textValues.d.ts +8 -95
  51. package/dist/types/models/IEctStore.d.ts +1 -0
  52. package/dist/types/models/ITranslationValues.d.ts +101 -0
  53. package/package.json +1 -1
  54. package/dist/cjs/agreement-check_19.cjs.entry.js +0 -10012
  55. package/dist/cjs/index-41696e0e.js +0 -1573
  56. package/dist/cjs/index.cjs.js +0 -2
  57. package/dist/cjs/loader-dots.cjs.entry.js +0 -19
  58. package/dist/cjs/loader.cjs.js +0 -22
  59. package/dist/cjs/qbs-ect-cmp.cjs.js +0 -23
  60. package/dist/cjs/random-actions.cjs.entry.js +0 -22
  61. package/dist/cjs/store-f1a0f55c.js +0 -413
  62. package/dist/collection/assets/canvas-masks/face_green.svg +0 -8
  63. package/dist/collection/assets/canvas-masks/face_white.svg +0 -8
  64. package/dist/collection/assets/canvas-masks/id_green.svg +0 -6
  65. package/dist/collection/assets/canvas-masks/id_white.svg +0 -6
  66. package/dist/collection/assets/complete.svg +0 -4
  67. package/dist/collection/assets/landing/device.svg +0 -14
  68. package/dist/collection/assets/landing/id.svg +0 -3
  69. package/dist/collection/assets/landing/info.svg +0 -3
  70. package/dist/collection/assets/landing/validation.svg +0 -16
  71. package/dist/collection/assets/loader.svg +0 -29
  72. package/dist/collection/collection-manifest.json +0 -32
  73. package/dist/collection/components/base-component.js +0 -59
  74. package/dist/collection/components/common/agreement-check/agreement-check.css +0 -0
  75. package/dist/collection/components/common/agreement-check/agreement-check.js +0 -101
  76. package/dist/collection/components/common/camera-error/camera-error.css +0 -0
  77. package/dist/collection/components/common/camera-error/camera-error.js +0 -91
  78. package/dist/collection/components/common/capture-error/capture-error.css +0 -0
  79. package/dist/collection/components/common/capture-error/capture-error.js +0 -101
  80. package/dist/collection/components/common/how-to-info/how-to-info.css +0 -0
  81. package/dist/collection/components/common/how-to-info/how-to-info.js +0 -122
  82. package/dist/collection/components/common/id-back-capture/id-back-capture.css +0 -35
  83. package/dist/collection/components/common/id-capture/id-capture.css +0 -35
  84. package/dist/collection/components/common/id-tilt/id-tilt.css +0 -35
  85. package/dist/collection/components/common/random-actions/random-actions.css +0 -0
  86. package/dist/collection/components/common/random-actions/random-actions.js +0 -20
  87. package/dist/collection/components/common/selfie-capture/selfie-capture.css +0 -7
  88. package/dist/collection/components/common/selfie-tilt/selfie-tilt.css +0 -7
  89. package/dist/collection/components/controls/camera/camera.css +0 -47
  90. package/dist/collection/components/controls/camera/camera.js +0 -289
  91. package/dist/collection/components/controls/loader-dots/loader-dots.css +0 -61
  92. package/dist/collection/components/controls/loader-dots/loader-dots.js +0 -18
  93. package/dist/collection/components/flow/agreement-info/agreement-info.css +0 -0
  94. package/dist/collection/components/flow/agreement-info/agreement-info.js +0 -106
  95. package/dist/collection/components/flow/end-redirect/end-redirect.css +0 -128
  96. package/dist/collection/components/flow/end-redirect/end-redirect.js +0 -44
  97. package/dist/collection/components/flow/error-end/error-end.css +0 -0
  98. package/dist/collection/components/flow/error-end/error-end.js +0 -61
  99. package/dist/collection/components/flow/landing-validation/landing-validation.css +0 -0
  100. package/dist/collection/components/flow/landing-validation/landing-validation.js +0 -122
  101. package/dist/collection/components/flow/mobile-redirect/mobile-redirect.css +0 -10
  102. package/dist/collection/components/flow/mobile-redirect/mobile-redirect.js +0 -144
  103. package/dist/collection/components/flow/process-id/process-id.css +0 -0
  104. package/dist/collection/components/flow/sms-code-validation/sms-code-validation.css +0 -0
  105. package/dist/collection/components/flow/sms-code-validation/sms-code-validation.js +0 -140
  106. package/dist/collection/components/flow/user-liveness/user-liveness.css +0 -0
  107. package/dist/collection/components/identification-component/identification-component.css +0 -991
  108. package/dist/collection/components/identification-component/identification-component.js +0 -387
  109. package/dist/collection/global.js +0 -0
  110. package/dist/collection/helpers/ApiCall.js +0 -223
  111. package/dist/collection/helpers/DeviceDetection.js +0 -85
  112. package/dist/collection/helpers/Events.js +0 -58
  113. package/dist/collection/helpers/ML5.js +0 -38
  114. package/dist/collection/helpers/Stream.js +0 -229
  115. package/dist/collection/helpers/canvas.js +0 -10
  116. package/dist/collection/helpers/index.js +0 -21
  117. package/dist/collection/helpers/security.js +0 -25
  118. package/dist/collection/helpers/store.js +0 -47
  119. package/dist/collection/helpers/textValues.js +0 -145
  120. package/dist/collection/index.js +0 -1
  121. package/dist/collection/libs/FaceML5Detector/FaceML5Detector.js +0 -229
  122. package/dist/collection/libs/FaceML5Detector/FacePose.js +0 -85
  123. package/dist/collection/libs/IDML5Detector/IDML5Detector.js +0 -99
  124. package/dist/collection/models/FlowStatus.js +0 -14
  125. package/dist/collection/models/FlowSteps.js +0 -30
  126. package/dist/collection/models/IAbortResult.js +0 -1
  127. package/dist/collection/models/IAddRequest.js +0 -1
  128. package/dist/collection/models/IAgreement.js +0 -1
  129. package/dist/collection/models/ICamera.js +0 -1
  130. package/dist/collection/models/IEctStore.js +0 -1
  131. package/dist/collection/models/IGeneration.js +0 -1
  132. package/dist/collection/models/ILinkSend.js +0 -1
  133. package/dist/collection/models/ILogResult.js +0 -1
  134. package/dist/collection/models/IOrderStatus.js +0 -1
  135. package/dist/collection/models/IOtpCheck.js +0 -1
  136. package/dist/collection/models/IOtpSend.js +0 -1
  137. package/dist/collection/models/IUploadFile.js +0 -1
  138. package/dist/collection/models/IVerificationMode.js +0 -5
  139. package/dist/collection/models/OrderStatuses.js +0 -8
  140. package/dist/esm/agreement-check_19.entry.js +0 -9990
  141. package/dist/esm/index-cf54a432.js +0 -1543
  142. package/dist/esm/index.js +0 -1
  143. package/dist/esm/loader.js +0 -18
  144. package/dist/esm/polyfills/core-js.js +0 -11
  145. package/dist/esm/polyfills/css-shim.js +0 -1
  146. package/dist/esm/polyfills/dom.js +0 -79
  147. package/dist/esm/polyfills/es5-html-element.js +0 -1
  148. package/dist/esm/polyfills/index.js +0 -34
  149. package/dist/esm/polyfills/system.js +0 -6
  150. package/dist/esm/qbs-ect-cmp.js +0 -18
  151. package/dist/index.cjs.js +0 -1
  152. package/dist/index.js +0 -1
  153. package/dist/loader/cdn.js +0 -3
  154. package/dist/loader/index.cjs.js +0 -3
  155. package/dist/loader/index.d.ts +0 -21
  156. package/dist/loader/index.es2017.js +0 -3
  157. package/dist/loader/index.js +0 -4
  158. package/dist/loader/package.json +0 -11
  159. package/dist/qbs-ect-cmp/p-054dc5b3.entry.js +0 -1
  160. package/dist/qbs-ect-cmp/p-0b381be5.js +0 -1
  161. package/dist/qbs-ect-cmp/p-4ef6223b.entry.js +0 -1373
  162. package/dist/qbs-ect-cmp/p-6be3b9ca.entry.js +0 -1
  163. package/dist/qbs-ect-cmp/p-8942656c.js +0 -2
@@ -0,0 +1,3104 @@
1
+ import { M as ML5 } from './ML5-657ef934.js';
2
+ import { d as delay, b as blobToBase64 } from './utils-8225f0b7.js';
3
+ import { s as state } from './textValues-6bcc85dd.js';
4
+ import { c as createCommonjsModule } from './_commonjsHelpers-321aa363.js';
5
+ import { M as MobileOS, B as Browser } from './IDevice-15ecfdeb.js';
6
+
7
+ const idWhiteSvg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzM1IiBoZWlnaHQ9IjIzOCIgdmlld0JveD0iMCAwIDMzNSAyMzgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8cGF0aCBkPSJNMzM0Ljg4NiA0Ni45MjQxSDMyNy45MDhWNy45NzUzN0gyODguMjczVjAuOTkzMTY0SDMzNC44ODZWNDYuOTI0MVoiIGZpbGw9IiNFNkU2RTYiLz4NCjxwYXRoIGQ9Ik0zMzUuMDAxIDIzNy4wMDdIMjg5LjA3VjIzMC4wMjVIMzI4LjAxOVYxOTAuMzlIMzM1LjAwMVYyMzcuMDA3WiIgZmlsbD0iI0U2RTZFNiIvPg0KPHBhdGggZD0iTTQ2LjcyNzEgMjM3LjAwN0gwLjEwOTg2M1YxOTEuMDcySDcuMDkyMDdWMjMwLjAyNUg0Ni43MjcxVjIzNy4wMDdaIiBmaWxsPSIjRTZFNkU2Ii8+DQo8cGF0aCBkPSJNNi45ODE3MiA0Ny42MTA0SC0wLjAwMDQ4ODI4MVYwLjk5MzE2NEg0NS45MzA1VjcuOTc1MzdINi45ODE3MlY0Ny42MTA0WiIgZmlsbD0iI0U2RTZFNiIvPg0KPC9zdmc+DQo=';
8
+
9
+ const idGreenSvg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzM1IiBoZWlnaHQ9IjIzOCIgdmlld0JveD0iMCAwIDMzNSAyMzgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQo8cGF0aCBkPSJNMzM0Ljg4NiA0Ni45MjQxSDMyNy45MDhWNy45NzUzN0gyODguMjczVjAuOTkzMTY0SDMzNC44ODZWNDYuOTI0MVoiIGZpbGw9IiM0Y2E1ODUiLz4NCjxwYXRoIGQ9Ik0zMzUuMDAxIDIzNy4wMDdIMjg5LjA3VjIzMC4wMjVIMzI4LjAxOVYxOTAuMzlIMzM1LjAwMVYyMzcuMDA3WiIgZmlsbD0iIzRjYTU4NSIvPg0KPHBhdGggZD0iTTQ2LjcyNzEgMjM3LjAwN0gwLjEwOTg2M1YxOTEuMDcySDcuMDkyMDdWMjMwLjAyNUg0Ni43MjcxVjIzNy4wMDdaIiBmaWxsPSIjNGNhNTg1Ii8+DQo8cGF0aCBkPSJNNi45ODE3MiA0Ny42MTA0SC0wLjAwMDQ4ODI4MVYwLjk5MzE2NEg0NS45MzA1VjcuOTc1MzdINi45ODE3MlY0Ny42MTA0WiIgZmlsbD0iIzRjYTU4NSIvPg0KPC9zdmc+DQo=';
10
+
11
+ var VerificationMode;
12
+ (function (VerificationMode) {
13
+ VerificationMode[VerificationMode["Full"] = 0] = "Full";
14
+ VerificationMode[VerificationMode["Tilt"] = 1] = "Tilt";
15
+ })(VerificationMode || (VerificationMode = {}));
16
+
17
+ class IDML5Detector {
18
+ static getInstance(stream, isMobile) {
19
+ if (!IDML5Detector.instance) {
20
+ IDML5Detector.instance = new IDML5Detector(stream, isMobile);
21
+ }
22
+ return IDML5Detector.instance;
23
+ }
24
+ constructor(stream, _isMobile) {
25
+ this.MAX_DETECTION = 1000 * 25;
26
+ this.initTime = null;
27
+ this.checked = false;
28
+ this.start = null;
29
+ this.stream = stream;
30
+ this.ml5 = ML5.getInstance();
31
+ }
32
+ updateHtmlElements(videoElement, canvasElement, _component) {
33
+ this.videoElement = videoElement;
34
+ this.canvasElement = canvasElement;
35
+ // this.component = component;
36
+ }
37
+ initDetector(mode) {
38
+ this.initTime = Date.now();
39
+ this.continue = true;
40
+ if (mode == VerificationMode.Full)
41
+ this.targetedLabel = 'full';
42
+ else
43
+ this.targetedLabel = 'tilted';
44
+ // this.width = this.videoElement.videoWidth;
45
+ // this.height = this.videoElement.videoHeight;
46
+ this.drawFrame('white');
47
+ delay(2000).then(() => this.classifyVideo());
48
+ }
49
+ classifyVideo() {
50
+ if (this.checked) {
51
+ if (this.start == null)
52
+ this.start = Date.now();
53
+ if (Date.now() > this.start + 500) {
54
+ this.continue = false;
55
+ this.stream.verificationReady();
56
+ }
57
+ }
58
+ if (Date.now() - this.initTime >= this.MAX_DETECTION) {
59
+ this.continue = false;
60
+ this.stream.timeElapsed();
61
+ }
62
+ if (this.continue)
63
+ this.ml5.classifier.classify(this.videoElement, this.gotResults.bind(this));
64
+ }
65
+ async gotResults(error, results) {
66
+ if (error) {
67
+ alert(error);
68
+ this.stream.timeElapsed();
69
+ return;
70
+ }
71
+ if (results[0].label == this.targetedLabel && results[0].confidence > 0.9 && !this.checked) {
72
+ this.checked = true;
73
+ this.stream.autoCapturing();
74
+ await this.drawFrame('green');
75
+ }
76
+ if (results[0].label == this.targetedLabel && results[0].confidence > 0.8 && !this.checked) {
77
+ this.checked = true;
78
+ await this.drawFrame('green');
79
+ }
80
+ this.classifyVideo();
81
+ }
82
+ async drawFrame(color, persistent = false) {
83
+ return new Promise(resolve => {
84
+ const img = new Image();
85
+ if (color == 'green')
86
+ img.src = idGreenSvg;
87
+ else
88
+ img.src = idWhiteSvg;
89
+ img.onload = async () => {
90
+ const canvas = this.canvasElement;
91
+ const canvasContext = canvas.getContext('2d');
92
+ const hRatio = canvas.width / img.width;
93
+ const vRatio = canvas.height / img.height;
94
+ const ratio = Math.min(hRatio, vRatio);
95
+ const paddingX = 150;
96
+ const paddingY = 150;
97
+ const centerShift_x = (canvas.width - img.width * ratio) / 2;
98
+ const centerShift_y = (canvas.height - img.height * ratio) / 2;
99
+ canvasContext.drawImage(img, 0, 0, img.width, img.height, centerShift_x + paddingX, centerShift_y + paddingY, img.width * ratio - paddingX * 2, img.height * ratio - paddingY * 2);
100
+ if (color != 'white' && !persistent) {
101
+ await delay(1000);
102
+ this.drawFrame('white');
103
+ }
104
+ resolve();
105
+ };
106
+ });
107
+ }
108
+ }
109
+
110
+ var FacePose;
111
+ (function (FacePose) {
112
+ FacePose[FacePose["LookLeft"] = 0] = "LookLeft";
113
+ FacePose[FacePose["LookRight"] = 1] = "LookRight";
114
+ FacePose[FacePose["LookUp"] = 2] = "LookUp";
115
+ FacePose[FacePose["LookDown"] = 3] = "LookDown";
116
+ //TiltLeft,
117
+ //TiltRight,
118
+ FacePose[FacePose["Main"] = 4] = "Main";
119
+ })(FacePose || (FacePose = {}));
120
+ class FacePosePick {
121
+ static randomEnum(anEnum) {
122
+ const enumValues = Object.keys(anEnum)
123
+ .map(n => Number.parseInt(n))
124
+ .filter(n => !Number.isNaN(n));
125
+ const randomIndex = Math.floor(Math.random() * (enumValues.length - 1));
126
+ const randomEnumValue = enumValues[randomIndex];
127
+ return randomEnumValue;
128
+ }
129
+ }
130
+ class FaceLandmarks {
131
+ constructor(result, w, h) {
132
+ this.leftEye = this.centerOfPoints(result.parts.rightEye, w, h);
133
+ this.rightEye = this.centerOfPoints(result.parts.leftEye, w, h);
134
+ this.leftEyeBrow = this.centerOfPoints(result.parts.rightEyeBrow, w, h);
135
+ this.rightEyeBrow = this.centerOfPoints(result.parts.leftEyeBrow, w, h);
136
+ this.mouth = this.centerOfPoints(result.parts.mouth, w, h);
137
+ this.nose = this.centerOfPoints(result.parts.nose, w, h);
138
+ }
139
+ eyesDistance() {
140
+ return Math.round(Math.hypot(this.leftEye.x - this.rightEye.x, this.leftEye.y - this.rightEye.y));
141
+ }
142
+ eyesLevel() {
143
+ return Math.round(this.leftEye.y - this.rightEye.y);
144
+ }
145
+ eyesCenter() {
146
+ var fp = new FacePoint();
147
+ fp.x = Math.round((this.leftEye.x + this.rightEye.x) / 2);
148
+ fp.y = Math.round((this.leftEye.y + this.rightEye.y) / 2);
149
+ return fp;
150
+ }
151
+ leftEyeNoseDistanceX() {
152
+ return Math.abs(this.leftEye.x - this.nose.x);
153
+ }
154
+ rightEyeNoseDistanceX() {
155
+ return Math.abs(this.rightEye.x - this.nose.x);
156
+ }
157
+ leftEyeNoseDistanceY() {
158
+ return Math.abs(this.leftEye.y - this.nose.y);
159
+ }
160
+ rightEyeNoseDistanceY() {
161
+ return Math.abs(this.rightEye.y - this.nose.y);
162
+ }
163
+ eyesNoseDistance() {
164
+ return Math.round(Math.hypot(this.eyesCenter().x - this.nose.x, this.eyesCenter().y - this.nose.y));
165
+ }
166
+ noseMouthDistance() {
167
+ return Math.round(Math.hypot(this.nose.x - this.mouth.x, this.nose.y - this.mouth.y));
168
+ }
169
+ eyesMouthDistance() {
170
+ return Math.round(Math.hypot(this.eyesCenter().x - this.mouth.x, this.eyesCenter().y - this.mouth.y));
171
+ }
172
+ leftEyeEyeBrowDistance() {
173
+ return Math.round(Math.hypot(this.leftEye.x - this.leftEyeBrow.x, this.leftEye.y - this.leftEyeBrow.y));
174
+ }
175
+ rightEyeEyeBrowDistance() {
176
+ return Math.round(Math.hypot(this.rightEye.x - this.rightEyeBrow.x, this.rightEye.y - this.rightEyeBrow.y));
177
+ }
178
+ centerOfPoints(arr, _width, _height) {
179
+ var minX, maxX, minY, maxY;
180
+ for (var i = 0; i < arr.length; i++) {
181
+ minX = arr[i].x < minX || minX == null ? arr[i].x : minX;
182
+ maxX = arr[i].x > maxX || maxX == null ? arr[i].x : maxX;
183
+ minY = arr[i].y < minY || minY == null ? arr[i].y : minY;
184
+ maxY = arr[i].y > maxY || maxY == null ? arr[i].y : maxY;
185
+ }
186
+ var point = [(minX + maxX) / 2, (minY + maxY) / 2];
187
+ var fp = new FacePoint();
188
+ fp.x = Math.round(point[0]);
189
+ fp.y = Math.round(point[1]);
190
+ return fp;
191
+ }
192
+ }
193
+ class FacePoint {
194
+ }
195
+
196
+ const faceWhiteSvg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjIyNC45OTk5OTk5OTk5OTk5NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIHZlcnNpb249IjEuMSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQogPGc+DQogIDx0aXRsZT5MYXllciAxPC90aXRsZT4NCiAgPGcgc3Ryb2tlPSJudWxsIiBpZD0iTGF5ZXIgMSI+DQogICA8cGF0aCBzdHJva2U9IiNmZmZmZmYiIGlkPSJzdmdfMSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZmlsbD0ibm9uZSIgZD0ibTc0LjI3NzY1LDYuOTI3NjFjLTExLjM3NTk3LC0wLjAxNzEzIC0zMy41NjU1MSw1LjEwNDMzIC00Ni44MTMxNiwxOS40OTQ4MWMtNi43NDE0Myw3LjMyMjkyIC0xOC4xMjI2OSwyMy4wNjk2NyAtMTkuMjY3NTgsNTkuNjEzNjljLTAuNTE5MDYsMTYuNTY5MjEgNS4wNDUyNCw2MC42MjUzMyAxMC4yNDAwNiw3Ni40Njc3NWMzLjYzMTMsMTEuMDc0NjggMjcuNDgyMTUsNDMuOTMzNDkgNDQuNDkwNiw1My42ODI1MWM0LjgwNzkxLDIuNzU1NDYgMTEuMjk2NjgsMi42ODI1MSAxMi40MjI1NSwyLjY4MjUxYzEuMTg4NzYsLTAuMDg0NTcgNy4zMzAyNiwwLjA3Mjk0IDEyLjEzNzY1LC0yLjY4MjUxYzE3LjAwODQ2LC05Ljc0OTAyIDQwLjQwMjA4LC00Mi43Njg1MSA0NC40OTA2LC01My42ODI1MWM0LjQwMDM4LC0xMS43NDQ5MSAxMC43NTk2NSwtNTkuODk4NTQgMTAuMjQwMDYsLTc2LjQ2Nzc1Yy0xLjE0NDg5LC0zNi41NDQwMiAtMTIuNTI2MTUsLTUyLjI5MDc3IC0xOS4yNjc1OCwtNTkuNjEzNjljLTEzLjI0NzY1LC0xNC4zOTA0OCAtMzUuMzA2NjMsLTE5LjUyOTMzIC00Ni43NzgyNywtMTkuNDk0ODFjLTAuNzQ2ODgsMC4wMDIyMiAtMS44OTQ5NCwwIC0xLjg5NDk0LDB6IiBzdHJva2Utd2lkdGg9IjciLz4NCiAgPC9nPg0KIDwvZz4NCjwvc3ZnPg0K';
197
+
198
+ const faceGreenSvg = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUwIiBoZWlnaHQ9IjIyNC45OTk5OTk5OTk5OTk5NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIHZlcnNpb249IjEuMSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQogPGc+DQogIDx0aXRsZT5MYXllciAxPC90aXRsZT4NCiAgPGcgc3Ryb2tlPSJudWxsIiBpZD0iTGF5ZXIgMSI+DQogICA8cGF0aCBzdHJva2U9IiM0Y2E1ODUiIGlkPSJzdmdfMSIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZmlsbD0ibm9uZSIgZD0ibTc0LjI3NzY1LDYuOTI3NjFjLTExLjM3NTk3LC0wLjAxNzEzIC0zMy41NjU1MSw1LjEwNDMzIC00Ni44MTMxNiwxOS40OTQ4MWMtNi43NDE0Myw3LjMyMjkyIC0xOC4xMjI2OSwyMy4wNjk2NyAtMTkuMjY3NTgsNTkuNjEzNjljLTAuNTE5MDYsMTYuNTY5MjEgNS4wNDUyNCw2MC42MjUzMyAxMC4yNDAwNiw3Ni40Njc3NWMzLjYzMTMsMTEuMDc0NjggMjcuNDgyMTUsNDMuOTMzNDkgNDQuNDkwNiw1My42ODI1MWM0LjgwNzkxLDIuNzU1NDYgMTEuMjk2NjgsMi42ODI1MSAxMi40MjI1NSwyLjY4MjUxYzEuMTg4NzYsLTAuMDg0NTcgNy4zMzAyNiwwLjA3Mjk0IDEyLjEzNzY1LC0yLjY4MjUxYzE3LjAwODQ2LC05Ljc0OTAyIDQwLjQwMjA4LC00Mi43Njg1MSA0NC40OTA2LC01My42ODI1MWM0LjQwMDM4LC0xMS43NDQ5MSAxMC43NTk2NSwtNTkuODk4NTQgMTAuMjQwMDYsLTc2LjQ2Nzc1Yy0xLjE0NDg5LC0zNi41NDQwMiAtMTIuNTI2MTUsLTUyLjI5MDc3IC0xOS4yNjc1OCwtNTkuNjEzNjljLTEzLjI0NzY1LC0xNC4zOTA0OCAtMzUuMzA2NjMsLTE5LjUyOTMzIC00Ni43NzgyNywtMTkuNDk0ODFjLTAuNzQ2ODgsMC4wMDIyMiAtMS44OTQ5NCwwIC0xLjg5NDk0LDB6IiBzdHJva2Utd2lkdGg9IjciLz4NCiAgPC9nPg0KIDwvZz4NCjwvc3ZnPg0K';
199
+
200
+ class FaceML5Detector {
201
+ static getInstance(stream, isMobile) {
202
+ if (!FaceML5Detector.instance) {
203
+ FaceML5Detector.instance = new FaceML5Detector(stream, isMobile);
204
+ }
205
+ return FaceML5Detector.instance;
206
+ }
207
+ constructor(stream, isMobile) {
208
+ this.MAX_DETECTION = 1000 * 30;
209
+ this.initTime = null;
210
+ this.validFaceFound = false;
211
+ this.start = null;
212
+ this.frontFace = null;
213
+ this.presentedFacePose = null;
214
+ this.validFacePose = false;
215
+ this.checkPose = false;
216
+ this.MAX_NUMBER_FACES = 1;
217
+ this.MIN_FACE_SCORE = 0.65;
218
+ // private readonly MIN_FACE_SIZE_FOR_MOBILE = 200;
219
+ // private readonly MIN_FACE_SIZE_FOR_DESKTOP = 350;
220
+ this.MIN_OCCUPIED_SPACE_FOR_DESKTOP = 15;
221
+ this.MIN_OCCUPIED_SPACE_FOR_MOBILE = 20;
222
+ this.X_OFFSET_FROM_FRAME = 0;
223
+ this.Y_OFFSET_FROM_FRAME = 0;
224
+ this.stream = stream;
225
+ this.ml5 = ML5.getInstance();
226
+ this.isMobile = isMobile;
227
+ }
228
+ updateHtmlElements(videoElement, canvasElement, _component) {
229
+ this.videoElement = videoElement;
230
+ this.canvasElement = canvasElement;
231
+ // this.component = component;
232
+ }
233
+ initDetector(mode) {
234
+ this.initTime = Date.now();
235
+ this.continue = true;
236
+ this.checkPose = mode == VerificationMode.Tilt;
237
+ this.width = this.videoElement.videoWidth;
238
+ this.height = this.videoElement.videoHeight;
239
+ // this.videoRatio = getVideoRatio(this.videoElement);
240
+ this.drawFrame('white');
241
+ delay(2000).then(() => this.detectFaces());
242
+ }
243
+ detectFaces() {
244
+ if (this.validFaceFound || this.validFacePose) {
245
+ if (this.start == null)
246
+ this.start = Date.now();
247
+ if (Date.now() > this.start + 3000) {
248
+ this.continue = false;
249
+ this.stream.verificationReady();
250
+ }
251
+ }
252
+ else if (Date.now() - this.initTime >= this.MAX_DETECTION) {
253
+ this.continue = false;
254
+ this.stream.timeElapsed();
255
+ }
256
+ // if (this.presentedFacePose != null && !this.validFacePose) {
257
+ // this.continue = false;
258
+ // this.stream.timeElapsed();
259
+ // }
260
+ if (this.continue)
261
+ this.ml5.faceapi.detect(this.videoElement, this.gotResults.bind(this));
262
+ }
263
+ async gotResults(error, results) {
264
+ if (error) {
265
+ alert(error);
266
+ this.stream.timeElapsed();
267
+ return;
268
+ }
269
+ if (results.length > 0) {
270
+ if (this.checkPose) {
271
+ await this.checkFacePose(results);
272
+ }
273
+ else {
274
+ if (this.isSingleFace(results) && this.checkProbability(results) && this.checkFaceSize(results) && this.checkFaceIndent(results)) {
275
+ if (!this.validFaceFound) {
276
+ this.validFaceFound = true;
277
+ this.stream.autoCapturing();
278
+ // this.frontFace = new FaceLandmarks(results[0], this.width, this.height);
279
+ await this.drawFrame('green', true);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ this.detectFaces();
285
+ }
286
+ async drawFrame(color, persistent = false) {
287
+ return new Promise(resolve => {
288
+ const img = new Image();
289
+ if (color == 'green')
290
+ img.src = faceGreenSvg;
291
+ else
292
+ img.src = faceWhiteSvg;
293
+ img.onload = async () => {
294
+ const canvas = this.canvasElement;
295
+ const canvasContext = canvas.getContext('2d');
296
+ const hRatio = canvas.width / img.width;
297
+ const vRatio = canvas.height / img.height;
298
+ const ratio = Math.min(hRatio, vRatio);
299
+ const portraitOrientation = canvas.width < canvas.height;
300
+ const paddingX = !portraitOrientation ? 40 : 80;
301
+ const paddingY = portraitOrientation ? 160 : 80;
302
+ const centerShift_x = (canvas.width - img.width * ratio) / 2;
303
+ const centerShift_y = (canvas.height - img.height * ratio) / 2;
304
+ canvasContext.drawImage(img, 0, 0, img.width, img.height, centerShift_x + paddingX, centerShift_y + paddingY, img.width * ratio - paddingX * 2, img.height * ratio - paddingY * 2);
305
+ if (color != 'white' && !persistent) {
306
+ await delay(1000);
307
+ this.drawFrame('white');
308
+ }
309
+ resolve();
310
+ };
311
+ });
312
+ }
313
+ isSingleFace(results) {
314
+ return results.length == this.MAX_NUMBER_FACES;
315
+ }
316
+ checkProbability(result) {
317
+ // console.log('prob: ' + result[0].detection.score);
318
+ return result[0].detection.score > this.MIN_FACE_SCORE;
319
+ }
320
+ checkFaceSize(result) {
321
+ const faceBox = result[0].detection.box;
322
+ const { area } = faceBox;
323
+ // const { width, height, area } = faceBox;
324
+ const { imageHeight, imageWidth } = result[0].detection;
325
+ const occupiedSize = 100 / ((imageHeight * imageWidth) / area);
326
+ // const minSide = Math.min(width / this.videoRatio, height / this.videoRatio);
327
+ // console.log('size: ' + occupiedSize +'/'+(this.isMobile ? this.MIN_OCCUPIED_SPACE_FOR_MOBILE : this.MIN_OCCUPIED_SPACE_FOR_DESKTOP));
328
+ return (
329
+ // minSide > (this.isMobile ? this.MIN_FACE_SIZE_FOR_MOBILE : this.MIN_FACE_SIZE_FOR_DESKTOP) &&
330
+ occupiedSize > (this.isMobile ? this.MIN_OCCUPIED_SPACE_FOR_MOBILE : this.MIN_OCCUPIED_SPACE_FOR_DESKTOP));
331
+ }
332
+ checkFaceIndent(result) {
333
+ const faceBox = result[0].detection.box;
334
+ const { top, left, bottom, right } = faceBox;
335
+ const { imageHeight, imageWidth } = result[0].detection;
336
+ const topIndent = (top * 100) / imageHeight;
337
+ const leftIndent = (left * 100) / imageWidth;
338
+ const rightIndent = ((imageWidth - right) * 100) / imageWidth;
339
+ const bottomIndent = ((imageHeight - bottom) * 100) / imageHeight;
340
+ // console.log('indent: '+topIndent+' | '+leftIndent+' | '+rightIndent+' | '+bottomIndent);
341
+ return !(topIndent < this.Y_OFFSET_FROM_FRAME || leftIndent < this.X_OFFSET_FROM_FRAME || rightIndent < this.X_OFFSET_FROM_FRAME || bottomIndent < this.Y_OFFSET_FROM_FRAME);
342
+ }
343
+ async checkFacePose(results) {
344
+ let face = new FaceLandmarks(results[0], this.width, this.height);
345
+ // this.drawLandmarks(results);
346
+ // this.drawPoints(face);
347
+ if (this.frontFace == null) {
348
+ this.frontFace = face;
349
+ // await this.drawFrame('green');
350
+ if (state.debug)
351
+ console.log('face ok');
352
+ }
353
+ else if (this.frontFace != null && this.presentedFacePose == null) {
354
+ let ff = this.frontFace;
355
+ if (face.nose.y < ff.nose.y - ff.eyesDistance() * 0.4)
356
+ this.presentedFacePose = FacePose.LookUp;
357
+ if (face.nose.y > ff.nose.y + ff.eyesDistance() * 0.4)
358
+ this.presentedFacePose = FacePose.LookDown;
359
+ if (face.nose.x > ff.nose.x + ff.eyesDistance() * 0.5)
360
+ this.presentedFacePose = FacePose.LookLeft;
361
+ if (face.nose.x < ff.nose.x - ff.eyesDistance() * 0.5)
362
+ this.presentedFacePose = FacePose.LookRight;
363
+ if (this.stream.facePose !== null) {
364
+ await delay(3000);
365
+ this.validFacePose = true;
366
+ await this.drawFrame('green', true);
367
+ }
368
+ }
369
+ }
370
+ }
371
+
372
+ var piexif = createCommonjsModule(function (module, exports) {
373
+ /* piexifjs
374
+
375
+ The MIT License (MIT)
376
+
377
+ Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)
378
+
379
+ Permission is hereby granted, free of charge, to any person obtaining a copy
380
+ of this software and associated documentation files (the "Software"), to deal
381
+ in the Software without restriction, including without limitation the rights
382
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
383
+ copies of the Software, and to permit persons to whom the Software is
384
+ furnished to do so, subject to the following conditions:
385
+
386
+ The above copyright notice and this permission notice shall be included in all
387
+ copies or substantial portions of the Software.
388
+
389
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
390
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
391
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
392
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
393
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
394
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
395
+ SOFTWARE.
396
+ */
397
+
398
+ (function () {
399
+ "use strict";
400
+ var that = {};
401
+ that.version = "1.0.4";
402
+
403
+ that.remove = function (jpeg) {
404
+ var b64 = false;
405
+ if (jpeg.slice(0, 2) == "\xff\xd8") {
406
+ } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
407
+ jpeg = atob(jpeg.split(",")[1]);
408
+ b64 = true;
409
+ } else {
410
+ throw new Error("Given data is not jpeg.");
411
+ }
412
+
413
+ var segments = splitIntoSegments(jpeg);
414
+ var newSegments = segments.filter(function(seg){
415
+ return !(seg.slice(0, 2) == "\xff\xe1" &&
416
+ seg.slice(4, 10) == "Exif\x00\x00");
417
+ });
418
+
419
+ var new_data = newSegments.join("");
420
+ if (b64) {
421
+ new_data = "data:image/jpeg;base64," + btoa(new_data);
422
+ }
423
+
424
+ return new_data;
425
+ };
426
+
427
+
428
+ that.insert = function (exif, jpeg) {
429
+ var b64 = false;
430
+ if (exif.slice(0, 6) != "\x45\x78\x69\x66\x00\x00") {
431
+ throw new Error("Given data is not exif.");
432
+ }
433
+ if (jpeg.slice(0, 2) == "\xff\xd8") {
434
+ } else if (jpeg.slice(0, 23) == "data:image/jpeg;base64," || jpeg.slice(0, 22) == "data:image/jpg;base64,") {
435
+ jpeg = atob(jpeg.split(",")[1]);
436
+ b64 = true;
437
+ } else {
438
+ throw new Error("Given data is not jpeg.");
439
+ }
440
+
441
+ var exifStr = "\xff\xe1" + pack(">H", [exif.length + 2]) + exif;
442
+ var segments = splitIntoSegments(jpeg);
443
+ var new_data = mergeSegments(segments, exifStr);
444
+ if (b64) {
445
+ new_data = "data:image/jpeg;base64," + btoa(new_data);
446
+ }
447
+
448
+ return new_data;
449
+ };
450
+
451
+
452
+ that.load = function (data) {
453
+ var input_data;
454
+ if (typeof (data) == "string") {
455
+ if (data.slice(0, 2) == "\xff\xd8") {
456
+ input_data = data;
457
+ } else if (data.slice(0, 23) == "data:image/jpeg;base64," || data.slice(0, 22) == "data:image/jpg;base64,") {
458
+ input_data = atob(data.split(",")[1]);
459
+ } else if (data.slice(0, 4) == "Exif") {
460
+ input_data = data.slice(6);
461
+ } else {
462
+ throw new Error("'load' gots invalid file data.");
463
+ }
464
+ } else {
465
+ throw new Error("'load' gots invalid type argument.");
466
+ }
467
+
468
+ var exifDict = {};
469
+ var exif_dict = {
470
+ "0th": {},
471
+ "Exif": {},
472
+ "GPS": {},
473
+ "Interop": {},
474
+ "1st": {},
475
+ "thumbnail": null
476
+ };
477
+ var exifReader = new ExifReader(input_data);
478
+ if (exifReader.tiftag === null) {
479
+ return exif_dict;
480
+ }
481
+
482
+ if (exifReader.tiftag.slice(0, 2) == "\x49\x49") {
483
+ exifReader.endian_mark = "<";
484
+ } else {
485
+ exifReader.endian_mark = ">";
486
+ }
487
+
488
+ var pointer = unpack(exifReader.endian_mark + "L",
489
+ exifReader.tiftag.slice(4, 8))[0];
490
+ exif_dict["0th"] = exifReader.get_ifd(pointer, "0th");
491
+
492
+ var first_ifd_pointer = exif_dict["0th"]["first_ifd_pointer"];
493
+ delete exif_dict["0th"]["first_ifd_pointer"];
494
+
495
+ if (34665 in exif_dict["0th"]) {
496
+ pointer = exif_dict["0th"][34665];
497
+ exif_dict["Exif"] = exifReader.get_ifd(pointer, "Exif");
498
+ }
499
+ if (34853 in exif_dict["0th"]) {
500
+ pointer = exif_dict["0th"][34853];
501
+ exif_dict["GPS"] = exifReader.get_ifd(pointer, "GPS");
502
+ }
503
+ if (40965 in exif_dict["Exif"]) {
504
+ pointer = exif_dict["Exif"][40965];
505
+ exif_dict["Interop"] = exifReader.get_ifd(pointer, "Interop");
506
+ }
507
+ if (first_ifd_pointer != "\x00\x00\x00\x00") {
508
+ pointer = unpack(exifReader.endian_mark + "L",
509
+ first_ifd_pointer)[0];
510
+ exif_dict["1st"] = exifReader.get_ifd(pointer, "1st");
511
+ if ((513 in exif_dict["1st"]) && (514 in exif_dict["1st"])) {
512
+ var end = exif_dict["1st"][513] + exif_dict["1st"][514];
513
+ var thumb = exifReader.tiftag.slice(exif_dict["1st"][513], end);
514
+ exif_dict["thumbnail"] = thumb;
515
+ }
516
+ }
517
+
518
+ return exif_dict;
519
+ };
520
+
521
+
522
+ that.dump = function (exif_dict_original) {
523
+ var TIFF_HEADER_LENGTH = 8;
524
+
525
+ var exif_dict = copy(exif_dict_original);
526
+ var header = "Exif\x00\x00\x4d\x4d\x00\x2a\x00\x00\x00\x08";
527
+ var exif_is = false;
528
+ var gps_is = false;
529
+ var interop_is = false;
530
+ var first_is = false;
531
+
532
+ var zeroth_ifd,
533
+ exif_ifd,
534
+ interop_ifd,
535
+ gps_ifd,
536
+ first_ifd;
537
+
538
+ if ("0th" in exif_dict) {
539
+ zeroth_ifd = exif_dict["0th"];
540
+ } else {
541
+ zeroth_ifd = {};
542
+ }
543
+
544
+ if ((("Exif" in exif_dict) && (Object.keys(exif_dict["Exif"]).length)) ||
545
+ (("Interop" in exif_dict) && (Object.keys(exif_dict["Interop"]).length))) {
546
+ zeroth_ifd[34665] = 1;
547
+ exif_is = true;
548
+ exif_ifd = exif_dict["Exif"];
549
+ if (("Interop" in exif_dict) && Object.keys(exif_dict["Interop"]).length) {
550
+ exif_ifd[40965] = 1;
551
+ interop_is = true;
552
+ interop_ifd = exif_dict["Interop"];
553
+ } else if (Object.keys(exif_ifd).indexOf(that.ExifIFD.InteroperabilityTag.toString()) > -1) {
554
+ delete exif_ifd[40965];
555
+ }
556
+ } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.ExifTag.toString()) > -1) {
557
+ delete zeroth_ifd[34665];
558
+ }
559
+
560
+ if (("GPS" in exif_dict) && (Object.keys(exif_dict["GPS"]).length)) {
561
+ zeroth_ifd[that.ImageIFD.GPSTag] = 1;
562
+ gps_is = true;
563
+ gps_ifd = exif_dict["GPS"];
564
+ } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.GPSTag.toString()) > -1) {
565
+ delete zeroth_ifd[that.ImageIFD.GPSTag];
566
+ }
567
+
568
+ if (("1st" in exif_dict) &&
569
+ ("thumbnail" in exif_dict) &&
570
+ (exif_dict["thumbnail"] != null)) {
571
+ first_is = true;
572
+ exif_dict["1st"][513] = 1;
573
+ exif_dict["1st"][514] = 1;
574
+ first_ifd = exif_dict["1st"];
575
+ }
576
+
577
+ var zeroth_set = _dict_to_bytes(zeroth_ifd, "0th", 0);
578
+ var zeroth_length = (zeroth_set[0].length + exif_is * 12 + gps_is * 12 + 4 +
579
+ zeroth_set[1].length);
580
+
581
+ var exif_set,
582
+ exif_bytes = "",
583
+ exif_length = 0,
584
+ gps_set,
585
+ gps_bytes = "",
586
+ gps_length = 0,
587
+ interop_set,
588
+ interop_bytes = "",
589
+ interop_length = 0,
590
+ first_set,
591
+ first_bytes = "",
592
+ thumbnail;
593
+ if (exif_is) {
594
+ exif_set = _dict_to_bytes(exif_ifd, "Exif", zeroth_length);
595
+ exif_length = exif_set[0].length + interop_is * 12 + exif_set[1].length;
596
+ }
597
+ if (gps_is) {
598
+ gps_set = _dict_to_bytes(gps_ifd, "GPS", zeroth_length + exif_length);
599
+ gps_bytes = gps_set.join("");
600
+ gps_length = gps_bytes.length;
601
+ }
602
+ if (interop_is) {
603
+ var offset = zeroth_length + exif_length + gps_length;
604
+ interop_set = _dict_to_bytes(interop_ifd, "Interop", offset);
605
+ interop_bytes = interop_set.join("");
606
+ interop_length = interop_bytes.length;
607
+ }
608
+ if (first_is) {
609
+ var offset = zeroth_length + exif_length + gps_length + interop_length;
610
+ first_set = _dict_to_bytes(first_ifd, "1st", offset);
611
+ thumbnail = _get_thumbnail(exif_dict["thumbnail"]);
612
+ if (thumbnail.length > 64000) {
613
+ throw new Error("Given thumbnail is too large. max 64kB");
614
+ }
615
+ }
616
+
617
+ var exif_pointer = "",
618
+ gps_pointer = "",
619
+ interop_pointer = "",
620
+ first_ifd_pointer = "\x00\x00\x00\x00";
621
+ if (exif_is) {
622
+ var pointer_value = TIFF_HEADER_LENGTH + zeroth_length;
623
+ var pointer_str = pack(">L", [pointer_value]);
624
+ var key = 34665;
625
+ var key_str = pack(">H", [key]);
626
+ var type_str = pack(">H", [TYPES["Long"]]);
627
+ var length_str = pack(">L", [1]);
628
+ exif_pointer = key_str + type_str + length_str + pointer_str;
629
+ }
630
+ if (gps_is) {
631
+ var pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length;
632
+ var pointer_str = pack(">L", [pointer_value]);
633
+ var key = 34853;
634
+ var key_str = pack(">H", [key]);
635
+ var type_str = pack(">H", [TYPES["Long"]]);
636
+ var length_str = pack(">L", [1]);
637
+ gps_pointer = key_str + type_str + length_str + pointer_str;
638
+ }
639
+ if (interop_is) {
640
+ var pointer_value = (TIFF_HEADER_LENGTH +
641
+ zeroth_length + exif_length + gps_length);
642
+ var pointer_str = pack(">L", [pointer_value]);
643
+ var key = 40965;
644
+ var key_str = pack(">H", [key]);
645
+ var type_str = pack(">H", [TYPES["Long"]]);
646
+ var length_str = pack(">L", [1]);
647
+ interop_pointer = key_str + type_str + length_str + pointer_str;
648
+ }
649
+ if (first_is) {
650
+ var pointer_value = (TIFF_HEADER_LENGTH + zeroth_length +
651
+ exif_length + gps_length + interop_length);
652
+ first_ifd_pointer = pack(">L", [pointer_value]);
653
+ var thumbnail_pointer = (pointer_value + first_set[0].length + 24 +
654
+ 4 + first_set[1].length);
655
+ var thumbnail_p_bytes = ("\x02\x01\x00\x04\x00\x00\x00\x01" +
656
+ pack(">L", [thumbnail_pointer]));
657
+ var thumbnail_length_bytes = ("\x02\x02\x00\x04\x00\x00\x00\x01" +
658
+ pack(">L", [thumbnail.length]));
659
+ first_bytes = (first_set[0] + thumbnail_p_bytes +
660
+ thumbnail_length_bytes + "\x00\x00\x00\x00" +
661
+ first_set[1] + thumbnail);
662
+ }
663
+
664
+ var zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer +
665
+ first_ifd_pointer + zeroth_set[1]);
666
+ if (exif_is) {
667
+ exif_bytes = exif_set[0] + interop_pointer + exif_set[1];
668
+ }
669
+
670
+ return (header + zeroth_bytes + exif_bytes + gps_bytes +
671
+ interop_bytes + first_bytes);
672
+ };
673
+
674
+
675
+ function copy(obj) {
676
+ return JSON.parse(JSON.stringify(obj));
677
+ }
678
+
679
+
680
+ function _get_thumbnail(jpeg) {
681
+ var segments = splitIntoSegments(jpeg);
682
+ while (("\xff\xe0" <= segments[1].slice(0, 2)) && (segments[1].slice(0, 2) <= "\xff\xef")) {
683
+ segments = [segments[0]].concat(segments.slice(2));
684
+ }
685
+ return segments.join("");
686
+ }
687
+
688
+
689
+ function _pack_byte(array) {
690
+ return pack(">" + nStr("B", array.length), array);
691
+ }
692
+
693
+
694
+ function _pack_short(array) {
695
+ return pack(">" + nStr("H", array.length), array);
696
+ }
697
+
698
+
699
+ function _pack_long(array) {
700
+ return pack(">" + nStr("L", array.length), array);
701
+ }
702
+
703
+
704
+ function _value_to_bytes(raw_value, value_type, offset) {
705
+ var four_bytes_over = "";
706
+ var value_str = "";
707
+ var length,
708
+ new_value,
709
+ num,
710
+ den;
711
+
712
+ if (value_type == "Byte") {
713
+ length = raw_value.length;
714
+ if (length <= 4) {
715
+ value_str = (_pack_byte(raw_value) +
716
+ nStr("\x00", 4 - length));
717
+ } else {
718
+ value_str = pack(">L", [offset]);
719
+ four_bytes_over = _pack_byte(raw_value);
720
+ }
721
+ } else if (value_type == "Short") {
722
+ length = raw_value.length;
723
+ if (length <= 2) {
724
+ value_str = (_pack_short(raw_value) +
725
+ nStr("\x00\x00", 2 - length));
726
+ } else {
727
+ value_str = pack(">L", [offset]);
728
+ four_bytes_over = _pack_short(raw_value);
729
+ }
730
+ } else if (value_type == "Long") {
731
+ length = raw_value.length;
732
+ if (length <= 1) {
733
+ value_str = _pack_long(raw_value);
734
+ } else {
735
+ value_str = pack(">L", [offset]);
736
+ four_bytes_over = _pack_long(raw_value);
737
+ }
738
+ } else if (value_type == "Ascii") {
739
+ new_value = raw_value + "\x00";
740
+ length = new_value.length;
741
+ if (length > 4) {
742
+ value_str = pack(">L", [offset]);
743
+ four_bytes_over = new_value;
744
+ } else {
745
+ value_str = new_value + nStr("\x00", 4 - length);
746
+ }
747
+ } else if (value_type == "Rational") {
748
+ if (typeof (raw_value[0]) == "number") {
749
+ length = 1;
750
+ num = raw_value[0];
751
+ den = raw_value[1];
752
+ new_value = pack(">L", [num]) + pack(">L", [den]);
753
+ } else {
754
+ length = raw_value.length;
755
+ new_value = "";
756
+ for (var n = 0; n < length; n++) {
757
+ num = raw_value[n][0];
758
+ den = raw_value[n][1];
759
+ new_value += (pack(">L", [num]) +
760
+ pack(">L", [den]));
761
+ }
762
+ }
763
+ value_str = pack(">L", [offset]);
764
+ four_bytes_over = new_value;
765
+ } else if (value_type == "SRational") {
766
+ if (typeof (raw_value[0]) == "number") {
767
+ length = 1;
768
+ num = raw_value[0];
769
+ den = raw_value[1];
770
+ new_value = pack(">l", [num]) + pack(">l", [den]);
771
+ } else {
772
+ length = raw_value.length;
773
+ new_value = "";
774
+ for (var n = 0; n < length; n++) {
775
+ num = raw_value[n][0];
776
+ den = raw_value[n][1];
777
+ new_value += (pack(">l", [num]) +
778
+ pack(">l", [den]));
779
+ }
780
+ }
781
+ value_str = pack(">L", [offset]);
782
+ four_bytes_over = new_value;
783
+ } else if (value_type == "Undefined") {
784
+ length = raw_value.length;
785
+ if (length > 4) {
786
+ value_str = pack(">L", [offset]);
787
+ four_bytes_over = raw_value;
788
+ } else {
789
+ value_str = raw_value + nStr("\x00", 4 - length);
790
+ }
791
+ }
792
+
793
+ var length_str = pack(">L", [length]);
794
+
795
+ return [length_str, value_str, four_bytes_over];
796
+ }
797
+
798
+ function _dict_to_bytes(ifd_dict, ifd, ifd_offset) {
799
+ var TIFF_HEADER_LENGTH = 8;
800
+ var tag_count = Object.keys(ifd_dict).length;
801
+ var entry_header = pack(">H", [tag_count]);
802
+ var entries_length;
803
+ if (["0th", "1st"].indexOf(ifd) > -1) {
804
+ entries_length = 2 + tag_count * 12 + 4;
805
+ } else {
806
+ entries_length = 2 + tag_count * 12;
807
+ }
808
+ var entries = "";
809
+ var values = "";
810
+ var key;
811
+
812
+ for (var key in ifd_dict) {
813
+ if (typeof (key) == "string") {
814
+ key = parseInt(key);
815
+ }
816
+ if ((ifd == "0th") && ([34665, 34853].indexOf(key) > -1)) {
817
+ continue;
818
+ } else if ((ifd == "Exif") && (key == 40965)) {
819
+ continue;
820
+ } else if ((ifd == "1st") && ([513, 514].indexOf(key) > -1)) {
821
+ continue;
822
+ }
823
+
824
+ var raw_value = ifd_dict[key];
825
+ var key_str = pack(">H", [key]);
826
+ var value_type = TAGS[ifd][key]["type"];
827
+ var type_str = pack(">H", [TYPES[value_type]]);
828
+
829
+ if (typeof (raw_value) == "number") {
830
+ raw_value = [raw_value];
831
+ }
832
+ var offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + values.length;
833
+ var b = _value_to_bytes(raw_value, value_type, offset);
834
+ var length_str = b[0];
835
+ var value_str = b[1];
836
+ var four_bytes_over = b[2];
837
+
838
+ entries += key_str + type_str + length_str + value_str;
839
+ values += four_bytes_over;
840
+ }
841
+
842
+ return [entry_header + entries, values];
843
+ }
844
+
845
+
846
+
847
+ function ExifReader(data) {
848
+ var segments,
849
+ app1;
850
+ if (data.slice(0, 2) == "\xff\xd8") { // JPEG
851
+ segments = splitIntoSegments(data);
852
+ app1 = getExifSeg(segments);
853
+ if (app1) {
854
+ this.tiftag = app1.slice(10);
855
+ } else {
856
+ this.tiftag = null;
857
+ }
858
+ } else if (["\x49\x49", "\x4d\x4d"].indexOf(data.slice(0, 2)) > -1) { // TIFF
859
+ this.tiftag = data;
860
+ } else if (data.slice(0, 4) == "Exif") { // Exif
861
+ this.tiftag = data.slice(6);
862
+ } else {
863
+ throw new Error("Given file is neither JPEG nor TIFF.");
864
+ }
865
+ }
866
+
867
+ ExifReader.prototype = {
868
+ get_ifd: function (pointer, ifd_name) {
869
+ var ifd_dict = {};
870
+ var tag_count = unpack(this.endian_mark + "H",
871
+ this.tiftag.slice(pointer, pointer + 2))[0];
872
+ var offset = pointer + 2;
873
+ var t;
874
+ if (["0th", "1st"].indexOf(ifd_name) > -1) {
875
+ t = "Image";
876
+ } else {
877
+ t = ifd_name;
878
+ }
879
+
880
+ for (var x = 0; x < tag_count; x++) {
881
+ pointer = offset + 12 * x;
882
+ var tag = unpack(this.endian_mark + "H",
883
+ this.tiftag.slice(pointer, pointer + 2))[0];
884
+ var value_type = unpack(this.endian_mark + "H",
885
+ this.tiftag.slice(pointer + 2, pointer + 4))[0];
886
+ var value_num = unpack(this.endian_mark + "L",
887
+ this.tiftag.slice(pointer + 4, pointer + 8))[0];
888
+ var value = this.tiftag.slice(pointer + 8, pointer + 12);
889
+
890
+ var v_set = [value_type, value_num, value];
891
+ if (tag in TAGS[t]) {
892
+ ifd_dict[tag] = this.convert_value(v_set);
893
+ }
894
+ }
895
+
896
+ if (ifd_name == "0th") {
897
+ pointer = offset + 12 * tag_count;
898
+ ifd_dict["first_ifd_pointer"] = this.tiftag.slice(pointer, pointer + 4);
899
+ }
900
+
901
+ return ifd_dict;
902
+ },
903
+
904
+ convert_value: function (val) {
905
+ var data = null;
906
+ var t = val[0];
907
+ var length = val[1];
908
+ var value = val[2];
909
+ var pointer;
910
+
911
+ if (t == 1) { // BYTE
912
+ if (length > 4) {
913
+ pointer = unpack(this.endian_mark + "L", value)[0];
914
+ data = unpack(this.endian_mark + nStr("B", length),
915
+ this.tiftag.slice(pointer, pointer + length));
916
+ } else {
917
+ data = unpack(this.endian_mark + nStr("B", length), value.slice(0, length));
918
+ }
919
+ } else if (t == 2) { // ASCII
920
+ if (length > 4) {
921
+ pointer = unpack(this.endian_mark + "L", value)[0];
922
+ data = this.tiftag.slice(pointer, pointer + length - 1);
923
+ } else {
924
+ data = value.slice(0, length - 1);
925
+ }
926
+ } else if (t == 3) { // SHORT
927
+ if (length > 2) {
928
+ pointer = unpack(this.endian_mark + "L", value)[0];
929
+ data = unpack(this.endian_mark + nStr("H", length),
930
+ this.tiftag.slice(pointer, pointer + length * 2));
931
+ } else {
932
+ data = unpack(this.endian_mark + nStr("H", length),
933
+ value.slice(0, length * 2));
934
+ }
935
+ } else if (t == 4) { // LONG
936
+ if (length > 1) {
937
+ pointer = unpack(this.endian_mark + "L", value)[0];
938
+ data = unpack(this.endian_mark + nStr("L", length),
939
+ this.tiftag.slice(pointer, pointer + length * 4));
940
+ } else {
941
+ data = unpack(this.endian_mark + nStr("L", length),
942
+ value);
943
+ }
944
+ } else if (t == 5) { // RATIONAL
945
+ pointer = unpack(this.endian_mark + "L", value)[0];
946
+ if (length > 1) {
947
+ data = [];
948
+ for (var x = 0; x < length; x++) {
949
+ data.push([unpack(this.endian_mark + "L",
950
+ this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
951
+ unpack(this.endian_mark + "L",
952
+ this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
953
+ ]);
954
+ }
955
+ } else {
956
+ data = [unpack(this.endian_mark + "L",
957
+ this.tiftag.slice(pointer, pointer + 4))[0],
958
+ unpack(this.endian_mark + "L",
959
+ this.tiftag.slice(pointer + 4, pointer + 8))[0]
960
+ ];
961
+ }
962
+ } else if (t == 7) { // UNDEFINED BYTES
963
+ if (length > 4) {
964
+ pointer = unpack(this.endian_mark + "L", value)[0];
965
+ data = this.tiftag.slice(pointer, pointer + length);
966
+ } else {
967
+ data = value.slice(0, length);
968
+ }
969
+ } else if (t == 9) { // SLONG
970
+ if (length > 1) {
971
+ pointer = unpack(this.endian_mark + "L", value)[0];
972
+ data = unpack(this.endian_mark + nStr("l", length),
973
+ this.tiftag.slice(pointer, pointer + length * 4));
974
+ } else {
975
+ data = unpack(this.endian_mark + nStr("l", length),
976
+ value);
977
+ }
978
+ } else if (t == 10) { // SRATIONAL
979
+ pointer = unpack(this.endian_mark + "L", value)[0];
980
+ if (length > 1) {
981
+ data = [];
982
+ for (var x = 0; x < length; x++) {
983
+ data.push([unpack(this.endian_mark + "l",
984
+ this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],
985
+ unpack(this.endian_mark + "l",
986
+ this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]
987
+ ]);
988
+ }
989
+ } else {
990
+ data = [unpack(this.endian_mark + "l",
991
+ this.tiftag.slice(pointer, pointer + 4))[0],
992
+ unpack(this.endian_mark + "l",
993
+ this.tiftag.slice(pointer + 4, pointer + 8))[0]
994
+ ];
995
+ }
996
+ } else {
997
+ throw new Error("Exif might be wrong. Got incorrect value " +
998
+ "type to decode. type:" + t);
999
+ }
1000
+
1001
+ if ((data instanceof Array) && (data.length == 1)) {
1002
+ return data[0];
1003
+ } else {
1004
+ return data;
1005
+ }
1006
+ },
1007
+ };
1008
+
1009
+
1010
+ if (typeof window !== "undefined" && typeof window.btoa === "function") {
1011
+ var btoa = window.btoa;
1012
+ }
1013
+ if (typeof btoa === "undefined") {
1014
+ var btoa = function (input) { var output = "";
1015
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
1016
+ var i = 0;
1017
+ var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
1018
+
1019
+ while (i < input.length) {
1020
+
1021
+ chr1 = input.charCodeAt(i++);
1022
+ chr2 = input.charCodeAt(i++);
1023
+ chr3 = input.charCodeAt(i++);
1024
+
1025
+ enc1 = chr1 >> 2;
1026
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
1027
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
1028
+ enc4 = chr3 & 63;
1029
+
1030
+ if (isNaN(chr2)) {
1031
+ enc3 = enc4 = 64;
1032
+ } else if (isNaN(chr3)) {
1033
+ enc4 = 64;
1034
+ }
1035
+
1036
+ output = output +
1037
+ keyStr.charAt(enc1) + keyStr.charAt(enc2) +
1038
+ keyStr.charAt(enc3) + keyStr.charAt(enc4);
1039
+
1040
+ }
1041
+
1042
+ return output;
1043
+ };
1044
+ }
1045
+
1046
+
1047
+ if (typeof window !== "undefined" && typeof window.atob === "function") {
1048
+ var atob = window.atob;
1049
+ }
1050
+ if (typeof atob === "undefined") {
1051
+ var atob = function (input) {
1052
+ var output = "";
1053
+ var chr1, chr2, chr3;
1054
+ var enc1, enc2, enc3, enc4;
1055
+ var i = 0;
1056
+ var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
1057
+
1058
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
1059
+
1060
+ while (i < input.length) {
1061
+
1062
+ enc1 = keyStr.indexOf(input.charAt(i++));
1063
+ enc2 = keyStr.indexOf(input.charAt(i++));
1064
+ enc3 = keyStr.indexOf(input.charAt(i++));
1065
+ enc4 = keyStr.indexOf(input.charAt(i++));
1066
+
1067
+ chr1 = (enc1 << 2) | (enc2 >> 4);
1068
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
1069
+ chr3 = ((enc3 & 3) << 6) | enc4;
1070
+
1071
+ output = output + String.fromCharCode(chr1);
1072
+
1073
+ if (enc3 != 64) {
1074
+ output = output + String.fromCharCode(chr2);
1075
+ }
1076
+ if (enc4 != 64) {
1077
+ output = output + String.fromCharCode(chr3);
1078
+ }
1079
+
1080
+ }
1081
+
1082
+ return output;
1083
+ };
1084
+ }
1085
+
1086
+
1087
+ function getImageSize(imageArray) {
1088
+ var segments = slice2Segments(imageArray);
1089
+ var seg,
1090
+ width,
1091
+ height,
1092
+ SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207];
1093
+
1094
+ for (var x = 0; x < segments.length; x++) {
1095
+ seg = segments[x];
1096
+ if (SOF.indexOf(seg[1]) >= 0) {
1097
+ height = seg[5] * 256 + seg[6];
1098
+ width = seg[7] * 256 + seg[8];
1099
+ break;
1100
+ }
1101
+ }
1102
+ return [width, height];
1103
+ }
1104
+
1105
+
1106
+ function pack(mark, array) {
1107
+ if (!(array instanceof Array)) {
1108
+ throw new Error("'pack' error. Got invalid type argument.");
1109
+ }
1110
+ if ((mark.length - 1) != array.length) {
1111
+ throw new Error("'pack' error. " + (mark.length - 1) + " marks, " + array.length + " elements.");
1112
+ }
1113
+
1114
+ var littleEndian;
1115
+ if (mark[0] == "<") {
1116
+ littleEndian = true;
1117
+ } else if (mark[0] == ">") {
1118
+ littleEndian = false;
1119
+ } else {
1120
+ throw new Error("");
1121
+ }
1122
+ var packed = "";
1123
+ var p = 1;
1124
+ var val = null;
1125
+ var c = null;
1126
+ var valStr = null;
1127
+
1128
+ while (c = mark[p]) {
1129
+ if (c.toLowerCase() == "b") {
1130
+ val = array[p - 1];
1131
+ if ((c == "b") && (val < 0)) {
1132
+ val += 0x100;
1133
+ }
1134
+ if ((val > 0xff) || (val < 0)) {
1135
+ throw new Error("'pack' error.");
1136
+ } else {
1137
+ valStr = String.fromCharCode(val);
1138
+ }
1139
+ } else if (c == "H") {
1140
+ val = array[p - 1];
1141
+ if ((val > 0xffff) || (val < 0)) {
1142
+ throw new Error("'pack' error.");
1143
+ } else {
1144
+ valStr = String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
1145
+ String.fromCharCode(val % 0x100);
1146
+ if (littleEndian) {
1147
+ valStr = valStr.split("").reverse().join("");
1148
+ }
1149
+ }
1150
+ } else if (c.toLowerCase() == "l") {
1151
+ val = array[p - 1];
1152
+ if ((c == "l") && (val < 0)) {
1153
+ val += 0x100000000;
1154
+ }
1155
+ if ((val > 0xffffffff) || (val < 0)) {
1156
+ throw new Error("'pack' error.");
1157
+ } else {
1158
+ valStr = String.fromCharCode(Math.floor(val / 0x1000000)) +
1159
+ String.fromCharCode(Math.floor((val % 0x1000000) / 0x10000)) +
1160
+ String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +
1161
+ String.fromCharCode(val % 0x100);
1162
+ if (littleEndian) {
1163
+ valStr = valStr.split("").reverse().join("");
1164
+ }
1165
+ }
1166
+ } else {
1167
+ throw new Error("'pack' error.");
1168
+ }
1169
+
1170
+ packed += valStr;
1171
+ p += 1;
1172
+ }
1173
+
1174
+ return packed;
1175
+ }
1176
+
1177
+ function unpack(mark, str) {
1178
+ if (typeof (str) != "string") {
1179
+ throw new Error("'unpack' error. Got invalid type argument.");
1180
+ }
1181
+ var l = 0;
1182
+ for (var markPointer = 1; markPointer < mark.length; markPointer++) {
1183
+ if (mark[markPointer].toLowerCase() == "b") {
1184
+ l += 1;
1185
+ } else if (mark[markPointer].toLowerCase() == "h") {
1186
+ l += 2;
1187
+ } else if (mark[markPointer].toLowerCase() == "l") {
1188
+ l += 4;
1189
+ } else {
1190
+ throw new Error("'unpack' error. Got invalid mark.");
1191
+ }
1192
+ }
1193
+
1194
+ if (l != str.length) {
1195
+ throw new Error("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length);
1196
+ }
1197
+
1198
+ var littleEndian;
1199
+ if (mark[0] == "<") {
1200
+ littleEndian = true;
1201
+ } else if (mark[0] == ">") {
1202
+ littleEndian = false;
1203
+ } else {
1204
+ throw new Error("'unpack' error.");
1205
+ }
1206
+ var unpacked = [];
1207
+ var strPointer = 0;
1208
+ var p = 1;
1209
+ var val = null;
1210
+ var c = null;
1211
+ var length = null;
1212
+ var sliced = "";
1213
+
1214
+ while (c = mark[p]) {
1215
+ if (c.toLowerCase() == "b") {
1216
+ length = 1;
1217
+ sliced = str.slice(strPointer, strPointer + length);
1218
+ val = sliced.charCodeAt(0);
1219
+ if ((c == "b") && (val >= 0x80)) {
1220
+ val -= 0x100;
1221
+ }
1222
+ } else if (c == "H") {
1223
+ length = 2;
1224
+ sliced = str.slice(strPointer, strPointer + length);
1225
+ if (littleEndian) {
1226
+ sliced = sliced.split("").reverse().join("");
1227
+ }
1228
+ val = sliced.charCodeAt(0) * 0x100 +
1229
+ sliced.charCodeAt(1);
1230
+ } else if (c.toLowerCase() == "l") {
1231
+ length = 4;
1232
+ sliced = str.slice(strPointer, strPointer + length);
1233
+ if (littleEndian) {
1234
+ sliced = sliced.split("").reverse().join("");
1235
+ }
1236
+ val = sliced.charCodeAt(0) * 0x1000000 +
1237
+ sliced.charCodeAt(1) * 0x10000 +
1238
+ sliced.charCodeAt(2) * 0x100 +
1239
+ sliced.charCodeAt(3);
1240
+ if ((c == "l") && (val >= 0x80000000)) {
1241
+ val -= 0x100000000;
1242
+ }
1243
+ } else {
1244
+ throw new Error("'unpack' error. " + c);
1245
+ }
1246
+
1247
+ unpacked.push(val);
1248
+ strPointer += length;
1249
+ p += 1;
1250
+ }
1251
+
1252
+ return unpacked;
1253
+ }
1254
+
1255
+ function nStr(ch, num) {
1256
+ var str = "";
1257
+ for (var i = 0; i < num; i++) {
1258
+ str += ch;
1259
+ }
1260
+ return str;
1261
+ }
1262
+
1263
+ function splitIntoSegments(data) {
1264
+ if (data.slice(0, 2) != "\xff\xd8") {
1265
+ throw new Error("Given data isn't JPEG.");
1266
+ }
1267
+
1268
+ var head = 2;
1269
+ var segments = ["\xff\xd8"];
1270
+ while (true) {
1271
+ if (data.slice(head, head + 2) == "\xff\xda") {
1272
+ segments.push(data.slice(head));
1273
+ break;
1274
+ } else {
1275
+ var length = unpack(">H", data.slice(head + 2, head + 4))[0];
1276
+ var endPoint = head + length + 2;
1277
+ segments.push(data.slice(head, endPoint));
1278
+ head = endPoint;
1279
+ }
1280
+
1281
+ if (head >= data.length) {
1282
+ throw new Error("Wrong JPEG data.");
1283
+ }
1284
+ }
1285
+ return segments;
1286
+ }
1287
+
1288
+
1289
+ function getExifSeg(segments) {
1290
+ var seg;
1291
+ for (var i = 0; i < segments.length; i++) {
1292
+ seg = segments[i];
1293
+ if (seg.slice(0, 2) == "\xff\xe1" &&
1294
+ seg.slice(4, 10) == "Exif\x00\x00") {
1295
+ return seg;
1296
+ }
1297
+ }
1298
+ return null;
1299
+ }
1300
+
1301
+
1302
+ function mergeSegments(segments, exif) {
1303
+ var hasExifSegment = false;
1304
+ var additionalAPP1ExifSegments = [];
1305
+
1306
+ segments.forEach(function(segment, i) {
1307
+ // Replace first occurence of APP1:Exif segment
1308
+ if (segment.slice(0, 2) == "\xff\xe1" &&
1309
+ segment.slice(4, 10) == "Exif\x00\x00"
1310
+ ) {
1311
+ if (!hasExifSegment) {
1312
+ segments[i] = exif;
1313
+ hasExifSegment = true;
1314
+ } else {
1315
+ additionalAPP1ExifSegments.unshift(i);
1316
+ }
1317
+ }
1318
+ });
1319
+
1320
+ // Remove additional occurences of APP1:Exif segment
1321
+ additionalAPP1ExifSegments.forEach(function(segmentIndex) {
1322
+ segments.splice(segmentIndex, 1);
1323
+ });
1324
+
1325
+ if (!hasExifSegment && exif) {
1326
+ segments = [segments[0], exif].concat(segments.slice(1));
1327
+ }
1328
+
1329
+ return segments.join("");
1330
+ }
1331
+
1332
+
1333
+ function toHex(str) {
1334
+ var hexStr = "";
1335
+ for (var i = 0; i < str.length; i++) {
1336
+ var h = str.charCodeAt(i);
1337
+ var hex = ((h < 10) ? "0" : "") + h.toString(16);
1338
+ hexStr += hex + " ";
1339
+ }
1340
+ return hexStr;
1341
+ }
1342
+
1343
+
1344
+ var TYPES = {
1345
+ "Byte": 1,
1346
+ "Ascii": 2,
1347
+ "Short": 3,
1348
+ "Long": 4,
1349
+ "Rational": 5,
1350
+ "Undefined": 7,
1351
+ "SLong": 9,
1352
+ "SRational": 10
1353
+ };
1354
+
1355
+
1356
+ var TAGS = {
1357
+ 'Image': {
1358
+ 11: {
1359
+ 'name': 'ProcessingSoftware',
1360
+ 'type': 'Ascii'
1361
+ },
1362
+ 254: {
1363
+ 'name': 'NewSubfileType',
1364
+ 'type': 'Long'
1365
+ },
1366
+ 255: {
1367
+ 'name': 'SubfileType',
1368
+ 'type': 'Short'
1369
+ },
1370
+ 256: {
1371
+ 'name': 'ImageWidth',
1372
+ 'type': 'Long'
1373
+ },
1374
+ 257: {
1375
+ 'name': 'ImageLength',
1376
+ 'type': 'Long'
1377
+ },
1378
+ 258: {
1379
+ 'name': 'BitsPerSample',
1380
+ 'type': 'Short'
1381
+ },
1382
+ 259: {
1383
+ 'name': 'Compression',
1384
+ 'type': 'Short'
1385
+ },
1386
+ 262: {
1387
+ 'name': 'PhotometricInterpretation',
1388
+ 'type': 'Short'
1389
+ },
1390
+ 263: {
1391
+ 'name': 'Threshholding',
1392
+ 'type': 'Short'
1393
+ },
1394
+ 264: {
1395
+ 'name': 'CellWidth',
1396
+ 'type': 'Short'
1397
+ },
1398
+ 265: {
1399
+ 'name': 'CellLength',
1400
+ 'type': 'Short'
1401
+ },
1402
+ 266: {
1403
+ 'name': 'FillOrder',
1404
+ 'type': 'Short'
1405
+ },
1406
+ 269: {
1407
+ 'name': 'DocumentName',
1408
+ 'type': 'Ascii'
1409
+ },
1410
+ 270: {
1411
+ 'name': 'ImageDescription',
1412
+ 'type': 'Ascii'
1413
+ },
1414
+ 271: {
1415
+ 'name': 'Make',
1416
+ 'type': 'Ascii'
1417
+ },
1418
+ 272: {
1419
+ 'name': 'Model',
1420
+ 'type': 'Ascii'
1421
+ },
1422
+ 273: {
1423
+ 'name': 'StripOffsets',
1424
+ 'type': 'Long'
1425
+ },
1426
+ 274: {
1427
+ 'name': 'Orientation',
1428
+ 'type': 'Short'
1429
+ },
1430
+ 277: {
1431
+ 'name': 'SamplesPerPixel',
1432
+ 'type': 'Short'
1433
+ },
1434
+ 278: {
1435
+ 'name': 'RowsPerStrip',
1436
+ 'type': 'Long'
1437
+ },
1438
+ 279: {
1439
+ 'name': 'StripByteCounts',
1440
+ 'type': 'Long'
1441
+ },
1442
+ 282: {
1443
+ 'name': 'XResolution',
1444
+ 'type': 'Rational'
1445
+ },
1446
+ 283: {
1447
+ 'name': 'YResolution',
1448
+ 'type': 'Rational'
1449
+ },
1450
+ 284: {
1451
+ 'name': 'PlanarConfiguration',
1452
+ 'type': 'Short'
1453
+ },
1454
+ 290: {
1455
+ 'name': 'GrayResponseUnit',
1456
+ 'type': 'Short'
1457
+ },
1458
+ 291: {
1459
+ 'name': 'GrayResponseCurve',
1460
+ 'type': 'Short'
1461
+ },
1462
+ 292: {
1463
+ 'name': 'T4Options',
1464
+ 'type': 'Long'
1465
+ },
1466
+ 293: {
1467
+ 'name': 'T6Options',
1468
+ 'type': 'Long'
1469
+ },
1470
+ 296: {
1471
+ 'name': 'ResolutionUnit',
1472
+ 'type': 'Short'
1473
+ },
1474
+ 301: {
1475
+ 'name': 'TransferFunction',
1476
+ 'type': 'Short'
1477
+ },
1478
+ 305: {
1479
+ 'name': 'Software',
1480
+ 'type': 'Ascii'
1481
+ },
1482
+ 306: {
1483
+ 'name': 'DateTime',
1484
+ 'type': 'Ascii'
1485
+ },
1486
+ 315: {
1487
+ 'name': 'Artist',
1488
+ 'type': 'Ascii'
1489
+ },
1490
+ 316: {
1491
+ 'name': 'HostComputer',
1492
+ 'type': 'Ascii'
1493
+ },
1494
+ 317: {
1495
+ 'name': 'Predictor',
1496
+ 'type': 'Short'
1497
+ },
1498
+ 318: {
1499
+ 'name': 'WhitePoint',
1500
+ 'type': 'Rational'
1501
+ },
1502
+ 319: {
1503
+ 'name': 'PrimaryChromaticities',
1504
+ 'type': 'Rational'
1505
+ },
1506
+ 320: {
1507
+ 'name': 'ColorMap',
1508
+ 'type': 'Short'
1509
+ },
1510
+ 321: {
1511
+ 'name': 'HalftoneHints',
1512
+ 'type': 'Short'
1513
+ },
1514
+ 322: {
1515
+ 'name': 'TileWidth',
1516
+ 'type': 'Short'
1517
+ },
1518
+ 323: {
1519
+ 'name': 'TileLength',
1520
+ 'type': 'Short'
1521
+ },
1522
+ 324: {
1523
+ 'name': 'TileOffsets',
1524
+ 'type': 'Short'
1525
+ },
1526
+ 325: {
1527
+ 'name': 'TileByteCounts',
1528
+ 'type': 'Short'
1529
+ },
1530
+ 330: {
1531
+ 'name': 'SubIFDs',
1532
+ 'type': 'Long'
1533
+ },
1534
+ 332: {
1535
+ 'name': 'InkSet',
1536
+ 'type': 'Short'
1537
+ },
1538
+ 333: {
1539
+ 'name': 'InkNames',
1540
+ 'type': 'Ascii'
1541
+ },
1542
+ 334: {
1543
+ 'name': 'NumberOfInks',
1544
+ 'type': 'Short'
1545
+ },
1546
+ 336: {
1547
+ 'name': 'DotRange',
1548
+ 'type': 'Byte'
1549
+ },
1550
+ 337: {
1551
+ 'name': 'TargetPrinter',
1552
+ 'type': 'Ascii'
1553
+ },
1554
+ 338: {
1555
+ 'name': 'ExtraSamples',
1556
+ 'type': 'Short'
1557
+ },
1558
+ 339: {
1559
+ 'name': 'SampleFormat',
1560
+ 'type': 'Short'
1561
+ },
1562
+ 340: {
1563
+ 'name': 'SMinSampleValue',
1564
+ 'type': 'Short'
1565
+ },
1566
+ 341: {
1567
+ 'name': 'SMaxSampleValue',
1568
+ 'type': 'Short'
1569
+ },
1570
+ 342: {
1571
+ 'name': 'TransferRange',
1572
+ 'type': 'Short'
1573
+ },
1574
+ 343: {
1575
+ 'name': 'ClipPath',
1576
+ 'type': 'Byte'
1577
+ },
1578
+ 344: {
1579
+ 'name': 'XClipPathUnits',
1580
+ 'type': 'Long'
1581
+ },
1582
+ 345: {
1583
+ 'name': 'YClipPathUnits',
1584
+ 'type': 'Long'
1585
+ },
1586
+ 346: {
1587
+ 'name': 'Indexed',
1588
+ 'type': 'Short'
1589
+ },
1590
+ 347: {
1591
+ 'name': 'JPEGTables',
1592
+ 'type': 'Undefined'
1593
+ },
1594
+ 351: {
1595
+ 'name': 'OPIProxy',
1596
+ 'type': 'Short'
1597
+ },
1598
+ 512: {
1599
+ 'name': 'JPEGProc',
1600
+ 'type': 'Long'
1601
+ },
1602
+ 513: {
1603
+ 'name': 'JPEGInterchangeFormat',
1604
+ 'type': 'Long'
1605
+ },
1606
+ 514: {
1607
+ 'name': 'JPEGInterchangeFormatLength',
1608
+ 'type': 'Long'
1609
+ },
1610
+ 515: {
1611
+ 'name': 'JPEGRestartInterval',
1612
+ 'type': 'Short'
1613
+ },
1614
+ 517: {
1615
+ 'name': 'JPEGLosslessPredictors',
1616
+ 'type': 'Short'
1617
+ },
1618
+ 518: {
1619
+ 'name': 'JPEGPointTransforms',
1620
+ 'type': 'Short'
1621
+ },
1622
+ 519: {
1623
+ 'name': 'JPEGQTables',
1624
+ 'type': 'Long'
1625
+ },
1626
+ 520: {
1627
+ 'name': 'JPEGDCTables',
1628
+ 'type': 'Long'
1629
+ },
1630
+ 521: {
1631
+ 'name': 'JPEGACTables',
1632
+ 'type': 'Long'
1633
+ },
1634
+ 529: {
1635
+ 'name': 'YCbCrCoefficients',
1636
+ 'type': 'Rational'
1637
+ },
1638
+ 530: {
1639
+ 'name': 'YCbCrSubSampling',
1640
+ 'type': 'Short'
1641
+ },
1642
+ 531: {
1643
+ 'name': 'YCbCrPositioning',
1644
+ 'type': 'Short'
1645
+ },
1646
+ 532: {
1647
+ 'name': 'ReferenceBlackWhite',
1648
+ 'type': 'Rational'
1649
+ },
1650
+ 700: {
1651
+ 'name': 'XMLPacket',
1652
+ 'type': 'Byte'
1653
+ },
1654
+ 18246: {
1655
+ 'name': 'Rating',
1656
+ 'type': 'Short'
1657
+ },
1658
+ 18249: {
1659
+ 'name': 'RatingPercent',
1660
+ 'type': 'Short'
1661
+ },
1662
+ 32781: {
1663
+ 'name': 'ImageID',
1664
+ 'type': 'Ascii'
1665
+ },
1666
+ 33421: {
1667
+ 'name': 'CFARepeatPatternDim',
1668
+ 'type': 'Short'
1669
+ },
1670
+ 33422: {
1671
+ 'name': 'CFAPattern',
1672
+ 'type': 'Byte'
1673
+ },
1674
+ 33423: {
1675
+ 'name': 'BatteryLevel',
1676
+ 'type': 'Rational'
1677
+ },
1678
+ 33432: {
1679
+ 'name': 'Copyright',
1680
+ 'type': 'Ascii'
1681
+ },
1682
+ 33434: {
1683
+ 'name': 'ExposureTime',
1684
+ 'type': 'Rational'
1685
+ },
1686
+ 34377: {
1687
+ 'name': 'ImageResources',
1688
+ 'type': 'Byte'
1689
+ },
1690
+ 34665: {
1691
+ 'name': 'ExifTag',
1692
+ 'type': 'Long'
1693
+ },
1694
+ 34675: {
1695
+ 'name': 'InterColorProfile',
1696
+ 'type': 'Undefined'
1697
+ },
1698
+ 34853: {
1699
+ 'name': 'GPSTag',
1700
+ 'type': 'Long'
1701
+ },
1702
+ 34857: {
1703
+ 'name': 'Interlace',
1704
+ 'type': 'Short'
1705
+ },
1706
+ 34858: {
1707
+ 'name': 'TimeZoneOffset',
1708
+ 'type': 'Long'
1709
+ },
1710
+ 34859: {
1711
+ 'name': 'SelfTimerMode',
1712
+ 'type': 'Short'
1713
+ },
1714
+ 37387: {
1715
+ 'name': 'FlashEnergy',
1716
+ 'type': 'Rational'
1717
+ },
1718
+ 37388: {
1719
+ 'name': 'SpatialFrequencyResponse',
1720
+ 'type': 'Undefined'
1721
+ },
1722
+ 37389: {
1723
+ 'name': 'Noise',
1724
+ 'type': 'Undefined'
1725
+ },
1726
+ 37390: {
1727
+ 'name': 'FocalPlaneXResolution',
1728
+ 'type': 'Rational'
1729
+ },
1730
+ 37391: {
1731
+ 'name': 'FocalPlaneYResolution',
1732
+ 'type': 'Rational'
1733
+ },
1734
+ 37392: {
1735
+ 'name': 'FocalPlaneResolutionUnit',
1736
+ 'type': 'Short'
1737
+ },
1738
+ 37393: {
1739
+ 'name': 'ImageNumber',
1740
+ 'type': 'Long'
1741
+ },
1742
+ 37394: {
1743
+ 'name': 'SecurityClassification',
1744
+ 'type': 'Ascii'
1745
+ },
1746
+ 37395: {
1747
+ 'name': 'ImageHistory',
1748
+ 'type': 'Ascii'
1749
+ },
1750
+ 37397: {
1751
+ 'name': 'ExposureIndex',
1752
+ 'type': 'Rational'
1753
+ },
1754
+ 37398: {
1755
+ 'name': 'TIFFEPStandardID',
1756
+ 'type': 'Byte'
1757
+ },
1758
+ 37399: {
1759
+ 'name': 'SensingMethod',
1760
+ 'type': 'Short'
1761
+ },
1762
+ 40091: {
1763
+ 'name': 'XPTitle',
1764
+ 'type': 'Byte'
1765
+ },
1766
+ 40092: {
1767
+ 'name': 'XPComment',
1768
+ 'type': 'Byte'
1769
+ },
1770
+ 40093: {
1771
+ 'name': 'XPAuthor',
1772
+ 'type': 'Byte'
1773
+ },
1774
+ 40094: {
1775
+ 'name': 'XPKeywords',
1776
+ 'type': 'Byte'
1777
+ },
1778
+ 40095: {
1779
+ 'name': 'XPSubject',
1780
+ 'type': 'Byte'
1781
+ },
1782
+ 50341: {
1783
+ 'name': 'PrintImageMatching',
1784
+ 'type': 'Undefined'
1785
+ },
1786
+ 50706: {
1787
+ 'name': 'DNGVersion',
1788
+ 'type': 'Byte'
1789
+ },
1790
+ 50707: {
1791
+ 'name': 'DNGBackwardVersion',
1792
+ 'type': 'Byte'
1793
+ },
1794
+ 50708: {
1795
+ 'name': 'UniqueCameraModel',
1796
+ 'type': 'Ascii'
1797
+ },
1798
+ 50709: {
1799
+ 'name': 'LocalizedCameraModel',
1800
+ 'type': 'Byte'
1801
+ },
1802
+ 50710: {
1803
+ 'name': 'CFAPlaneColor',
1804
+ 'type': 'Byte'
1805
+ },
1806
+ 50711: {
1807
+ 'name': 'CFALayout',
1808
+ 'type': 'Short'
1809
+ },
1810
+ 50712: {
1811
+ 'name': 'LinearizationTable',
1812
+ 'type': 'Short'
1813
+ },
1814
+ 50713: {
1815
+ 'name': 'BlackLevelRepeatDim',
1816
+ 'type': 'Short'
1817
+ },
1818
+ 50714: {
1819
+ 'name': 'BlackLevel',
1820
+ 'type': 'Rational'
1821
+ },
1822
+ 50715: {
1823
+ 'name': 'BlackLevelDeltaH',
1824
+ 'type': 'SRational'
1825
+ },
1826
+ 50716: {
1827
+ 'name': 'BlackLevelDeltaV',
1828
+ 'type': 'SRational'
1829
+ },
1830
+ 50717: {
1831
+ 'name': 'WhiteLevel',
1832
+ 'type': 'Short'
1833
+ },
1834
+ 50718: {
1835
+ 'name': 'DefaultScale',
1836
+ 'type': 'Rational'
1837
+ },
1838
+ 50719: {
1839
+ 'name': 'DefaultCropOrigin',
1840
+ 'type': 'Short'
1841
+ },
1842
+ 50720: {
1843
+ 'name': 'DefaultCropSize',
1844
+ 'type': 'Short'
1845
+ },
1846
+ 50721: {
1847
+ 'name': 'ColorMatrix1',
1848
+ 'type': 'SRational'
1849
+ },
1850
+ 50722: {
1851
+ 'name': 'ColorMatrix2',
1852
+ 'type': 'SRational'
1853
+ },
1854
+ 50723: {
1855
+ 'name': 'CameraCalibration1',
1856
+ 'type': 'SRational'
1857
+ },
1858
+ 50724: {
1859
+ 'name': 'CameraCalibration2',
1860
+ 'type': 'SRational'
1861
+ },
1862
+ 50725: {
1863
+ 'name': 'ReductionMatrix1',
1864
+ 'type': 'SRational'
1865
+ },
1866
+ 50726: {
1867
+ 'name': 'ReductionMatrix2',
1868
+ 'type': 'SRational'
1869
+ },
1870
+ 50727: {
1871
+ 'name': 'AnalogBalance',
1872
+ 'type': 'Rational'
1873
+ },
1874
+ 50728: {
1875
+ 'name': 'AsShotNeutral',
1876
+ 'type': 'Short'
1877
+ },
1878
+ 50729: {
1879
+ 'name': 'AsShotWhiteXY',
1880
+ 'type': 'Rational'
1881
+ },
1882
+ 50730: {
1883
+ 'name': 'BaselineExposure',
1884
+ 'type': 'SRational'
1885
+ },
1886
+ 50731: {
1887
+ 'name': 'BaselineNoise',
1888
+ 'type': 'Rational'
1889
+ },
1890
+ 50732: {
1891
+ 'name': 'BaselineSharpness',
1892
+ 'type': 'Rational'
1893
+ },
1894
+ 50733: {
1895
+ 'name': 'BayerGreenSplit',
1896
+ 'type': 'Long'
1897
+ },
1898
+ 50734: {
1899
+ 'name': 'LinearResponseLimit',
1900
+ 'type': 'Rational'
1901
+ },
1902
+ 50735: {
1903
+ 'name': 'CameraSerialNumber',
1904
+ 'type': 'Ascii'
1905
+ },
1906
+ 50736: {
1907
+ 'name': 'LensInfo',
1908
+ 'type': 'Rational'
1909
+ },
1910
+ 50737: {
1911
+ 'name': 'ChromaBlurRadius',
1912
+ 'type': 'Rational'
1913
+ },
1914
+ 50738: {
1915
+ 'name': 'AntiAliasStrength',
1916
+ 'type': 'Rational'
1917
+ },
1918
+ 50739: {
1919
+ 'name': 'ShadowScale',
1920
+ 'type': 'SRational'
1921
+ },
1922
+ 50740: {
1923
+ 'name': 'DNGPrivateData',
1924
+ 'type': 'Byte'
1925
+ },
1926
+ 50741: {
1927
+ 'name': 'MakerNoteSafety',
1928
+ 'type': 'Short'
1929
+ },
1930
+ 50778: {
1931
+ 'name': 'CalibrationIlluminant1',
1932
+ 'type': 'Short'
1933
+ },
1934
+ 50779: {
1935
+ 'name': 'CalibrationIlluminant2',
1936
+ 'type': 'Short'
1937
+ },
1938
+ 50780: {
1939
+ 'name': 'BestQualityScale',
1940
+ 'type': 'Rational'
1941
+ },
1942
+ 50781: {
1943
+ 'name': 'RawDataUniqueID',
1944
+ 'type': 'Byte'
1945
+ },
1946
+ 50827: {
1947
+ 'name': 'OriginalRawFileName',
1948
+ 'type': 'Byte'
1949
+ },
1950
+ 50828: {
1951
+ 'name': 'OriginalRawFileData',
1952
+ 'type': 'Undefined'
1953
+ },
1954
+ 50829: {
1955
+ 'name': 'ActiveArea',
1956
+ 'type': 'Short'
1957
+ },
1958
+ 50830: {
1959
+ 'name': 'MaskedAreas',
1960
+ 'type': 'Short'
1961
+ },
1962
+ 50831: {
1963
+ 'name': 'AsShotICCProfile',
1964
+ 'type': 'Undefined'
1965
+ },
1966
+ 50832: {
1967
+ 'name': 'AsShotPreProfileMatrix',
1968
+ 'type': 'SRational'
1969
+ },
1970
+ 50833: {
1971
+ 'name': 'CurrentICCProfile',
1972
+ 'type': 'Undefined'
1973
+ },
1974
+ 50834: {
1975
+ 'name': 'CurrentPreProfileMatrix',
1976
+ 'type': 'SRational'
1977
+ },
1978
+ 50879: {
1979
+ 'name': 'ColorimetricReference',
1980
+ 'type': 'Short'
1981
+ },
1982
+ 50931: {
1983
+ 'name': 'CameraCalibrationSignature',
1984
+ 'type': 'Byte'
1985
+ },
1986
+ 50932: {
1987
+ 'name': 'ProfileCalibrationSignature',
1988
+ 'type': 'Byte'
1989
+ },
1990
+ 50934: {
1991
+ 'name': 'AsShotProfileName',
1992
+ 'type': 'Byte'
1993
+ },
1994
+ 50935: {
1995
+ 'name': 'NoiseReductionApplied',
1996
+ 'type': 'Rational'
1997
+ },
1998
+ 50936: {
1999
+ 'name': 'ProfileName',
2000
+ 'type': 'Byte'
2001
+ },
2002
+ 50937: {
2003
+ 'name': 'ProfileHueSatMapDims',
2004
+ 'type': 'Long'
2005
+ },
2006
+ 50938: {
2007
+ 'name': 'ProfileHueSatMapData1',
2008
+ 'type': 'Float'
2009
+ },
2010
+ 50939: {
2011
+ 'name': 'ProfileHueSatMapData2',
2012
+ 'type': 'Float'
2013
+ },
2014
+ 50940: {
2015
+ 'name': 'ProfileToneCurve',
2016
+ 'type': 'Float'
2017
+ },
2018
+ 50941: {
2019
+ 'name': 'ProfileEmbedPolicy',
2020
+ 'type': 'Long'
2021
+ },
2022
+ 50942: {
2023
+ 'name': 'ProfileCopyright',
2024
+ 'type': 'Byte'
2025
+ },
2026
+ 50964: {
2027
+ 'name': 'ForwardMatrix1',
2028
+ 'type': 'SRational'
2029
+ },
2030
+ 50965: {
2031
+ 'name': 'ForwardMatrix2',
2032
+ 'type': 'SRational'
2033
+ },
2034
+ 50966: {
2035
+ 'name': 'PreviewApplicationName',
2036
+ 'type': 'Byte'
2037
+ },
2038
+ 50967: {
2039
+ 'name': 'PreviewApplicationVersion',
2040
+ 'type': 'Byte'
2041
+ },
2042
+ 50968: {
2043
+ 'name': 'PreviewSettingsName',
2044
+ 'type': 'Byte'
2045
+ },
2046
+ 50969: {
2047
+ 'name': 'PreviewSettingsDigest',
2048
+ 'type': 'Byte'
2049
+ },
2050
+ 50970: {
2051
+ 'name': 'PreviewColorSpace',
2052
+ 'type': 'Long'
2053
+ },
2054
+ 50971: {
2055
+ 'name': 'PreviewDateTime',
2056
+ 'type': 'Ascii'
2057
+ },
2058
+ 50972: {
2059
+ 'name': 'RawImageDigest',
2060
+ 'type': 'Undefined'
2061
+ },
2062
+ 50973: {
2063
+ 'name': 'OriginalRawFileDigest',
2064
+ 'type': 'Undefined'
2065
+ },
2066
+ 50974: {
2067
+ 'name': 'SubTileBlockSize',
2068
+ 'type': 'Long'
2069
+ },
2070
+ 50975: {
2071
+ 'name': 'RowInterleaveFactor',
2072
+ 'type': 'Long'
2073
+ },
2074
+ 50981: {
2075
+ 'name': 'ProfileLookTableDims',
2076
+ 'type': 'Long'
2077
+ },
2078
+ 50982: {
2079
+ 'name': 'ProfileLookTableData',
2080
+ 'type': 'Float'
2081
+ },
2082
+ 51008: {
2083
+ 'name': 'OpcodeList1',
2084
+ 'type': 'Undefined'
2085
+ },
2086
+ 51009: {
2087
+ 'name': 'OpcodeList2',
2088
+ 'type': 'Undefined'
2089
+ },
2090
+ 51022: {
2091
+ 'name': 'OpcodeList3',
2092
+ 'type': 'Undefined'
2093
+ }
2094
+ },
2095
+ 'Exif': {
2096
+ 33434: {
2097
+ 'name': 'ExposureTime',
2098
+ 'type': 'Rational'
2099
+ },
2100
+ 33437: {
2101
+ 'name': 'FNumber',
2102
+ 'type': 'Rational'
2103
+ },
2104
+ 34850: {
2105
+ 'name': 'ExposureProgram',
2106
+ 'type': 'Short'
2107
+ },
2108
+ 34852: {
2109
+ 'name': 'SpectralSensitivity',
2110
+ 'type': 'Ascii'
2111
+ },
2112
+ 34855: {
2113
+ 'name': 'ISOSpeedRatings',
2114
+ 'type': 'Short'
2115
+ },
2116
+ 34856: {
2117
+ 'name': 'OECF',
2118
+ 'type': 'Undefined'
2119
+ },
2120
+ 34864: {
2121
+ 'name': 'SensitivityType',
2122
+ 'type': 'Short'
2123
+ },
2124
+ 34865: {
2125
+ 'name': 'StandardOutputSensitivity',
2126
+ 'type': 'Long'
2127
+ },
2128
+ 34866: {
2129
+ 'name': 'RecommendedExposureIndex',
2130
+ 'type': 'Long'
2131
+ },
2132
+ 34867: {
2133
+ 'name': 'ISOSpeed',
2134
+ 'type': 'Long'
2135
+ },
2136
+ 34868: {
2137
+ 'name': 'ISOSpeedLatitudeyyy',
2138
+ 'type': 'Long'
2139
+ },
2140
+ 34869: {
2141
+ 'name': 'ISOSpeedLatitudezzz',
2142
+ 'type': 'Long'
2143
+ },
2144
+ 36864: {
2145
+ 'name': 'ExifVersion',
2146
+ 'type': 'Undefined'
2147
+ },
2148
+ 36867: {
2149
+ 'name': 'DateTimeOriginal',
2150
+ 'type': 'Ascii'
2151
+ },
2152
+ 36868: {
2153
+ 'name': 'DateTimeDigitized',
2154
+ 'type': 'Ascii'
2155
+ },
2156
+ 37121: {
2157
+ 'name': 'ComponentsConfiguration',
2158
+ 'type': 'Undefined'
2159
+ },
2160
+ 37122: {
2161
+ 'name': 'CompressedBitsPerPixel',
2162
+ 'type': 'Rational'
2163
+ },
2164
+ 37377: {
2165
+ 'name': 'ShutterSpeedValue',
2166
+ 'type': 'SRational'
2167
+ },
2168
+ 37378: {
2169
+ 'name': 'ApertureValue',
2170
+ 'type': 'Rational'
2171
+ },
2172
+ 37379: {
2173
+ 'name': 'BrightnessValue',
2174
+ 'type': 'SRational'
2175
+ },
2176
+ 37380: {
2177
+ 'name': 'ExposureBiasValue',
2178
+ 'type': 'SRational'
2179
+ },
2180
+ 37381: {
2181
+ 'name': 'MaxApertureValue',
2182
+ 'type': 'Rational'
2183
+ },
2184
+ 37382: {
2185
+ 'name': 'SubjectDistance',
2186
+ 'type': 'Rational'
2187
+ },
2188
+ 37383: {
2189
+ 'name': 'MeteringMode',
2190
+ 'type': 'Short'
2191
+ },
2192
+ 37384: {
2193
+ 'name': 'LightSource',
2194
+ 'type': 'Short'
2195
+ },
2196
+ 37385: {
2197
+ 'name': 'Flash',
2198
+ 'type': 'Short'
2199
+ },
2200
+ 37386: {
2201
+ 'name': 'FocalLength',
2202
+ 'type': 'Rational'
2203
+ },
2204
+ 37396: {
2205
+ 'name': 'SubjectArea',
2206
+ 'type': 'Short'
2207
+ },
2208
+ 37500: {
2209
+ 'name': 'MakerNote',
2210
+ 'type': 'Undefined'
2211
+ },
2212
+ 37510: {
2213
+ 'name': 'UserComment',
2214
+ 'type': 'Ascii'
2215
+ },
2216
+ 37520: {
2217
+ 'name': 'SubSecTime',
2218
+ 'type': 'Ascii'
2219
+ },
2220
+ 37521: {
2221
+ 'name': 'SubSecTimeOriginal',
2222
+ 'type': 'Ascii'
2223
+ },
2224
+ 37522: {
2225
+ 'name': 'SubSecTimeDigitized',
2226
+ 'type': 'Ascii'
2227
+ },
2228
+ 40960: {
2229
+ 'name': 'FlashpixVersion',
2230
+ 'type': 'Undefined'
2231
+ },
2232
+ 40961: {
2233
+ 'name': 'ColorSpace',
2234
+ 'type': 'Short'
2235
+ },
2236
+ 40962: {
2237
+ 'name': 'PixelXDimension',
2238
+ 'type': 'Long'
2239
+ },
2240
+ 40963: {
2241
+ 'name': 'PixelYDimension',
2242
+ 'type': 'Long'
2243
+ },
2244
+ 40964: {
2245
+ 'name': 'RelatedSoundFile',
2246
+ 'type': 'Ascii'
2247
+ },
2248
+ 40965: {
2249
+ 'name': 'InteroperabilityTag',
2250
+ 'type': 'Long'
2251
+ },
2252
+ 41483: {
2253
+ 'name': 'FlashEnergy',
2254
+ 'type': 'Rational'
2255
+ },
2256
+ 41484: {
2257
+ 'name': 'SpatialFrequencyResponse',
2258
+ 'type': 'Undefined'
2259
+ },
2260
+ 41486: {
2261
+ 'name': 'FocalPlaneXResolution',
2262
+ 'type': 'Rational'
2263
+ },
2264
+ 41487: {
2265
+ 'name': 'FocalPlaneYResolution',
2266
+ 'type': 'Rational'
2267
+ },
2268
+ 41488: {
2269
+ 'name': 'FocalPlaneResolutionUnit',
2270
+ 'type': 'Short'
2271
+ },
2272
+ 41492: {
2273
+ 'name': 'SubjectLocation',
2274
+ 'type': 'Short'
2275
+ },
2276
+ 41493: {
2277
+ 'name': 'ExposureIndex',
2278
+ 'type': 'Rational'
2279
+ },
2280
+ 41495: {
2281
+ 'name': 'SensingMethod',
2282
+ 'type': 'Short'
2283
+ },
2284
+ 41728: {
2285
+ 'name': 'FileSource',
2286
+ 'type': 'Undefined'
2287
+ },
2288
+ 41729: {
2289
+ 'name': 'SceneType',
2290
+ 'type': 'Undefined'
2291
+ },
2292
+ 41730: {
2293
+ 'name': 'CFAPattern',
2294
+ 'type': 'Undefined'
2295
+ },
2296
+ 41985: {
2297
+ 'name': 'CustomRendered',
2298
+ 'type': 'Short'
2299
+ },
2300
+ 41986: {
2301
+ 'name': 'ExposureMode',
2302
+ 'type': 'Short'
2303
+ },
2304
+ 41987: {
2305
+ 'name': 'WhiteBalance',
2306
+ 'type': 'Short'
2307
+ },
2308
+ 41988: {
2309
+ 'name': 'DigitalZoomRatio',
2310
+ 'type': 'Rational'
2311
+ },
2312
+ 41989: {
2313
+ 'name': 'FocalLengthIn35mmFilm',
2314
+ 'type': 'Short'
2315
+ },
2316
+ 41990: {
2317
+ 'name': 'SceneCaptureType',
2318
+ 'type': 'Short'
2319
+ },
2320
+ 41991: {
2321
+ 'name': 'GainControl',
2322
+ 'type': 'Short'
2323
+ },
2324
+ 41992: {
2325
+ 'name': 'Contrast',
2326
+ 'type': 'Short'
2327
+ },
2328
+ 41993: {
2329
+ 'name': 'Saturation',
2330
+ 'type': 'Short'
2331
+ },
2332
+ 41994: {
2333
+ 'name': 'Sharpness',
2334
+ 'type': 'Short'
2335
+ },
2336
+ 41995: {
2337
+ 'name': 'DeviceSettingDescription',
2338
+ 'type': 'Undefined'
2339
+ },
2340
+ 41996: {
2341
+ 'name': 'SubjectDistanceRange',
2342
+ 'type': 'Short'
2343
+ },
2344
+ 42016: {
2345
+ 'name': 'ImageUniqueID',
2346
+ 'type': 'Ascii'
2347
+ },
2348
+ 42032: {
2349
+ 'name': 'CameraOwnerName',
2350
+ 'type': 'Ascii'
2351
+ },
2352
+ 42033: {
2353
+ 'name': 'BodySerialNumber',
2354
+ 'type': 'Ascii'
2355
+ },
2356
+ 42034: {
2357
+ 'name': 'LensSpecification',
2358
+ 'type': 'Rational'
2359
+ },
2360
+ 42035: {
2361
+ 'name': 'LensMake',
2362
+ 'type': 'Ascii'
2363
+ },
2364
+ 42036: {
2365
+ 'name': 'LensModel',
2366
+ 'type': 'Ascii'
2367
+ },
2368
+ 42037: {
2369
+ 'name': 'LensSerialNumber',
2370
+ 'type': 'Ascii'
2371
+ },
2372
+ 42240: {
2373
+ 'name': 'Gamma',
2374
+ 'type': 'Rational'
2375
+ }
2376
+ },
2377
+ 'GPS': {
2378
+ 0: {
2379
+ 'name': 'GPSVersionID',
2380
+ 'type': 'Byte'
2381
+ },
2382
+ 1: {
2383
+ 'name': 'GPSLatitudeRef',
2384
+ 'type': 'Ascii'
2385
+ },
2386
+ 2: {
2387
+ 'name': 'GPSLatitude',
2388
+ 'type': 'Rational'
2389
+ },
2390
+ 3: {
2391
+ 'name': 'GPSLongitudeRef',
2392
+ 'type': 'Ascii'
2393
+ },
2394
+ 4: {
2395
+ 'name': 'GPSLongitude',
2396
+ 'type': 'Rational'
2397
+ },
2398
+ 5: {
2399
+ 'name': 'GPSAltitudeRef',
2400
+ 'type': 'Byte'
2401
+ },
2402
+ 6: {
2403
+ 'name': 'GPSAltitude',
2404
+ 'type': 'Rational'
2405
+ },
2406
+ 7: {
2407
+ 'name': 'GPSTimeStamp',
2408
+ 'type': 'Rational'
2409
+ },
2410
+ 8: {
2411
+ 'name': 'GPSSatellites',
2412
+ 'type': 'Ascii'
2413
+ },
2414
+ 9: {
2415
+ 'name': 'GPSStatus',
2416
+ 'type': 'Ascii'
2417
+ },
2418
+ 10: {
2419
+ 'name': 'GPSMeasureMode',
2420
+ 'type': 'Ascii'
2421
+ },
2422
+ 11: {
2423
+ 'name': 'GPSDOP',
2424
+ 'type': 'Rational'
2425
+ },
2426
+ 12: {
2427
+ 'name': 'GPSSpeedRef',
2428
+ 'type': 'Ascii'
2429
+ },
2430
+ 13: {
2431
+ 'name': 'GPSSpeed',
2432
+ 'type': 'Rational'
2433
+ },
2434
+ 14: {
2435
+ 'name': 'GPSTrackRef',
2436
+ 'type': 'Ascii'
2437
+ },
2438
+ 15: {
2439
+ 'name': 'GPSTrack',
2440
+ 'type': 'Rational'
2441
+ },
2442
+ 16: {
2443
+ 'name': 'GPSImgDirectionRef',
2444
+ 'type': 'Ascii'
2445
+ },
2446
+ 17: {
2447
+ 'name': 'GPSImgDirection',
2448
+ 'type': 'Rational'
2449
+ },
2450
+ 18: {
2451
+ 'name': 'GPSMapDatum',
2452
+ 'type': 'Ascii'
2453
+ },
2454
+ 19: {
2455
+ 'name': 'GPSDestLatitudeRef',
2456
+ 'type': 'Ascii'
2457
+ },
2458
+ 20: {
2459
+ 'name': 'GPSDestLatitude',
2460
+ 'type': 'Rational'
2461
+ },
2462
+ 21: {
2463
+ 'name': 'GPSDestLongitudeRef',
2464
+ 'type': 'Ascii'
2465
+ },
2466
+ 22: {
2467
+ 'name': 'GPSDestLongitude',
2468
+ 'type': 'Rational'
2469
+ },
2470
+ 23: {
2471
+ 'name': 'GPSDestBearingRef',
2472
+ 'type': 'Ascii'
2473
+ },
2474
+ 24: {
2475
+ 'name': 'GPSDestBearing',
2476
+ 'type': 'Rational'
2477
+ },
2478
+ 25: {
2479
+ 'name': 'GPSDestDistanceRef',
2480
+ 'type': 'Ascii'
2481
+ },
2482
+ 26: {
2483
+ 'name': 'GPSDestDistance',
2484
+ 'type': 'Rational'
2485
+ },
2486
+ 27: {
2487
+ 'name': 'GPSProcessingMethod',
2488
+ 'type': 'Undefined'
2489
+ },
2490
+ 28: {
2491
+ 'name': 'GPSAreaInformation',
2492
+ 'type': 'Undefined'
2493
+ },
2494
+ 29: {
2495
+ 'name': 'GPSDateStamp',
2496
+ 'type': 'Ascii'
2497
+ },
2498
+ 30: {
2499
+ 'name': 'GPSDifferential',
2500
+ 'type': 'Short'
2501
+ },
2502
+ 31: {
2503
+ 'name': 'GPSHPositioningError',
2504
+ 'type': 'Rational'
2505
+ }
2506
+ },
2507
+ 'Interop': {
2508
+ 1: {
2509
+ 'name': 'InteroperabilityIndex',
2510
+ 'type': 'Ascii'
2511
+ }
2512
+ },
2513
+ };
2514
+ TAGS["0th"] = TAGS["Image"];
2515
+ TAGS["1st"] = TAGS["Image"];
2516
+ that.TAGS = TAGS;
2517
+
2518
+
2519
+ that.ImageIFD = {
2520
+ ProcessingSoftware:11,
2521
+ NewSubfileType:254,
2522
+ SubfileType:255,
2523
+ ImageWidth:256,
2524
+ ImageLength:257,
2525
+ BitsPerSample:258,
2526
+ Compression:259,
2527
+ PhotometricInterpretation:262,
2528
+ Threshholding:263,
2529
+ CellWidth:264,
2530
+ CellLength:265,
2531
+ FillOrder:266,
2532
+ DocumentName:269,
2533
+ ImageDescription:270,
2534
+ Make:271,
2535
+ Model:272,
2536
+ StripOffsets:273,
2537
+ Orientation:274,
2538
+ SamplesPerPixel:277,
2539
+ RowsPerStrip:278,
2540
+ StripByteCounts:279,
2541
+ XResolution:282,
2542
+ YResolution:283,
2543
+ PlanarConfiguration:284,
2544
+ GrayResponseUnit:290,
2545
+ GrayResponseCurve:291,
2546
+ T4Options:292,
2547
+ T6Options:293,
2548
+ ResolutionUnit:296,
2549
+ TransferFunction:301,
2550
+ Software:305,
2551
+ DateTime:306,
2552
+ Artist:315,
2553
+ HostComputer:316,
2554
+ Predictor:317,
2555
+ WhitePoint:318,
2556
+ PrimaryChromaticities:319,
2557
+ ColorMap:320,
2558
+ HalftoneHints:321,
2559
+ TileWidth:322,
2560
+ TileLength:323,
2561
+ TileOffsets:324,
2562
+ TileByteCounts:325,
2563
+ SubIFDs:330,
2564
+ InkSet:332,
2565
+ InkNames:333,
2566
+ NumberOfInks:334,
2567
+ DotRange:336,
2568
+ TargetPrinter:337,
2569
+ ExtraSamples:338,
2570
+ SampleFormat:339,
2571
+ SMinSampleValue:340,
2572
+ SMaxSampleValue:341,
2573
+ TransferRange:342,
2574
+ ClipPath:343,
2575
+ XClipPathUnits:344,
2576
+ YClipPathUnits:345,
2577
+ Indexed:346,
2578
+ JPEGTables:347,
2579
+ OPIProxy:351,
2580
+ JPEGProc:512,
2581
+ JPEGInterchangeFormat:513,
2582
+ JPEGInterchangeFormatLength:514,
2583
+ JPEGRestartInterval:515,
2584
+ JPEGLosslessPredictors:517,
2585
+ JPEGPointTransforms:518,
2586
+ JPEGQTables:519,
2587
+ JPEGDCTables:520,
2588
+ JPEGACTables:521,
2589
+ YCbCrCoefficients:529,
2590
+ YCbCrSubSampling:530,
2591
+ YCbCrPositioning:531,
2592
+ ReferenceBlackWhite:532,
2593
+ XMLPacket:700,
2594
+ Rating:18246,
2595
+ RatingPercent:18249,
2596
+ ImageID:32781,
2597
+ CFARepeatPatternDim:33421,
2598
+ CFAPattern:33422,
2599
+ BatteryLevel:33423,
2600
+ Copyright:33432,
2601
+ ExposureTime:33434,
2602
+ ImageResources:34377,
2603
+ ExifTag:34665,
2604
+ InterColorProfile:34675,
2605
+ GPSTag:34853,
2606
+ Interlace:34857,
2607
+ TimeZoneOffset:34858,
2608
+ SelfTimerMode:34859,
2609
+ FlashEnergy:37387,
2610
+ SpatialFrequencyResponse:37388,
2611
+ Noise:37389,
2612
+ FocalPlaneXResolution:37390,
2613
+ FocalPlaneYResolution:37391,
2614
+ FocalPlaneResolutionUnit:37392,
2615
+ ImageNumber:37393,
2616
+ SecurityClassification:37394,
2617
+ ImageHistory:37395,
2618
+ ExposureIndex:37397,
2619
+ TIFFEPStandardID:37398,
2620
+ SensingMethod:37399,
2621
+ XPTitle:40091,
2622
+ XPComment:40092,
2623
+ XPAuthor:40093,
2624
+ XPKeywords:40094,
2625
+ XPSubject:40095,
2626
+ PrintImageMatching:50341,
2627
+ DNGVersion:50706,
2628
+ DNGBackwardVersion:50707,
2629
+ UniqueCameraModel:50708,
2630
+ LocalizedCameraModel:50709,
2631
+ CFAPlaneColor:50710,
2632
+ CFALayout:50711,
2633
+ LinearizationTable:50712,
2634
+ BlackLevelRepeatDim:50713,
2635
+ BlackLevel:50714,
2636
+ BlackLevelDeltaH:50715,
2637
+ BlackLevelDeltaV:50716,
2638
+ WhiteLevel:50717,
2639
+ DefaultScale:50718,
2640
+ DefaultCropOrigin:50719,
2641
+ DefaultCropSize:50720,
2642
+ ColorMatrix1:50721,
2643
+ ColorMatrix2:50722,
2644
+ CameraCalibration1:50723,
2645
+ CameraCalibration2:50724,
2646
+ ReductionMatrix1:50725,
2647
+ ReductionMatrix2:50726,
2648
+ AnalogBalance:50727,
2649
+ AsShotNeutral:50728,
2650
+ AsShotWhiteXY:50729,
2651
+ BaselineExposure:50730,
2652
+ BaselineNoise:50731,
2653
+ BaselineSharpness:50732,
2654
+ BayerGreenSplit:50733,
2655
+ LinearResponseLimit:50734,
2656
+ CameraSerialNumber:50735,
2657
+ LensInfo:50736,
2658
+ ChromaBlurRadius:50737,
2659
+ AntiAliasStrength:50738,
2660
+ ShadowScale:50739,
2661
+ DNGPrivateData:50740,
2662
+ MakerNoteSafety:50741,
2663
+ CalibrationIlluminant1:50778,
2664
+ CalibrationIlluminant2:50779,
2665
+ BestQualityScale:50780,
2666
+ RawDataUniqueID:50781,
2667
+ OriginalRawFileName:50827,
2668
+ OriginalRawFileData:50828,
2669
+ ActiveArea:50829,
2670
+ MaskedAreas:50830,
2671
+ AsShotICCProfile:50831,
2672
+ AsShotPreProfileMatrix:50832,
2673
+ CurrentICCProfile:50833,
2674
+ CurrentPreProfileMatrix:50834,
2675
+ ColorimetricReference:50879,
2676
+ CameraCalibrationSignature:50931,
2677
+ ProfileCalibrationSignature:50932,
2678
+ AsShotProfileName:50934,
2679
+ NoiseReductionApplied:50935,
2680
+ ProfileName:50936,
2681
+ ProfileHueSatMapDims:50937,
2682
+ ProfileHueSatMapData1:50938,
2683
+ ProfileHueSatMapData2:50939,
2684
+ ProfileToneCurve:50940,
2685
+ ProfileEmbedPolicy:50941,
2686
+ ProfileCopyright:50942,
2687
+ ForwardMatrix1:50964,
2688
+ ForwardMatrix2:50965,
2689
+ PreviewApplicationName:50966,
2690
+ PreviewApplicationVersion:50967,
2691
+ PreviewSettingsName:50968,
2692
+ PreviewSettingsDigest:50969,
2693
+ PreviewColorSpace:50970,
2694
+ PreviewDateTime:50971,
2695
+ RawImageDigest:50972,
2696
+ OriginalRawFileDigest:50973,
2697
+ SubTileBlockSize:50974,
2698
+ RowInterleaveFactor:50975,
2699
+ ProfileLookTableDims:50981,
2700
+ ProfileLookTableData:50982,
2701
+ OpcodeList1:51008,
2702
+ OpcodeList2:51009,
2703
+ OpcodeList3:51022,
2704
+ NoiseProfile:51041,
2705
+ };
2706
+
2707
+
2708
+ that.ExifIFD = {
2709
+ ExposureTime:33434,
2710
+ FNumber:33437,
2711
+ ExposureProgram:34850,
2712
+ SpectralSensitivity:34852,
2713
+ ISOSpeedRatings:34855,
2714
+ OECF:34856,
2715
+ SensitivityType:34864,
2716
+ StandardOutputSensitivity:34865,
2717
+ RecommendedExposureIndex:34866,
2718
+ ISOSpeed:34867,
2719
+ ISOSpeedLatitudeyyy:34868,
2720
+ ISOSpeedLatitudezzz:34869,
2721
+ ExifVersion:36864,
2722
+ DateTimeOriginal:36867,
2723
+ DateTimeDigitized:36868,
2724
+ ComponentsConfiguration:37121,
2725
+ CompressedBitsPerPixel:37122,
2726
+ ShutterSpeedValue:37377,
2727
+ ApertureValue:37378,
2728
+ BrightnessValue:37379,
2729
+ ExposureBiasValue:37380,
2730
+ MaxApertureValue:37381,
2731
+ SubjectDistance:37382,
2732
+ MeteringMode:37383,
2733
+ LightSource:37384,
2734
+ Flash:37385,
2735
+ FocalLength:37386,
2736
+ SubjectArea:37396,
2737
+ MakerNote:37500,
2738
+ UserComment:37510,
2739
+ SubSecTime:37520,
2740
+ SubSecTimeOriginal:37521,
2741
+ SubSecTimeDigitized:37522,
2742
+ FlashpixVersion:40960,
2743
+ ColorSpace:40961,
2744
+ PixelXDimension:40962,
2745
+ PixelYDimension:40963,
2746
+ RelatedSoundFile:40964,
2747
+ InteroperabilityTag:40965,
2748
+ FlashEnergy:41483,
2749
+ SpatialFrequencyResponse:41484,
2750
+ FocalPlaneXResolution:41486,
2751
+ FocalPlaneYResolution:41487,
2752
+ FocalPlaneResolutionUnit:41488,
2753
+ SubjectLocation:41492,
2754
+ ExposureIndex:41493,
2755
+ SensingMethod:41495,
2756
+ FileSource:41728,
2757
+ SceneType:41729,
2758
+ CFAPattern:41730,
2759
+ CustomRendered:41985,
2760
+ ExposureMode:41986,
2761
+ WhiteBalance:41987,
2762
+ DigitalZoomRatio:41988,
2763
+ FocalLengthIn35mmFilm:41989,
2764
+ SceneCaptureType:41990,
2765
+ GainControl:41991,
2766
+ Contrast:41992,
2767
+ Saturation:41993,
2768
+ Sharpness:41994,
2769
+ DeviceSettingDescription:41995,
2770
+ SubjectDistanceRange:41996,
2771
+ ImageUniqueID:42016,
2772
+ CameraOwnerName:42032,
2773
+ BodySerialNumber:42033,
2774
+ LensSpecification:42034,
2775
+ LensMake:42035,
2776
+ LensModel:42036,
2777
+ LensSerialNumber:42037,
2778
+ Gamma:42240,
2779
+ };
2780
+
2781
+
2782
+ that.GPSIFD = {
2783
+ GPSVersionID:0,
2784
+ GPSLatitudeRef:1,
2785
+ GPSLatitude:2,
2786
+ GPSLongitudeRef:3,
2787
+ GPSLongitude:4,
2788
+ GPSAltitudeRef:5,
2789
+ GPSAltitude:6,
2790
+ GPSTimeStamp:7,
2791
+ GPSSatellites:8,
2792
+ GPSStatus:9,
2793
+ GPSMeasureMode:10,
2794
+ GPSDOP:11,
2795
+ GPSSpeedRef:12,
2796
+ GPSSpeed:13,
2797
+ GPSTrackRef:14,
2798
+ GPSTrack:15,
2799
+ GPSImgDirectionRef:16,
2800
+ GPSImgDirection:17,
2801
+ GPSMapDatum:18,
2802
+ GPSDestLatitudeRef:19,
2803
+ GPSDestLatitude:20,
2804
+ GPSDestLongitudeRef:21,
2805
+ GPSDestLongitude:22,
2806
+ GPSDestBearingRef:23,
2807
+ GPSDestBearing:24,
2808
+ GPSDestDistanceRef:25,
2809
+ GPSDestDistance:26,
2810
+ GPSProcessingMethod:27,
2811
+ GPSAreaInformation:28,
2812
+ GPSDateStamp:29,
2813
+ GPSDifferential:30,
2814
+ GPSHPositioningError:31,
2815
+ };
2816
+
2817
+
2818
+ that.InteropIFD = {
2819
+ InteroperabilityIndex:1,
2820
+ };
2821
+
2822
+ that.GPSHelper = {
2823
+ degToDmsRational:function (degFloat) {
2824
+ var degAbs = Math.abs(degFloat);
2825
+ var minFloat = degAbs % 1 * 60;
2826
+ var secFloat = minFloat % 1 * 60;
2827
+ var deg = Math.floor(degAbs);
2828
+ var min = Math.floor(minFloat);
2829
+ var sec = Math.round(secFloat * 100);
2830
+
2831
+ return [[deg, 1], [min, 1], [sec, 100]];
2832
+ },
2833
+
2834
+ dmsRationalToDeg:function (dmsArray, ref) {
2835
+ var sign = (ref === 'S' || ref === 'W') ? -1.0 : 1.0;
2836
+ var deg = dmsArray[0][0] / dmsArray[0][1] +
2837
+ dmsArray[1][0] / dmsArray[1][1] / 60.0 +
2838
+ dmsArray[2][0] / dmsArray[2][1] / 3600.0;
2839
+
2840
+ return deg * sign;
2841
+ }
2842
+ };
2843
+
2844
+
2845
+ if ('object' !== 'undefined') {
2846
+ if ('object' !== 'undefined' && module.exports) {
2847
+ exports = module.exports = that;
2848
+ }
2849
+ exports.piexif = that;
2850
+ } else {
2851
+ window.piexif = that;
2852
+ }
2853
+
2854
+ })();
2855
+ });
2856
+
2857
+ const addExifInImg = async (blob, track, videoSize) => {
2858
+ const base64 = await blobToBase64(blob);
2859
+ const exif = piexif.load(base64);
2860
+ const devices = await navigator.mediaDevices.enumerateDevices();
2861
+ const cameraNames = devices.filter(device => device.kind === 'videoinput').map(device => device.label);
2862
+ const json = {
2863
+ width: videoSize.width,
2864
+ height: videoSize.height,
2865
+ usedCamera: track.label,
2866
+ camerasOnDevice: cameraNames,
2867
+ };
2868
+ const newExif = {
2869
+ '0th': Object.assign(Object.assign({}, exif['0th']), { [piexif.ImageIFD.Model]: json.usedCamera, [piexif.ImageIFD.ImageWidth]: json.width, [piexif.ImageIFD.ImageLength]: json.height }),
2870
+ 'Exif': Object.assign(Object.assign({}, exif['Exif']), { [piexif.ExifIFD.UserComment]: JSON.stringify(json) }),
2871
+ 'GPS': Object.assign({}, exif['GPS']),
2872
+ 'Interop': Object.assign({}, exif['Interop']),
2873
+ '1st': Object.assign({}, exif['1st']),
2874
+ 'thumbnail': exif['thumbnail'],
2875
+ };
2876
+ const newExifBinary = piexif.dump(newExif);
2877
+ const newPhotoData = piexif.insert(newExifBinary, base64);
2878
+ return await fetch(newPhotoData).then(res => res.blob());
2879
+ };
2880
+
2881
+ var ImageFormat;
2882
+ (function (ImageFormat) {
2883
+ ImageFormat["JPEG"] = "image/jpeg";
2884
+ ImageFormat["PNG"] = "image/png";
2885
+ })(ImageFormat || (ImageFormat = {}));
2886
+ class Stream {
2887
+ setFaceDetection(val) {
2888
+ this.faceDetection = val;
2889
+ this.idDetection = !val;
2890
+ }
2891
+ setIdDetection(val) {
2892
+ this.idDetection = val;
2893
+ this.faceDetection = !val;
2894
+ }
2895
+ // public setProbabilityThreshold(val: number): void {
2896
+ // Detector.getInstance().setProbabilityThreshold(val);
2897
+ // }
2898
+ setCallbackChangeTitle(fun) {
2899
+ this.callbackChangeTitle = fun;
2900
+ }
2901
+ setCallbackVideoStarted(fun) {
2902
+ this.callbackVideoStarted = fun;
2903
+ }
2904
+ setCallbackErrors(fun) {
2905
+ this.callbackErrors = fun;
2906
+ }
2907
+ setCallbackAutoCapturing(fun) {
2908
+ this.callbackAutoCapturing = fun;
2909
+ }
2910
+ // public setCallbackFaceDetectionErrors(fun: (e: PipelineResult) => void): void {
2911
+ // this.callbackFaceDetectionErrors = fun;
2912
+ // }
2913
+ setCallbackRecordingReady(fun) {
2914
+ this.callbackRecordingReady = fun;
2915
+ }
2916
+ setCallbackTimeElapsed(fun) {
2917
+ this.callbackTimeElapsed = fun;
2918
+ }
2919
+ setVerificationFinished(fun) {
2920
+ this.verificationFinished = fun;
2921
+ }
2922
+ constructor(mode) {
2923
+ this.streamPaused = false;
2924
+ this.recordedChunks = [];
2925
+ this.videoSize = { width: 0, height: 0 };
2926
+ this.pauseStream = () => {
2927
+ this.streamPaused = true;
2928
+ this.mediaRecorder.pause();
2929
+ this.videoElement.pause();
2930
+ // this.dropMask();
2931
+ // if (this.faceDetection) Detector.getInstance().stopDetector();
2932
+ };
2933
+ this.initFacePose();
2934
+ this.idML5Detector = IDML5Detector.getInstance(this, state.device.isMobile);
2935
+ this.faceML5Detector = FaceML5Detector.getInstance(this, state.device.isMobile);
2936
+ this.verificationMode = mode;
2937
+ }
2938
+ static getInstance(mode) {
2939
+ if (!Stream.instance) {
2940
+ Stream.instance = new Stream(mode);
2941
+ }
2942
+ return Stream.instance;
2943
+ }
2944
+ // public returnErrors(errors: PipelineResult) {
2945
+ // this.callbackFaceDetectionErrors(errors);
2946
+ // }
2947
+ autoCapturing() {
2948
+ this.callbackAutoCapturing();
2949
+ }
2950
+ timeElapsed() {
2951
+ this.callbackTimeElapsed();
2952
+ }
2953
+ verificationReady() {
2954
+ this.verificationFinished();
2955
+ }
2956
+ updateHtmlElements(videoElement, canvasElement, component) {
2957
+ this.videoElement = videoElement;
2958
+ this.canvasElement = canvasElement;
2959
+ this.idML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
2960
+ this.faceML5Detector.updateHtmlElements(this.videoElement, this.canvasElement, component);
2961
+ }
2962
+ static orientationChange() { }
2963
+ startStream(stream) {
2964
+ if (this.stream)
2965
+ this.stream.getTracks().forEach((track) => track.stop());
2966
+ this.stream = stream;
2967
+ if (!this.videoElement || this.videoElement == null) {
2968
+ return;
2969
+ }
2970
+ if ('srcObject' in this.videoElement) {
2971
+ this.videoElement.srcObject = stream;
2972
+ }
2973
+ else {
2974
+ // @ts-ignore
2975
+ this.videoElement.src = window.URL.createObjectURL(stream);
2976
+ }
2977
+ this.videoElement.addEventListener('loadedmetadata', async (_e) => {
2978
+ this.videoElement.play().then(() => {
2979
+ this.streamPaused = false;
2980
+ this.updateCanvasSize(this.canvasElement);
2981
+ this.updateVideoSize(this.videoElement);
2982
+ this.callbackVideoStarted();
2983
+ if (this.idDetection)
2984
+ this.startIdDetection();
2985
+ if (this.faceDetection)
2986
+ this.startFaceDetection();
2987
+ });
2988
+ }, false);
2989
+ }
2990
+ async initStream(stream) {
2991
+ this.startStream(stream);
2992
+ this.recordStream();
2993
+ }
2994
+ async resumeStream() {
2995
+ this.streamPaused = false;
2996
+ this.mediaRecorder.resume();
2997
+ await this.videoElement.play();
2998
+ // this.drawMask();
2999
+ // if (this.faceDetection) await Detector.getInstance().startDetector();
3000
+ }
3001
+ recordStream() {
3002
+ if (this.mediaRecorder && this.mediaRecorder.state == 'recording')
3003
+ return;
3004
+ var options = { mimeType: Stream.webmMimeType.mime, videoBitsPerSecond: 1500000 };
3005
+ if (!MediaRecorder.isTypeSupported(options.mimeType)) {
3006
+ if (state.device.mobileOS == MobileOS.iOS || state.device.browser == Browser.Safari)
3007
+ options.mimeType = Stream.mp4MimeType.mime;
3008
+ }
3009
+ this.recordedChunks = [];
3010
+ this.mediaRecorder = new MediaRecorder(this.stream, options);
3011
+ this.mediaRecorder.ondataavailable = event => {
3012
+ this.recordedChunks.push(event.data);
3013
+ };
3014
+ this.mediaRecorder.onstop = _e => {
3015
+ var rec = new Blob(this.recordedChunks, {
3016
+ type: options.mimeType.split(';')[0],
3017
+ });
3018
+ this.callbackRecordingReady(rec);
3019
+ };
3020
+ this.mediaRecorder.start(); // Start recording, and dump data every second
3021
+ }
3022
+ updateCanvasSize(canvas) {
3023
+ this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
3024
+ canvas.width = this.videoSize.width;
3025
+ canvas.height = this.videoSize.height;
3026
+ }
3027
+ updateVideoSize(video) {
3028
+ this.videoSize = { width: this.videoElement.videoWidth, height: this.videoElement.videoHeight };
3029
+ video.width = this.videoSize.width;
3030
+ video.height = this.videoSize.height;
3031
+ }
3032
+ dropStream() {
3033
+ if (!this.streamStopped()) {
3034
+ this.stream.getTracks().forEach((track) => track.stop());
3035
+ this.videoElement.srcObject = null;
3036
+ }
3037
+ if (this.mediaRecorder && this.mediaRecorder.state != 'inactive') {
3038
+ this.mediaRecorder.stop();
3039
+ }
3040
+ // if (this.faceDetection) Detector.getInstance().stopDetector();
3041
+ }
3042
+ streamStopped() {
3043
+ return !(this.stream && this.stream.getTracks && this.stream.getTracks().length > 0);
3044
+ }
3045
+ async takePhoto() {
3046
+ const canvas = document.createElement('canvas');
3047
+ canvas.style.visibility = 'hidden';
3048
+ canvas.width = this.videoElement.videoWidth;
3049
+ canvas.height = this.videoElement.videoHeight;
3050
+ return await this.getFrame(canvas);
3051
+ }
3052
+ getFrame(canvas) {
3053
+ return new Promise(resolve => {
3054
+ const context = canvas.getContext('2d');
3055
+ context.drawImage(this.videoElement, 0, 0, canvas.width, canvas.height);
3056
+ canvas.toBlob((frame) => {
3057
+ if (frame.type === ImageFormat.JPEG && !state.device.isAppleDevice) {
3058
+ try {
3059
+ addExifInImg(frame, this.stream.getTracks()[0], this.videoSize).then(updatedFrame => resolve(updatedFrame));
3060
+ }
3061
+ catch (e) {
3062
+ resolve(frame);
3063
+ this.callbackErrors(e, false);
3064
+ }
3065
+ }
3066
+ else {
3067
+ resolve(frame);
3068
+ }
3069
+ }, ImageFormat.PNG, 1);
3070
+ //let outCanvContext = this.canvasElement.getContext('2d');
3071
+ //outCanvContext.drawImage(this.videoElement, 0, 0, this.canvasElement.width, this.canvasElement.height);
3072
+ });
3073
+ }
3074
+ async startIdDetection() {
3075
+ if (this.streamPaused)
3076
+ return;
3077
+ this.idML5Detector.initDetector(this.verificationMode);
3078
+ }
3079
+ async startFaceDetection() {
3080
+ if (this.streamPaused)
3081
+ return;
3082
+ this.faceML5Detector.initDetector(this.verificationMode);
3083
+ }
3084
+ initFacePose() {
3085
+ this.facePose = FacePosePick.randomEnum(FacePose);
3086
+ }
3087
+ requestFacePose() {
3088
+ // var pose = FacePose.TiltLeft;
3089
+ this.callbackChangeTitle(this.facePose);
3090
+ return this.facePose;
3091
+ }
3092
+ changeFacePose() {
3093
+ this.callbackChangeTitle(null);
3094
+ }
3095
+ changeIDPose(pose) {
3096
+ this.callbackChangeTitle(pose);
3097
+ }
3098
+ }
3099
+ Stream.mp4MimeType = { type: 'video/mp4', codec: 'codecs:h264', extension: 'mp4', mime: 'video/mp4;codecs:h264' };
3100
+ Stream.webmMimeType = { type: 'video/webm', codec: 'codecs=vp8', extension: 'webm', mime: 'video/webm;codecs=vp8' };
3101
+ window.addEventListener('resize', Stream.orientationChange, false);
3102
+ window.addEventListener('orientationchange', Stream.orientationChange, false);
3103
+
3104
+ export { FaceML5Detector as F, IDML5Detector as I, Stream as S, VerificationMode as V, FacePose as a };