@cogeotiff/core 9.2.0 → 9.4.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 +29 -0
- package/build/__benchmark__/cog.read.benchmark.js +4 -2
- package/build/__benchmark__/source.file.d.ts +4 -0
- package/build/__benchmark__/source.file.d.ts.map +1 -1
- package/build/__benchmark__/source.file.js +2 -0
- package/build/__test__/cog.read.test.js +94 -1
- package/build/const/tiff.mime.d.ts +3 -0
- package/build/const/tiff.mime.d.ts.map +1 -1
- package/build/const/tiff.mime.js +23 -0
- package/build/const/tiff.tag.id.d.ts +35 -8
- package/build/const/tiff.tag.id.d.ts.map +1 -1
- package/build/const/tiff.tag.id.js +30 -2
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -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.tag.d.ts +1 -1
- package/build/read/tiff.tag.d.ts.map +1 -1
- package/build/read/tiff.tag.factory.d.ts +14 -1
- package/build/read/tiff.tag.factory.d.ts.map +1 -1
- package/build/read/tiff.tag.factory.js +60 -3
- package/build/tiff.d.ts +6 -2
- package/build/tiff.d.ts.map +1 -1
- package/build/tiff.image.d.ts +3 -0
- package/build/tiff.image.d.ts.map +1 -1
- package/build/tiff.image.js +23 -6
- package/build/tiff.js +4 -3
- package/package.json +2 -2
- package/src/__benchmark__/cog.read.benchmark.ts +4 -2
- package/src/__benchmark__/source.file.ts +2 -0
- package/src/__test__/cog.read.test.ts +127 -2
- package/src/const/tiff.mime.ts +23 -0
- package/src/const/tiff.tag.id.ts +35 -7
- package/src/index.ts +3 -0
- 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/tiff.image.ts +23 -6
- package/src/tiff.ts +12 -3
|
@@ -3,6 +3,7 @@ import { TiffTag, TiffTagConvertArray } from '../const/tiff.tag.id.js';
|
|
|
3
3
|
import { TiffTagValueType } from '../const/tiff.tag.value.js';
|
|
4
4
|
import { getUint, getUint64 } from '../util/bytes.js';
|
|
5
5
|
import { hasBytes } from './data.view.offset.js';
|
|
6
|
+
import { isLittleEndian } from './endian.js';
|
|
6
7
|
import { getTiffTagSize } from './tiff.value.reader.js';
|
|
7
8
|
function readTagValue(fieldType, bytes, offset, isLittleEndian) {
|
|
8
9
|
switch (fieldType) {
|
|
@@ -36,6 +37,31 @@ function readTagValue(fieldType, bytes, offset, isLittleEndian) {
|
|
|
36
37
|
throw new Error(`Unknown read type "${fieldType}" "${TiffTagValueType[fieldType]}"`);
|
|
37
38
|
}
|
|
38
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Convert a tiff tag value to a typed array if the local endian matches the tiff endian
|
|
42
|
+
*
|
|
43
|
+
* @param tiff
|
|
44
|
+
* @param bytes
|
|
45
|
+
* @param offset Offset in the data view to read from
|
|
46
|
+
* @param length Number of bytes to read
|
|
47
|
+
* @param type type of tiff tag
|
|
48
|
+
* @returns the value if the type is a typed array and the endianness matches otherwise null
|
|
49
|
+
*/
|
|
50
|
+
export function readTypedValue(tiff, bytes, offset, length, type) {
|
|
51
|
+
switch (type) {
|
|
52
|
+
case TiffTagValueType.Uint8:
|
|
53
|
+
return new Uint8Array(bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length));
|
|
54
|
+
case TiffTagValueType.Uint16:
|
|
55
|
+
if (tiff.isLittleEndian !== isLittleEndian)
|
|
56
|
+
return null;
|
|
57
|
+
return new Uint16Array(bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length));
|
|
58
|
+
case TiffTagValueType.Uint32:
|
|
59
|
+
if (tiff.isLittleEndian !== isLittleEndian)
|
|
60
|
+
return null;
|
|
61
|
+
return new Uint32Array(bytes.buffer.slice(bytes.byteOffset + offset, bytes.byteOffset + offset + length));
|
|
62
|
+
}
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
39
65
|
function readValue(tiff, tagId, bytes, offset, type, count) {
|
|
40
66
|
const typeSize = getTiffTagSize(type);
|
|
41
67
|
const dataLength = count * typeSize;
|
|
@@ -51,6 +77,15 @@ function readValue(tiff, tagId, bytes, offset, type, count) {
|
|
|
51
77
|
case TiffTagValueType.Ascii:
|
|
52
78
|
return String.fromCharCode.apply(null, new Uint8Array(bytes.buffer, offset, dataLength - 1));
|
|
53
79
|
}
|
|
80
|
+
// TODO should we convert all tag values to typed arrays if possible?
|
|
81
|
+
if (tagId === TiffTag.TileOffsets ||
|
|
82
|
+
tagId === TiffTag.TileByteCounts ||
|
|
83
|
+
tagId === TiffTag.StripOffsets ||
|
|
84
|
+
tagId === TiffTag.StripByteCounts) {
|
|
85
|
+
const typedOutput = readTypedValue(tiff, bytes, offset, dataLength, type);
|
|
86
|
+
if (typedOutput)
|
|
87
|
+
return typedOutput;
|
|
88
|
+
}
|
|
54
89
|
const output = [];
|
|
55
90
|
for (let i = 0; i < dataLength; i += typeSize) {
|
|
56
91
|
output.push(readTagValue(type, bytes, offset + i, tiff.isLittleEndian));
|
|
@@ -94,9 +129,16 @@ export function createTag(tiff, view, offset) {
|
|
|
94
129
|
value: [],
|
|
95
130
|
tagOffset: offset,
|
|
96
131
|
};
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
132
|
+
if (hasBytes(view, dataOffset, dataLength)) {
|
|
133
|
+
const val = readTypedValue(tiff, view, dataOffset - view.sourceOffset, dataLength, dataType);
|
|
134
|
+
if (val) {
|
|
135
|
+
tag.value = val;
|
|
136
|
+
tag.isLoaded = true;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
setBytes(tag, view);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
100
142
|
return tag;
|
|
101
143
|
}
|
|
102
144
|
// If we already have the bytes in the view read them in
|
|
@@ -128,6 +170,7 @@ export async function fetchAllOffsets(tiff, tag) {
|
|
|
128
170
|
tag.view.sourceOffset = tag.dataOffset;
|
|
129
171
|
}
|
|
130
172
|
tag.value = readValue(tiff, tag.id, tag.view, 0, tag.dataType, tag.count);
|
|
173
|
+
tag.view = undefined;
|
|
131
174
|
tag.isLoaded = true;
|
|
132
175
|
return tag.value;
|
|
133
176
|
}
|
|
@@ -161,3 +204,17 @@ export async function getValueAt(tiff, tag, index) {
|
|
|
161
204
|
tag.value[index] = value;
|
|
162
205
|
return value;
|
|
163
206
|
}
|
|
207
|
+
export function getValueAtSync(tiff, tag, index) {
|
|
208
|
+
if (index > tag.count || index < 0)
|
|
209
|
+
throw new Error('TagOffset: out of bounds :' + index);
|
|
210
|
+
if (tag.value[index] != null)
|
|
211
|
+
return tag.value[index];
|
|
212
|
+
if (tag.view == null)
|
|
213
|
+
return null;
|
|
214
|
+
const dataTypeSize = getTiffTagSize(tag.dataType);
|
|
215
|
+
const value = readValue(tiff, undefined, tag.view, index * dataTypeSize, tag.dataType, 1);
|
|
216
|
+
if (typeof value !== 'number')
|
|
217
|
+
throw new Error('Value is not a number');
|
|
218
|
+
tag.value[index] = value;
|
|
219
|
+
return value;
|
|
220
|
+
}
|
package/build/tiff.d.ts
CHANGED
|
@@ -3,6 +3,10 @@ import { TiffGhostOptions } from './read/tiff.gdal.js';
|
|
|
3
3
|
import type { TiffIfdConfig } from './read/tiff.ifd.config.js';
|
|
4
4
|
import type { Source } from './source.js';
|
|
5
5
|
import { TiffImage } from './tiff.image.js';
|
|
6
|
+
export interface TiffCreationOptions {
|
|
7
|
+
/** When initializing the tiff, read data in blocks of this size (in KB) */
|
|
8
|
+
defaultReadSize: number;
|
|
9
|
+
}
|
|
6
10
|
export declare class Tiff {
|
|
7
11
|
/** Read 16KB blocks at a time */
|
|
8
12
|
static DefaultReadSize: number;
|
|
@@ -24,9 +28,9 @@ export declare class Tiff {
|
|
|
24
28
|
isInitialized: boolean;
|
|
25
29
|
private _initPromise?;
|
|
26
30
|
/** A Tiff constructed from a source will not be pre-initialized with {@link init}. */
|
|
27
|
-
constructor(source: Source);
|
|
31
|
+
constructor(source: Source, options?: TiffCreationOptions);
|
|
28
32
|
/** Create a tiff and initialize it by reading the tiff headers */
|
|
29
|
-
static create(source: Source): Promise<Tiff>;
|
|
33
|
+
static create(source: Source, options?: TiffCreationOptions): Promise<Tiff>;
|
|
30
34
|
/**
|
|
31
35
|
* Initialize the tiff loading in the header and all image headers.
|
|
32
36
|
*
|
package/build/tiff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiff.d.ts","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,qBAAa,IAAI;IACf,iCAAiC;IACjC,MAAM,CAAC,eAAe,SAAa;IACnC,iCAAiC;IACjC,eAAe,SAAwB;IACvC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,OAAO,cAAoB;IAC3B,0CAA0C;IAC1C,MAAM,EAAE,SAAS,EAAE,CAAM;IACzB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,EAAE,aAAa,CAAiB;IACzC,8CAA8C;IAC9C,cAAc,UAAS;IACvB,6BAA6B;IAC7B,aAAa,UAAS;IAEtB,OAAO,CAAC,YAAY,CAAC,CAAgB;IAErC,sFAAsF;gBAC1E,MAAM,EAAE,MAAM;
|
|
1
|
+
{"version":3,"file":"tiff.d.ts","sourceRoot":"","sources":["../src/tiff.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAItD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAG/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,IAAI;IACf,iCAAiC;IACjC,MAAM,CAAC,eAAe,SAAa;IACnC,iCAAiC;IACjC,eAAe,SAAwB;IACvC,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,OAAO,cAAoB;IAC3B,0CAA0C;IAC1C,MAAM,EAAE,SAAS,EAAE,CAAM;IACzB,2BAA2B;IAC3B,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,4CAA4C;IAC5C,SAAS,EAAE,aAAa,CAAiB;IACzC,8CAA8C;IAC9C,cAAc,UAAS;IACvB,6BAA6B;IAC7B,aAAa,UAAS;IAEtB,OAAO,CAAC,YAAY,CAAC,CAAgB;IAErC,sFAAsF;gBAC1E,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,mBAA+D;IAKpG,kEAAkE;IAClE,MAAM,CAAC,MAAM,CACX,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,mBAA+D,GACvE,OAAO,CAAC,IAAI,CAAC;IAIhB;;;;;OAKG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAMrB;;;;OAIG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;IAoBnD,qEAAqE;YACvD,UAAU;IAgExB;;;;;OAKG;IACH,OAAO,CAAC,OAAO;CAsBhB"}
|
package/build/tiff.image.d.ts
CHANGED
|
@@ -235,6 +235,9 @@ export declare class TiffImage {
|
|
|
235
235
|
hasTile(x: number, y: number): Promise<boolean>;
|
|
236
236
|
/**
|
|
237
237
|
* Load the offset and byteCount of a tile
|
|
238
|
+
*
|
|
239
|
+
* if the tiff is sparse, offset and byteCount will be zero if the tile is empty
|
|
240
|
+
*
|
|
238
241
|
* @param index index in the tile array
|
|
239
242
|
* @returns Offset and byteCount for the tile
|
|
240
243
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tiff.image.d.ts","sourceRoot":"","sources":["../src/tiff.image.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tiff.image.d.ts","sourceRoot":"","sources":["../src/tiff.image.ts"],"names":[],"mappings":"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"}
|
package/build/tiff.image.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getCompressionMimeType, TiffCompressionMimeType, TiffMimeType } from './const/tiff.mime.js';
|
|
2
2
|
import { Compression, ModelTypeCode, SubFileType, TiffTag, TiffTagGeo } from './const/tiff.tag.id.js';
|
|
3
|
-
import { fetchAllOffsets, fetchLazy, getValueAt } from './read/tiff.tag.factory.js';
|
|
3
|
+
import { fetchAllOffsets, fetchLazy, getValueAt, getValueAtSync } from './read/tiff.tag.factory.js';
|
|
4
4
|
import { getUint } from './util/bytes.js';
|
|
5
5
|
/** Invalid EPSG code */
|
|
6
6
|
export const InvalidProjectionCode = 32767;
|
|
@@ -494,15 +494,25 @@ export class TiffImage {
|
|
|
494
494
|
}
|
|
495
495
|
/**
|
|
496
496
|
* Load the offset and byteCount of a tile
|
|
497
|
+
*
|
|
498
|
+
* if the tiff is sparse, offset and byteCount will be zero if the tile is empty
|
|
499
|
+
*
|
|
497
500
|
* @param index index in the tile array
|
|
498
501
|
* @returns Offset and byteCount for the tile
|
|
499
502
|
*/
|
|
500
503
|
async getTileSize(index) {
|
|
504
|
+
// If both the tile offset and tile byte counts are loaded,
|
|
505
|
+
// we can get the offset and byte count synchronously without needing to fetch any additional data
|
|
506
|
+
const byteCounts = this.tags.get(TiffTag.TileByteCounts);
|
|
507
|
+
const tileOffset = getOffsetSync(this.tiff, this.tileOffset, index);
|
|
508
|
+
const tileSize = getOffsetSync(this.tiff, byteCounts, index);
|
|
509
|
+
if (tileOffset != null && tileSize != null)
|
|
510
|
+
return { offset: tileOffset, imageSize: tileSize };
|
|
501
511
|
// GDAL optimizes tiles by storing the size of the tile in
|
|
502
512
|
// the few bytes leading up to the tile
|
|
503
513
|
const leaderBytes = this.tiff.options?.tileLeaderByteSize;
|
|
504
514
|
if (leaderBytes) {
|
|
505
|
-
const offset = await getOffset(this.tiff, this.tileOffset, index);
|
|
515
|
+
const offset = tileOffset ?? (await getOffset(this.tiff, this.tileOffset, index));
|
|
506
516
|
// Sparse tiff no data found
|
|
507
517
|
if (offset === 0)
|
|
508
518
|
return { offset: 0, imageSize: 0 };
|
|
@@ -511,17 +521,22 @@ export class TiffImage {
|
|
|
511
521
|
const bytes = await this.tiff.source.fetch(offset - leaderBytes, leaderBytes);
|
|
512
522
|
return { offset, imageSize: getUint(new DataView(bytes), 0, leaderBytes, this.tiff.isLittleEndian) };
|
|
513
523
|
}
|
|
514
|
-
const byteCounts = this.tags.get(TiffTag.TileByteCounts);
|
|
515
524
|
if (byteCounts == null)
|
|
516
525
|
throw new Error('No tile byte counts found');
|
|
517
526
|
const [offset, imageSize] = await Promise.all([
|
|
518
|
-
getOffset(this.tiff, this.tileOffset, index),
|
|
519
|
-
getOffset(this.tiff, byteCounts, index),
|
|
527
|
+
tileOffset ?? getOffset(this.tiff, this.tileOffset, index),
|
|
528
|
+
tileSize ?? getOffset(this.tiff, byteCounts, index),
|
|
520
529
|
]);
|
|
521
530
|
return { offset, imageSize };
|
|
522
531
|
}
|
|
523
532
|
}
|
|
524
533
|
function getOffset(tiff, x, index) {
|
|
534
|
+
const val = getOffsetSync(tiff, x, index);
|
|
535
|
+
if (val != null)
|
|
536
|
+
return Promise.resolve(val);
|
|
537
|
+
return getValueAt(tiff, x, index);
|
|
538
|
+
}
|
|
539
|
+
function getOffsetSync(tiff, x, index) {
|
|
525
540
|
if (index < 0) {
|
|
526
541
|
throw new Error(`Tiff: ${tiff.source.url.href} out of bounds ${TiffTag[x.id]} index:${index} total:${x.count}`);
|
|
527
542
|
}
|
|
@@ -530,5 +545,7 @@ function getOffset(tiff, x, index) {
|
|
|
530
545
|
return 0;
|
|
531
546
|
if (x.type === 'inline')
|
|
532
547
|
return x.value[index];
|
|
533
|
-
|
|
548
|
+
if (x.isLoaded)
|
|
549
|
+
return x.value[index];
|
|
550
|
+
return getValueAtSync(tiff, x, index);
|
|
534
551
|
}
|
package/build/tiff.js
CHANGED
|
@@ -28,12 +28,13 @@ export class Tiff {
|
|
|
28
28
|
isInitialized = false;
|
|
29
29
|
_initPromise;
|
|
30
30
|
/** A Tiff constructed from a source will not be pre-initialized with {@link init}. */
|
|
31
|
-
constructor(source) {
|
|
31
|
+
constructor(source, options = { defaultReadSize: Tiff.DefaultReadSize }) {
|
|
32
32
|
this.source = source;
|
|
33
|
+
this.defaultReadSize = options.defaultReadSize;
|
|
33
34
|
}
|
|
34
35
|
/** Create a tiff and initialize it by reading the tiff headers */
|
|
35
|
-
static create(source) {
|
|
36
|
-
return new Tiff(source).init();
|
|
36
|
+
static create(source, options = { defaultReadSize: Tiff.DefaultReadSize }) {
|
|
37
|
+
return new Tiff(source, options).init();
|
|
37
38
|
}
|
|
38
39
|
/**
|
|
39
40
|
* Initialize the tiff loading in the header and all image headers.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cogeotiff/core",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.4.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": "2cb33fbbd63f87fc2535282a4dd4426a449dd758"
|
|
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,6 +21,7 @@ export class TestFileSource implements Source {
|
|
|
20
21
|
|
|
21
22
|
async fetch(offset: number, length: number): Promise<ArrayBuffer> {
|
|
22
23
|
const fileData = await this.data;
|
|
24
|
+
this.fetches.push({ offset, length });
|
|
23
25
|
return fileData.buffer.slice(fileData.byteOffset + offset, fileData.byteOffset + offset + length) as ArrayBuffer;
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -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 {
|
|
@@ -19,6 +19,12 @@ function validate(tif: Tiff): void {
|
|
|
19
19
|
assert.deepEqual(firstTif.size, { width: 64, height: 64 });
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
describe('TiffTag', () => {
|
|
23
|
+
it('should have the correct ModelTransformation tag id', () => {
|
|
24
|
+
assert.equal(TiffTag.ModelTransformation, 34264);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
22
28
|
describe('CogRead', () => {
|
|
23
29
|
it('should read big endian', async () => {
|
|
24
30
|
const source = new TestFileSource(new URL('../../data/big.endian.tiff', import.meta.url));
|
|
@@ -30,6 +36,8 @@ describe('CogRead', () => {
|
|
|
30
36
|
assert.equal(tiff.version, TiffVersion.Tiff);
|
|
31
37
|
assert.equal(tiff.images.length, 1);
|
|
32
38
|
const firstImage = tiff.images[0];
|
|
39
|
+
const byteCounts = await firstImage.fetch(TiffTag.TileByteCounts);
|
|
40
|
+
assert.deepEqual([...(byteCounts ?? [])], [511]);
|
|
33
41
|
|
|
34
42
|
assert.equal(firstImage.compression, 'application/zstd');
|
|
35
43
|
assert.equal(firstImage.isTiled(), true);
|
|
@@ -48,6 +56,14 @@ describe('CogRead', () => {
|
|
|
48
56
|
assert.equal(tiff.version, TiffVersion.BigTiff);
|
|
49
57
|
assert.equal(tiff.images[0].epsg, null);
|
|
50
58
|
validate(tiff);
|
|
59
|
+
|
|
60
|
+
const [byteCounts, tileOffsets] = await Promise.all([
|
|
61
|
+
tiff.images[0].fetch(TiffTag.TileByteCounts),
|
|
62
|
+
tiff.images[0].fetch(TiffTag.TileOffsets),
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
assert.deepEqual([...(byteCounts ?? [])], [196608]);
|
|
66
|
+
assert.deepEqual([...(tileOffsets ?? [])], [272]);
|
|
51
67
|
});
|
|
52
68
|
|
|
53
69
|
it('should fail reading a empty byte tiff', async () => {
|
|
@@ -87,6 +103,88 @@ describe('CogRead', () => {
|
|
|
87
103
|
assert.equal(tiff.images.length, 5);
|
|
88
104
|
});
|
|
89
105
|
|
|
106
|
+
it('should read the byte count array if it is loaded', async () => {
|
|
107
|
+
const source = new TestFileSource(new URL('../../data/rgba8_cog.tiff', import.meta.url));
|
|
108
|
+
const fetchSize = 16 * 1024;
|
|
109
|
+
|
|
110
|
+
const tiff = new Tiff(source);
|
|
111
|
+
tiff.defaultReadSize = fetchSize;
|
|
112
|
+
await tiff.init();
|
|
113
|
+
|
|
114
|
+
assert.equal(source.fetches.length, 1);
|
|
115
|
+
assert.equal(source.fetches[0].length, fetchSize);
|
|
116
|
+
|
|
117
|
+
const img = tiff.images[0];
|
|
118
|
+
const byteCounts = img.tags.get(TiffTag.TileByteCounts) as TagOffset;
|
|
119
|
+
const tileOffsets = img.tags.get(TiffTag.TileOffsets) as TagOffset;
|
|
120
|
+
assert.equal(source.fetches.length, 1);
|
|
121
|
+
|
|
122
|
+
assert.equal(byteCounts.type, 'offset');
|
|
123
|
+
assert.equal(byteCounts.isLoaded, true);
|
|
124
|
+
|
|
125
|
+
assert.equal(tileOffsets.type, 'offset');
|
|
126
|
+
assert.equal(tileOffsets.isLoaded, true);
|
|
127
|
+
|
|
128
|
+
const tile = await img.getTile(0, 0);
|
|
129
|
+
assert.equal(tile?.bytes.byteLength, byteCounts.value[0]);
|
|
130
|
+
assert.equal(source.fetches.length, 2);
|
|
131
|
+
assert.deepEqual(source.fetches[1], { offset: tileOffsets.value[0], length: byteCounts.value[0] });
|
|
132
|
+
|
|
133
|
+
// force the offset to be unloaded
|
|
134
|
+
byteCounts.isLoaded = false;
|
|
135
|
+
const oldValue = byteCounts.value;
|
|
136
|
+
byteCounts.value = [];
|
|
137
|
+
const tileB = await img.getTile(0, 0);
|
|
138
|
+
assert.equal(tileB?.bytes.byteLength, oldValue[0]);
|
|
139
|
+
assert.equal(source.fetches.length, 4);
|
|
140
|
+
|
|
141
|
+
// Read the tile offset then the tile
|
|
142
|
+
assert.deepEqual(source.fetches[2], { offset: tileOffsets.value[0] - 4, length: 4 });
|
|
143
|
+
assert.deepEqual(source.fetches[3], { offset: tileOffsets.value[0], length: oldValue[0] });
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should read the byte count array if it is loaded (BigTiff)', async () => {
|
|
147
|
+
const source = new TestFileSource(new URL('../../data/rgba8_cog_big.tiff', import.meta.url));
|
|
148
|
+
const fetchSize = 16 * 1024;
|
|
149
|
+
|
|
150
|
+
const tiff = new Tiff(source);
|
|
151
|
+
tiff.defaultReadSize = fetchSize;
|
|
152
|
+
await tiff.init();
|
|
153
|
+
|
|
154
|
+
assert.equal(source.fetches.length, 1);
|
|
155
|
+
assert.equal(source.fetches[0].length, fetchSize);
|
|
156
|
+
|
|
157
|
+
const img = tiff.images[0];
|
|
158
|
+
const byteCounts = img.tags.get(TiffTag.TileByteCounts) as TagOffset;
|
|
159
|
+
const tileOffsets = img.tags.get(TiffTag.TileOffsets) as TagOffset;
|
|
160
|
+
assert.equal(source.fetches.length, 1);
|
|
161
|
+
|
|
162
|
+
assert.equal(byteCounts.type, 'offset');
|
|
163
|
+
assert.equal(byteCounts.isLoaded, true);
|
|
164
|
+
assert.equal(byteCounts.view == null, true);
|
|
165
|
+
|
|
166
|
+
assert.equal(tileOffsets.type, 'offset');
|
|
167
|
+
assert.equal(tileOffsets.isLoaded, false);
|
|
168
|
+
assert.equal(tileOffsets.view == null, false);
|
|
169
|
+
|
|
170
|
+
const tile = await img.getTile(0, 0);
|
|
171
|
+
assert.equal(tile?.bytes.byteLength, byteCounts.value[0]);
|
|
172
|
+
assert.equal(source.fetches.length, 2);
|
|
173
|
+
assert.deepEqual(source.fetches[1], { offset: tileOffsets.value[0], length: byteCounts.value[0] });
|
|
174
|
+
|
|
175
|
+
// force the offset to be unloaded
|
|
176
|
+
byteCounts.isLoaded = false;
|
|
177
|
+
const oldValue = byteCounts.value;
|
|
178
|
+
byteCounts.value = [];
|
|
179
|
+
byteCounts.view = undefined;
|
|
180
|
+
const tileB = await img.getTile(0, 0);
|
|
181
|
+
assert.equal(tileB?.bytes.byteLength, oldValue[0]);
|
|
182
|
+
assert.equal(source.fetches.length, 4);
|
|
183
|
+
// Read the tile offset then the tile
|
|
184
|
+
assert.deepEqual(source.fetches[2], { offset: tileOffsets.value[0] - 4, length: 4 });
|
|
185
|
+
assert.deepEqual(source.fetches[3], { offset: tileOffsets.value[0], length: oldValue[0] });
|
|
186
|
+
});
|
|
187
|
+
|
|
90
188
|
it('should read ifds from anywhere in the file', async () => {
|
|
91
189
|
const source = new TestFileSource(new URL('../../data/DEM_BS28_2016_1000_1141.tif', import.meta.url));
|
|
92
190
|
const tiff = await Tiff.create(source);
|
|
@@ -109,7 +207,9 @@ describe('CogRead', () => {
|
|
|
109
207
|
|
|
110
208
|
assert.equal(im.valueGeo(TiffTagGeo.GTCitationGeoKey), 'NZGD2000 / New Zealand Transverse Mercator 2000');
|
|
111
209
|
assert.equal(im.valueGeo(TiffTagGeo.GeodeticCitationGeoKey), 'NZGD2000');
|
|
112
|
-
|
|
210
|
+
|
|
211
|
+
const stripCount = await im.fetch(TiffTag.StripByteCounts);
|
|
212
|
+
assert.deepEqual([...(stripCount ?? [])], [8064, 8064, 8064, 8064, 8064, 8064, 8064, 5040]);
|
|
113
213
|
});
|
|
114
214
|
|
|
115
215
|
it('should read sub array ifds', async () => {
|
|
@@ -167,5 +267,30 @@ describe('CogRead', () => {
|
|
|
167
267
|
const tiff = await Tiff.create(source);
|
|
168
268
|
assert.equal(tiff.images.length, 5);
|
|
169
269
|
assert.equal(tiff.images[0].epsg, 3857);
|
|
270
|
+
|
|
271
|
+
const [byteCounts, tileOffsets] = await Promise.all([
|
|
272
|
+
tiff.images[0].fetch(TiffTag.TileByteCounts),
|
|
273
|
+
tiff.images[0].fetch(TiffTag.TileOffsets),
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
assert.deepEqual([...(byteCounts ?? [])], [64, 64, 68, 64, 64, 68, 64, 64, 68, 64, 64, 64, 64, 64, 64, 68]);
|
|
277
|
+
assert.deepEqual(
|
|
278
|
+
[...(tileOffsets ?? [])],
|
|
279
|
+
[797, 861, 925, 993, 1057, 1121, 1189, 1253, 1317, 1385, 1449, 1513, 1577, 1641, 1705, 1769],
|
|
280
|
+
);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should load a file with a model transformation tag', async () => {
|
|
284
|
+
const cogSourceFile = new URL('../../data/model_transformation.tif', import.meta.url);
|
|
285
|
+
|
|
286
|
+
const buf = await readFile(cogSourceFile);
|
|
287
|
+
const source = new SourceMemory(buf);
|
|
288
|
+
|
|
289
|
+
const tiff = await Tiff.create(source);
|
|
290
|
+
assert.equal(tiff.images.length, 1);
|
|
291
|
+
assert.deepEqual(
|
|
292
|
+
tiff.images[0].tags.get(TiffTag.ModelTransformation)?.value,
|
|
293
|
+
[10, 0, 0, 418080, 0, 10, 0, 4423680, 0, 0, 0, 0, 0, 0, 0, 1],
|
|
294
|
+
);
|
|
170
295
|
});
|
|
171
296
|
});
|
package/src/const/tiff.mime.ts
CHANGED
|
@@ -5,6 +5,9 @@ import { Compression } from './tiff.tag.id.js';
|
|
|
5
5
|
*/
|
|
6
6
|
export enum TiffMimeType {
|
|
7
7
|
None = 'application/octet-stream',
|
|
8
|
+
Jbig = 'image/jbig',
|
|
9
|
+
Dcs = 'image/x-kodak-dcs',
|
|
10
|
+
PackBits = 'application/packbits',
|
|
8
11
|
Jpeg = 'image/jpeg',
|
|
9
12
|
Jp2000 = 'image/jp2',
|
|
10
13
|
JpegXl = 'image/jpegxl',
|
|
@@ -29,6 +32,26 @@ export const TiffCompressionMimeType: Record<Compression, TiffMimeType> = {
|
|
|
29
32
|
[Compression.Zstd]: TiffMimeType.Zstd,
|
|
30
33
|
[Compression.Webp]: TiffMimeType.Webp,
|
|
31
34
|
[Compression.JpegXl]: TiffMimeType.JpegXl,
|
|
35
|
+
[Compression.Ccittrle]: TiffMimeType.None,
|
|
36
|
+
[Compression.CcittT4]: TiffMimeType.None,
|
|
37
|
+
[Compression.CcittT6]: TiffMimeType.None,
|
|
38
|
+
[Compression.T85]: TiffMimeType.Jbig,
|
|
39
|
+
[Compression.T43]: TiffMimeType.Jbig,
|
|
40
|
+
[Compression.Next]: TiffMimeType.None,
|
|
41
|
+
[Compression.Ccittrlew]: TiffMimeType.None,
|
|
42
|
+
[Compression.PackBits]: TiffMimeType.PackBits,
|
|
43
|
+
[Compression.ThunderScan]: TiffMimeType.None,
|
|
44
|
+
[Compression.It8ctpad]: TiffMimeType.None,
|
|
45
|
+
[Compression.It8lw]: TiffMimeType.None,
|
|
46
|
+
[Compression.It8mp]: TiffMimeType.None,
|
|
47
|
+
[Compression.It8bl]: TiffMimeType.None,
|
|
48
|
+
[Compression.PixarFilm]: TiffMimeType.None,
|
|
49
|
+
[Compression.PixarLog]: TiffMimeType.None,
|
|
50
|
+
[Compression.Dcs]: TiffMimeType.Dcs,
|
|
51
|
+
[Compression.Jbig]: TiffMimeType.Jbig,
|
|
52
|
+
[Compression.SgiLog]: TiffMimeType.None,
|
|
53
|
+
[Compression.SgiLog24]: TiffMimeType.None,
|
|
54
|
+
[Compression.JpegXlDng17]: TiffMimeType.JpegXl,
|
|
32
55
|
};
|
|
33
56
|
|
|
34
57
|
/**
|
package/src/const/tiff.tag.id.ts
CHANGED
|
@@ -66,17 +66,37 @@ export enum OldSubFileType {
|
|
|
66
66
|
/** Tiff compression types */
|
|
67
67
|
export enum Compression {
|
|
68
68
|
None = 1,
|
|
69
|
+
Ccittrle = 2,
|
|
70
|
+
CcittT4 = 3,
|
|
71
|
+
CcittT6 = 4,
|
|
69
72
|
Lzw = 5,
|
|
70
73
|
Jpeg6 = 6,
|
|
71
74
|
Jpeg = 7,
|
|
72
75
|
DeflateOther = 8,
|
|
76
|
+
T85 = 9,
|
|
77
|
+
T43 = 10,
|
|
78
|
+
Next = 32766,
|
|
79
|
+
Ccittrlew = 32771,
|
|
80
|
+
PackBits = 32773,
|
|
81
|
+
ThunderScan = 32809,
|
|
82
|
+
It8ctpad = 32895,
|
|
83
|
+
It8lw = 32896,
|
|
84
|
+
It8mp = 32897,
|
|
85
|
+
It8bl = 32898,
|
|
86
|
+
PixarFilm = 32908,
|
|
87
|
+
PixarLog = 32909,
|
|
73
88
|
Deflate = 32946,
|
|
74
|
-
|
|
89
|
+
Dcs = 32947,
|
|
90
|
+
Jbig = 34661,
|
|
91
|
+
SgiLog = 34676,
|
|
92
|
+
SgiLog24 = 34677,
|
|
93
|
+
Jp2000 = 34712,
|
|
75
94
|
Lerc = 34887,
|
|
76
95
|
Lzma = 34925,
|
|
77
96
|
Zstd = 50000,
|
|
78
97
|
Webp = 50001,
|
|
79
98
|
JpegXl = 50002,
|
|
99
|
+
JpegXlDng17 = 52546,
|
|
80
100
|
}
|
|
81
101
|
|
|
82
102
|
export enum PlanarConfiguration {
|
|
@@ -86,6 +106,14 @@ export enum PlanarConfiguration {
|
|
|
86
106
|
Separate = 2,
|
|
87
107
|
}
|
|
88
108
|
|
|
109
|
+
export enum Predictor {
|
|
110
|
+
None = 1,
|
|
111
|
+
/** Horizontal differencing */
|
|
112
|
+
Horizontal = 2,
|
|
113
|
+
/** Floating point */
|
|
114
|
+
FloatingPoint = 3,
|
|
115
|
+
}
|
|
116
|
+
|
|
89
117
|
export enum SampleFormat {
|
|
90
118
|
/** Unsigned integer data */
|
|
91
119
|
Uint = 1,
|
|
@@ -293,7 +321,7 @@ export enum TiffTag {
|
|
|
293
321
|
* 0, 0, 0, 1]
|
|
294
322
|
* ```
|
|
295
323
|
*/
|
|
296
|
-
ModelTransformation =
|
|
324
|
+
ModelTransformation = 34264,
|
|
297
325
|
/**
|
|
298
326
|
* List of GeoTiff tags
|
|
299
327
|
* {@link TiffTagGeo}
|
|
@@ -417,12 +445,12 @@ export interface TiffTagType {
|
|
|
417
445
|
|
|
418
446
|
[TiffTag.TileWidth]: number;
|
|
419
447
|
[TiffTag.TileHeight]: number;
|
|
420
|
-
[TiffTag.TileOffsets]: number[];
|
|
421
|
-
[TiffTag.TileByteCounts]: number[];
|
|
448
|
+
[TiffTag.TileOffsets]: number[] | Uint32Array | Uint16Array;
|
|
449
|
+
[TiffTag.TileByteCounts]: number[] | Uint32Array | Uint16Array;
|
|
422
450
|
[TiffTag.JpegTables]: number[];
|
|
423
451
|
|
|
424
|
-
[TiffTag.StripByteCounts]: number[];
|
|
425
|
-
[TiffTag.StripOffsets]: number[];
|
|
452
|
+
[TiffTag.StripByteCounts]: number[] | Uint32Array | Uint16Array;
|
|
453
|
+
[TiffTag.StripOffsets]: number[] | Uint32Array | Uint16Array;
|
|
426
454
|
|
|
427
455
|
[TiffTag.SamplesPerPixel]: number;
|
|
428
456
|
[TiffTag.SampleFormat]: SampleFormat[];
|
|
@@ -437,6 +465,7 @@ export interface TiffTagType {
|
|
|
437
465
|
|
|
438
466
|
[TiffTag.PlanarConfiguration]: PlanarConfiguration;
|
|
439
467
|
[TiffTag.Orientation]: Orientation;
|
|
468
|
+
[TiffTag.Predictor]: Predictor;
|
|
440
469
|
|
|
441
470
|
[TiffTag.LercParameters]: number[];
|
|
442
471
|
|
|
@@ -478,7 +507,6 @@ export interface TiffTagType {
|
|
|
478
507
|
[TiffTag.Indexed]: unknown;
|
|
479
508
|
[TiffTag.PageName]: unknown;
|
|
480
509
|
[TiffTag.PageNumber]: unknown;
|
|
481
|
-
[TiffTag.Predictor]: unknown;
|
|
482
510
|
[TiffTag.PrimaryChromaticities]: unknown;
|
|
483
511
|
[TiffTag.ReferenceBlackWhite]: unknown;
|
|
484
512
|
[TiffTag.SMinSampleValue]: unknown;
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export {
|
|
|
11
11
|
Orientation,
|
|
12
12
|
Photometric,
|
|
13
13
|
PlanarConfiguration,
|
|
14
|
+
Predictor,
|
|
14
15
|
RasterTypeKey,
|
|
15
16
|
SampleFormat,
|
|
16
17
|
SubFileType,
|
|
@@ -22,7 +23,9 @@ export { TiffVersion } from './const/tiff.version.js';
|
|
|
22
23
|
export type { Tag, TagInline, TagLazy, TagOffset } from './read/tiff.tag.js';
|
|
23
24
|
export { getTiffTagSize } from './read/tiff.value.reader.js';
|
|
24
25
|
export type { Source } from './source.js';
|
|
26
|
+
export type { TiffImageTileCount } from './tiff.image.js';
|
|
25
27
|
export { TiffImage } from './tiff.image.js';
|
|
28
|
+
export type { TiffCreationOptions } from './tiff.js';
|
|
26
29
|
export { Tiff } from './tiff.js';
|
|
27
30
|
export { toHex } from './util/util.hex.js';
|
|
28
31
|
export type { BoundingBox, Point, Size, Vector } from './vector.js';
|