@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.
Files changed (119) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/build/__benchmark__/cog.read.benchmark.d.ts +1 -0
  3. package/build/__benchmark__/cog.read.benchmark.d.ts.map +1 -0
  4. package/build/__benchmark__/cog.read.benchmark.js +4 -3
  5. package/build/__benchmark__/source.file.d.ts +5 -0
  6. package/build/__benchmark__/source.file.d.ts.map +1 -0
  7. package/build/__benchmark__/source.file.js +4 -13
  8. package/build/__benchmark__/source.memory.d.ts +1 -0
  9. package/build/__benchmark__/source.memory.d.ts.map +1 -0
  10. package/build/__benchmark__/source.memory.js +3 -19
  11. package/build/__test__/cog.image.test.d.ts +1 -0
  12. package/build/__test__/cog.image.test.d.ts.map +1 -0
  13. package/build/__test__/cog.image.test.js +0 -1
  14. package/build/__test__/cog.read.test.d.ts +1 -0
  15. package/build/__test__/cog.read.test.d.ts.map +1 -0
  16. package/build/__test__/cog.read.test.js +81 -2
  17. package/build/__test__/example.d.ts +1 -0
  18. package/build/__test__/example.d.ts.map +1 -0
  19. package/build/__test__/example.js +0 -1
  20. package/build/const/index.d.ts +1 -0
  21. package/build/const/index.d.ts.map +1 -0
  22. package/build/const/index.js +0 -1
  23. package/build/const/tiff.endian.d.ts +1 -0
  24. package/build/const/tiff.endian.d.ts.map +1 -0
  25. package/build/const/tiff.endian.js +0 -1
  26. package/build/const/tiff.mime.d.ts +1 -0
  27. package/build/const/tiff.mime.d.ts.map +1 -0
  28. package/build/const/tiff.mime.js +0 -1
  29. package/build/const/tiff.tag.id.d.ts +16 -8
  30. package/build/const/tiff.tag.id.d.ts.map +1 -0
  31. package/build/const/tiff.tag.id.js +10 -3
  32. package/build/const/tiff.tag.value.d.ts +1 -0
  33. package/build/const/tiff.tag.value.d.ts.map +1 -0
  34. package/build/const/tiff.tag.value.js +0 -1
  35. package/build/const/tiff.version.d.ts +1 -0
  36. package/build/const/tiff.version.d.ts.map +1 -0
  37. package/build/const/tiff.version.js +0 -1
  38. package/build/index.d.ts +4 -2
  39. package/build/index.d.ts.map +1 -0
  40. package/build/index.js +2 -4
  41. package/build/read/data.view.offset.d.ts +1 -0
  42. package/build/read/data.view.offset.d.ts.map +1 -0
  43. package/build/read/data.view.offset.js +0 -1
  44. package/build/read/endian.d.ts +2 -0
  45. package/build/read/endian.d.ts.map +1 -0
  46. package/build/read/endian.js +5 -0
  47. package/build/read/tiff.gdal.d.ts +1 -0
  48. package/build/read/tiff.gdal.d.ts.map +1 -0
  49. package/build/read/tiff.gdal.js +1 -9
  50. package/build/read/tiff.ifd.config.d.ts +1 -0
  51. package/build/read/tiff.ifd.config.d.ts.map +1 -0
  52. package/build/read/tiff.ifd.config.js +0 -1
  53. package/build/read/tiff.tag.d.ts +2 -1
  54. package/build/read/tiff.tag.d.ts.map +1 -0
  55. package/build/read/tiff.tag.factory.d.ts +15 -1
  56. package/build/read/tiff.tag.factory.d.ts.map +1 -0
  57. package/build/read/tiff.tag.factory.js +60 -4
  58. package/build/read/tiff.tag.js +0 -1
  59. package/build/read/tiff.value.reader.d.ts +1 -0
  60. package/build/read/tiff.value.reader.d.ts.map +1 -0
  61. package/build/read/tiff.value.reader.js +0 -1
  62. package/build/source.d.ts +4 -1
  63. package/build/source.d.ts.map +1 -0
  64. package/build/source.js +0 -1
  65. package/build/tiff.d.ts +12 -3
  66. package/build/tiff.d.ts.map +1 -0
  67. package/build/tiff.image.d.ts +11 -2
  68. package/build/tiff.image.d.ts.map +1 -0
  69. package/build/tiff.image.js +51 -69
  70. package/build/tiff.js +28 -74
  71. package/build/util/bytes.d.ts +1 -0
  72. package/build/util/bytes.d.ts.map +1 -0
  73. package/build/util/bytes.js +0 -1
  74. package/build/util/util.hex.d.ts +1 -0
  75. package/build/util/util.hex.d.ts.map +1 -0
  76. package/build/util/util.hex.js +0 -1
  77. package/build/vector.d.ts +1 -0
  78. package/build/vector.d.ts.map +1 -0
  79. package/build/vector.js +0 -1
  80. package/package.json +2 -2
  81. package/src/__benchmark__/cog.read.benchmark.ts +4 -2
  82. package/src/__benchmark__/source.file.ts +3 -1
  83. package/src/__benchmark__/source.memory.ts +2 -2
  84. package/src/__test__/cog.image.test.ts +1 -1
  85. package/src/__test__/cog.read.test.ts +107 -2
  86. package/src/const/tiff.tag.id.ts +16 -8
  87. package/src/index.ts +14 -11
  88. package/src/read/endian.ts +6 -0
  89. package/src/read/tiff.tag.factory.ts +73 -3
  90. package/src/read/tiff.tag.ts +1 -1
  91. package/src/source.ts +1 -1
  92. package/src/tiff.image.ts +40 -26
  93. package/src/tiff.ts +18 -4
  94. package/tsconfig.json +1 -2
  95. package/build/__benchmark__/cog.read.benchmark.js.map +0 -1
  96. package/build/__benchmark__/source.file.js.map +0 -1
  97. package/build/__benchmark__/source.memory.js.map +0 -1
  98. package/build/__test__/cog.image.test.js.map +0 -1
  99. package/build/__test__/cog.read.test.js.map +0 -1
  100. package/build/__test__/example.js.map +0 -1
  101. package/build/const/index.js.map +0 -1
  102. package/build/const/tiff.endian.js.map +0 -1
  103. package/build/const/tiff.mime.js.map +0 -1
  104. package/build/const/tiff.tag.id.js.map +0 -1
  105. package/build/const/tiff.tag.value.js.map +0 -1
  106. package/build/const/tiff.version.js.map +0 -1
  107. package/build/index.js.map +0 -1
  108. package/build/read/data.view.offset.js.map +0 -1
  109. package/build/read/tiff.gdal.js.map +0 -1
  110. package/build/read/tiff.ifd.config.js.map +0 -1
  111. package/build/read/tiff.tag.factory.js.map +0 -1
  112. package/build/read/tiff.tag.js.map +0 -1
  113. package/build/read/tiff.value.reader.js.map +0 -1
  114. package/build/source.js.map +0 -1
  115. package/build/tiff.image.js.map +0 -1
  116. package/build/tiff.js.map +0 -1
  117. package/build/util/bytes.js.map +0 -1
  118. package/build/util/util.hex.js.map +0 -1
  119. package/build/vector.js.map +0 -1
