@mapcatch/util 2.0.6 → 2.0.7
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/dist/catchUtil.min.cjs.js +2928 -0
- package/dist/catchUtil.min.esm.js +44499 -42811
- package/dist/catchUtil.min.js +248 -248
- package/package.json +11 -2
- package/src/constants/annotation_color.js +0 -7
- package/src/constants/annotation_draw_style.js +0 -228
- package/src/constants/annotation_label_style.js +0 -76
- package/src/constants/annotation_style.js +0 -118
- package/src/constants/bmap_types.js +0 -44
- package/src/constants/cameras.js +0 -5
- package/src/constants/crs.js +0 -42099
- package/src/constants/crs_types.js +0 -22
- package/src/constants/default_layers.js +0 -149
- package/src/constants/dsm_colors.js +0 -10
- package/src/constants/error_codes.js +0 -44
- package/src/constants/height_colors.js +0 -1
- package/src/constants/index.js +0 -20
- package/src/constants/layer_folders.js +0 -6
- package/src/constants/layer_groups.js +0 -34
- package/src/constants/layer_groups_multispectral.js +0 -34
- package/src/constants/layer_icons.js +0 -19
- package/src/constants/map_style.js +0 -11
- package/src/constants/measurement_fields.js +0 -208
- package/src/constants/task_params.js +0 -33
- package/src/constants/tools.js +0 -20
- package/src/event/event.js +0 -191
- package/src/event/event_bus.js +0 -5
- package/src/event/index.js +0 -2
- package/src/gl-operations/constants.js +0 -9
- package/src/gl-operations/default_options.js +0 -98
- package/src/gl-operations/index.js +0 -533
- package/src/gl-operations/reglCommands/contours.js +0 -27
- package/src/gl-operations/reglCommands/default.js +0 -46
- package/src/gl-operations/reglCommands/hillshading.js +0 -340
- package/src/gl-operations/reglCommands/index.js +0 -6
- package/src/gl-operations/reglCommands/multiLayers.js +0 -303
- package/src/gl-operations/reglCommands/transitions.js +0 -111
- package/src/gl-operations/reglCommands/util.js +0 -71
- package/src/gl-operations/renderer.js +0 -210
- package/src/gl-operations/shaders/fragment/convertDem.js +0 -26
- package/src/gl-operations/shaders/fragment/convolutionSmooth.js +0 -55
- package/src/gl-operations/shaders/fragment/diffCalc.js +0 -34
- package/src/gl-operations/shaders/fragment/drawResult.js +0 -47
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvAmbientShadows.js +0 -79
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvDirect.js +0 -60
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvFinalBaselayer.js +0 -31
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvFinalColorscale.js +0 -61
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvMergeAndScaleTiles.js +0 -27
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvNormals.js +0 -26
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvSmooth.js +0 -54
- package/src/gl-operations/shaders/fragment/hillshading/hsAdvSoftShadows.js +0 -81
- package/src/gl-operations/shaders/fragment/hillshading/hsPregen.js +0 -55
- package/src/gl-operations/shaders/fragment/interpolateColor.js +0 -66
- package/src/gl-operations/shaders/fragment/interpolateColorOnly.js +0 -50
- package/src/gl-operations/shaders/fragment/interpolateValue.js +0 -137
- package/src/gl-operations/shaders/fragment/multiAnalyze1Calc.js +0 -36
- package/src/gl-operations/shaders/fragment/multiAnalyze2Calc.js +0 -46
- package/src/gl-operations/shaders/fragment/multiAnalyze3Calc.js +0 -54
- package/src/gl-operations/shaders/fragment/multiAnalyze4Calc.js +0 -62
- package/src/gl-operations/shaders/fragment/multiAnalyze5Calc.js +0 -70
- package/src/gl-operations/shaders/fragment/multiAnalyze6Calc.js +0 -78
- package/src/gl-operations/shaders/fragment/single.js +0 -93
- package/src/gl-operations/shaders/transform.js +0 -22
- package/src/gl-operations/shaders/util/computeColor.glsl +0 -85
- package/src/gl-operations/shaders/util/getTexelValue.glsl +0 -10
- package/src/gl-operations/shaders/util/isCloseEnough.glsl +0 -9
- package/src/gl-operations/shaders/util/rgbaToFloat.glsl +0 -18
- package/src/gl-operations/shaders/vertex/double.js +0 -17
- package/src/gl-operations/shaders/vertex/multi3.js +0 -20
- package/src/gl-operations/shaders/vertex/multi4.js +0 -23
- package/src/gl-operations/shaders/vertex/multi5.js +0 -26
- package/src/gl-operations/shaders/vertex/multi6.js +0 -29
- package/src/gl-operations/shaders/vertex/single.js +0 -13
- package/src/gl-operations/shaders/vertex/singleNotTransformed.js +0 -12
- package/src/gl-operations/texture_manager.js +0 -141
- package/src/gl-operations/util.js +0 -336
- package/src/index.js +0 -20
- package/src/measure/index.js +0 -209
- package/src/measure/tile_cache.js +0 -88
- package/src/mvs/index.js +0 -26
- package/src/mvs/protos/index.js +0 -12
- package/src/mvs/protos/proto_10.js +0 -155
- package/src/observation_pretict.js +0 -168
- package/src/photo-parser/exif/gps_tags.js +0 -33
- package/src/photo-parser/exif/ifd1_tags.js +0 -22
- package/src/photo-parser/exif/index.js +0 -143
- package/src/photo-parser/exif/parse_image.js +0 -290
- package/src/photo-parser/exif/string_values.js +0 -137
- package/src/photo-parser/exif/tags.js +0 -75
- package/src/photo-parser/exif/tiff_tags.js +0 -35
- package/src/photo-parser/exif/util.js +0 -103
- package/src/photo-parser/image-size/detector.js +0 -24
- package/src/photo-parser/image-size/fromFile.js +0 -55
- package/src/photo-parser/image-size/index.js +0 -2
- package/src/photo-parser/image-size/lookup.js +0 -37
- package/src/photo-parser/image-size/types/bmp.js +0 -10
- package/src/photo-parser/image-size/types/cur.js +0 -16
- package/src/photo-parser/image-size/types/dds.js +0 -10
- package/src/photo-parser/image-size/types/gif.js +0 -11
- package/src/photo-parser/image-size/types/heif.js +0 -35
- package/src/photo-parser/image-size/types/icns.js +0 -112
- package/src/photo-parser/image-size/types/ico.js +0 -74
- package/src/photo-parser/image-size/types/index.js +0 -43
- package/src/photo-parser/image-size/types/j2c.js +0 -11
- package/src/photo-parser/image-size/types/jp2.js +0 -22
- package/src/photo-parser/image-size/types/jpg.js +0 -157
- package/src/photo-parser/image-size/types/ktx.js +0 -18
- package/src/photo-parser/image-size/types/png.js +0 -36
- package/src/photo-parser/image-size/types/pnm.js +0 -74
- package/src/photo-parser/image-size/types/psd.js +0 -10
- package/src/photo-parser/image-size/types/svg.js +0 -100
- package/src/photo-parser/image-size/types/tga.js +0 -14
- package/src/photo-parser/image-size/types/tiff.js +0 -92
- package/src/photo-parser/image-size/types/utils.js +0 -83
- package/src/photo-parser/image-size/types/webp.js +0 -67
- package/src/photo-parser/index.js +0 -185
- package/src/report/annotations_report.js +0 -446
- package/src/report/index.js +0 -2
- package/src/report/map_util.js +0 -81
- package/src/report/pdf_creator.js +0 -247
- package/src/report/report.js +0 -581
- package/src/transform.js +0 -207
- package/src/util.js +0 -671
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { toUTF8String } from './utils'
|
|
2
|
-
|
|
3
|
-
const PNMTypes = {
|
|
4
|
-
P1: 'pbm/ascii',
|
|
5
|
-
P2: 'pgm/ascii',
|
|
6
|
-
P3: 'ppm/ascii',
|
|
7
|
-
P4: 'pbm',
|
|
8
|
-
P5: 'pgm',
|
|
9
|
-
P6: 'ppm',
|
|
10
|
-
P7: 'pam',
|
|
11
|
-
PF: 'pfm'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const handlers = {
|
|
15
|
-
default: (lines) => {
|
|
16
|
-
let dimensions = []
|
|
17
|
-
|
|
18
|
-
while (lines.length > 0) {
|
|
19
|
-
const line = lines.shift()
|
|
20
|
-
if (line[0] === '#') {
|
|
21
|
-
continue
|
|
22
|
-
}
|
|
23
|
-
dimensions = line.split(' ')
|
|
24
|
-
break
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (dimensions.length === 2) {
|
|
28
|
-
return {
|
|
29
|
-
height: parseInt(dimensions[1], 10),
|
|
30
|
-
width: parseInt(dimensions[0], 10)
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
throw new TypeError('Invalid PNM')
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
pam: (lines) => {
|
|
37
|
-
const size = {}
|
|
38
|
-
while (lines.length > 0) {
|
|
39
|
-
const line = lines.shift()
|
|
40
|
-
if (line.length > 16 || line.charCodeAt(0) > 128) {
|
|
41
|
-
continue
|
|
42
|
-
}
|
|
43
|
-
const [key, value] = line.split(' ')
|
|
44
|
-
if (key && value) {
|
|
45
|
-
size[key.toLowerCase()] = parseInt(value, 10)
|
|
46
|
-
}
|
|
47
|
-
if (size.height && size.width) {
|
|
48
|
-
break
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (size.height && size.width) {
|
|
53
|
-
return {
|
|
54
|
-
height: size.height,
|
|
55
|
-
width: size.width
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
throw new TypeError('Invalid PAM')
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export const PNM = {
|
|
64
|
-
validate: (input) => toUTF8String(input, 0, 2) in PNMTypes,
|
|
65
|
-
|
|
66
|
-
calculate (input) {
|
|
67
|
-
const signature = toUTF8String(input, 0, 2)
|
|
68
|
-
const type = PNMTypes[signature]
|
|
69
|
-
// TODO: this probably generates garbage. move to a stream based parser
|
|
70
|
-
const lines = toUTF8String(input, 3).split(/[\r\n]+/)
|
|
71
|
-
const handler = handlers[type] || handlers.default
|
|
72
|
-
return handler(lines)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { toUTF8String } from './utils'
|
|
2
|
-
|
|
3
|
-
const svgReg = /<svg\s([^>"']|"[^"]*"|'[^']*')*>/
|
|
4
|
-
|
|
5
|
-
const extractorRegExps = {
|
|
6
|
-
height: /\sheight=(['"])([^%]+?)\1/,
|
|
7
|
-
root: svgReg,
|
|
8
|
-
viewbox: /\sviewBox=(['"])(.+?)\1/i,
|
|
9
|
-
width: /\swidth=(['"])([^%]+?)\1/
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const INCH_CM = 2.54
|
|
13
|
-
const units = {
|
|
14
|
-
in: 96,
|
|
15
|
-
cm: 96 / INCH_CM,
|
|
16
|
-
em: 16,
|
|
17
|
-
ex: 8,
|
|
18
|
-
m: (96 / INCH_CM) * 100,
|
|
19
|
-
mm: 96 / INCH_CM / 10,
|
|
20
|
-
pc: 96 / 72 / 12,
|
|
21
|
-
pt: 96 / 72,
|
|
22
|
-
px: 1
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const unitsReg = new RegExp(
|
|
26
|
-
`^([0-9.]+(?:e\\d+)?)(${Object.keys(units).join('|')})?$`
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
function parseLength (len) {
|
|
30
|
-
const m = unitsReg.exec(len)
|
|
31
|
-
if (!m) {
|
|
32
|
-
return undefined
|
|
33
|
-
}
|
|
34
|
-
return Math.round(Number(m[1]) * (units[m[2]] || 1))
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function parseViewbox (viewbox) {
|
|
38
|
-
const bounds = viewbox.split(' ')
|
|
39
|
-
return {
|
|
40
|
-
height: parseLength(bounds[3]),
|
|
41
|
-
width: parseLength(bounds[2])
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function parseAttributes (root) {
|
|
46
|
-
const width = root.match(extractorRegExps.width)
|
|
47
|
-
const height = root.match(extractorRegExps.height)
|
|
48
|
-
const viewbox = root.match(extractorRegExps.viewbox)
|
|
49
|
-
return {
|
|
50
|
-
height: height && (parseLength(height[2])),
|
|
51
|
-
viewbox: viewbox && (parseViewbox(viewbox[2])),
|
|
52
|
-
width: width && (parseLength(width[2]))
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function calculateByDimensions (attrs) {
|
|
57
|
-
return {
|
|
58
|
-
height: attrs.height,
|
|
59
|
-
width: attrs.width
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function calculateByViewbox (attrs, viewbox) {
|
|
64
|
-
const ratio = (viewbox.width) / (viewbox.height)
|
|
65
|
-
if (attrs.width) {
|
|
66
|
-
return {
|
|
67
|
-
height: Math.floor(attrs.width / ratio),
|
|
68
|
-
width: attrs.width
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (attrs.height) {
|
|
72
|
-
return {
|
|
73
|
-
height: attrs.height,
|
|
74
|
-
width: Math.floor(attrs.height * ratio)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
height: viewbox.height,
|
|
79
|
-
width: viewbox.width
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const SVG = {
|
|
84
|
-
// Scan only the first kilo-byte to speed up the check on larger files
|
|
85
|
-
validate: (input) => svgReg.test(toUTF8String(input, 0, 1000)),
|
|
86
|
-
|
|
87
|
-
calculate (input) {
|
|
88
|
-
const root = toUTF8String(input).match(extractorRegExps.root)
|
|
89
|
-
if (root) {
|
|
90
|
-
const attrs = parseAttributes(root[0])
|
|
91
|
-
if (attrs.width && attrs.height) {
|
|
92
|
-
return calculateByDimensions(attrs)
|
|
93
|
-
}
|
|
94
|
-
if (attrs.viewbox) {
|
|
95
|
-
return calculateByViewbox(attrs, attrs.viewbox)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
throw new TypeError('Invalid SVG')
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { readUInt16LE } from './utils'
|
|
2
|
-
|
|
3
|
-
export const TGA = {
|
|
4
|
-
validate (input) {
|
|
5
|
-
return readUInt16LE(input, 0) === 0 && readUInt16LE(input, 4) === 0
|
|
6
|
-
},
|
|
7
|
-
|
|
8
|
-
calculate (input) {
|
|
9
|
-
return {
|
|
10
|
-
height: readUInt16LE(input, 14),
|
|
11
|
-
width: readUInt16LE(input, 12)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
// based on http://www.compix.com/fileformattif.htm
|
|
2
|
-
// TO-DO: support big-endian as well
|
|
3
|
-
import { readUInt, toHexString, toUTF8String } from './utils'
|
|
4
|
-
|
|
5
|
-
// Read IFD (image-file-directory) into a buffer
|
|
6
|
-
function readIFD (input, isBigEndian) {
|
|
7
|
-
const ifdOffset = readUInt(input, 32, 4, isBigEndian)
|
|
8
|
-
return input.slice(ifdOffset + 2)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// TIFF values seem to be messed up on Big-Endian, this helps
|
|
12
|
-
function readValue (input, isBigEndian) {
|
|
13
|
-
const low = readUInt(input, 16, 8, isBigEndian)
|
|
14
|
-
const high = readUInt(input, 16, 10, isBigEndian)
|
|
15
|
-
return (high << 16) + low
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// move to the next tag
|
|
19
|
-
function nextTag (input) {
|
|
20
|
-
if (input.length > 24) {
|
|
21
|
-
return input.slice(12)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Extract IFD tags from TIFF metadata
|
|
26
|
-
function extractTags (input, isBigEndian) {
|
|
27
|
-
const tags = {}
|
|
28
|
-
|
|
29
|
-
let temp = input
|
|
30
|
-
while (temp && temp.length) {
|
|
31
|
-
const code = readUInt(temp, 16, 0, isBigEndian)
|
|
32
|
-
const type = readUInt(temp, 16, 2, isBigEndian)
|
|
33
|
-
const length = readUInt(temp, 32, 4, isBigEndian)
|
|
34
|
-
|
|
35
|
-
// 0 means end of IFD
|
|
36
|
-
if (code === 0) {
|
|
37
|
-
break
|
|
38
|
-
} else {
|
|
39
|
-
// 256 is width, 257 is height
|
|
40
|
-
// if (code === 256 || code === 257) {
|
|
41
|
-
if (length === 1 && (type === 3 || type === 4)) {
|
|
42
|
-
tags[code] = readValue(temp, isBigEndian)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// move to the next tag
|
|
46
|
-
temp = nextTag(temp)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return tags
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Test if the TIFF is Big Endian or Little Endian
|
|
54
|
-
function determineEndianness (input) {
|
|
55
|
-
const signature = toUTF8String(input, 0, 2)
|
|
56
|
-
if ('II' === signature) {
|
|
57
|
-
return 'LE'
|
|
58
|
-
} else if ('MM' === signature) {
|
|
59
|
-
return 'BE'
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const signatures = [
|
|
64
|
-
// '492049', // currently not supported
|
|
65
|
-
'49492a00', // Little endian
|
|
66
|
-
'4d4d002a' // Big Endian
|
|
67
|
-
// '4d4d002a', // BigTIFF > 4GB. currently not supported
|
|
68
|
-
]
|
|
69
|
-
|
|
70
|
-
export const TIFF = {
|
|
71
|
-
validate: (input) => signatures.includes(toHexString(input, 0, 4)),
|
|
72
|
-
|
|
73
|
-
calculate (input) {
|
|
74
|
-
// Determine BE/LE
|
|
75
|
-
const isBigEndian = determineEndianness(input) === 'BE'
|
|
76
|
-
|
|
77
|
-
// read the IFD
|
|
78
|
-
const ifdBuffer = readIFD(input, isBigEndian)
|
|
79
|
-
|
|
80
|
-
// extract the tags from the IFD
|
|
81
|
-
const tags = extractTags(ifdBuffer, isBigEndian)
|
|
82
|
-
|
|
83
|
-
const width = tags[256]
|
|
84
|
-
const height = tags[257]
|
|
85
|
-
|
|
86
|
-
if (!width || !height) {
|
|
87
|
-
throw new TypeError('Invalid Tiff. Missing tags')
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return { height, width }
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
const decoder = new TextDecoder()
|
|
2
|
-
export const toUTF8String = (
|
|
3
|
-
input,
|
|
4
|
-
start = 0,
|
|
5
|
-
end = input.length
|
|
6
|
-
) => decoder.decode(input.slice(start, end))
|
|
7
|
-
|
|
8
|
-
export const toHexString = (input, start = 0, end = input.length) =>
|
|
9
|
-
input
|
|
10
|
-
.slice(start, end)
|
|
11
|
-
.reduce((memo, i) => memo + ('0' + i.toString(16)).slice(-2), '')
|
|
12
|
-
|
|
13
|
-
export const readInt16LE = (input, offset = 0) => {
|
|
14
|
-
const val = input[offset] + input[offset + 1] * 2 ** 8
|
|
15
|
-
return val | ((val & (2 ** 15)) * 0x1fffe)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const readUInt16BE = (input, offset = 0) =>
|
|
19
|
-
input[offset] * 2 ** 8 + input[offset + 1]
|
|
20
|
-
|
|
21
|
-
export const readUInt16LE = (input, offset = 0) =>
|
|
22
|
-
input[offset] + input[offset + 1] * 2 ** 8
|
|
23
|
-
|
|
24
|
-
export const readUInt24LE = (input, offset = 0) =>
|
|
25
|
-
input[offset] + input[offset + 1] * 2 ** 8 + input[offset + 2] * 2 ** 16
|
|
26
|
-
|
|
27
|
-
export const readInt32LE = (input, offset = 0) =>
|
|
28
|
-
input[offset] +
|
|
29
|
-
input[offset + 1] * 2 ** 8 +
|
|
30
|
-
input[offset + 2] * 2 ** 16 +
|
|
31
|
-
(input[offset + 3] << 24)
|
|
32
|
-
|
|
33
|
-
export const readUInt32BE = (input, offset = 0) =>
|
|
34
|
-
input[offset] * 2 ** 24 +
|
|
35
|
-
input[offset + 1] * 2 ** 16 +
|
|
36
|
-
input[offset + 2] * 2 ** 8 +
|
|
37
|
-
input[offset + 3]
|
|
38
|
-
|
|
39
|
-
export const readUInt32LE = (input, offset = 0) =>
|
|
40
|
-
input[offset] +
|
|
41
|
-
input[offset + 1] * 2 ** 8 +
|
|
42
|
-
input[offset + 2] * 2 ** 16 +
|
|
43
|
-
input[offset + 3] * 2 ** 24
|
|
44
|
-
|
|
45
|
-
// Abstract reading multi-byte unsigned integers
|
|
46
|
-
const methods = {
|
|
47
|
-
readUInt16BE,
|
|
48
|
-
readUInt16LE,
|
|
49
|
-
readUInt32BE,
|
|
50
|
-
readUInt32LE
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function readUInt (
|
|
54
|
-
input,
|
|
55
|
-
bits,
|
|
56
|
-
offset,
|
|
57
|
-
isBigEndian
|
|
58
|
-
) {
|
|
59
|
-
offset = offset || 0
|
|
60
|
-
const endian = isBigEndian ? 'BE' : 'LE'
|
|
61
|
-
const methodName = 'readUInt' + bits + endian
|
|
62
|
-
return methods[methodName](input, offset)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function readBox (buffer, offset) {
|
|
66
|
-
if (buffer.length - offset < 4) return
|
|
67
|
-
const boxSize = readUInt32BE(buffer, offset)
|
|
68
|
-
if (buffer.length - offset < boxSize) return
|
|
69
|
-
return {
|
|
70
|
-
name: toUTF8String(buffer, 4 + offset, 8 + offset),
|
|
71
|
-
offset,
|
|
72
|
-
size: boxSize
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function findBox (buffer, boxName, offset) {
|
|
77
|
-
while (offset < buffer.length) {
|
|
78
|
-
const box = readBox(buffer, offset)
|
|
79
|
-
if (!box) break
|
|
80
|
-
if (box.name === boxName) return box
|
|
81
|
-
offset += box.size
|
|
82
|
-
}
|
|
83
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
// based on https://developers.google.com/speed/webp/docs/riff_container
|
|
2
|
-
import { toHexString, toUTF8String, readInt16LE, readUInt24LE } from './utils'
|
|
3
|
-
|
|
4
|
-
function calculateExtended (input) {
|
|
5
|
-
return {
|
|
6
|
-
height: 1 + readUInt24LE(input, 7),
|
|
7
|
-
width: 1 + readUInt24LE(input, 4)
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function calculateLossless (input) {
|
|
12
|
-
return {
|
|
13
|
-
height:
|
|
14
|
-
1 +
|
|
15
|
-
(((input[4] & 0xf) << 10) | (input[3] << 2) | ((input[2] & 0xc0) >> 6)),
|
|
16
|
-
width: 1 + (((input[2] & 0x3f) << 8) | input[1])
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function calculateLossy (input) {
|
|
21
|
-
// `& 0x3fff` returns the last 14 bits
|
|
22
|
-
// TO-DO: include webp scaling in the calculations
|
|
23
|
-
return {
|
|
24
|
-
height: readInt16LE(input, 8) & 0x3fff,
|
|
25
|
-
width: readInt16LE(input, 6) & 0x3fff
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const WEBP = {
|
|
30
|
-
validate (input) {
|
|
31
|
-
const riffHeader = 'RIFF' === toUTF8String(input, 0, 4)
|
|
32
|
-
const webpHeader = 'WEBP' === toUTF8String(input, 8, 12)
|
|
33
|
-
const vp8Header = 'VP8' === toUTF8String(input, 12, 15)
|
|
34
|
-
return riffHeader && webpHeader && vp8Header
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
calculate (input) {
|
|
38
|
-
const chunkHeader = toUTF8String(input, 12, 16)
|
|
39
|
-
input = input.slice(20, 30)
|
|
40
|
-
|
|
41
|
-
// Extended webp stream signature
|
|
42
|
-
if (chunkHeader === 'VP8X') {
|
|
43
|
-
const extendedHeader = input[0]
|
|
44
|
-
const validStart = (extendedHeader & 0xc0) === 0
|
|
45
|
-
const validEnd = (extendedHeader & 0x01) === 0
|
|
46
|
-
if (validStart && validEnd) {
|
|
47
|
-
return calculateExtended(input)
|
|
48
|
-
} else {
|
|
49
|
-
// TODO: breaking change
|
|
50
|
-
throw new TypeError('Invalid WebP')
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Lossless webp stream signature
|
|
55
|
-
if (chunkHeader === 'VP8 ' && input[0] !== 0x2f) {
|
|
56
|
-
return calculateLossy(input)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Lossy webp stream signature
|
|
60
|
-
const signature = toHexString(input, 3, 6)
|
|
61
|
-
if (chunkHeader === 'VP8L' && signature !== '9d012a') {
|
|
62
|
-
return calculateLossless(input)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
throw new TypeError('Invalid WebP')
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import {getPhotoMetadata} from './exif'
|
|
2
|
-
import moment from 'moment'
|
|
3
|
-
import * as util from '../util'
|
|
4
|
-
import _ from 'lodash'
|
|
5
|
-
|
|
6
|
-
export async function parsePhoto (file) {
|
|
7
|
-
let tags = await getPhotoMetadata(file)
|
|
8
|
-
const {width, height, exif, xmp, filesize, md5} = tags
|
|
9
|
-
let imageMetaData = {width, height, filesize, md5}
|
|
10
|
-
let lng = NaN, lat = NaN, alt = NaN
|
|
11
|
-
let yaw = NaN, pitch = NaN, roll = NaN
|
|
12
|
-
let x_std = NaN, y_std = NaN, z_std = NaN
|
|
13
|
-
let pos = [lng, lat, alt]
|
|
14
|
-
let flatedXmp = util.flatObject(xmp)
|
|
15
|
-
let {GPSAltitude, GPSLatitude, GPSLatitudeRef, GPSLongitude, GPSLongitudeRef} = exif || {}
|
|
16
|
-
if (GPSLongitude && GPSLatitude) {
|
|
17
|
-
pos = [
|
|
18
|
-
util.getGeoCoordOperator(GPSLongitudeRef) * util.toRadian(GPSLongitude),
|
|
19
|
-
util.getGeoCoordOperator(GPSLatitudeRef) * util.toRadian(GPSLatitude),
|
|
20
|
-
+GPSAltitude
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
for(let key in flatedXmp) {
|
|
24
|
-
let value = flatedXmp[key]
|
|
25
|
-
if (key === 'drone-dji:GpsLongtitude' || key === 'drone-dji:GpsLongitude') {
|
|
26
|
-
lng = Number(value)
|
|
27
|
-
} else if (key === 'drone-dji:GpsLatitude') {
|
|
28
|
-
lat = Number(value)
|
|
29
|
-
} else if (key === 'drone-dji:AbsoluteAltitude') {
|
|
30
|
-
alt = Number(value)
|
|
31
|
-
} else if (key === 'drone-dji:GimbalYawDegree') {
|
|
32
|
-
yaw = Number(value)
|
|
33
|
-
} else if (key === 'drone-dji:GimbalPitchDegree') {
|
|
34
|
-
pitch = Number(value)
|
|
35
|
-
} else if (key === 'drone-dji:GimbalRollDegree') {
|
|
36
|
-
roll = Number(value)
|
|
37
|
-
} else if (key === 'drone-dji:RtkStdLon') {
|
|
38
|
-
x_std = Number(value)
|
|
39
|
-
} else if (key === 'drone-dji:RtkStdLat') {
|
|
40
|
-
y_std = Number(value)
|
|
41
|
-
} else if (key === 'drone-dji:RtkStdHgt') {
|
|
42
|
-
z_std = Number(value)
|
|
43
|
-
} else if (key === 'drone-dji:DewarpFlag') {
|
|
44
|
-
imageMetaData.dewarp_flag = Boolean(Number(value))
|
|
45
|
-
} else if (key === 'drone-dji:RtkFlag') {
|
|
46
|
-
imageMetaData.rtk_flag = Number(value)
|
|
47
|
-
} else if (key === 'drone-dji:RelativeAltitude') {
|
|
48
|
-
imageMetaData.relative_altitude = Number(value)
|
|
49
|
-
} else if (key === 'tiff:Model') {
|
|
50
|
-
imageMetaData.camera_model = value
|
|
51
|
-
} else if (key === 'drone-dji:DewarpData') {
|
|
52
|
-
let params = value.split(';')[1].split(',')
|
|
53
|
-
let pre_calib_param = params.map(d => Number(d))
|
|
54
|
-
pre_calib_param[2] = width / 2 + pre_calib_param[2]
|
|
55
|
-
pre_calib_param[3] = height / 2 + pre_calib_param[3]
|
|
56
|
-
imageMetaData.pre_calib_param = pre_calib_param
|
|
57
|
-
} else if (key === 'drone-dji:CaptureUUID') {
|
|
58
|
-
imageMetaData.capture_uuid = value
|
|
59
|
-
} else if (key === 'drone-dji:DroneID') {
|
|
60
|
-
imageMetaData.drone_id = value
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
for(let key in flatedXmp) {
|
|
64
|
-
let value = flatedXmp[key]
|
|
65
|
-
if (key === 'drone-dji:GpsStatus' && value === 'RTK' && Number.isNaN(x_std)) {
|
|
66
|
-
x_std = 0.02
|
|
67
|
-
y_std = 0.02
|
|
68
|
-
} else if (key === 'drone-dji:AltitudeType' && value === 'RtkAlt' && Number.isNaN(z_std)) {
|
|
69
|
-
z_std = 0.02
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (!Number.isNaN(x_std) && !Number.isNaN(y_std) && !Number.isNaN(z_std)) {
|
|
73
|
-
imageMetaData.pos_std = [x_std, y_std, z_std]
|
|
74
|
-
}
|
|
75
|
-
if (!Number.isNaN(yaw) && !Number.isNaN(pitch) && !Number.isNaN(roll)) {
|
|
76
|
-
imageMetaData.pitch_roll_yaw = [pitch, roll, yaw]
|
|
77
|
-
imageMetaData.orientation = util.getRotationMatrix(pitch, roll, yaw)
|
|
78
|
-
}
|
|
79
|
-
if (exif?.DateTime) {
|
|
80
|
-
imageMetaData.capture_time = moment(exif.DateTime, 'YYYY:MM:DD HH:mm:ss').valueOf()
|
|
81
|
-
} else if (exif?.DateTimeOriginal) {
|
|
82
|
-
imageMetaData.capture_time = moment(exif.DateTimeOriginal, 'YYYY:MM:DD HH:mm:ss').valueOf()
|
|
83
|
-
}
|
|
84
|
-
if (exif?.FocalLengthIn35mmFilm) {
|
|
85
|
-
imageMetaData.focal_length_in_35mm = exif.FocalLengthIn35mmFilm
|
|
86
|
-
}
|
|
87
|
-
if (util.hasNaN(pos)) {
|
|
88
|
-
pos = [lng, lat, alt]
|
|
89
|
-
}
|
|
90
|
-
if (!util.hasNaN(pos)) {
|
|
91
|
-
imageMetaData.pos = pos
|
|
92
|
-
imageMetaData.absolute_altitude = pos[2]
|
|
93
|
-
imageMetaData.coordinate_system = {
|
|
94
|
-
type: 2,
|
|
95
|
-
label: 'WGS 84',
|
|
96
|
-
type_name: 'Geographic',
|
|
97
|
-
epsg_code: 4326
|
|
98
|
-
}
|
|
99
|
-
if (!util.hasNaN([x_std, y_std, z_std])) { // 估算pos_sigma
|
|
100
|
-
let pos_sigma = []
|
|
101
|
-
let accuracy = Math.sqrt(Math.pow(x_std, 2) + Math.pow(y_std, 2))
|
|
102
|
-
if (accuracy < 0.03) {
|
|
103
|
-
pos_sigma[0] = pos_sigma[1] = 0.03
|
|
104
|
-
} else if (accuracy < 0.2) {
|
|
105
|
-
pos_sigma[0] = pos_sigma[1] = 0.2
|
|
106
|
-
} else {
|
|
107
|
-
pos_sigma[0] = pos_sigma[1] = 2.0
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (z_std < 0.03) {
|
|
111
|
-
pos_sigma[2] = 0.06
|
|
112
|
-
} else if (z_std < 0.2) {
|
|
113
|
-
pos_sigma[2] = 0.5
|
|
114
|
-
} else {
|
|
115
|
-
pos_sigma[2] = 5.0
|
|
116
|
-
}
|
|
117
|
-
imageMetaData.pos_sigma = pos_sigma
|
|
118
|
-
} else {
|
|
119
|
-
imageMetaData.pos_sigma = [2, 2, 5]
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return imageMetaData
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function parsePhotos (files, cb) {
|
|
126
|
-
let cameras = []
|
|
127
|
-
let processQueue = files
|
|
128
|
-
let total = files.length
|
|
129
|
-
let concurrence = 20 // 并发数
|
|
130
|
-
let request = 0 // 当前正在解析的照片数
|
|
131
|
-
|
|
132
|
-
return new Promise((resolve) => {
|
|
133
|
-
const run = () => {
|
|
134
|
-
for(let i = request;i < concurrence;i++) {
|
|
135
|
-
let file = processQueue.pop()
|
|
136
|
-
if (!file) {
|
|
137
|
-
break
|
|
138
|
-
}
|
|
139
|
-
request++
|
|
140
|
-
this.parsePhoto(file).then(meta_data => {
|
|
141
|
-
request--
|
|
142
|
-
let ext = file.split('.').pop()
|
|
143
|
-
let camera = {
|
|
144
|
-
width: meta_data.width,
|
|
145
|
-
height: meta_data.height,
|
|
146
|
-
ext,
|
|
147
|
-
parameters: meta_data.pre_calib_param || null
|
|
148
|
-
}
|
|
149
|
-
let item = cameras.find(d => {
|
|
150
|
-
return d.width === camera.width && d.height === camera.height && d.ext === camera.ext && _.isEqual(d.parameters, camera.parameters)
|
|
151
|
-
})
|
|
152
|
-
if (!item) {
|
|
153
|
-
item = camera
|
|
154
|
-
item.fileList = []
|
|
155
|
-
cameras.push(item)
|
|
156
|
-
}
|
|
157
|
-
item.fileList.push({
|
|
158
|
-
name: file.split('\\').pop(),
|
|
159
|
-
filesize: meta_data.filesize,
|
|
160
|
-
md5: meta_data.md5,
|
|
161
|
-
filePath: file,
|
|
162
|
-
meta_data
|
|
163
|
-
})
|
|
164
|
-
done()
|
|
165
|
-
}).catch(err => {
|
|
166
|
-
request--
|
|
167
|
-
done()
|
|
168
|
-
console.error(err)
|
|
169
|
-
})
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
const done = () => {
|
|
173
|
-
if (processQueue.length) {
|
|
174
|
-
run()
|
|
175
|
-
} else if (!request) {
|
|
176
|
-
resolve(cameras)
|
|
177
|
-
}
|
|
178
|
-
let parsed = total - processQueue.length - request
|
|
179
|
-
if (cb) {
|
|
180
|
-
cb(parsed, total)
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
run()
|
|
184
|
-
})
|
|
185
|
-
}
|