geotiff 3.0.4-beta.1 → 3.0.4-beta.2
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/package.json +2 -1
- package/src/compression/basedecoder.js +50 -0
- package/src/compression/deflate.js +9 -0
- package/src/compression/index.js +185 -0
- package/src/compression/jpeg.js +1116 -0
- package/src/compression/lerc.js +42 -0
- package/src/compression/lzw.js +158 -0
- package/src/compression/packbits.js +27 -0
- package/src/compression/raw.js +8 -0
- package/src/compression/webimage.js +60 -0
- package/src/compression/zstd.js +11 -0
- package/src/dataslice.js +191 -0
- package/src/dataview64.js +153 -0
- package/src/geotiff.js +799 -0
- package/src/geotiffimage.js +1083 -0
- package/src/geotiffwriter.js +667 -0
- package/src/globals.js +437 -0
- package/src/imagefiledirectory.js +630 -0
- package/src/logging.js +69 -0
- package/src/pool.js +166 -0
- package/src/predictor.js +106 -0
- package/src/resample.js +222 -0
- package/src/rgb.ts +124 -0
- package/src/source/arraybuffer.js +33 -0
- package/src/source/basesource.js +41 -0
- package/src/source/blockedsource.js +299 -0
- package/src/source/client/base.js +48 -0
- package/src/source/client/fetch.js +54 -0
- package/src/source/client/http.js +94 -0
- package/src/source/client/xhr.js +70 -0
- package/src/source/file.js +99 -0
- package/src/source/filereader.js +44 -0
- package/src/source/httputils.js +152 -0
- package/src/source/remote.js +232 -0
- package/src/utils.ts +235 -0
- package/src/worker/create.js +8 -0
- package/src/worker/decoder.js +20 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "geotiff",
|
|
3
|
-
"version": "3.0.4-beta.
|
|
3
|
+
"version": "3.0.4-beta.2",
|
|
4
4
|
"description": "GeoTIFF image decoding in JavaScript",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"types": "dist-module/geotiff.d.ts",
|
|
28
28
|
"files": [
|
|
29
|
+
"src",
|
|
29
30
|
"dist-module",
|
|
30
31
|
"dist-node",
|
|
31
32
|
"dist-browser"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { applyPredictor } from '../predictor.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} BaseDecoderParameters
|
|
5
|
+
* @property {number} tileWidth
|
|
6
|
+
* @property {number} tileHeight
|
|
7
|
+
* @property {number} predictor
|
|
8
|
+
* @property {number|number[]|import('../geotiff.js').TypedArray} bitsPerSample
|
|
9
|
+
* @property {number} planarConfiguration
|
|
10
|
+
* @property {number} [samplesPerPixel]
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export default class BaseDecoder {
|
|
14
|
+
/**
|
|
15
|
+
* @param {BaseDecoderParameters} parameters
|
|
16
|
+
*/
|
|
17
|
+
constructor(parameters) {
|
|
18
|
+
this.parameters = parameters;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @abstract
|
|
23
|
+
* @param {ArrayBufferLike} _buffer
|
|
24
|
+
* @returns {Promise<ArrayBufferLike>|ArrayBufferLike}
|
|
25
|
+
*/
|
|
26
|
+
decodeBlock(_buffer) {
|
|
27
|
+
throw new Error('decodeBlock not implemented');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {ArrayBufferLike} buffer
|
|
32
|
+
* @returns {Promise<ArrayBufferLike>}
|
|
33
|
+
*/
|
|
34
|
+
async decode(buffer) {
|
|
35
|
+
const decoded = await this.decodeBlock(buffer);
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
tileWidth, tileHeight, predictor, bitsPerSample, planarConfiguration,
|
|
39
|
+
} = this.parameters;
|
|
40
|
+
if (predictor !== 1) {
|
|
41
|
+
const isBitsPerSampleArray = Array.isArray(bitsPerSample) || ArrayBuffer.isView(bitsPerSample);
|
|
42
|
+
const adaptedBitsPerSample = isBitsPerSampleArray ? Array.from(bitsPerSample) : [bitsPerSample];
|
|
43
|
+
return applyPredictor(
|
|
44
|
+
decoded, predictor, tileWidth, tileHeight, adaptedBitsPerSample,
|
|
45
|
+
planarConfiguration,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return decoded;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/** @import BaseDecoder, {BaseDecoderParameters} from "./basedecoder.js" */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} RegistryEntry
|
|
5
|
+
* @property {function():Promise<typeof BaseDecoder>} importFn
|
|
6
|
+
* @property {function(import("../imagefiledirectory").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn
|
|
7
|
+
* @property {boolean} preferWorker
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** @type {Map<number | undefined, RegistryEntry>} */
|
|
11
|
+
const registry = new Map();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Default decoder parameter retrieval function
|
|
15
|
+
* @param {import("../imagefiledirectory").ImageFileDirectory} fileDirectory
|
|
16
|
+
* @returns {Promise<BaseDecoderParameters>}
|
|
17
|
+
*/
|
|
18
|
+
async function defaultDecoderParameterFn(fileDirectory) {
|
|
19
|
+
const isTiled = !fileDirectory.hasTag('StripOffsets');
|
|
20
|
+
return /** @type {BaseDecoderParameters} */ ({
|
|
21
|
+
tileWidth: isTiled
|
|
22
|
+
? await fileDirectory.loadValue('TileWidth')
|
|
23
|
+
: await fileDirectory.loadValue('ImageWidth'),
|
|
24
|
+
tileHeight: isTiled
|
|
25
|
+
? await fileDirectory.loadValue('TileLength')
|
|
26
|
+
: (
|
|
27
|
+
await fileDirectory.loadValue('RowsPerStrip')
|
|
28
|
+
|| await fileDirectory.loadValue('ImageLength')
|
|
29
|
+
),
|
|
30
|
+
planarConfiguration: await fileDirectory.loadValue('PlanarConfiguration'),
|
|
31
|
+
bitsPerSample: await fileDirectory.loadValue('BitsPerSample'),
|
|
32
|
+
predictor: await fileDirectory.loadValue('Predictor') || 1,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Register a decoder for a specific compression method or a range of compressions
|
|
38
|
+
* @param {(number|undefined|(number|undefined)[])} cases ids of the compression methods to register for
|
|
39
|
+
* @param {function():Promise<typeof BaseDecoder>} importFn the function to import the decoder
|
|
40
|
+
* @param {function(import("../imagefiledirectory").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn
|
|
41
|
+
* @param {boolean} preferWorker_ Whether to prefer running the decoder in a worker
|
|
42
|
+
*/
|
|
43
|
+
export function addDecoder(cases, importFn, decoderParameterFn = defaultDecoderParameterFn, preferWorker_ = true) {
|
|
44
|
+
if (!Array.isArray(cases)) {
|
|
45
|
+
cases = [cases]; // eslint-disable-line no-param-reassign
|
|
46
|
+
}
|
|
47
|
+
cases.forEach((c) => {
|
|
48
|
+
registry.set(c, { importFn, decoderParameterFn, preferWorker: preferWorker_ });
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the required decoder parameters for a specific compression method
|
|
54
|
+
* @param {number|undefined} compression
|
|
55
|
+
* @param {import('../imagefiledirectory.js').ImageFileDirectory} fileDirectory
|
|
56
|
+
*/
|
|
57
|
+
export async function getDecoderParameters(compression, fileDirectory) {
|
|
58
|
+
if (!registry.has(compression)) {
|
|
59
|
+
throw new Error(`Unknown compression method identifier: ${compression}`);
|
|
60
|
+
}
|
|
61
|
+
const { decoderParameterFn } = /** @type {RegistryEntry} */ (registry.get(compression));
|
|
62
|
+
return decoderParameterFn(fileDirectory);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get a decoder for a specific compression and parameters
|
|
67
|
+
* @param {number} compression the compression method identifier
|
|
68
|
+
* @param {BaseDecoderParameters} decoderParameters the parameters for the decoder
|
|
69
|
+
* @returns {Promise<import('./basedecoder.js').default>}
|
|
70
|
+
*/
|
|
71
|
+
export async function getDecoder(compression, decoderParameters) {
|
|
72
|
+
if (!registry.has(compression)) {
|
|
73
|
+
throw new Error(`Unknown compression method identifier: ${compression}`);
|
|
74
|
+
}
|
|
75
|
+
const { importFn } = /** @type {RegistryEntry} */ (registry.get(compression));
|
|
76
|
+
const Decoder = await importFn();
|
|
77
|
+
return new Decoder(decoderParameters);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Whether to prefer running the decoder in a worker
|
|
82
|
+
* @param {number|undefined} compression the compression method identifier
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
export function preferWorker(compression) {
|
|
86
|
+
if (!registry.has(compression)) {
|
|
87
|
+
throw new Error(`Unknown compression method identifier: ${compression}`);
|
|
88
|
+
}
|
|
89
|
+
return /** @type {RegistryEntry} */ (registry.get(compression)).preferWorker;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const defaultDecoderDefinitions = [
|
|
93
|
+
// No compression
|
|
94
|
+
{
|
|
95
|
+
cases: [undefined, 1],
|
|
96
|
+
importFn: () => import('./raw.js').then((m) => m.default),
|
|
97
|
+
preferWorker: false,
|
|
98
|
+
},
|
|
99
|
+
// LZW
|
|
100
|
+
{
|
|
101
|
+
cases: 5,
|
|
102
|
+
importFn: () => import('./lzw.js').then((m) => m.default),
|
|
103
|
+
},
|
|
104
|
+
// Old-style JPEG
|
|
105
|
+
{
|
|
106
|
+
cases: 6,
|
|
107
|
+
importFn: () => {
|
|
108
|
+
throw new Error('old style JPEG compression is not supported.');
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
// JPEG
|
|
112
|
+
{
|
|
113
|
+
cases: 7,
|
|
114
|
+
importFn: () => import('./jpeg.js').then((m) => m.default),
|
|
115
|
+
/**
|
|
116
|
+
* @param {import("../imagefiledirectory").ImageFileDirectory} fileDirectory
|
|
117
|
+
*/
|
|
118
|
+
decoderParameterFn: async (fileDirectory) => {
|
|
119
|
+
return {
|
|
120
|
+
...await defaultDecoderParameterFn(fileDirectory),
|
|
121
|
+
JPEGTables: await fileDirectory.loadValue('JPEGTables'),
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
// Deflate / Adobe Deflate
|
|
126
|
+
{
|
|
127
|
+
cases: [8, 32946],
|
|
128
|
+
importFn: () => import('./deflate.js').then((m) => m.default),
|
|
129
|
+
},
|
|
130
|
+
// PackBits
|
|
131
|
+
{
|
|
132
|
+
cases: 32773,
|
|
133
|
+
importFn: () => import('./packbits.js').then((m) => m.default),
|
|
134
|
+
},
|
|
135
|
+
// LERC
|
|
136
|
+
{
|
|
137
|
+
cases: 34887,
|
|
138
|
+
importFn: () => import('./lerc.js')
|
|
139
|
+
.then(async (m) => {
|
|
140
|
+
await m.zstd.init();
|
|
141
|
+
return m;
|
|
142
|
+
})
|
|
143
|
+
.then((m) => m.default),
|
|
144
|
+
/**
|
|
145
|
+
* @param {import("../imagefiledirectory").ImageFileDirectory} fileDirectory
|
|
146
|
+
*/
|
|
147
|
+
decoderParameterFn: async (fileDirectory) => {
|
|
148
|
+
return {
|
|
149
|
+
...await defaultDecoderParameterFn(fileDirectory),
|
|
150
|
+
LercParameters: await fileDirectory.loadValue('LercParameters'),
|
|
151
|
+
};
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
// zstd
|
|
155
|
+
{
|
|
156
|
+
cases: 50000,
|
|
157
|
+
importFn: () => import('./zstd.js')
|
|
158
|
+
.then(async (m) => {
|
|
159
|
+
await m.zstd.init();
|
|
160
|
+
return m;
|
|
161
|
+
})
|
|
162
|
+
.then((m) => m.default),
|
|
163
|
+
},
|
|
164
|
+
// WebP Images
|
|
165
|
+
{
|
|
166
|
+
cases: 50001,
|
|
167
|
+
importFn: () => import('./webimage.js').then((m) => m.default),
|
|
168
|
+
/**
|
|
169
|
+
* @param {import("../imagefiledirectory").ImageFileDirectory} fileDirectory
|
|
170
|
+
*/
|
|
171
|
+
decoderParameterFn: async (fileDirectory) => {
|
|
172
|
+
return {
|
|
173
|
+
...await defaultDecoderParameterFn(fileDirectory),
|
|
174
|
+
samplesPerPixel: Number(await fileDirectory.loadValue('SamplesPerPixel')) || 4,
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
preferWorker: false,
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
// Add default decoders to registry (end-user may override with other implementations)
|
|
182
|
+
for (const decoderDefinition of defaultDecoderDefinitions) {
|
|
183
|
+
const { cases, importFn, decoderParameterFn, preferWorker: preferWorker_ } = decoderDefinition;
|
|
184
|
+
addDecoder(cases, importFn, decoderParameterFn, preferWorker_);
|
|
185
|
+
}
|