@@ -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"}
@@ -42,4 +42,3 @@ export function getUint(view, offset, bs, isLittleEndian) {
42
42
  return getUint64(view, offset, isLittleEndian);
43
43
  }
44
44
  }
45
- //# sourceMappingURL=bytes.js.map
@@ -8,3 +8,4 @@
8
8
  * @returns hex string eg 0x0015
9
9
  **/
10
10
  export declare function toHex(num: number, padding?: number, prefix?: boolean): string;
11
+ //# sourceMappingURL=util.hex.d.ts.map
@@ -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"}
@@ -13,4 +13,3 @@ export function toHex(num, padding = 4, prefix = true) {
13
13
  return '0x' + hex;
14
14
  return hex;
15
15
  }
16
- //# sourceMappingURL=util.hex.js.map
package/build/vector.d.ts CHANGED
@@ -11,3 +11,4 @@ export interface BoundingBox extends Point, Size {
11
11
  export interface Vector extends Point {
12
12
  z: number;
13
13
  }
14
+ //# sourceMappingURL=vector.d.ts.map
@@ -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
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=vector.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogeotiff/core",
3
- "version": "9.1.2",
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": "4781a6375adf419da9f0319d15c8a67284dfb0c4"
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 tiff.images[0].fetch(TiffTag.TileByteCounts);
23
- await tiff.images[0].fetch(TiffTag.TileOffsets);
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
- return fileData.buffer.slice(fileData.byteOffset + offset, fileData.byteOffset + offset + length);
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
- assert.deepEqual(await im.fetch(TiffTag.StripByteCounts), [8064, 8064, 8064, 8064, 8064, 8064, 8064, 5040]);
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
  });
@@ -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 libegotiff
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 libegotiff
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';
@@ -0,0 +1,6 @@
1
+ const buffer = new ArrayBuffer(4);
2
+ const uint32 = new Uint32Array(buffer);
3
+ const uint8 = new Uint8Array(buffer);
4
+ uint32[0] = 1;
5
+
6
+ export const isLittleEndian = uint8[0] === 1;
@@ -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
- // Some offsets are quite long and don't need to read them often, so only read the tags we are interested in when we need to
137
- if (tagId === TiffTag.TileOffsets && hasBytes(view, dataOffset, dataLength)) setBytes(tag, view);
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<number[]> {
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
+ }
@@ -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>;