@cogeotiff/core 8.0.1 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/build/__benchmark__/cog.read.benchmark.js +4 -0
- package/build/__benchmark__/cog.read.benchmark.js.map +1 -1
- package/build/__test__/cog.read.test.js +15 -1
- package/build/__test__/cog.read.test.js.map +1 -1
- package/build/cog.tiff.image.d.ts +44 -16
- package/build/cog.tiff.image.js +98 -70
- package/build/cog.tiff.image.js.map +1 -1
- package/build/cog.tiff.js +11 -1
- package/build/cog.tiff.js.map +1 -1
- package/build/const/index.d.ts +1 -1
- package/build/const/index.js +1 -1
- package/build/const/index.js.map +1 -1
- package/build/const/tiff.endian.d.ts +2 -1
- package/build/const/tiff.endian.js +2 -1
- package/build/const/tiff.endian.js.map +1 -1
- package/build/const/tiff.tag.id.d.ts +2 -2
- package/build/const/tiff.tag.id.js +154 -154
- package/build/const/tiff.tag.id.js.map +1 -1
- package/build/index.d.ts +3 -3
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/read/tiff.gdal.d.ts +4 -4
- package/build/read/tiff.gdal.js +4 -4
- package/build/read/tiff.tag.d.ts +8 -5
- package/build/read/tiff.tag.factory.d.ts +7 -1
- package/build/read/tiff.tag.factory.js +27 -8
- package/build/read/tiff.tag.factory.js.map +1 -1
- package/build/source.d.ts +12 -0
- package/package.json +2 -2
- package/src/__benchmark__/cog.read.benchmark.ts +5 -0
- package/src/__test__/cog.read.test.ts +18 -1
- package/src/cog.tiff.image.ts +106 -80
- package/src/cog.tiff.ts +17 -4
- package/src/const/index.ts +1 -1
- package/src/const/tiff.endian.ts +2 -1
- package/src/const/tiff.tag.id.ts +2 -2
- package/src/index.ts +3 -3
- package/src/read/tiff.gdal.ts +4 -4
- package/src/read/tiff.tag.factory.ts +32 -11
- package/src/read/tiff.tag.ts +8 -5
- package/src/source.ts +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [8.1.0](https://github.com/blacha/cogeotiff/compare/core-v8.0.2...core-v8.1.0) (2023-08-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **cli:** fetch all tiff tags with --fetch-tags ([#1155](https://github.com/blacha/cogeotiff/issues/1155)) ([4067751](https://github.com/blacha/cogeotiff/commit/406775184eed18ab10ae2816ecbedea9706b20f5))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **core:** do not read past the end of a file ([#1152](https://github.com/blacha/cogeotiff/issues/1152)) ([fd0be56](https://github.com/blacha/cogeotiff/commit/fd0be56eee6944239502cd8ffd7a6fe89e76b984))
|
|
14
|
+
|
|
15
|
+
## [8.0.2](https://github.com/blacha/cogeotiff/compare/core-v8.0.1...core-v8.0.2) (2023-08-05)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **core:** expose TiffTag and TiffTagGeo ([d538bdc](https://github.com/blacha/cogeotiff/commit/d538bdc833bf76ba8d730a1062156916715585b4))
|
|
21
|
+
|
|
3
22
|
## [8.0.1](https://github.com/blacha/cogeotiff/compare/core-v8.0.0...core-v8.0.1) (2023-08-05)
|
|
4
23
|
|
|
5
24
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'fs/promises';
|
|
2
2
|
import { CogTiff } from '../cog.tiff.js';
|
|
3
3
|
import { SourceMemory } from './source.memory.js';
|
|
4
|
+
import { TiffTag } from '../index.js';
|
|
4
5
|
// console.log = console.trace;
|
|
5
6
|
/** Read a tile from every image inside of a tiff 300 tiles read */
|
|
6
7
|
async function main() {
|
|
@@ -14,6 +15,9 @@ async function main() {
|
|
|
14
15
|
// 6 images
|
|
15
16
|
for (const img of tiff.images)
|
|
16
17
|
await img.getTile(0, 0);
|
|
18
|
+
// Force loading all the byte arrays in which benchmarks the bulk array loading
|
|
19
|
+
await tiff.images[0].fetch(TiffTag.TileByteCounts);
|
|
20
|
+
await tiff.images[0].fetch(TiffTag.TileOffsets);
|
|
17
21
|
}
|
|
18
22
|
}
|
|
19
23
|
main();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cog.read.benchmark.js","sourceRoot":"","sources":["../../src/__benchmark__/cog.read.benchmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cog.read.benchmark.js","sourceRoot":"","sources":["../../src/__benchmark__/cog.read.benchmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,+BAA+B;AAC/B,mEAAmE;AACnE,KAAK,UAAU,IAAI;IACjB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;IACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAK,EAAE,CAAC,EAAE,EAAE;QAC9B,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAElC,WAAW;QACX,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvD,+EAA+E;QAC/E,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACnD,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;KACjD;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { describe, it } from 'node:test';
|
|
3
|
+
import { TestFileSource } from '../__benchmark__/source.file.js';
|
|
3
4
|
import { CogTiff } from '../cog.tiff.js';
|
|
4
5
|
import { TiffMimeType } from '../const/tiff.mime.js';
|
|
5
|
-
import { TestFileSource } from '../__benchmark__/source.file.js';
|
|
6
6
|
import { TiffVersion } from '../const/tiff.version.js';
|
|
7
|
+
import { TiffTag, TiffTagGeo } from '../index.js';
|
|
7
8
|
function validate(tif) {
|
|
8
9
|
assert.equal(tif.images.length, 5);
|
|
9
10
|
const [firstTif] = tif.images;
|
|
@@ -50,5 +51,18 @@ describe('CogRead', () => {
|
|
|
50
51
|
await tiff.init();
|
|
51
52
|
assert.equal(tiff.images.length, 5);
|
|
52
53
|
});
|
|
54
|
+
it('should read ifds from anywhere in the file', async () => {
|
|
55
|
+
const source = new TestFileSource(new URL('../../data/DEM_BS28_2016_1000_1141.tif', import.meta.url));
|
|
56
|
+
const tiff = await CogTiff.create(source);
|
|
57
|
+
assert.equal(tiff.images.length, 1);
|
|
58
|
+
const im = tiff.images[0];
|
|
59
|
+
assert.equal(im.isGeoTagsLoaded, true);
|
|
60
|
+
assert.equal(im.epsg, 2193);
|
|
61
|
+
assert.equal(im.compression, TiffMimeType.None);
|
|
62
|
+
assert.equal(im.isTiled(), false);
|
|
63
|
+
assert.equal(im.tagsGeo.get(TiffTagGeo.GTCitationGeoKey), 'NZGD2000 / New Zealand Transverse Mercator 2000');
|
|
64
|
+
assert.equal(im.tagsGeo.get(TiffTagGeo.GeogCitationGeoKey), 'NZGD2000');
|
|
65
|
+
assert.deepEqual(await im.fetch(TiffTag.StripByteCounts), [8064, 8064, 8064, 8064, 8064, 8064, 8064, 5040]);
|
|
66
|
+
});
|
|
53
67
|
});
|
|
54
68
|
//# sourceMappingURL=cog.read.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cog.read.test.js","sourceRoot":"","sources":["../../src/__test__/cog.read.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"cog.read.test.js","sourceRoot":"","sources":["../../src/__test__/cog.read.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { CogTiff } from './cog.tiff.js';
|
|
2
2
|
import { TiffMimeType } from './const/tiff.mime.js';
|
|
3
|
-
import {
|
|
3
|
+
import { TiffTag, TiffTagGeo } from './const/tiff.tag.id.js';
|
|
4
4
|
import { Tag, TagOffset } from './read/tiff.tag.js';
|
|
5
5
|
import { BoundingBox, Size } from './vector.js';
|
|
6
|
+
/** Invalid EPSG code */
|
|
6
7
|
export declare const InvalidProjectionCode = 32767;
|
|
7
8
|
/**
|
|
8
9
|
* Number of tiles used inside this image
|
|
@@ -14,7 +15,7 @@ export interface CogTiffImageTiledCount {
|
|
|
14
15
|
y: number;
|
|
15
16
|
}
|
|
16
17
|
/** Tags that are commonly accessed for geotiffs */
|
|
17
|
-
export declare const ImportantTags: Set<
|
|
18
|
+
export declare const ImportantTags: Set<TiffTag>;
|
|
18
19
|
/**
|
|
19
20
|
* Size of a individual tile
|
|
20
21
|
*/
|
|
@@ -26,15 +27,21 @@ export interface CogTiffImageTileSize {
|
|
|
26
27
|
}
|
|
27
28
|
export declare class CogTiffImage {
|
|
28
29
|
/** All IFD tags that have been read for the image */
|
|
29
|
-
tags: Map<
|
|
30
|
-
/**
|
|
30
|
+
tags: Map<TiffTag, Tag>;
|
|
31
|
+
/**
|
|
32
|
+
* Id of the tif image, generally the image index inside the tif
|
|
33
|
+
* where 0 is the root image, and every sub image is +1
|
|
34
|
+
*
|
|
35
|
+
* @example 0, 1, 2
|
|
36
|
+
*/
|
|
31
37
|
id: number;
|
|
38
|
+
/** Reference to the TIFF that owns this image */
|
|
32
39
|
tiff: CogTiff;
|
|
33
40
|
/** Has loadGeoTiffTags been called */
|
|
34
41
|
isGeoTagsLoaded: boolean;
|
|
35
42
|
/** Sub tags stored in TiffTag.GeoKeyDirectory */
|
|
36
|
-
tagsGeo: Map<
|
|
37
|
-
constructor(tiff: CogTiff, id: number, tags: Map<
|
|
43
|
+
tagsGeo: Map<TiffTagGeo, string | number>;
|
|
44
|
+
constructor(tiff: CogTiff, id: number, tags: Map<TiffTag, Tag>);
|
|
38
45
|
/**
|
|
39
46
|
* Force loading of important tags if they have not already been loaded
|
|
40
47
|
*
|
|
@@ -42,22 +49,34 @@ export declare class CogTiffImage {
|
|
|
42
49
|
*/
|
|
43
50
|
init(loadGeoTags?: boolean): Promise<void>;
|
|
44
51
|
/**
|
|
45
|
-
* Get the value of a TiffTag if it
|
|
52
|
+
* Get the value of a TiffTag if it has been loaded, null otherwise
|
|
53
|
+
*
|
|
54
|
+
* if the value is not loaded @see {CogTiffImage.fetch}
|
|
55
|
+
* @returns value if loaded, null otherwise
|
|
46
56
|
*/
|
|
47
|
-
value<T>(tag:
|
|
57
|
+
value<T>(tag: TiffTag): T | null;
|
|
48
58
|
/**
|
|
49
59
|
* Load and unpack the GeoKeyDirectory
|
|
60
|
+
*
|
|
61
|
+
* @see {TiffTag.GeoKeyDirectory}
|
|
50
62
|
*/
|
|
51
63
|
loadGeoTiffTags(): Promise<void>;
|
|
52
64
|
/**
|
|
53
|
-
* Get the associated
|
|
65
|
+
* Get the associated TiffTagGeo
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* image.valueGeo(TiffTagGeo.GTRasterTypeGeoKey)
|
|
70
|
+
* ```
|
|
71
|
+
* @throws if {@link loadGeoTiffTags} has not been called
|
|
54
72
|
*/
|
|
55
|
-
valueGeo(tag:
|
|
73
|
+
valueGeo(tag: TiffTagGeo): string | number | undefined;
|
|
56
74
|
/**
|
|
57
75
|
* Load a tag, if it is not currently loaded, fetch the required data for the tag.
|
|
76
|
+
*
|
|
58
77
|
* @param tag tag to fetch
|
|
59
78
|
*/
|
|
60
|
-
fetch<T>(tag:
|
|
79
|
+
fetch<T>(tag: TiffTag): Promise<T | null>;
|
|
61
80
|
/**
|
|
62
81
|
* Get the origin point for the image
|
|
63
82
|
*
|
|
@@ -81,7 +100,7 @@ export declare class CogTiffImage {
|
|
|
81
100
|
/**
|
|
82
101
|
* Get the compression used by the tile
|
|
83
102
|
*
|
|
84
|
-
* @see TiffCompression
|
|
103
|
+
* @see {@link TiffCompression}
|
|
85
104
|
*
|
|
86
105
|
* @returns Compression type eg webp
|
|
87
106
|
*/
|
|
@@ -128,7 +147,9 @@ export declare class CogTiffImage {
|
|
|
128
147
|
get stripCount(): number;
|
|
129
148
|
getTileBounds(x: number, y: number): BoundingBox;
|
|
130
149
|
/**
|
|
131
|
-
* Read a strip into a
|
|
150
|
+
* Read a strip into a ArrayBuffer
|
|
151
|
+
*
|
|
152
|
+
* Image has to be striped see {@link stripCount}
|
|
132
153
|
*
|
|
133
154
|
* @param index Strip index to read
|
|
134
155
|
*/
|
|
@@ -141,9 +162,9 @@ export declare class CogTiffImage {
|
|
|
141
162
|
/** Read image bytes at the given offset */
|
|
142
163
|
private getBytes;
|
|
143
164
|
/**
|
|
144
|
-
* Load
|
|
165
|
+
* Load a tile into a ArrayBuffer
|
|
145
166
|
*
|
|
146
|
-
* This will also apply the JPEG compression tables
|
|
167
|
+
* if the tile compression is JPEG, This will also apply the JPEG compression tables to the resulting ArrayBuffer see {@link getJpegHeader}
|
|
147
168
|
*
|
|
148
169
|
* @param x Tile x offset
|
|
149
170
|
* @param y Tile y offset
|
|
@@ -155,13 +176,20 @@ export declare class CogTiffImage {
|
|
|
155
176
|
/**
|
|
156
177
|
* Does this tile exist in the tiff and does it actually have a value
|
|
157
178
|
*
|
|
158
|
-
* Sparse tiffs can have a lot of empty tiles,
|
|
179
|
+
* Sparse tiffs can have a lot of empty tiles, they set the tile size to `0 bytes` when the tile is empty
|
|
180
|
+
* this checks the tile byte size to validate if it actually has any data.
|
|
159
181
|
*
|
|
160
182
|
* @param x Tile x offset
|
|
161
183
|
* @param y Tile y offset
|
|
184
|
+
*
|
|
162
185
|
* @returns if the tile exists and has data
|
|
163
186
|
*/
|
|
164
187
|
hasTile(x: number, y: number): Promise<boolean>;
|
|
188
|
+
/**
|
|
189
|
+
* Load the offset and byteCount of a tile
|
|
190
|
+
* @param index index in the tile array
|
|
191
|
+
* @returns Offset and byteCount for the tile
|
|
192
|
+
*/
|
|
165
193
|
getTileSize(index: number): Promise<{
|
|
166
194
|
offset: number;
|
|
167
195
|
imageSize: number;
|
package/build/cog.tiff.image.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { getUint } from './util/bytes.js';
|
|
2
2
|
import { TiffCompression, TiffMimeType } from './const/tiff.mime.js';
|
|
3
|
-
import {
|
|
4
|
-
import { fetchLazy, getValueAt } from './read/tiff.tag.factory.js';
|
|
5
|
-
|
|
3
|
+
import { TiffTag, TiffTagGeo } from './const/tiff.tag.id.js';
|
|
4
|
+
import { fetchAllOffsets, fetchLazy, getValueAt } from './read/tiff.tag.factory.js';
|
|
5
|
+
/** Invalid EPSG code */
|
|
6
6
|
export const InvalidProjectionCode = 32767;
|
|
7
7
|
/** Tags that are commonly accessed for geotiffs */
|
|
8
8
|
export const ImportantTags = new Set([
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
TiffTag.Compression,
|
|
10
|
+
TiffTag.ImageHeight,
|
|
11
|
+
TiffTag.ImageWidth,
|
|
12
|
+
TiffTag.ModelPixelScale,
|
|
13
|
+
TiffTag.ModelTiePoint,
|
|
14
|
+
TiffTag.ModelTransformation,
|
|
15
|
+
TiffTag.TileHeight,
|
|
16
|
+
TiffTag.TileWidth,
|
|
17
|
+
TiffTag.GeoKeyDirectory,
|
|
18
|
+
TiffTag.GeoAsciiParams,
|
|
19
|
+
TiffTag.GeoDoubleParams,
|
|
20
|
+
TiffTag.TileOffsets,
|
|
21
21
|
]);
|
|
22
22
|
export class CogTiffImage {
|
|
23
23
|
constructor(tiff, id, tags) {
|
|
@@ -28,13 +28,19 @@ export class CogTiffImage {
|
|
|
28
28
|
writable: true,
|
|
29
29
|
value: void 0
|
|
30
30
|
});
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Id of the tif image, generally the image index inside the tif
|
|
33
|
+
* where 0 is the root image, and every sub image is +1
|
|
34
|
+
*
|
|
35
|
+
* @example 0, 1, 2
|
|
36
|
+
*/
|
|
32
37
|
Object.defineProperty(this, "id", {
|
|
33
38
|
enumerable: true,
|
|
34
39
|
configurable: true,
|
|
35
40
|
writable: true,
|
|
36
41
|
value: void 0
|
|
37
42
|
});
|
|
43
|
+
/** Reference to the TIFF that owns this image */
|
|
38
44
|
Object.defineProperty(this, "tiff", {
|
|
39
45
|
enumerable: true,
|
|
40
46
|
configurable: true,
|
|
@@ -66,26 +72,29 @@ export class CogTiffImage {
|
|
|
66
72
|
*/
|
|
67
73
|
async init(loadGeoTags = true) {
|
|
68
74
|
const requiredTags = [
|
|
69
|
-
this.fetch(
|
|
70
|
-
this.fetch(
|
|
71
|
-
this.fetch(
|
|
72
|
-
this.fetch(
|
|
73
|
-
this.fetch(
|
|
74
|
-
this.fetch(
|
|
75
|
-
this.fetch(
|
|
76
|
-
this.fetch(
|
|
75
|
+
this.fetch(TiffTag.Compression),
|
|
76
|
+
this.fetch(TiffTag.ImageHeight),
|
|
77
|
+
this.fetch(TiffTag.ImageWidth),
|
|
78
|
+
this.fetch(TiffTag.ModelPixelScale),
|
|
79
|
+
this.fetch(TiffTag.ModelTiePoint),
|
|
80
|
+
this.fetch(TiffTag.ModelTransformation),
|
|
81
|
+
this.fetch(TiffTag.TileHeight),
|
|
82
|
+
this.fetch(TiffTag.TileWidth),
|
|
77
83
|
];
|
|
78
84
|
if (loadGeoTags) {
|
|
79
|
-
requiredTags.push(this.fetch(
|
|
80
|
-
requiredTags.push(this.fetch(
|
|
81
|
-
requiredTags.push(this.fetch(
|
|
85
|
+
requiredTags.push(this.fetch(TiffTag.GeoKeyDirectory));
|
|
86
|
+
requiredTags.push(this.fetch(TiffTag.GeoAsciiParams));
|
|
87
|
+
requiredTags.push(this.fetch(TiffTag.GeoDoubleParams));
|
|
82
88
|
}
|
|
83
89
|
await Promise.all(requiredTags);
|
|
84
90
|
if (loadGeoTags)
|
|
85
91
|
await this.loadGeoTiffTags();
|
|
86
92
|
}
|
|
87
93
|
/**
|
|
88
|
-
* Get the value of a TiffTag if it
|
|
94
|
+
* Get the value of a TiffTag if it has been loaded, null otherwise
|
|
95
|
+
*
|
|
96
|
+
* if the value is not loaded @see {CogTiffImage.fetch}
|
|
97
|
+
* @returns value if loaded, null otherwise
|
|
89
98
|
*/
|
|
90
99
|
value(tag) {
|
|
91
100
|
const sourceTag = this.tags.get(tag);
|
|
@@ -97,12 +106,14 @@ export class CogTiffImage {
|
|
|
97
106
|
}
|
|
98
107
|
/**
|
|
99
108
|
* Load and unpack the GeoKeyDirectory
|
|
109
|
+
*
|
|
110
|
+
* @see {TiffTag.GeoKeyDirectory}
|
|
100
111
|
*/
|
|
101
112
|
async loadGeoTiffTags() {
|
|
102
113
|
// Already loaded
|
|
103
114
|
if (this.isGeoTagsLoaded)
|
|
104
115
|
return;
|
|
105
|
-
const sourceTag = this.tags.get(
|
|
116
|
+
const sourceTag = this.tags.get(TiffTag.GeoKeyDirectory);
|
|
106
117
|
if (sourceTag == null) {
|
|
107
118
|
this.isGeoTagsLoaded = true;
|
|
108
119
|
return;
|
|
@@ -110,9 +121,9 @@ export class CogTiffImage {
|
|
|
110
121
|
if (sourceTag.type === 'lazy' && sourceTag.value == null) {
|
|
111
122
|
// Load all the required keys
|
|
112
123
|
await Promise.all([
|
|
113
|
-
this.fetch(
|
|
114
|
-
this.fetch(
|
|
115
|
-
this.fetch(
|
|
124
|
+
this.fetch(TiffTag.GeoKeyDirectory),
|
|
125
|
+
this.fetch(TiffTag.GeoAsciiParams),
|
|
126
|
+
this.fetch(TiffTag.GeoDoubleParams),
|
|
116
127
|
]);
|
|
117
128
|
}
|
|
118
129
|
this.isGeoTagsLoaded = true;
|
|
@@ -123,26 +134,32 @@ export class CogTiffImage {
|
|
|
123
134
|
throw new Error('Invalid geo tags found');
|
|
124
135
|
for (let i = 4; i <= geoTags[3] * 4; i += 4) {
|
|
125
136
|
const key = geoTags[i];
|
|
126
|
-
const
|
|
137
|
+
const locationTagId = geoTags[i + 1];
|
|
127
138
|
const offset = geoTags[i + 3];
|
|
128
|
-
if (
|
|
139
|
+
if (locationTagId === 0) {
|
|
129
140
|
this.tagsGeo.set(key, offset);
|
|
130
141
|
continue;
|
|
131
142
|
}
|
|
132
|
-
const tag = this.tags.get(
|
|
143
|
+
const tag = this.tags.get(locationTagId);
|
|
133
144
|
if (tag == null || tag.value == null)
|
|
134
145
|
continue;
|
|
135
146
|
const count = geoTags[i + 2];
|
|
136
|
-
if (
|
|
137
|
-
this.tagsGeo.set(key, tag.value[offset + count - 1]);
|
|
138
|
-
}
|
|
139
|
-
else if (typeof tag.value === 'string') {
|
|
147
|
+
if (typeof tag.value === 'string') {
|
|
140
148
|
this.tagsGeo.set(key, tag.value.slice(offset, offset + count - 1).trim());
|
|
141
149
|
}
|
|
150
|
+
else {
|
|
151
|
+
throw new Error('Failed to extract GeoTiffTags');
|
|
152
|
+
}
|
|
142
153
|
}
|
|
143
154
|
}
|
|
144
155
|
/**
|
|
145
|
-
* Get the associated
|
|
156
|
+
* Get the associated TiffTagGeo
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* image.valueGeo(TiffTagGeo.GTRasterTypeGeoKey)
|
|
161
|
+
* ```
|
|
162
|
+
* @throws if {@link loadGeoTiffTags} has not been called
|
|
146
163
|
*/
|
|
147
164
|
valueGeo(tag) {
|
|
148
165
|
if (this.isGeoTagsLoaded === false)
|
|
@@ -151,6 +168,7 @@ export class CogTiffImage {
|
|
|
151
168
|
}
|
|
152
169
|
/**
|
|
153
170
|
* Load a tag, if it is not currently loaded, fetch the required data for the tag.
|
|
171
|
+
*
|
|
154
172
|
* @param tag tag to fetch
|
|
155
173
|
*/
|
|
156
174
|
async fetch(tag) {
|
|
@@ -163,6 +181,8 @@ export class CogTiffImage {
|
|
|
163
181
|
return fetchLazy(sourceTag, this.tiff);
|
|
164
182
|
if (sourceTag.isLoaded)
|
|
165
183
|
return sourceTag.value;
|
|
184
|
+
if (sourceTag.type === 'offset')
|
|
185
|
+
return fetchAllOffsets(this.tiff, sourceTag);
|
|
166
186
|
throw new Error('Cannot fetch:' + tag);
|
|
167
187
|
}
|
|
168
188
|
/**
|
|
@@ -171,27 +191,27 @@ export class CogTiffImage {
|
|
|
171
191
|
* @returns origin point of the image
|
|
172
192
|
*/
|
|
173
193
|
get origin() {
|
|
174
|
-
const tiePoints = this.value(
|
|
194
|
+
const tiePoints = this.value(TiffTag.ModelTiePoint);
|
|
175
195
|
if (tiePoints != null && tiePoints.length === 6) {
|
|
176
196
|
return [tiePoints[3], tiePoints[4], tiePoints[5]];
|
|
177
197
|
}
|
|
178
|
-
const modelTransformation = this.value(
|
|
198
|
+
const modelTransformation = this.value(TiffTag.ModelTransformation);
|
|
179
199
|
if (modelTransformation != null) {
|
|
180
200
|
return [modelTransformation[3], modelTransformation[7], modelTransformation[11]];
|
|
181
201
|
}
|
|
182
202
|
// If this is a sub image, use the origin from the top level image
|
|
183
|
-
if (this.value(
|
|
203
|
+
if (this.value(TiffTag.NewSubFileType) === 1 && this.id !== 0) {
|
|
184
204
|
return this.tiff.images[0].origin;
|
|
185
205
|
}
|
|
186
206
|
throw new Error('Image does not have a geo transformation.');
|
|
187
207
|
}
|
|
188
208
|
/** Is there enough geo information on this image to figure out where its actually located */
|
|
189
209
|
get isGeoLocated() {
|
|
190
|
-
const isImageLocated = this.value(
|
|
210
|
+
const isImageLocated = this.value(TiffTag.ModelPixelScale) != null || this.value(TiffTag.ModelTransformation) != null;
|
|
191
211
|
if (isImageLocated)
|
|
192
212
|
return true;
|
|
193
213
|
// If this is a sub image, use the isGeoLocated from the top level image
|
|
194
|
-
if (this.value(
|
|
214
|
+
if (this.value(TiffTag.NewSubFileType) === 1 && this.id !== 0)
|
|
195
215
|
return this.tiff.images[0].isGeoLocated;
|
|
196
216
|
return false;
|
|
197
217
|
}
|
|
@@ -201,16 +221,16 @@ export class CogTiffImage {
|
|
|
201
221
|
* @returns [x,y,z] pixel scale
|
|
202
222
|
*/
|
|
203
223
|
get resolution() {
|
|
204
|
-
const modelPixelScale = this.value(
|
|
224
|
+
const modelPixelScale = this.value(TiffTag.ModelPixelScale);
|
|
205
225
|
if (modelPixelScale != null) {
|
|
206
226
|
return [modelPixelScale[0], -modelPixelScale[1], modelPixelScale[2]];
|
|
207
227
|
}
|
|
208
|
-
const modelTransformation = this.value(
|
|
228
|
+
const modelTransformation = this.value(TiffTag.ModelTransformation);
|
|
209
229
|
if (modelTransformation != null) {
|
|
210
230
|
return [modelTransformation[0], modelTransformation[5], modelTransformation[10]];
|
|
211
231
|
}
|
|
212
232
|
// If this is a sub image, use the resolution from the top level image
|
|
213
|
-
if (this.value(
|
|
233
|
+
if (this.value(TiffTag.NewSubFileType) === 1 && this.id !== 0) {
|
|
214
234
|
const firstImg = this.tiff.images[0];
|
|
215
235
|
const [resX, resY, resZ] = firstImg.resolution;
|
|
216
236
|
const firstImgSize = firstImg.size;
|
|
@@ -241,12 +261,12 @@ export class CogTiffImage {
|
|
|
241
261
|
/**
|
|
242
262
|
* Get the compression used by the tile
|
|
243
263
|
*
|
|
244
|
-
* @see TiffCompression
|
|
264
|
+
* @see {@link TiffCompression}
|
|
245
265
|
*
|
|
246
266
|
* @returns Compression type eg webp
|
|
247
267
|
*/
|
|
248
268
|
get compression() {
|
|
249
|
-
const compression = this.value(
|
|
269
|
+
const compression = this.value(TiffTag.Compression);
|
|
250
270
|
if (compression == null || typeof compression !== 'number')
|
|
251
271
|
return null;
|
|
252
272
|
return TiffCompression[compression];
|
|
@@ -257,7 +277,7 @@ export class CogTiffImage {
|
|
|
257
277
|
* @returns EPSG Code if it exists
|
|
258
278
|
*/
|
|
259
279
|
get epsg() {
|
|
260
|
-
const projection = this.valueGeo(
|
|
280
|
+
const projection = this.valueGeo(TiffTagGeo.ProjectedCSTypeGeoKey);
|
|
261
281
|
if (projection === InvalidProjectionCode)
|
|
262
282
|
return null;
|
|
263
283
|
return projection;
|
|
@@ -269,23 +289,23 @@ export class CogTiffImage {
|
|
|
269
289
|
*/
|
|
270
290
|
get size() {
|
|
271
291
|
return {
|
|
272
|
-
width: this.value(
|
|
273
|
-
height: this.value(
|
|
292
|
+
width: this.value(TiffTag.ImageWidth),
|
|
293
|
+
height: this.value(TiffTag.ImageHeight),
|
|
274
294
|
};
|
|
275
295
|
}
|
|
276
296
|
/**
|
|
277
297
|
* Determine if this image is tiled
|
|
278
298
|
*/
|
|
279
299
|
isTiled() {
|
|
280
|
-
return this.value(
|
|
300
|
+
return this.value(TiffTag.TileWidth) !== null;
|
|
281
301
|
}
|
|
282
302
|
/**
|
|
283
303
|
* Get size of individual tiles
|
|
284
304
|
*/
|
|
285
305
|
get tileSize() {
|
|
286
306
|
return {
|
|
287
|
-
width: this.value(
|
|
288
|
-
height: this.value(
|
|
307
|
+
width: this.value(TiffTag.TileWidth),
|
|
308
|
+
height: this.value(TiffTag.TileHeight),
|
|
289
309
|
};
|
|
290
310
|
}
|
|
291
311
|
/**
|
|
@@ -306,7 +326,7 @@ export class CogTiffImage {
|
|
|
306
326
|
* @returns file offset to where the tiffs are stored
|
|
307
327
|
*/
|
|
308
328
|
get tileOffset() {
|
|
309
|
-
const tileOffset = this.tags.get(
|
|
329
|
+
const tileOffset = this.tags.get(TiffTag.TileOffsets);
|
|
310
330
|
if (tileOffset == null)
|
|
311
331
|
throw new Error('No tile offsets found');
|
|
312
332
|
return tileOffset;
|
|
@@ -319,7 +339,7 @@ export class CogTiffImage {
|
|
|
319
339
|
* @returns number of strips present
|
|
320
340
|
*/
|
|
321
341
|
get stripCount() {
|
|
322
|
-
const tileOffset = this.tags.get(
|
|
342
|
+
const tileOffset = this.tags.get(TiffTag.StripByteCounts);
|
|
323
343
|
if (tileOffset == null)
|
|
324
344
|
return 0;
|
|
325
345
|
return tileOffset.count;
|
|
@@ -334,15 +354,17 @@ export class CogTiffImage {
|
|
|
334
354
|
return { x: left, y: top, width, height };
|
|
335
355
|
}
|
|
336
356
|
/**
|
|
337
|
-
* Read a strip into a
|
|
357
|
+
* Read a strip into a ArrayBuffer
|
|
358
|
+
*
|
|
359
|
+
* Image has to be striped see {@link stripCount}
|
|
338
360
|
*
|
|
339
361
|
* @param index Strip index to read
|
|
340
362
|
*/
|
|
341
363
|
async getStrip(index) {
|
|
342
364
|
if (this.isTiled())
|
|
343
365
|
throw new Error('Cannot read stripes, tiff is tiled: ' + index);
|
|
344
|
-
const byteCounts = this.tags.get(
|
|
345
|
-
const offsets = this.tags.get(
|
|
366
|
+
const byteCounts = this.tags.get(TiffTag.StripByteCounts);
|
|
367
|
+
const offsets = this.tags.get(TiffTag.StripOffsets);
|
|
346
368
|
if (index >= byteCounts.count)
|
|
347
369
|
throw new Error('Cannot read strip, index out of bounds');
|
|
348
370
|
const [byteCount, offset] = await Promise.all([
|
|
@@ -355,7 +377,7 @@ export class CogTiffImage {
|
|
|
355
377
|
getJpegHeader(bytes) {
|
|
356
378
|
// Both the JPEGTable and the Bytes with have the start of image and end of image markers
|
|
357
379
|
// StartOfImage 0xffd8 EndOfImage 0xffd9
|
|
358
|
-
const tables = this.value(
|
|
380
|
+
const tables = this.value(TiffTag.JPEGTables);
|
|
359
381
|
if (tables == null)
|
|
360
382
|
throw new Error('Unable to find Jpeg header');
|
|
361
383
|
// Remove EndOfImage marker
|
|
@@ -369,7 +391,7 @@ export class CogTiffImage {
|
|
|
369
391
|
async getBytes(offset, byteCount) {
|
|
370
392
|
const mimeType = this.compression;
|
|
371
393
|
if (mimeType == null)
|
|
372
|
-
throw new Error('Unsupported compression: ' + this.value(
|
|
394
|
+
throw new Error('Unsupported compression: ' + this.value(TiffTag.Compression));
|
|
373
395
|
if (byteCount === 0)
|
|
374
396
|
return null;
|
|
375
397
|
const bytes = await this.tiff.source.fetch(offset, byteCount);
|
|
@@ -381,9 +403,9 @@ export class CogTiffImage {
|
|
|
381
403
|
return { mimeType, bytes };
|
|
382
404
|
}
|
|
383
405
|
/**
|
|
384
|
-
* Load
|
|
406
|
+
* Load a tile into a ArrayBuffer
|
|
385
407
|
*
|
|
386
|
-
* This will also apply the JPEG compression tables
|
|
408
|
+
* if the tile compression is JPEG, This will also apply the JPEG compression tables to the resulting ArrayBuffer see {@link getJpegHeader}
|
|
387
409
|
*
|
|
388
410
|
* @param x Tile x offset
|
|
389
411
|
* @param y Tile y offset
|
|
@@ -395,7 +417,7 @@ export class CogTiffImage {
|
|
|
395
417
|
if (tiles == null)
|
|
396
418
|
throw new Error('Tiff is not tiled');
|
|
397
419
|
if (mimeType == null)
|
|
398
|
-
throw new Error('Unsupported compression: ' + this.value(
|
|
420
|
+
throw new Error('Unsupported compression: ' + this.value(TiffTag.Compression));
|
|
399
421
|
// TODO support GhostOptionTileOrder
|
|
400
422
|
const nyTiles = Math.ceil(size.height / tiles.height);
|
|
401
423
|
const nxTiles = Math.ceil(size.width / tiles.width);
|
|
@@ -407,16 +429,17 @@ export class CogTiffImage {
|
|
|
407
429
|
if (idx >= totalTiles)
|
|
408
430
|
throw new Error(`Tile index is outside of tile range: ${idx} >= ${totalTiles}`);
|
|
409
431
|
const { offset, imageSize } = await this.getTileSize(idx);
|
|
410
|
-
// console.log({ x, y, offset, imageSize });
|
|
411
432
|
return this.getBytes(offset, imageSize);
|
|
412
433
|
}
|
|
413
434
|
/**
|
|
414
435
|
* Does this tile exist in the tiff and does it actually have a value
|
|
415
436
|
*
|
|
416
|
-
* Sparse tiffs can have a lot of empty tiles,
|
|
437
|
+
* Sparse tiffs can have a lot of empty tiles, they set the tile size to `0 bytes` when the tile is empty
|
|
438
|
+
* this checks the tile byte size to validate if it actually has any data.
|
|
417
439
|
*
|
|
418
440
|
* @param x Tile x offset
|
|
419
441
|
* @param y Tile y offset
|
|
442
|
+
*
|
|
420
443
|
* @returns if the tile exists and has data
|
|
421
444
|
*/
|
|
422
445
|
async hasTile(x, y) {
|
|
@@ -433,6 +456,11 @@ export class CogTiffImage {
|
|
|
433
456
|
const ret = await this.getTileSize(idx);
|
|
434
457
|
return ret.offset > 0;
|
|
435
458
|
}
|
|
459
|
+
/**
|
|
460
|
+
* Load the offset and byteCount of a tile
|
|
461
|
+
* @param index index in the tile array
|
|
462
|
+
* @returns Offset and byteCount for the tile
|
|
463
|
+
*/
|
|
436
464
|
async getTileSize(index) {
|
|
437
465
|
// GDAL optimizes tiles by storing the size of the tile in
|
|
438
466
|
// the few bytes leading up to the tile
|
|
@@ -447,7 +475,7 @@ export class CogTiffImage {
|
|
|
447
475
|
const bytes = await this.tiff.source.fetch(offset - leaderBytes, leaderBytes);
|
|
448
476
|
return { offset, imageSize: getUint(new DataView(bytes), 0, leaderBytes, this.tiff.isLittleEndian) };
|
|
449
477
|
}
|
|
450
|
-
const byteCounts = this.tags.get(
|
|
478
|
+
const byteCounts = this.tags.get(TiffTag.TileByteCounts);
|
|
451
479
|
if (byteCounts == null)
|
|
452
480
|
throw new Error('No tile byte counts found');
|
|
453
481
|
const [offset, imageSize] = await Promise.all([
|
|
@@ -461,7 +489,7 @@ function getOffset(tiff, x, index) {
|
|
|
461
489
|
if (index > x.count || index < 0)
|
|
462
490
|
throw new Error('TagIndex: out of bounds ' + x.id + ' @ ' + index);
|
|
463
491
|
if (x.type === 'inline') {
|
|
464
|
-
if (
|
|
492
|
+
if (x.count > 1)
|
|
465
493
|
return x.value[index];
|
|
466
494
|
return x.value;
|
|
467
495
|
}
|