@cogeotiff/core 9.1.2 → 9.3.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 +27 -0
- package/build/__benchmark__/cog.read.benchmark.d.ts +1 -0
- package/build/__benchmark__/cog.read.benchmark.d.ts.map +1 -0
- package/build/__benchmark__/cog.read.benchmark.js +4 -3
- package/build/__benchmark__/source.file.d.ts +5 -0
- package/build/__benchmark__/source.file.d.ts.map +1 -0
- package/build/__benchmark__/source.file.js +4 -13
- package/build/__benchmark__/source.memory.d.ts +1 -0
- package/build/__benchmark__/source.memory.d.ts.map +1 -0
- package/build/__benchmark__/source.memory.js +3 -19
- package/build/__test__/cog.image.test.d.ts +1 -0
- package/build/__test__/cog.image.test.d.ts.map +1 -0
- package/build/__test__/cog.image.test.js +0 -1
- package/build/__test__/cog.read.test.d.ts +1 -0
- package/build/__test__/cog.read.test.d.ts.map +1 -0
- package/build/__test__/cog.read.test.js +81 -2
- package/build/__test__/example.d.ts +1 -0
- package/build/__test__/example.d.ts.map +1 -0
- package/build/__test__/example.js +0 -1
- package/build/const/index.d.ts +1 -0
- package/build/const/index.d.ts.map +1 -0
- package/build/const/index.js +0 -1
- package/build/const/tiff.endian.d.ts +1 -0
- package/build/const/tiff.endian.d.ts.map +1 -0
- package/build/const/tiff.endian.js +0 -1
- package/build/const/tiff.mime.d.ts +1 -0
- package/build/const/tiff.mime.d.ts.map +1 -0
- package/build/const/tiff.mime.js +0 -1
- package/build/const/tiff.tag.id.d.ts +16 -8
- package/build/const/tiff.tag.id.d.ts.map +1 -0
- package/build/const/tiff.tag.id.js +10 -3
- package/build/const/tiff.tag.value.d.ts +1 -0
- package/build/const/tiff.tag.value.d.ts.map +1 -0
- package/build/const/tiff.tag.value.js +0 -1
- package/build/const/tiff.version.d.ts +1 -0
- package/build/const/tiff.version.d.ts.map +1 -0
- package/build/const/tiff.version.js +0 -1
- package/build/index.d.ts +4 -2
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2 -4
- package/build/read/data.view.offset.d.ts +1 -0
- package/build/read/data.view.offset.d.ts.map +1 -0
- package/build/read/data.view.offset.js +0 -1
- package/build/read/endian.d.ts +2 -0
- package/build/read/endian.d.ts.map +1 -0
- package/build/read/endian.js +5 -0
- package/build/read/tiff.gdal.d.ts +1 -0
- package/build/read/tiff.gdal.d.ts.map +1 -0
- package/build/read/tiff.gdal.js +1 -9
- package/build/read/tiff.ifd.config.d.ts +1 -0
- package/build/read/tiff.ifd.config.d.ts.map +1 -0
- package/build/read/tiff.ifd.config.js +0 -1
- package/build/read/tiff.tag.d.ts +2 -1
- package/build/read/tiff.tag.d.ts.map +1 -0
- package/build/read/tiff.tag.factory.d.ts +15 -1
- package/build/read/tiff.tag.factory.d.ts.map +1 -0
- package/build/read/tiff.tag.factory.js +60 -4
- package/build/read/tiff.tag.js +0 -1
- package/build/read/tiff.value.reader.d.ts +1 -0
- package/build/read/tiff.value.reader.d.ts.map +1 -0
- package/build/read/tiff.value.reader.js +0 -1
- package/build/source.d.ts +4 -1
- package/build/source.d.ts.map +1 -0
- package/build/source.js +0 -1
- package/build/tiff.d.ts +12 -3
- package/build/tiff.d.ts.map +1 -0
- package/build/tiff.image.d.ts +11 -2
- package/build/tiff.image.d.ts.map +1 -0
- package/build/tiff.image.js +51 -69
- package/build/tiff.js +28 -74
- package/build/util/bytes.d.ts +1 -0
- package/build/util/bytes.d.ts.map +1 -0
- package/build/util/bytes.js +0 -1
- package/build/util/util.hex.d.ts +1 -0
- package/build/util/util.hex.d.ts.map +1 -0
- package/build/util/util.hex.js +0 -1
- package/build/vector.d.ts +1 -0
- package/build/vector.d.ts.map +1 -0
- package/build/vector.js +0 -1
- package/package.json +2 -2
- package/src/__benchmark__/cog.read.benchmark.ts +4 -2
- package/src/__benchmark__/source.file.ts +3 -1
- package/src/__benchmark__/source.memory.ts +2 -2
- package/src/__test__/cog.image.test.ts +1 -1
- package/src/__test__/cog.read.test.ts +107 -2
- package/src/const/tiff.tag.id.ts +16 -8
- package/src/index.ts +14 -11
- package/src/read/endian.ts +6 -0
- package/src/read/tiff.tag.factory.ts +73 -3
- package/src/read/tiff.tag.ts +1 -1
- package/src/source.ts +1 -1
- package/src/tiff.image.ts +40 -26
- package/src/tiff.ts +18 -4
- package/tsconfig.json +1 -2
- package/build/__benchmark__/cog.read.benchmark.js.map +0 -1
- package/build/__benchmark__/source.file.js.map +0 -1
- package/build/__benchmark__/source.memory.js.map +0 -1
- package/build/__test__/cog.image.test.js.map +0 -1
- package/build/__test__/cog.read.test.js.map +0 -1
- package/build/__test__/example.js.map +0 -1
- package/build/const/index.js.map +0 -1
- package/build/const/tiff.endian.js.map +0 -1
- package/build/const/tiff.mime.js.map +0 -1
- package/build/const/tiff.tag.id.js.map +0 -1
- package/build/const/tiff.tag.value.js.map +0 -1
- package/build/const/tiff.version.js.map +0 -1
- package/build/index.js.map +0 -1
- package/build/read/data.view.offset.js.map +0 -1
- package/build/read/tiff.gdal.js.map +0 -1
- package/build/read/tiff.ifd.config.js.map +0 -1
- package/build/read/tiff.tag.factory.js.map +0 -1
- package/build/read/tiff.tag.js.map +0 -1
- package/build/read/tiff.value.reader.js.map +0 -1
- package/build/source.js.map +0 -1
- package/build/tiff.image.js.map +0 -1
- package/build/tiff.js.map +0 -1
- package/build/util/bytes.js.map +0 -1
- package/build/util/util.hex.js.map +0 -1
- package/build/vector.js.map +0 -1
package/build/util/bytes.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export declare enum ByteSize {
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function getUint64(view: DataView, offset: number, isLittleEndian: boolean): number;
|
|
19
19
|
export declare function getUint(view: DataView, offset: number, bs: ByteSize, isLittleEndian: boolean): number;
|
|
20
|
+
//# sourceMappingURL=bytes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytes.d.ts","sourceRoot":"","sources":["../../src/util/bytes.ts"],"names":[],"mappings":"AAAA,oBAAY,aAAa;IACvB,MAAM,IAAI;IACV,OAAO,IAAI;CACZ;AAED,oBAAY,QAAQ;IAClB,MAAM,IAAI;IACV,MAAM,IAAI;IACV,MAAM,IAAI;IACV,KAAK,IAAI;CACV;AAID;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,CAazF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,CAWrG"}
|
package/build/util/bytes.js
CHANGED
package/build/util/util.hex.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.hex.d.ts","sourceRoot":"","sources":["../../src/util/util.hex.ts"],"names":[],"mappings":"AAAA;;;;;;;;IAQI;AACJ,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,SAAI,EAAE,MAAM,UAAO,GAAG,MAAM,CAIrE"}
|
package/build/util/util.hex.js
CHANGED
package/build/vector.d.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vector.d.ts","sourceRoot":"","sources":["../src/vector.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,KAAK;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK,EAAE,IAAI;CAAG;AACnD,MAAM,WAAW,MAAO,SAAQ,KAAK;IACnC,CAAC,EAAE,MAAM,CAAC;CACX"}
|
package/build/vector.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cogeotiff/core",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.3.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/blacha/cogeotiff.git",
|
|
@@ -23,5 +23,5 @@
|
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
|
-
"gitHead": "
|
|
26
|
+
"gitHead": "82b82e9d9f8996dfb0cb48827c143e134acc9865"
|
|
27
27
|
}
|
|
@@ -4,6 +4,7 @@ import { TiffTag } from '../index.js';
|
|
|
4
4
|
import { Tiff } from '../tiff.js';
|
|
5
5
|
import { SourceMemory } from './source.memory.js';
|
|
6
6
|
|
|
7
|
+
Tiff.DefaultReadSize = 64 * 1024;
|
|
7
8
|
// console.log = console.trace;
|
|
8
9
|
/** Read a tile from every image inside of a tiff 300 tiles read */
|
|
9
10
|
async function main(): Promise<void> {
|
|
@@ -18,9 +19,10 @@ async function main(): Promise<void> {
|
|
|
18
19
|
// 6 images
|
|
19
20
|
for (const img of tiff.images) await img.getTile(0, 0);
|
|
20
21
|
|
|
22
|
+
const img = tiff.images[0];
|
|
21
23
|
// Force loading all the byte arrays in which benchmarks the bulk array loading
|
|
22
|
-
await
|
|
23
|
-
await
|
|
24
|
+
await img.fetch(TiffTag.TileByteCounts);
|
|
25
|
+
await img.fetch(TiffTag.TileOffsets);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -9,6 +9,7 @@ const gunzipP = promisify(gunzip);
|
|
|
9
9
|
export class TestFileSource implements Source {
|
|
10
10
|
url: URL;
|
|
11
11
|
data: Promise<Buffer>;
|
|
12
|
+
fetches: { offset: number; length: number }[] = [];
|
|
12
13
|
|
|
13
14
|
constructor(fileName: URL) {
|
|
14
15
|
this.url = fileName;
|
|
@@ -20,7 +21,8 @@ export class TestFileSource implements Source {
|
|
|
20
21
|
|
|
21
22
|
async fetch(offset: number, length: number): Promise<ArrayBuffer> {
|
|
22
23
|
const fileData = await this.data;
|
|
23
|
-
|
|
24
|
+
this.fetches.push({ offset, length });
|
|
25
|
+
return fileData.buffer.slice(fileData.byteOffset + offset, fileData.byteOffset + offset + length) as ArrayBuffer;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
get size(): Promise<number> {
|
|
@@ -7,8 +7,8 @@ export class SourceMemory implements Source {
|
|
|
7
7
|
|
|
8
8
|
static toArrayBuffer(buf: Buffer | Uint8Array | ArrayBuffer): ArrayBuffer {
|
|
9
9
|
if (buf instanceof ArrayBuffer) return buf;
|
|
10
|
-
if (buf.byteLength === buf.buffer.byteLength) return buf.buffer;
|
|
11
|
-
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
10
|
+
if (buf.byteLength === buf.buffer.byteLength) return buf.buffer as ArrayBuffer;
|
|
11
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
constructor(bytes: Buffer | Uint8Array | ArrayBuffer) {
|
|
@@ -103,7 +103,7 @@ describe('Cog.Big', () => {
|
|
|
103
103
|
|
|
104
104
|
it('should read using a memory source', async () => {
|
|
105
105
|
const bytes = await fs.readFile(new URL('../../data/sparse.tiff', import.meta.url));
|
|
106
|
-
const source = new SourceMemory(bytes.buffer);
|
|
106
|
+
const source = new SourceMemory(bytes.buffer as ArrayBuffer);
|
|
107
107
|
const cog = new Tiff(source);
|
|
108
108
|
await cog.init();
|
|
109
109
|
|
|
@@ -7,7 +7,7 @@ import { SourceMemory } from '../__benchmark__/source.memory.js';
|
|
|
7
7
|
import { TiffMimeType } from '../const/tiff.mime.js';
|
|
8
8
|
import { Photometric, SampleFormat } from '../const/tiff.tag.id.js';
|
|
9
9
|
import { TiffVersion } from '../const/tiff.version.js';
|
|
10
|
-
import { TiffTag, TiffTagGeo } from '../index.js';
|
|
10
|
+
import { TagOffset, TiffTag, TiffTagGeo } from '../index.js';
|
|
11
11
|
import { Tiff } from '../tiff.js';
|
|
12
12
|
|
|
13
13
|
function validate(tif: Tiff): void {
|
|
@@ -30,6 +30,8 @@ describe('CogRead', () => {
|
|
|
30
30
|
assert.equal(tiff.version, TiffVersion.Tiff);
|
|
31
31
|
assert.equal(tiff.images.length, 1);
|
|
32
32
|
const firstImage = tiff.images[0];
|
|
33
|
+
const byteCounts = await firstImage.fetch(TiffTag.TileByteCounts);
|
|
34
|
+
assert.deepEqual([...(byteCounts ?? [])], [511]);
|
|
33
35
|
|
|
34
36
|
assert.equal(firstImage.compression, 'application/zstd');
|
|
35
37
|
assert.equal(firstImage.isTiled(), true);
|
|
@@ -48,6 +50,14 @@ describe('CogRead', () => {
|
|
|
48
50
|
assert.equal(tiff.version, TiffVersion.BigTiff);
|
|
49
51
|
assert.equal(tiff.images[0].epsg, null);
|
|
50
52
|
validate(tiff);
|
|
53
|
+
|
|
54
|
+
const [byteCounts, tileOffsets] = await Promise.all([
|
|
55
|
+
tiff.images[0].fetch(TiffTag.TileByteCounts),
|
|
56
|
+
tiff.images[0].fetch(TiffTag.TileOffsets),
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
assert.deepEqual([...(byteCounts ?? [])], [196608]);
|
|
60
|
+
assert.deepEqual([...(tileOffsets ?? [])], [272]);
|
|
51
61
|
});
|
|
52
62
|
|
|
53
63
|
it('should fail reading a empty byte tiff', async () => {
|
|
@@ -87,6 +97,88 @@ describe('CogRead', () => {
|
|
|
87
97
|
assert.equal(tiff.images.length, 5);
|
|
88
98
|
});
|
|
89
99
|
|
|
100
|
+
it('should read the byte count array if it is loaded', async () => {
|
|
101
|
+
const source = new TestFileSource(new URL('../../data/rgba8_cog.tiff', import.meta.url));
|
|
102
|
+
const fetchSize = 16 * 1024;
|
|
103
|
+
|
|
104
|
+
const tiff = new Tiff(source);
|
|
105
|
+
tiff.defaultReadSize = fetchSize;
|
|
106
|
+
await tiff.init();
|
|
107
|
+
|
|
108
|
+
assert.equal(source.fetches.length, 1);
|
|
109
|
+
assert.equal(source.fetches[0].length, fetchSize);
|
|
110
|
+
|
|
111
|
+
const img = tiff.images[0];
|
|
112
|
+
const byteCounts = img.tags.get(TiffTag.TileByteCounts) as TagOffset;
|
|
113
|
+
const tileOffsets = img.tags.get(TiffTag.TileOffsets) as TagOffset;
|
|
114
|
+
assert.equal(source.fetches.length, 1);
|
|
115
|
+
|
|
116
|
+
assert.equal(byteCounts.type, 'offset');
|
|
117
|
+
assert.equal(byteCounts.isLoaded, true);
|
|
118
|
+
|
|
119
|
+
assert.equal(tileOffsets.type, 'offset');
|
|
120
|
+
assert.equal(tileOffsets.isLoaded, true);
|
|
121
|
+
|
|
122
|
+
const tile = await img.getTile(0, 0);
|
|
123
|
+
assert.equal(tile?.bytes.byteLength, byteCounts.value[0]);
|
|
124
|
+
assert.equal(source.fetches.length, 2);
|
|
125
|
+
assert.deepEqual(source.fetches[1], { offset: tileOffsets.value[0], length: byteCounts.value[0] });
|
|
126
|
+
|
|
127
|
+
// force the offset to be unloaded
|
|
128
|
+
byteCounts.isLoaded = false;
|
|
129
|
+
const oldValue = byteCounts.value;
|
|
130
|
+
byteCounts.value = [];
|
|
131
|
+
const tileB = await img.getTile(0, 0);
|
|
132
|
+
assert.equal(tileB?.bytes.byteLength, oldValue[0]);
|
|
133
|
+
assert.equal(source.fetches.length, 4);
|
|
134
|
+
|
|
135
|
+
// Read the tile offset then the tile
|
|
136
|
+
assert.deepEqual(source.fetches[2], { offset: tileOffsets.value[0] - 4, length: 4 });
|
|
137
|
+
assert.deepEqual(source.fetches[3], { offset: tileOffsets.value[0], length: oldValue[0] });
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it('should read the byte count array if it is loaded (BigTiff)', async () => {
|
|
141
|
+
const source = new TestFileSource(new URL('../../data/rgba8_cog_big.tiff', import.meta.url));
|
|
142
|
+
const fetchSize = 16 * 1024;
|
|
143
|
+
|
|
144
|
+
const tiff = new Tiff(source);
|
|
145
|
+
tiff.defaultReadSize = fetchSize;
|
|
146
|
+
await tiff.init();
|
|
147
|
+
|
|
148
|
+
assert.equal(source.fetches.length, 1);
|
|
149
|
+
assert.equal(source.fetches[0].length, fetchSize);
|
|
150
|
+
|
|
151
|
+
const img = tiff.images[0];
|
|
152
|
+
const byteCounts = img.tags.get(TiffTag.TileByteCounts) as TagOffset;
|
|
153
|
+
const tileOffsets = img.tags.get(TiffTag.TileOffsets) as TagOffset;
|
|
154
|
+
assert.equal(source.fetches.length, 1);
|
|
155
|
+
|
|
156
|
+
assert.equal(byteCounts.type, 'offset');
|
|
157
|
+
assert.equal(byteCounts.isLoaded, true);
|
|
158
|
+
assert.equal(byteCounts.view == null, true);
|
|
159
|
+
|
|
160
|
+
assert.equal(tileOffsets.type, 'offset');
|
|
161
|
+
assert.equal(tileOffsets.isLoaded, false);
|
|
162
|
+
assert.equal(tileOffsets.view == null, false);
|
|
163
|
+
|
|
164
|
+
const tile = await img.getTile(0, 0);
|
|
165
|
+
assert.equal(tile?.bytes.byteLength, byteCounts.value[0]);
|
|
166
|
+
assert.equal(source.fetches.length, 2);
|
|
167
|
+
assert.deepEqual(source.fetches[1], { offset: tileOffsets.value[0], length: byteCounts.value[0] });
|
|
168
|
+
|
|
169
|
+
// force the offset to be unloaded
|
|
170
|
+
byteCounts.isLoaded = false;
|
|
171
|
+
const oldValue = byteCounts.value;
|
|
172
|
+
byteCounts.value = [];
|
|
173
|
+
byteCounts.view = undefined;
|
|
174
|
+
const tileB = await img.getTile(0, 0);
|
|
175
|
+
assert.equal(tileB?.bytes.byteLength, oldValue[0]);
|
|
176
|
+
assert.equal(source.fetches.length, 4);
|
|
177
|
+
// Read the tile offset then the tile
|
|
178
|
+
assert.deepEqual(source.fetches[2], { offset: tileOffsets.value[0] - 4, length: 4 });
|
|
179
|
+
assert.deepEqual(source.fetches[3], { offset: tileOffsets.value[0], length: oldValue[0] });
|
|
180
|
+
});
|
|
181
|
+
|
|
90
182
|
it('should read ifds from anywhere in the file', async () => {
|
|
91
183
|
const source = new TestFileSource(new URL('../../data/DEM_BS28_2016_1000_1141.tif', import.meta.url));
|
|
92
184
|
const tiff = await Tiff.create(source);
|
|
@@ -109,7 +201,9 @@ describe('CogRead', () => {
|
|
|
109
201
|
|
|
110
202
|
assert.equal(im.valueGeo(TiffTagGeo.GTCitationGeoKey), 'NZGD2000 / New Zealand Transverse Mercator 2000');
|
|
111
203
|
assert.equal(im.valueGeo(TiffTagGeo.GeodeticCitationGeoKey), 'NZGD2000');
|
|
112
|
-
|
|
204
|
+
|
|
205
|
+
const stripCount = await im.fetch(TiffTag.StripByteCounts);
|
|
206
|
+
assert.deepEqual([...(stripCount ?? [])], [8064, 8064, 8064, 8064, 8064, 8064, 8064, 5040]);
|
|
113
207
|
});
|
|
114
208
|
|
|
115
209
|
it('should read sub array ifds', async () => {
|
|
@@ -167,5 +261,16 @@ describe('CogRead', () => {
|
|
|
167
261
|
const tiff = await Tiff.create(source);
|
|
168
262
|
assert.equal(tiff.images.length, 5);
|
|
169
263
|
assert.equal(tiff.images[0].epsg, 3857);
|
|
264
|
+
|
|
265
|
+
const [byteCounts, tileOffsets] = await Promise.all([
|
|
266
|
+
tiff.images[0].fetch(TiffTag.TileByteCounts),
|
|
267
|
+
tiff.images[0].fetch(TiffTag.TileOffsets),
|
|
268
|
+
]);
|
|
269
|
+
|
|
270
|
+
assert.deepEqual([...(byteCounts ?? [])], [64, 64, 68, 64, 64, 68, 64, 64, 68, 64, 64, 64, 64, 64, 64, 68]);
|
|
271
|
+
assert.deepEqual(
|
|
272
|
+
[...(tileOffsets ?? [])],
|
|
273
|
+
[797, 861, 925, 993, 1057, 1121, 1189, 1253, 1317, 1385, 1449, 1513, 1577, 1641, 1705, 1769],
|
|
274
|
+
);
|
|
170
275
|
});
|
|
171
276
|
});
|
package/src/const/tiff.tag.id.ts
CHANGED
|
@@ -86,6 +86,14 @@ export enum PlanarConfiguration {
|
|
|
86
86
|
Separate = 2,
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
export enum Predictor {
|
|
90
|
+
None = 1,
|
|
91
|
+
/** Horizontal differencing */
|
|
92
|
+
Horizontal = 2,
|
|
93
|
+
/** Floating point */
|
|
94
|
+
FloatingPoint = 3,
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
export enum SampleFormat {
|
|
90
98
|
/** Unsigned integer data */
|
|
91
99
|
Uint = 1,
|
|
@@ -417,13 +425,14 @@ export interface TiffTagType {
|
|
|
417
425
|
|
|
418
426
|
[TiffTag.TileWidth]: number;
|
|
419
427
|
[TiffTag.TileHeight]: number;
|
|
420
|
-
[TiffTag.TileOffsets]: number[];
|
|
421
|
-
[TiffTag.TileByteCounts]: number[];
|
|
428
|
+
[TiffTag.TileOffsets]: number[] | Uint32Array | Uint16Array;
|
|
429
|
+
[TiffTag.TileByteCounts]: number[] | Uint32Array | Uint16Array;
|
|
422
430
|
[TiffTag.JpegTables]: number[];
|
|
423
431
|
|
|
424
|
-
[TiffTag.StripByteCounts]: number[];
|
|
425
|
-
[TiffTag.StripOffsets]: number[];
|
|
432
|
+
[TiffTag.StripByteCounts]: number[] | Uint32Array | Uint16Array;
|
|
433
|
+
[TiffTag.StripOffsets]: number[] | Uint32Array | Uint16Array;
|
|
426
434
|
|
|
435
|
+
[TiffTag.SamplesPerPixel]: number;
|
|
427
436
|
[TiffTag.SampleFormat]: SampleFormat[];
|
|
428
437
|
[TiffTag.GdalMetadata]: string;
|
|
429
438
|
[TiffTag.GdalNoData]: string;
|
|
@@ -436,6 +445,7 @@ export interface TiffTagType {
|
|
|
436
445
|
|
|
437
446
|
[TiffTag.PlanarConfiguration]: PlanarConfiguration;
|
|
438
447
|
[TiffTag.Orientation]: Orientation;
|
|
448
|
+
[TiffTag.Predictor]: Predictor;
|
|
439
449
|
|
|
440
450
|
[TiffTag.LercParameters]: number[];
|
|
441
451
|
|
|
@@ -460,7 +470,6 @@ export interface TiffTagType {
|
|
|
460
470
|
[TiffTag.Model]: unknown;
|
|
461
471
|
[TiffTag.ResolutionUnit]: unknown;
|
|
462
472
|
[TiffTag.RowsPerStrip]: unknown;
|
|
463
|
-
[TiffTag.SamplesPerPixel]: unknown;
|
|
464
473
|
[TiffTag.Software]: unknown;
|
|
465
474
|
|
|
466
475
|
[TiffTag.Threshholding]: unknown;
|
|
@@ -478,7 +487,6 @@ export interface TiffTagType {
|
|
|
478
487
|
[TiffTag.Indexed]: unknown;
|
|
479
488
|
[TiffTag.PageName]: unknown;
|
|
480
489
|
[TiffTag.PageNumber]: unknown;
|
|
481
|
-
[TiffTag.Predictor]: unknown;
|
|
482
490
|
[TiffTag.PrimaryChromaticities]: unknown;
|
|
483
491
|
[TiffTag.ReferenceBlackWhite]: unknown;
|
|
484
492
|
[TiffTag.SMinSampleValue]: unknown;
|
|
@@ -751,7 +759,7 @@ export interface TiffTagGeoType {
|
|
|
751
759
|
/**
|
|
752
760
|
* EPSG Angular Units. exist between [9100, 9199]
|
|
753
761
|
*
|
|
754
|
-
* Taken from
|
|
762
|
+
* Taken from libgeotiff
|
|
755
763
|
*/
|
|
756
764
|
export enum AngularUnit {
|
|
757
765
|
Radian = 9101,
|
|
@@ -766,7 +774,7 @@ export enum AngularUnit {
|
|
|
766
774
|
/**
|
|
767
775
|
* ESPG Liner units exist between [9000, 9099]
|
|
768
776
|
*
|
|
769
|
-
* Taken from
|
|
777
|
+
* Taken from libgeotiff
|
|
770
778
|
*/
|
|
771
779
|
export enum LinearUnit {
|
|
772
780
|
Metre = 9001,
|
package/src/index.ts
CHANGED
|
@@ -1,17 +1,6 @@
|
|
|
1
1
|
export { TiffEndian } from './const/tiff.endian.js';
|
|
2
2
|
export { TiffCompressionMimeType as TiffCompression, TiffMimeType } from './const/tiff.mime.js';
|
|
3
3
|
export type { TiffTagGeoType, TiffTagType } from './const/tiff.tag.id.js';
|
|
4
|
-
export { TiffTag, TiffTagGeo } from './const/tiff.tag.id.js';
|
|
5
|
-
export { TiffTagValueType } from './const/tiff.tag.value.js';
|
|
6
|
-
export { TiffVersion } from './const/tiff.version.js';
|
|
7
|
-
export type { Tag, TagInline, TagLazy, TagOffset } from './read/tiff.tag.js';
|
|
8
|
-
export { getTiffTagSize } from './read/tiff.value.reader.js';
|
|
9
|
-
export type { Source } from './source.js';
|
|
10
|
-
export { TiffImage } from './tiff.image.js';
|
|
11
|
-
export { Tiff } from './tiff.js';
|
|
12
|
-
export { toHex } from './util/util.hex.js';
|
|
13
|
-
export type { BoundingBox, Point, Size, Vector } from './vector.js';
|
|
14
|
-
|
|
15
4
|
// Tag value constants
|
|
16
5
|
export {
|
|
17
6
|
AngularUnit,
|
|
@@ -22,7 +11,21 @@ export {
|
|
|
22
11
|
Orientation,
|
|
23
12
|
Photometric,
|
|
24
13
|
PlanarConfiguration,
|
|
14
|
+
Predictor,
|
|
25
15
|
RasterTypeKey,
|
|
26
16
|
SampleFormat,
|
|
27
17
|
SubFileType,
|
|
18
|
+
TiffTag,
|
|
19
|
+
TiffTagGeo,
|
|
28
20
|
} from './const/tiff.tag.id.js';
|
|
21
|
+
export { TiffTagValueType } from './const/tiff.tag.value.js';
|
|
22
|
+
export { TiffVersion } from './const/tiff.version.js';
|
|
23
|
+
export type { Tag, TagInline, TagLazy, TagOffset } from './read/tiff.tag.js';
|
|
24
|
+
export { getTiffTagSize } from './read/tiff.value.reader.js';
|
|
25
|
+
export type { Source } from './source.js';
|
|
26
|
+
export type { TiffImageTileCount } from './tiff.image.js';
|
|
27
|
+
export { TiffImage } from './tiff.image.js';
|
|
28
|
+
export type { TiffCreationOptions } from './tiff.js';
|
|
29
|
+
export { Tiff } from './tiff.js';
|
|
30
|
+
export { toHex } from './util/util.hex.js';
|
|
31
|
+
export type { BoundingBox, Point, Size, Vector } from './vector.js';
|
|
@@ -5,6 +5,7 @@ import type { Tiff } from '../tiff.js';
|
|
|
5
5
|
import { getUint, getUint64 } from '../util/bytes.js';
|
|
6
6
|
import type { DataViewOffset } from './data.view.offset.js';
|
|
7
7
|
import { hasBytes } from './data.view.offset.js';
|
|
8
|
+
import { isLittleEndian } from './endian.js';
|
|
8
9
|
import type { Tag, TagLazy, TagOffset } from './tiff.tag.js';
|
|
9
10
|
import { getTiffTagSize } from './tiff.value.reader.js';
|
|
10
11
|
|
|
@@ -57,6 +58,42 @@ function readTagValue(
|
|
|
57
58
|
}
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Convert a tiff tag value to a typed array if the local endian matches the tiff endian
|
|
63
|
+
*
|
|
64
|
+
* @param tiff
|
|
65
|
+
* @param bytes
|
|
66
|
+
* @param offset Offset in the data view to read from
|
|
67
|
+
* @param length Number of bytes to read
|
|
68
|
+
* @param type type of tiff tag
|
|
69
|
+
* @returns the value if the type is a typed array and the endianness matches otherwise null
|
|
70
|
+
*/
|
|
71
|
+
export function readTypedValue<T>(
|
|
72
|
+
tiff: Tiff,
|
|
73
|
+
bytes: DataView,
|
|
74
|
+
offset: number,
|
|
75
|
+
length: number,
|
|
76
|
+
type: TiffTagValueType,
|
|
77
|
+
): T | null {
|
|
78
|
+
switch (type) {
|
|
79
|
+
case TiffTagValueType.Uint8:
|
|
80
|
+
return new Uint8Array(
|
|
81
|
+
bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length),
|
|
82
|
+
) as unknown as T;
|
|
83
|
+
case TiffTagValueType.Uint16:
|
|
84
|
+
if (tiff.isLittleEndian !== isLittleEndian) return null;
|
|
85
|
+
return new Uint16Array(
|
|
86
|
+
bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length),
|
|
87
|
+
) as unknown as T;
|
|
88
|
+
case TiffTagValueType.Uint32:
|
|
89
|
+
if (tiff.isLittleEndian !== isLittleEndian) return null;
|
|
90
|
+
return new Uint32Array(
|
|
91
|
+
bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length),
|
|
92
|
+
) as unknown as T;
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
60
97
|
function readValue<T>(
|
|
61
98
|
tiff: Tiff,
|
|
62
99
|
tagId: TiffTag | undefined,
|
|
@@ -84,6 +121,17 @@ function readValue<T>(
|
|
|
84
121
|
) as unknown as T;
|
|
85
122
|
}
|
|
86
123
|
|
|
124
|
+
// TODO should we convert all tag values to typed arrays if possible?
|
|
125
|
+
if (
|
|
126
|
+
tagId === TiffTag.TileOffsets ||
|
|
127
|
+
tagId === TiffTag.TileByteCounts ||
|
|
128
|
+
tagId === TiffTag.StripOffsets ||
|
|
129
|
+
tagId === TiffTag.StripByteCounts
|
|
130
|
+
) {
|
|
131
|
+
const typedOutput = readTypedValue(tiff, bytes, offset, dataLength, type);
|
|
132
|
+
if (typedOutput) return typedOutput as unknown as T;
|
|
133
|
+
}
|
|
134
|
+
|
|
87
135
|
const output = [];
|
|
88
136
|
for (let i = 0; i < dataLength; i += typeSize) {
|
|
89
137
|
output.push(readTagValue(type, bytes, offset + i, tiff.isLittleEndian));
|
|
@@ -133,8 +181,17 @@ export function createTag(tiff: Tiff, view: DataViewOffset, offset: number): Tag
|
|
|
133
181
|
value: [],
|
|
134
182
|
tagOffset: offset,
|
|
135
183
|
};
|
|
136
|
-
|
|
137
|
-
if (
|
|
184
|
+
|
|
185
|
+
if (hasBytes(view, dataOffset, dataLength)) {
|
|
186
|
+
const val = readTypedValue(tiff, view, dataOffset - view.sourceOffset, dataLength, dataType);
|
|
187
|
+
if (val) {
|
|
188
|
+
tag.value = val as number[] | Uint32Array | Uint16Array;
|
|
189
|
+
tag.isLoaded = true;
|
|
190
|
+
} else {
|
|
191
|
+
setBytes(tag, view);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
138
195
|
return tag;
|
|
139
196
|
}
|
|
140
197
|
|
|
@@ -161,7 +218,7 @@ export async function fetchLazy<T>(tag: TagLazy<T>, tiff: Tiff): Promise<T> {
|
|
|
161
218
|
/**
|
|
162
219
|
* Fetch all the values from a {@link TagOffset}
|
|
163
220
|
*/
|
|
164
|
-
export async function fetchAllOffsets(tiff: Tiff, tag: TagOffset): Promise<
|
|
221
|
+
export async function fetchAllOffsets(tiff: Tiff, tag: TagOffset): Promise<TagOffset['value']> {
|
|
165
222
|
const dataTypeSize = getTiffTagSize(tag.dataType);
|
|
166
223
|
|
|
167
224
|
if (tag.view == null) {
|
|
@@ -171,6 +228,7 @@ export async function fetchAllOffsets(tiff: Tiff, tag: TagOffset): Promise<numbe
|
|
|
171
228
|
}
|
|
172
229
|
|
|
173
230
|
tag.value = readValue(tiff, tag.id, tag.view, 0, tag.dataType, tag.count);
|
|
231
|
+
tag.view = undefined;
|
|
174
232
|
tag.isLoaded = true;
|
|
175
233
|
return tag.value;
|
|
176
234
|
}
|
|
@@ -204,3 +262,15 @@ export async function getValueAt(tiff: Tiff, tag: TagOffset, index: number): Pro
|
|
|
204
262
|
tag.value[index] = value;
|
|
205
263
|
return value;
|
|
206
264
|
}
|
|
265
|
+
|
|
266
|
+
export function getValueAtSync(tiff: Tiff, tag: TagOffset, index: number): number | null {
|
|
267
|
+
if (index > tag.count || index < 0) throw new Error('TagOffset: out of bounds :' + index);
|
|
268
|
+
if (tag.value[index] != null) return tag.value[index];
|
|
269
|
+
if (tag.view == null) return null;
|
|
270
|
+
const dataTypeSize = getTiffTagSize(tag.dataType);
|
|
271
|
+
|
|
272
|
+
const value = readValue(tiff, undefined, tag.view, index * dataTypeSize, tag.dataType, 1);
|
|
273
|
+
if (typeof value !== 'number') throw new Error('Value is not a number');
|
|
274
|
+
tag.value[index] = value;
|
|
275
|
+
return value;
|
|
276
|
+
}
|
package/src/read/tiff.tag.ts
CHANGED
|
@@ -38,7 +38,7 @@ export interface TagInline<T> extends TagBase {
|
|
|
38
38
|
export interface TagOffset extends TagBase {
|
|
39
39
|
type: 'offset';
|
|
40
40
|
/** Values of the offsets this is a sparse array unless @see {TagOffset.isLoaded} is true */
|
|
41
|
-
value: number[];
|
|
41
|
+
value: number[] | Uint32Array | Uint16Array;
|
|
42
42
|
/** Have all the values been read */
|
|
43
43
|
isLoaded: boolean;
|
|
44
44
|
/** Raw buffer of the values for lazy decoding, as reading 100,000s of uint64s can take quite a long time */
|
package/src/source.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface Source {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/** Fetch bytes from a source */
|
|
16
|
-
fetch(offset: number, length?: number): Promise<ArrayBuffer>;
|
|
16
|
+
fetch(offset: number, length?: number, options?: { signal?: AbortSignal }): Promise<ArrayBuffer>;
|
|
17
17
|
|
|
18
18
|
/** Optionally close the source, useful for sources that have open connections of file descriptors */
|
|
19
19
|
close?(): Promise<void>;
|