@image-marker/web 0.1.0
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.
- package/CHANGELOG.md +11 -0
- package/README.md +100 -0
- package/api-contract.json +224 -0
- package/lib/commonjs/core/batch.d.ts +32 -0
- package/lib/commonjs/core/batch.js +85 -0
- package/lib/commonjs/core/content-credentials.d.ts +53 -0
- package/lib/commonjs/core/content-credentials.js +96 -0
- package/lib/commonjs/core/image-info.d.ts +30 -0
- package/lib/commonjs/core/image-info.js +348 -0
- package/lib/commonjs/core/index.d.ts +1014 -0
- package/lib/commonjs/core/index.js +92 -0
- package/lib/commonjs/core/invisible-watermark.d.ts +102 -0
- package/lib/commonjs/core/invisible-watermark.js +913 -0
- package/lib/commonjs/core/job.d.ts +57 -0
- package/lib/commonjs/core/job.js +151 -0
- package/lib/commonjs/core/layout.d.ts +19 -0
- package/lib/commonjs/core/layout.js +75 -0
- package/lib/commonjs/core/marker.d.ts +1 -0
- package/lib/commonjs/core/marker.js +11 -0
- package/lib/commonjs/core/recipe.d.ts +44 -0
- package/lib/commonjs/core/recipe.js +175 -0
- package/lib/commonjs/core/result.d.ts +34 -0
- package/lib/commonjs/core/result.js +41 -0
- package/lib/commonjs/core/trace-runtime.d.ts +43 -0
- package/lib/commonjs/core/trace-runtime.js +92 -0
- package/lib/commonjs/core/validate.d.ts +4 -0
- package/lib/commonjs/core/validate.js +192 -0
- package/lib/commonjs/core/web/browser.d.ts +105 -0
- package/lib/commonjs/core/web/browser.js +434 -0
- package/lib/commonjs/core/web/helpers.d.ts +41 -0
- package/lib/commonjs/core/web/helpers.js +264 -0
- package/lib/commonjs/core/web/index.d.ts +59 -0
- package/lib/commonjs/core/web/index.js +724 -0
- package/lib/commonjs/core/web/invisible-worker-client.d.ts +13 -0
- package/lib/commonjs/core/web/invisible-worker-client.js +140 -0
- package/lib/commonjs/core/web/renderer.d.ts +20 -0
- package/lib/commonjs/core/web/renderer.js +665 -0
- package/lib/commonjs/core/web/runtime.d.ts +106 -0
- package/lib/commonjs/core/web/runtime.js +2 -0
- package/lib/commonjs/editor/adapter.d.ts +26 -0
- package/lib/commonjs/editor/adapter.js +102 -0
- package/lib/commonjs/editor/controller.d.ts +106 -0
- package/lib/commonjs/editor/controller.js +919 -0
- package/lib/commonjs/editor/core-contract.d.ts +2 -0
- package/lib/commonjs/editor/core-contract.js +23 -0
- package/lib/commonjs/editor/geometry.d.ts +8 -0
- package/lib/commonjs/editor/geometry.js +109 -0
- package/lib/commonjs/editor/headless.d.ts +5 -0
- package/lib/commonjs/editor/headless.js +22 -0
- package/lib/commonjs/editor/presets.d.ts +19 -0
- package/lib/commonjs/editor/presets.js +64 -0
- package/lib/commonjs/editor/projection.d.ts +12 -0
- package/lib/commonjs/editor/projection.js +195 -0
- package/lib/commonjs/editor/types.d.ts +166 -0
- package/lib/commonjs/editor/types.js +2 -0
- package/lib/commonjs/editor-adapter.d.ts +7 -0
- package/lib/commonjs/editor-adapter.js +17 -0
- package/lib/commonjs/headless.d.ts +2 -0
- package/lib/commonjs/headless.js +26 -0
- package/lib/commonjs/index.d.ts +5 -0
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/module/core/batch.d.ts +32 -0
- package/lib/module/core/batch.js +82 -0
- package/lib/module/core/content-credentials.d.ts +53 -0
- package/lib/module/core/content-credentials.js +92 -0
- package/lib/module/core/image-info.d.ts +30 -0
- package/lib/module/core/image-info.js +343 -0
- package/lib/module/core/index.d.ts +1014 -0
- package/lib/module/core/index.js +56 -0
- package/lib/module/core/invisible-watermark.d.ts +102 -0
- package/lib/module/core/invisible-watermark.js +897 -0
- package/lib/module/core/job.d.ts +57 -0
- package/lib/module/core/job.js +143 -0
- package/lib/module/core/layout.d.ts +19 -0
- package/lib/module/core/layout.js +70 -0
- package/lib/module/core/marker.d.ts +1 -0
- package/lib/module/core/marker.js +4 -0
- package/lib/module/core/recipe.d.ts +44 -0
- package/lib/module/core/recipe.js +169 -0
- package/lib/module/core/result.d.ts +34 -0
- package/lib/module/core/result.js +38 -0
- package/lib/module/core/trace-runtime.d.ts +43 -0
- package/lib/module/core/trace-runtime.js +89 -0
- package/lib/module/core/validate.d.ts +4 -0
- package/lib/module/core/validate.js +187 -0
- package/lib/module/core/web/browser.d.ts +105 -0
- package/lib/module/core/web/browser.js +427 -0
- package/lib/module/core/web/helpers.d.ts +41 -0
- package/lib/module/core/web/helpers.js +251 -0
- package/lib/module/core/web/index.d.ts +59 -0
- package/lib/module/core/web/index.js +709 -0
- package/lib/module/core/web/invisible-worker-client.d.ts +13 -0
- package/lib/module/core/web/invisible-worker-client.js +137 -0
- package/lib/module/core/web/renderer.d.ts +20 -0
- package/lib/module/core/web/renderer.js +661 -0
- package/lib/module/core/web/runtime.d.ts +106 -0
- package/lib/module/core/web/runtime.js +1 -0
- package/lib/module/editor/adapter.d.ts +26 -0
- package/lib/module/editor/adapter.js +99 -0
- package/lib/module/editor/controller.d.ts +106 -0
- package/lib/module/editor/controller.js +915 -0
- package/lib/module/editor/core-contract.d.ts +2 -0
- package/lib/module/editor/core-contract.js +2 -0
- package/lib/module/editor/geometry.d.ts +8 -0
- package/lib/module/editor/geometry.js +103 -0
- package/lib/module/editor/headless.d.ts +5 -0
- package/lib/module/editor/headless.js +4 -0
- package/lib/module/editor/presets.d.ts +19 -0
- package/lib/module/editor/presets.js +57 -0
- package/lib/module/editor/projection.d.ts +12 -0
- package/lib/module/editor/projection.js +188 -0
- package/lib/module/editor/types.d.ts +166 -0
- package/lib/module/editor/types.js +1 -0
- package/lib/module/editor-adapter.d.ts +7 -0
- package/lib/module/editor-adapter.js +10 -0
- package/lib/module/headless.d.ts +2 -0
- package/lib/module/headless.js +2 -0
- package/lib/module/index.d.ts +5 -0
- package/lib/module/index.js +3 -0
- package/lib/module/package.json +1 -0
- package/lib/source-manifest.json +34 -0
- package/lib/worker/invisible-watermark.js +1 -0
- package/package.json +85 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
2
|
+
const FORMAT_MIME_TYPES = {
|
|
3
|
+
jpeg: 'image/jpeg',
|
|
4
|
+
png: 'image/png',
|
|
5
|
+
webp: 'image/webp',
|
|
6
|
+
gif: 'image/gif',
|
|
7
|
+
heif: 'image/heif',
|
|
8
|
+
bmp: 'image/bmp',
|
|
9
|
+
};
|
|
10
|
+
function assertPositiveDimension(value, name) {
|
|
11
|
+
if (typeof value !== 'number' ||
|
|
12
|
+
!Number.isFinite(value) ||
|
|
13
|
+
value <= 0 ||
|
|
14
|
+
!Number.isInteger(value)) {
|
|
15
|
+
throw new Error(`Image info ${name} must be a positive integer.`);
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
function isOrientation(value) {
|
|
20
|
+
return (typeof value === 'number' &&
|
|
21
|
+
Number.isInteger(value) &&
|
|
22
|
+
value >= 1 &&
|
|
23
|
+
value <= 8);
|
|
24
|
+
}
|
|
25
|
+
function orientationTransform(orientation) {
|
|
26
|
+
switch (orientation) {
|
|
27
|
+
case 2:
|
|
28
|
+
return { rotationDegrees: 0, mirrored: true };
|
|
29
|
+
case 3:
|
|
30
|
+
return { rotationDegrees: 180, mirrored: false };
|
|
31
|
+
case 4:
|
|
32
|
+
return { rotationDegrees: 180, mirrored: true };
|
|
33
|
+
case 5:
|
|
34
|
+
return { rotationDegrees: 90, mirrored: true };
|
|
35
|
+
case 6:
|
|
36
|
+
return { rotationDegrees: 90, mirrored: false };
|
|
37
|
+
case 7:
|
|
38
|
+
return { rotationDegrees: 270, mirrored: true };
|
|
39
|
+
case 8:
|
|
40
|
+
return { rotationDegrees: 270, mirrored: false };
|
|
41
|
+
default:
|
|
42
|
+
return { rotationDegrees: 0, mirrored: false };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function createMarkerImageInfo(metadata) {
|
|
46
|
+
const encodedWidth = assertPositiveDimension(metadata.width, 'encodedWidth');
|
|
47
|
+
const encodedHeight = assertPositiveDimension(metadata.height, 'encodedHeight');
|
|
48
|
+
const orientation = metadata.orientation ?? 1;
|
|
49
|
+
const transform = orientationTransform(orientation);
|
|
50
|
+
const swapsDimensions = orientation >= 5;
|
|
51
|
+
return {
|
|
52
|
+
width: swapsDimensions ? encodedHeight : encodedWidth,
|
|
53
|
+
height: swapsDimensions ? encodedWidth : encodedHeight,
|
|
54
|
+
encodedWidth,
|
|
55
|
+
encodedHeight,
|
|
56
|
+
format: metadata.format,
|
|
57
|
+
mimeType: metadata.mimeType ?? FORMAT_MIME_TYPES[metadata.format],
|
|
58
|
+
orientation,
|
|
59
|
+
...transform,
|
|
60
|
+
requiresNormalization: orientation !== 1,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function readUint16(view, offset, littleEndian) {
|
|
64
|
+
return offset >= 0 && offset + 2 <= view.byteLength
|
|
65
|
+
? view.getUint16(offset, littleEndian)
|
|
66
|
+
: undefined;
|
|
67
|
+
}
|
|
68
|
+
function readUint32(view, offset, littleEndian) {
|
|
69
|
+
return offset >= 0 && offset + 4 <= view.byteLength
|
|
70
|
+
? view.getUint32(offset, littleEndian)
|
|
71
|
+
: undefined;
|
|
72
|
+
}
|
|
73
|
+
function ascii(bytes, offset, length) {
|
|
74
|
+
if (offset < 0 || offset + length > bytes.length) {
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
return String.fromCharCode(...bytes.subarray(offset, offset + length));
|
|
78
|
+
}
|
|
79
|
+
function parseExifOrientation(view, tiffOffset, endOffset) {
|
|
80
|
+
if (tiffOffset + 8 > endOffset) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const byteOrder = view.getUint16(tiffOffset, false);
|
|
84
|
+
const littleEndian = byteOrder === 0x4949 ? true : byteOrder === 0x4d4d ? false : undefined;
|
|
85
|
+
if (littleEndian === undefined) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
if (readUint16(view, tiffOffset + 2, littleEndian) !== 42) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const ifdRelative = readUint32(view, tiffOffset + 4, littleEndian);
|
|
92
|
+
if (ifdRelative === undefined) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const ifdOffset = tiffOffset + ifdRelative;
|
|
96
|
+
const entryCount = readUint16(view, ifdOffset, littleEndian);
|
|
97
|
+
if (entryCount === undefined) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
for (let index = 0; index < entryCount; index += 1) {
|
|
101
|
+
const entryOffset = ifdOffset + 2 + index * 12;
|
|
102
|
+
if (entryOffset + 12 > endOffset) {
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
if (readUint16(view, entryOffset, littleEndian) !== 0x0112) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const value = readUint16(view, entryOffset + 8, littleEndian);
|
|
109
|
+
return isOrientation(value) ? value : undefined;
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
function parseJpeg(bytes, view) {
|
|
114
|
+
if (bytes[0] !== 0xff || bytes[1] !== 0xd8) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
let offset = 2;
|
|
118
|
+
let orientation;
|
|
119
|
+
while (offset + 4 <= bytes.length) {
|
|
120
|
+
if (bytes[offset] !== 0xff) {
|
|
121
|
+
offset += 1;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
let markerOffset = offset + 1;
|
|
125
|
+
while (bytes[markerOffset] === 0xff) {
|
|
126
|
+
markerOffset += 1;
|
|
127
|
+
}
|
|
128
|
+
const marker = bytes[markerOffset];
|
|
129
|
+
offset = markerOffset + 1;
|
|
130
|
+
if (marker === undefined || marker === 0xd9 || marker === 0xda) {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const segmentLength = readUint16(view, offset, false);
|
|
137
|
+
if (!segmentLength || segmentLength < 2) {
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
const dataOffset = offset + 2;
|
|
141
|
+
const segmentEnd = offset + segmentLength;
|
|
142
|
+
if (segmentEnd > bytes.length) {
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
if (marker === 0xe1 && ascii(bytes, dataOffset, 6) === 'Exif\u0000\u0000') {
|
|
146
|
+
orientation =
|
|
147
|
+
parseExifOrientation(view, dataOffset + 6, segmentEnd) ?? orientation;
|
|
148
|
+
}
|
|
149
|
+
const isStartOfFrame = marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker);
|
|
150
|
+
if (isStartOfFrame && dataOffset + 5 <= segmentEnd) {
|
|
151
|
+
const height = readUint16(view, dataOffset + 1, false);
|
|
152
|
+
const width = readUint16(view, dataOffset + 3, false);
|
|
153
|
+
if (width && height) {
|
|
154
|
+
return {
|
|
155
|
+
width,
|
|
156
|
+
height,
|
|
157
|
+
format: 'jpeg',
|
|
158
|
+
mimeType: 'image/jpeg',
|
|
159
|
+
orientation,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
offset = segmentEnd;
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
function parsePng(bytes, view) {
|
|
168
|
+
if (bytes.length >= 24 &&
|
|
169
|
+
bytes[0] === 0x89 &&
|
|
170
|
+
ascii(bytes, 1, 3) === 'PNG' &&
|
|
171
|
+
bytes[4] === 0x0d &&
|
|
172
|
+
bytes[5] === 0x0a &&
|
|
173
|
+
bytes[6] === 0x1a &&
|
|
174
|
+
bytes[7] === 0x0a) {
|
|
175
|
+
const width = readUint32(view, 16, false);
|
|
176
|
+
const height = readUint32(view, 20, false);
|
|
177
|
+
if (width && height) {
|
|
178
|
+
return { width, height, format: 'png', mimeType: 'image/png' };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
function parseGif(bytes, view) {
|
|
184
|
+
const signature = ascii(bytes, 0, 6);
|
|
185
|
+
if (signature !== 'GIF87a' && signature !== 'GIF89a') {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
const width = readUint16(view, 6, true);
|
|
189
|
+
const height = readUint16(view, 8, true);
|
|
190
|
+
return width && height
|
|
191
|
+
? { width, height, format: 'gif', mimeType: 'image/gif' }
|
|
192
|
+
: undefined;
|
|
193
|
+
}
|
|
194
|
+
function parseWebp(bytes, view) {
|
|
195
|
+
if (ascii(bytes, 0, 4) !== 'RIFF' || ascii(bytes, 8, 4) !== 'WEBP') {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
const chunk = ascii(bytes, 12, 4);
|
|
199
|
+
if (chunk === 'VP8X' && bytes.length >= 30) {
|
|
200
|
+
const width = 1 + (bytes[24] ?? 0) + ((bytes[25] ?? 0) << 8) + ((bytes[26] ?? 0) << 16);
|
|
201
|
+
const height = 1 + (bytes[27] ?? 0) + ((bytes[28] ?? 0) << 8) + ((bytes[29] ?? 0) << 16);
|
|
202
|
+
return { width, height, format: 'webp', mimeType: 'image/webp' };
|
|
203
|
+
}
|
|
204
|
+
if (chunk === 'VP8 ' && bytes.length >= 30) {
|
|
205
|
+
const width = (readUint16(view, 26, true) ?? 0) & 0x3fff;
|
|
206
|
+
const height = (readUint16(view, 28, true) ?? 0) & 0x3fff;
|
|
207
|
+
return width && height
|
|
208
|
+
? { width, height, format: 'webp', mimeType: 'image/webp' }
|
|
209
|
+
: undefined;
|
|
210
|
+
}
|
|
211
|
+
if (chunk === 'VP8L' && bytes.length >= 25 && bytes[20] === 0x2f) {
|
|
212
|
+
const bits = readUint32(view, 21, true) ?? 0;
|
|
213
|
+
const width = (bits & 0x3fff) + 1;
|
|
214
|
+
const height = ((bits >> 14) & 0x3fff) + 1;
|
|
215
|
+
return { width, height, format: 'webp', mimeType: 'image/webp' };
|
|
216
|
+
}
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
function parseBmp(bytes, view) {
|
|
220
|
+
if (ascii(bytes, 0, 2) !== 'BM' || bytes.length < 26) {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
const width = view.getInt32(18, true);
|
|
224
|
+
const height = Math.abs(view.getInt32(22, true));
|
|
225
|
+
return width > 0 && height > 0
|
|
226
|
+
? { width, height, format: 'bmp', mimeType: 'image/bmp' }
|
|
227
|
+
: undefined;
|
|
228
|
+
}
|
|
229
|
+
const HEIF_BRANDS = new Set([
|
|
230
|
+
'avif',
|
|
231
|
+
'avis',
|
|
232
|
+
'heic',
|
|
233
|
+
'heix',
|
|
234
|
+
'hevc',
|
|
235
|
+
'hevx',
|
|
236
|
+
'heim',
|
|
237
|
+
'heis',
|
|
238
|
+
'mif1',
|
|
239
|
+
'msf1',
|
|
240
|
+
]);
|
|
241
|
+
function parseHeif(bytes, view) {
|
|
242
|
+
if (ascii(bytes, 4, 4) !== 'ftyp' || !HEIF_BRANDS.has(ascii(bytes, 8, 4))) {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
let offset = 0;
|
|
246
|
+
while (offset + 16 <= bytes.length) {
|
|
247
|
+
let size = readUint32(view, offset, false) ?? 0;
|
|
248
|
+
const type = ascii(bytes, offset + 4, 4);
|
|
249
|
+
let headerSize = 8;
|
|
250
|
+
if (size === 1 && offset + 16 <= bytes.length) {
|
|
251
|
+
const high = readUint32(view, offset + 8, false) ?? 0;
|
|
252
|
+
const low = readUint32(view, offset + 12, false) ?? 0;
|
|
253
|
+
if (high !== 0) {
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
size = low;
|
|
257
|
+
headerSize = 16;
|
|
258
|
+
}
|
|
259
|
+
if (size < headerSize || offset + size > bytes.length) {
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
if (type === 'ispe' && size >= headerSize + 12) {
|
|
263
|
+
const width = readUint32(view, offset + headerSize + 4, false);
|
|
264
|
+
const height = readUint32(view, offset + headerSize + 8, false);
|
|
265
|
+
if (width && height) {
|
|
266
|
+
return { width, height, format: 'heif', mimeType: 'image/heif' };
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// `ispe` is nested, so inspect child bytes instead of requiring a full ISO
|
|
270
|
+
// BMFF parser. This is safe because the dimensions are validated below.
|
|
271
|
+
const nestedIndex = bytes.subarray(offset + headerSize, offset + size);
|
|
272
|
+
for (let index = 0; index + 20 <= nestedIndex.length; index += 1) {
|
|
273
|
+
if (ascii(nestedIndex, index + 4, 4) === 'ispe') {
|
|
274
|
+
const width = readUint32(new DataView(nestedIndex.buffer, nestedIndex.byteOffset, nestedIndex.byteLength), index + 12, false);
|
|
275
|
+
const height = readUint32(new DataView(nestedIndex.buffer, nestedIndex.byteOffset, nestedIndex.byteLength), index + 16, false);
|
|
276
|
+
if (width && height) {
|
|
277
|
+
return { width, height, format: 'heif', mimeType: 'image/heif' };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
offset += size;
|
|
282
|
+
}
|
|
283
|
+
return undefined;
|
|
284
|
+
}
|
|
285
|
+
/** Parse encoded metadata without decoding the image pixels. */
|
|
286
|
+
export function parseEncodedImageInfo(input) {
|
|
287
|
+
const bytes = input instanceof ArrayBuffer
|
|
288
|
+
? new Uint8Array(input)
|
|
289
|
+
: new Uint8Array(input.buffer, input.byteOffset, input.byteLength);
|
|
290
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
291
|
+
const metadata = parseJpeg(bytes, view) ??
|
|
292
|
+
parsePng(bytes, view) ??
|
|
293
|
+
parseGif(bytes, view) ??
|
|
294
|
+
parseWebp(bytes, view) ??
|
|
295
|
+
parseBmp(bytes, view) ??
|
|
296
|
+
parseHeif(bytes, view);
|
|
297
|
+
if (!metadata) {
|
|
298
|
+
throw new Error('Unsupported or invalid encoded image.');
|
|
299
|
+
}
|
|
300
|
+
return createMarkerImageInfo(metadata);
|
|
301
|
+
}
|
|
302
|
+
export function parseNativeImageInfo(serialized) {
|
|
303
|
+
let value;
|
|
304
|
+
try {
|
|
305
|
+
value = JSON.parse(serialized);
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
throw new Error('Native image metadata reader returned invalid JSON.');
|
|
309
|
+
}
|
|
310
|
+
if (!value || typeof value !== 'object') {
|
|
311
|
+
throw new Error('Native image metadata reader returned invalid data.');
|
|
312
|
+
}
|
|
313
|
+
const candidate = value;
|
|
314
|
+
const allowedFormats = [
|
|
315
|
+
'jpeg',
|
|
316
|
+
'png',
|
|
317
|
+
'webp',
|
|
318
|
+
'gif',
|
|
319
|
+
'heif',
|
|
320
|
+
'bmp',
|
|
321
|
+
'unknown',
|
|
322
|
+
];
|
|
323
|
+
if (!allowedFormats.includes(candidate.format) ||
|
|
324
|
+
!isOrientation(candidate.orientation) ||
|
|
325
|
+
(candidate.mimeType !== undefined && typeof candidate.mimeType !== 'string')) {
|
|
326
|
+
throw new Error('Native image metadata reader returned invalid data.');
|
|
327
|
+
}
|
|
328
|
+
const info = createMarkerImageInfo({
|
|
329
|
+
width: assertPositiveDimension(candidate.encodedWidth, 'encodedWidth'),
|
|
330
|
+
height: assertPositiveDimension(candidate.encodedHeight, 'encodedHeight'),
|
|
331
|
+
format: candidate.format,
|
|
332
|
+
mimeType: candidate.mimeType,
|
|
333
|
+
orientation: candidate.orientation,
|
|
334
|
+
});
|
|
335
|
+
if (candidate.width !== info.width ||
|
|
336
|
+
candidate.height !== info.height ||
|
|
337
|
+
candidate.rotationDegrees !== info.rotationDegrees ||
|
|
338
|
+
candidate.mirrored !== info.mirrored ||
|
|
339
|
+
candidate.requiresNormalization !== info.requiresNormalization) {
|
|
340
|
+
throw new Error('Native image metadata reader returned inconsistent data.');
|
|
341
|
+
}
|
|
342
|
+
return info;
|
|
343
|
+
}
|