@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,55 +0,0 @@
|
|
|
1
|
-
import * as fs from 'node:fs'
|
|
2
|
-
import * as path from 'node:path'
|
|
3
|
-
|
|
4
|
-
import { lookup } from './lookup'
|
|
5
|
-
|
|
6
|
-
// Maximum input size, with a default of 512 kilobytes.
|
|
7
|
-
// TO-DO: make this adaptive based on the initial signature of the image
|
|
8
|
-
const MaxInputSize = 512 * 1024
|
|
9
|
-
|
|
10
|
-
// This queue is for async `fs` operations, to avoid reaching file-descriptor limits
|
|
11
|
-
const queue = []
|
|
12
|
-
|
|
13
|
-
let concurrency = 100
|
|
14
|
-
export const setConcurrency = (c) => {
|
|
15
|
-
concurrency = c
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const processQueue = async () => {
|
|
19
|
-
const jobs = queue.splice(0, concurrency)
|
|
20
|
-
const promises = jobs.map(async ({ filePath, resolve, reject }) => {
|
|
21
|
-
let handle
|
|
22
|
-
try {
|
|
23
|
-
handle = await fs.promises.open(path.resolve(filePath), 'r')
|
|
24
|
-
} catch (err) {
|
|
25
|
-
return reject(err)
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
const { size } = await handle.stat()
|
|
29
|
-
if (size <= 0) {
|
|
30
|
-
throw new Error('Empty file')
|
|
31
|
-
}
|
|
32
|
-
const inputSize = Math.min(size, MaxInputSize)
|
|
33
|
-
const input = new Uint8Array(inputSize)
|
|
34
|
-
await handle.read(input, 0, inputSize, 0)
|
|
35
|
-
resolve(lookup(input))
|
|
36
|
-
} catch (err) {
|
|
37
|
-
reject(err)
|
|
38
|
-
} finally {
|
|
39
|
-
await handle.close()
|
|
40
|
-
}
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
await Promise.allSettled(promises)
|
|
44
|
-
|
|
45
|
-
if (queue.length) setTimeout(processQueue, 100)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @param {string} filePath - relative/absolute path of the image file
|
|
50
|
-
*/
|
|
51
|
-
export const imageSize = async (filePath) =>
|
|
52
|
-
new Promise < ISizeCalculationResult > ((resolve, reject) => {
|
|
53
|
-
queue.push({ filePath, resolve, reject })
|
|
54
|
-
processQueue()
|
|
55
|
-
})
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { typeHandlers } from './types/index'
|
|
2
|
-
import { detector } from './detector'
|
|
3
|
-
|
|
4
|
-
const globalOptions = {
|
|
5
|
-
disabledTypes: []
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Return size information based on an Uint8Array
|
|
10
|
-
*
|
|
11
|
-
* @param {Uint8Array} input
|
|
12
|
-
* @returns {ISizeCalculationResult}
|
|
13
|
-
*/
|
|
14
|
-
export function lookup (input) {
|
|
15
|
-
// detect the file type... don't rely on the extension
|
|
16
|
-
const type = detector(input)
|
|
17
|
-
|
|
18
|
-
if (typeof type !== 'undefined') {
|
|
19
|
-
if (globalOptions.disabledTypes.indexOf(type) > -1) {
|
|
20
|
-
throw new TypeError('disabled file type: ' + type)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// find an appropriate handler for this file type
|
|
24
|
-
const size = typeHandlers.get(type).calculate(input)
|
|
25
|
-
if (size !== undefined) {
|
|
26
|
-
size.type = size.type ?? type
|
|
27
|
-
return size
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// throw up, if we don't understand the file
|
|
32
|
-
throw new TypeError('unsupported file type: ' + type)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const disableTypes = (types) => {
|
|
36
|
-
globalOptions.disabledTypes = types
|
|
37
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { toUTF8String, readInt32LE, readUInt32LE } from './utils'
|
|
2
|
-
|
|
3
|
-
export const BMP = {
|
|
4
|
-
validate: (input) => toUTF8String(input, 0, 2) === 'BM',
|
|
5
|
-
|
|
6
|
-
calculate: (input) => ({
|
|
7
|
-
height: Math.abs(readInt32LE(input, 22)),
|
|
8
|
-
width: readUInt32LE(input, 18)
|
|
9
|
-
})
|
|
10
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ICO } from './ico'
|
|
2
|
-
import { readUInt16LE } from './utils'
|
|
3
|
-
|
|
4
|
-
const TYPE_CURSOR = 2
|
|
5
|
-
export const CUR = {
|
|
6
|
-
validate (input) {
|
|
7
|
-
const reserved = readUInt16LE(input, 0)
|
|
8
|
-
const imageCount = readUInt16LE(input, 4)
|
|
9
|
-
if (reserved !== 0 || imageCount === 0) return false
|
|
10
|
-
|
|
11
|
-
const imageType = readUInt16LE(input, 2)
|
|
12
|
-
return imageType === TYPE_CURSOR
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
calculate: (input) => ICO.calculate(input)
|
|
16
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { toUTF8String, readUInt16LE } from './utils'
|
|
2
|
-
|
|
3
|
-
const gifRegexp = /^GIF8[79]a/
|
|
4
|
-
export const GIF = {
|
|
5
|
-
validate: (input) => gifRegexp.test(toUTF8String(input, 0, 6)),
|
|
6
|
-
|
|
7
|
-
calculate: (input) => ({
|
|
8
|
-
height: readUInt16LE(input, 8),
|
|
9
|
-
width: readUInt16LE(input, 6)
|
|
10
|
-
})
|
|
11
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { findBox, readUInt32BE, toUTF8String } from './utils'
|
|
2
|
-
|
|
3
|
-
const brandMap = {
|
|
4
|
-
avif: 'avif',
|
|
5
|
-
mif1: 'heif',
|
|
6
|
-
msf1: 'heif', // hief-sequence
|
|
7
|
-
heic: 'heic',
|
|
8
|
-
heix: 'heic',
|
|
9
|
-
hevc: 'heic', // heic-sequence
|
|
10
|
-
hevx: 'heic' // heic-sequence
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const HEIF = {
|
|
14
|
-
validate (buffer) {
|
|
15
|
-
const ftype = toUTF8String(buffer, 4, 8)
|
|
16
|
-
const brand = toUTF8String(buffer, 8, 12)
|
|
17
|
-
return 'ftyp' === ftype && brand in brandMap
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
calculate (buffer) {
|
|
21
|
-
// Based on https://nokiatech.github.io/heif/technical.html
|
|
22
|
-
const metaBox = findBox(buffer, 'meta', 0)
|
|
23
|
-
const iprpBox = metaBox && findBox(buffer, 'iprp', metaBox.offset + 12)
|
|
24
|
-
const ipcoBox = iprpBox && findBox(buffer, 'ipco', iprpBox.offset + 8)
|
|
25
|
-
const ispeBox = ipcoBox && findBox(buffer, 'ispe', ipcoBox.offset + 8)
|
|
26
|
-
if (ispeBox) {
|
|
27
|
-
return {
|
|
28
|
-
height: readUInt32BE(buffer, ispeBox.offset + 16),
|
|
29
|
-
width: readUInt32BE(buffer, ispeBox.offset + 12),
|
|
30
|
-
type: toUTF8String(buffer, 8, 12)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
throw new TypeError('Invalid HEIF, no size found')
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { toUTF8String, readUInt32BE } from './utils'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ICNS Header
|
|
5
|
-
*
|
|
6
|
-
* | Offset | Size | Purpose |
|
|
7
|
-
* | 0 | 4 | Magic literal, must be "icns" (0x69, 0x63, 0x6e, 0x73) |
|
|
8
|
-
* | 4 | 4 | Length of file, in bytes, msb first. |
|
|
9
|
-
*
|
|
10
|
-
*/
|
|
11
|
-
const SIZE_HEADER = 4 + 4 // 8
|
|
12
|
-
const FILE_LENGTH_OFFSET = 4 // MSB => BIG ENDIAN
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Image Entry
|
|
16
|
-
*
|
|
17
|
-
* | Offset | Size | Purpose |
|
|
18
|
-
* | 0 | 4 | Icon type, see OSType below. |
|
|
19
|
-
* | 4 | 4 | Length of data, in bytes (including type and length), msb first. |
|
|
20
|
-
* | 8 | n | Icon data |
|
|
21
|
-
*/
|
|
22
|
-
const ENTRY_LENGTH_OFFSET = 4 // MSB => BIG ENDIAN
|
|
23
|
-
|
|
24
|
-
const ICON_TYPE_SIZE = {
|
|
25
|
-
ICON: 32,
|
|
26
|
-
'ICN#': 32,
|
|
27
|
-
// m => 16 x 16
|
|
28
|
-
'icm#': 16,
|
|
29
|
-
icm4: 16,
|
|
30
|
-
icm8: 16,
|
|
31
|
-
// s => 16 x 16
|
|
32
|
-
'ics#': 16,
|
|
33
|
-
ics4: 16,
|
|
34
|
-
ics8: 16,
|
|
35
|
-
is32: 16,
|
|
36
|
-
s8mk: 16,
|
|
37
|
-
icp4: 16,
|
|
38
|
-
// l => 32 x 32
|
|
39
|
-
icl4: 32,
|
|
40
|
-
icl8: 32,
|
|
41
|
-
il32: 32,
|
|
42
|
-
l8mk: 32,
|
|
43
|
-
icp5: 32,
|
|
44
|
-
ic11: 32,
|
|
45
|
-
// h => 48 x 48
|
|
46
|
-
ich4: 48,
|
|
47
|
-
ich8: 48,
|
|
48
|
-
ih32: 48,
|
|
49
|
-
h8mk: 48,
|
|
50
|
-
// . => 64 x 64
|
|
51
|
-
icp6: 64,
|
|
52
|
-
ic12: 32,
|
|
53
|
-
// t => 128 x 128
|
|
54
|
-
it32: 128,
|
|
55
|
-
t8mk: 128,
|
|
56
|
-
ic07: 128,
|
|
57
|
-
// . => 256 x 256
|
|
58
|
-
ic08: 256,
|
|
59
|
-
ic13: 256,
|
|
60
|
-
// . => 512 x 512
|
|
61
|
-
ic09: 512,
|
|
62
|
-
ic14: 512,
|
|
63
|
-
// . => 1024 x 1024
|
|
64
|
-
ic10: 1024
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function readImageHeader (
|
|
68
|
-
input,
|
|
69
|
-
imageOffset
|
|
70
|
-
) {
|
|
71
|
-
const imageLengthOffset = imageOffset + ENTRY_LENGTH_OFFSET
|
|
72
|
-
return [
|
|
73
|
-
toUTF8String(input, imageOffset, imageLengthOffset),
|
|
74
|
-
readUInt32BE(input, imageLengthOffset)
|
|
75
|
-
]
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getImageSize (type) {
|
|
79
|
-
const size = ICON_TYPE_SIZE[type]
|
|
80
|
-
return { width: size, height: size, type }
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const ICNS = {
|
|
84
|
-
validate: (input) => toUTF8String(input, 0, 4) === 'icns',
|
|
85
|
-
|
|
86
|
-
calculate (input) {
|
|
87
|
-
const inputLength = input.length
|
|
88
|
-
const fileLength = readUInt32BE(input, FILE_LENGTH_OFFSET)
|
|
89
|
-
let imageOffset = SIZE_HEADER
|
|
90
|
-
|
|
91
|
-
let imageHeader = readImageHeader(input, imageOffset)
|
|
92
|
-
let imageSize = getImageSize(imageHeader[0])
|
|
93
|
-
imageOffset += imageHeader[1]
|
|
94
|
-
|
|
95
|
-
if (imageOffset === fileLength) return imageSize
|
|
96
|
-
|
|
97
|
-
const result = {
|
|
98
|
-
height: imageSize.height,
|
|
99
|
-
images: [imageSize],
|
|
100
|
-
width: imageSize.width
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
while (imageOffset < fileLength && imageOffset < inputLength) {
|
|
104
|
-
imageHeader = readImageHeader(input, imageOffset)
|
|
105
|
-
imageSize = getImageSize(imageHeader[0])
|
|
106
|
-
imageOffset += imageHeader[1]
|
|
107
|
-
result.images.push(imageSize)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return result
|
|
111
|
-
}
|
|
112
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { readUInt16LE } from './utils'
|
|
2
|
-
|
|
3
|
-
const TYPE_ICON = 1
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* ICON Header
|
|
7
|
-
*
|
|
8
|
-
* | Offset | Size | Purpose |
|
|
9
|
-
* | 0 | 2 | Reserved. Must always be 0. |
|
|
10
|
-
* | 2 | 2 | Image type: 1 for icon (.ICO) image, 2 for cursor (.CUR) image. Other values are invalid. |
|
|
11
|
-
* | 4 | 2 | Number of images in the file. |
|
|
12
|
-
*
|
|
13
|
-
*/
|
|
14
|
-
const SIZE_HEADER = 2 + 2 + 2 // 6
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Image Entry
|
|
18
|
-
*
|
|
19
|
-
* | Offset | Size | Purpose |
|
|
20
|
-
* | 0 | 1 | Image width in pixels. Can be any number between 0 and 255. Value 0 means width is 256 pixels. |
|
|
21
|
-
* | 1 | 1 | Image height in pixels. Can be any number between 0 and 255. Value 0 means height is 256 pixels. |
|
|
22
|
-
* | 2 | 1 | Number of colors in the color palette. Should be 0 if the image does not use a color palette. |
|
|
23
|
-
* | 3 | 1 | Reserved. Should be 0. |
|
|
24
|
-
* | 4 | 2 | ICO format: Color planes. Should be 0 or 1. |
|
|
25
|
-
* | | | CUR format: The horizontal coordinates of the hotspot in number of pixels from the left. |
|
|
26
|
-
* | 6 | 2 | ICO format: Bits per pixel. |
|
|
27
|
-
* | | | CUR format: The vertical coordinates of the hotspot in number of pixels from the top. |
|
|
28
|
-
* | 8 | 4 | The size of the image's data in bytes |
|
|
29
|
-
* | 12 | 4 | The offset of BMP or PNG data from the beginning of the ICO/CUR file |
|
|
30
|
-
*
|
|
31
|
-
*/
|
|
32
|
-
const SIZE_IMAGE_ENTRY = 1 + 1 + 1 + 1 + 2 + 2 + 4 + 4 // 16
|
|
33
|
-
|
|
34
|
-
function getSizeFromOffset (input, offset) {
|
|
35
|
-
const value = input[offset]
|
|
36
|
-
return value === 0 ? 256 : value
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function getImageSize (input, imageIndex) {
|
|
40
|
-
const offset = SIZE_HEADER + imageIndex * SIZE_IMAGE_ENTRY
|
|
41
|
-
return {
|
|
42
|
-
height: getSizeFromOffset(input, offset + 1),
|
|
43
|
-
width: getSizeFromOffset(input, offset)
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const ICO = {
|
|
48
|
-
validate (input) {
|
|
49
|
-
const reserved = readUInt16LE(input, 0)
|
|
50
|
-
const imageCount = readUInt16LE(input, 4)
|
|
51
|
-
if (reserved !== 0 || imageCount === 0) return false
|
|
52
|
-
|
|
53
|
-
const imageType = readUInt16LE(input, 2)
|
|
54
|
-
return imageType === TYPE_ICON
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
calculate (input) {
|
|
58
|
-
const nbImages = readUInt16LE(input, 4)
|
|
59
|
-
const imageSize = getImageSize(input, 0)
|
|
60
|
-
|
|
61
|
-
if (nbImages === 1) return imageSize
|
|
62
|
-
|
|
63
|
-
const imgs = [imageSize]
|
|
64
|
-
for (let imageIndex = 1; imageIndex < nbImages; imageIndex += 1) {
|
|
65
|
-
imgs.push(getImageSize(input, imageIndex))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return {
|
|
69
|
-
height: imageSize.height,
|
|
70
|
-
images: imgs,
|
|
71
|
-
width: imageSize.width
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// load all available handlers explicitely for browserify support
|
|
2
|
-
import { BMP } from './bmp'
|
|
3
|
-
import { CUR } from './cur'
|
|
4
|
-
import { DDS } from './dds'
|
|
5
|
-
import { GIF } from './gif'
|
|
6
|
-
import { HEIF } from './heif'
|
|
7
|
-
import { ICNS } from './icns'
|
|
8
|
-
import { ICO } from './ico'
|
|
9
|
-
import { J2C } from './j2c'
|
|
10
|
-
import { JP2 } from './jp2'
|
|
11
|
-
import { JPG } from './jpg'
|
|
12
|
-
import { KTX } from './ktx'
|
|
13
|
-
import { PNG } from './png'
|
|
14
|
-
import { PNM } from './pnm'
|
|
15
|
-
import { PSD } from './psd'
|
|
16
|
-
import { SVG } from './svg'
|
|
17
|
-
import { TGA } from './tga'
|
|
18
|
-
import { TIFF } from './tiff'
|
|
19
|
-
import { WEBP } from './webp'
|
|
20
|
-
|
|
21
|
-
export const typeHandlers = new Map([
|
|
22
|
-
['bmp', BMP],
|
|
23
|
-
['cur', CUR],
|
|
24
|
-
['dds', DDS],
|
|
25
|
-
['gif', GIF],
|
|
26
|
-
['heif', HEIF],
|
|
27
|
-
['icns', ICNS],
|
|
28
|
-
['ico', ICO],
|
|
29
|
-
['j2c', J2C],
|
|
30
|
-
['jp2', JP2],
|
|
31
|
-
['jpg', JPG],
|
|
32
|
-
['ktx', KTX],
|
|
33
|
-
['png', PNG],
|
|
34
|
-
['pnm', PNM],
|
|
35
|
-
['psd', PSD],
|
|
36
|
-
['svg', SVG],
|
|
37
|
-
['tga', TGA],
|
|
38
|
-
['tiff', TIFF],
|
|
39
|
-
['webp', WEBP]
|
|
40
|
-
])
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
export const types = Array.from(typeHandlers.keys())
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { toHexString, readUInt32BE } from './utils'
|
|
2
|
-
|
|
3
|
-
export const J2C = {
|
|
4
|
-
// TODO: this doesn't seem right. SIZ marker doesn't have to be right after the SOC
|
|
5
|
-
validate: (input) => toHexString(input, 0, 4) === 'ff4fff51',
|
|
6
|
-
|
|
7
|
-
calculate: (input) => ({
|
|
8
|
-
height: readUInt32BE(input, 12),
|
|
9
|
-
width: readUInt32BE(input, 8)
|
|
10
|
-
})
|
|
11
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { readUInt32BE, findBox } from './utils'
|
|
2
|
-
|
|
3
|
-
export const JP2 = {
|
|
4
|
-
validate (input) {
|
|
5
|
-
if (readUInt32BE(input, 4) !== 0x6a502020 || readUInt32BE(input, 0) < 1) return false
|
|
6
|
-
const ftypBox = findBox(input, 'ftyp', 0)
|
|
7
|
-
if (!ftypBox) return false
|
|
8
|
-
return readUInt32BE(input, ftypBox.offset + 4) === 0x66747970
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
calculate (input) {
|
|
12
|
-
const jp2hBox = findBox(input, 'jp2h', 0)
|
|
13
|
-
const ihdrBox = jp2hBox && findBox(input, 'ihdr', jp2hBox.offset + 8)
|
|
14
|
-
if (ihdrBox) {
|
|
15
|
-
return {
|
|
16
|
-
height: readUInt32BE(input, ihdrBox.offset + 8),
|
|
17
|
-
width: readUInt32BE(input, ihdrBox.offset + 12)
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
throw new TypeError('Unsupported JPEG 2000 format')
|
|
21
|
-
}
|
|
22
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
// NOTE: we only support baseline and progressive JPGs here
|
|
2
|
-
// due to the structure of the loader class, we only get a buffer
|
|
3
|
-
// with a maximum size of 4096 bytes. so if the SOF marker is outside
|
|
4
|
-
// if this range we can't detect the file size correctly.
|
|
5
|
-
import { readUInt, readUInt16BE, toHexString } from './utils'
|
|
6
|
-
|
|
7
|
-
const EXIF_MARKER = '45786966'
|
|
8
|
-
const APP1_DATA_SIZE_BYTES = 2
|
|
9
|
-
const EXIF_HEADER_BYTES = 6
|
|
10
|
-
const TIFF_BYTE_ALIGN_BYTES = 2
|
|
11
|
-
const BIG_ENDIAN_BYTE_ALIGN = '4d4d'
|
|
12
|
-
const LITTLE_ENDIAN_BYTE_ALIGN = '4949'
|
|
13
|
-
|
|
14
|
-
// Each entry is exactly 12 bytes
|
|
15
|
-
const IDF_ENTRY_BYTES = 12
|
|
16
|
-
const NUM_DIRECTORY_ENTRIES_BYTES = 2
|
|
17
|
-
|
|
18
|
-
function isEXIF (input) {
|
|
19
|
-
return toHexString(input, 2, 6) === EXIF_MARKER
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function extractSize (input, index) {
|
|
23
|
-
return {
|
|
24
|
-
height: readUInt16BE(input, index),
|
|
25
|
-
width: readUInt16BE(input, index + 2)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function extractOrientation (exifBlock, isBigEndian) {
|
|
30
|
-
// TODO: assert that this contains 0x002A
|
|
31
|
-
// let STATIC_MOTOROLA_TIFF_HEADER_BYTES = 2
|
|
32
|
-
// let TIFF_IMAGE_FILE_DIRECTORY_BYTES = 4
|
|
33
|
-
|
|
34
|
-
// TODO: derive from TIFF_IMAGE_FILE_DIRECTORY_BYTES
|
|
35
|
-
const idfOffset = 8
|
|
36
|
-
|
|
37
|
-
// IDF osset works from right after the header bytes
|
|
38
|
-
// (so the offset includes the tiff byte align)
|
|
39
|
-
const offset = EXIF_HEADER_BYTES + idfOffset
|
|
40
|
-
|
|
41
|
-
const idfDirectoryEntries = readUInt(exifBlock, 16, offset, isBigEndian)
|
|
42
|
-
|
|
43
|
-
for (
|
|
44
|
-
let directoryEntryNumber = 0;
|
|
45
|
-
directoryEntryNumber < idfDirectoryEntries;
|
|
46
|
-
directoryEntryNumber++
|
|
47
|
-
) {
|
|
48
|
-
const start =
|
|
49
|
-
offset +
|
|
50
|
-
NUM_DIRECTORY_ENTRIES_BYTES +
|
|
51
|
-
directoryEntryNumber * IDF_ENTRY_BYTES
|
|
52
|
-
const end = start + IDF_ENTRY_BYTES
|
|
53
|
-
|
|
54
|
-
// Skip on corrupt EXIF blocks
|
|
55
|
-
if (start > exifBlock.length) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const block = exifBlock.slice(start, end)
|
|
60
|
-
const tagNumber = readUInt(block, 16, 0, isBigEndian)
|
|
61
|
-
|
|
62
|
-
// 0x0112 (decimal: 274) is the `orientation` tag ID
|
|
63
|
-
if (tagNumber === 274) {
|
|
64
|
-
const dataFormat = readUInt(block, 16, 2, isBigEndian)
|
|
65
|
-
if (dataFormat !== 3) {
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// unsinged int has 2 bytes per component
|
|
70
|
-
// if there would more than 4 bytes in total it's a pointer
|
|
71
|
-
const numberOfComponents = readUInt(block, 32, 4, isBigEndian)
|
|
72
|
-
if (numberOfComponents !== 1) {
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return readUInt(block, 16, 8, isBigEndian)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function validateExifBlock (input, index) {
|
|
82
|
-
// Skip APP1 Data Size
|
|
83
|
-
const exifBlock = input.slice(APP1_DATA_SIZE_BYTES, index)
|
|
84
|
-
|
|
85
|
-
// Consider byte alignment
|
|
86
|
-
const byteAlign = toHexString(
|
|
87
|
-
exifBlock,
|
|
88
|
-
EXIF_HEADER_BYTES,
|
|
89
|
-
EXIF_HEADER_BYTES + TIFF_BYTE_ALIGN_BYTES
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
// Ignore Empty EXIF. Validate byte alignment
|
|
93
|
-
const isBigEndian = byteAlign === BIG_ENDIAN_BYTE_ALIGN
|
|
94
|
-
const isLittleEndian = byteAlign === LITTLE_ENDIAN_BYTE_ALIGN
|
|
95
|
-
|
|
96
|
-
if (isBigEndian || isLittleEndian) {
|
|
97
|
-
return extractOrientation(exifBlock, isBigEndian)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function validateInput (input, index) {
|
|
102
|
-
// index should be within buffer limits
|
|
103
|
-
if (index > input.length) {
|
|
104
|
-
throw new TypeError('Corrupt JPG, exceeded buffer limits')
|
|
105
|
-
}
|
|
106
|
-
// Every JPEG block must begin with a 0xFF
|
|
107
|
-
if (input[index] !== 0xff) {
|
|
108
|
-
throw new TypeError('Invalid JPG, marker table corrupted')
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export const JPG = {
|
|
113
|
-
validate: (input) => toHexString(input, 0, 2) === 'ffd8',
|
|
114
|
-
|
|
115
|
-
calculate (input) {
|
|
116
|
-
// Skip 4 chars, they are for signature
|
|
117
|
-
input = input.slice(4)
|
|
118
|
-
|
|
119
|
-
let orientation
|
|
120
|
-
let next
|
|
121
|
-
while (input.length) {
|
|
122
|
-
// read length of the next block
|
|
123
|
-
const i = readUInt16BE(input, 0)
|
|
124
|
-
|
|
125
|
-
if (isEXIF(input)) {
|
|
126
|
-
orientation = validateExifBlock(input, i)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// ensure correct format
|
|
130
|
-
validateInput(input, i)
|
|
131
|
-
|
|
132
|
-
// 0xFFC0 is baseline standard(SOF)
|
|
133
|
-
// 0xFFC1 is baseline optimized(SOF)
|
|
134
|
-
// 0xFFC2 is progressive(SOF2)
|
|
135
|
-
next = input[i + 1]
|
|
136
|
-
if (next === 0xc0 || next === 0xc1 || next === 0xc2) {
|
|
137
|
-
const size = extractSize(input, i + 5)
|
|
138
|
-
|
|
139
|
-
// TODO: is orientation=0 a valid answer here?
|
|
140
|
-
if (!orientation) {
|
|
141
|
-
return size
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
height: size.height,
|
|
146
|
-
orientation,
|
|
147
|
-
width: size.width
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// move to the next block
|
|
152
|
-
input = input.slice(i + 2)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
throw new TypeError('Invalid JPG, no size found')
|
|
156
|
-
}
|
|
157
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { toUTF8String, readUInt32LE } from './utils'
|
|
2
|
-
|
|
3
|
-
export const KTX = {
|
|
4
|
-
validate: (input) => {
|
|
5
|
-
const signature = toUTF8String(input, 1, 7)
|
|
6
|
-
return ['KTX 11', 'KTX 20'].includes(signature)
|
|
7
|
-
},
|
|
8
|
-
|
|
9
|
-
calculate: (input) => {
|
|
10
|
-
const type = input[5] === 0x31 ? 'ktx' : 'ktx2'
|
|
11
|
-
const offset = type === 'ktx' ? 36 : 20
|
|
12
|
-
return ({
|
|
13
|
-
height: readUInt32LE(input, offset + 4),
|
|
14
|
-
width: readUInt32LE(input, offset),
|
|
15
|
-
type
|
|
16
|
-
})
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { toUTF8String, readUInt32BE } from './utils'
|
|
2
|
-
|
|
3
|
-
const pngSignature = 'PNG\r\n\x1a\n'
|
|
4
|
-
const pngImageHeaderChunkName = 'IHDR'
|
|
5
|
-
|
|
6
|
-
// Used to detect "fried" png's: http://www.jongware.com/pngdefry.html
|
|
7
|
-
const pngFriedChunkName = 'CgBI'
|
|
8
|
-
|
|
9
|
-
export const PNG = {
|
|
10
|
-
validate (input) {
|
|
11
|
-
if (pngSignature === toUTF8String(input, 1, 8)) {
|
|
12
|
-
let chunkName = toUTF8String(input, 12, 16)
|
|
13
|
-
if (chunkName === pngFriedChunkName) {
|
|
14
|
-
chunkName = toUTF8String(input, 28, 32)
|
|
15
|
-
}
|
|
16
|
-
if (chunkName !== pngImageHeaderChunkName) {
|
|
17
|
-
throw new TypeError('Invalid PNG')
|
|
18
|
-
}
|
|
19
|
-
return true
|
|
20
|
-
}
|
|
21
|
-
return false
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
calculate (input) {
|
|
25
|
-
if (toUTF8String(input, 12, 16) === pngFriedChunkName) {
|
|
26
|
-
return {
|
|
27
|
-
height: readUInt32BE(input, 36),
|
|
28
|
-
width: readUInt32BE(input, 32)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return {
|
|
32
|
-
height: readUInt32BE(input, 20),
|
|
33
|
-
width: readUInt32BE(input, 16)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|