@cogeotiff/core 7.2.1 → 8.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/CHANGELOG.md +5 -502
  2. package/README.md +23 -11
  3. package/build/__benchmark__/cog.read.benchmark.d.ts +0 -1
  4. package/build/__benchmark__/cog.read.benchmark.js +6 -4
  5. package/build/__benchmark__/cog.read.benchmark.js.map +1 -0
  6. package/build/__benchmark__/source.file.d.ts +9 -0
  7. package/build/__benchmark__/source.file.js +29 -0
  8. package/build/__benchmark__/source.file.js.map +1 -0
  9. package/build/__benchmark__/source.memory.d.ts +9 -0
  10. package/build/__benchmark__/source.memory.js +32 -0
  11. package/build/__benchmark__/source.memory.js.map +1 -0
  12. package/build/__test__/cog.image.test.d.ts +1 -2
  13. package/build/__test__/cog.image.test.js +82 -90
  14. package/build/__test__/cog.image.test.js.map +1 -0
  15. package/build/__test__/cog.read.test.d.ts +1 -2
  16. package/build/__test__/cog.read.test.js +37 -55
  17. package/build/__test__/cog.read.test.js.map +1 -0
  18. package/build/__test__/example.d.ts +1 -0
  19. package/build/__test__/example.js +27 -0
  20. package/build/__test__/example.js.map +1 -0
  21. package/build/cog.tiff.d.ts +22 -28
  22. package/build/cog.tiff.image.d.ts +11 -23
  23. package/build/cog.tiff.image.js +108 -62
  24. package/build/cog.tiff.image.js.map +1 -0
  25. package/build/cog.tiff.js +141 -97
  26. package/build/cog.tiff.js.map +1 -0
  27. package/build/const/index.d.ts +1 -2
  28. package/build/const/index.js +2 -2
  29. package/build/const/index.js.map +1 -0
  30. package/build/const/tiff.endian.d.ts +0 -1
  31. package/build/const/tiff.endian.js +1 -1
  32. package/build/const/tiff.endian.js.map +1 -0
  33. package/build/const/tiff.mime.d.ts +10 -11
  34. package/build/const/tiff.mime.js +22 -22
  35. package/build/const/tiff.mime.js.map +1 -0
  36. package/build/const/tiff.tag.id.d.ts +3 -3
  37. package/build/const/tiff.tag.id.js +4 -3
  38. package/build/const/tiff.tag.id.js.map +1 -0
  39. package/build/const/tiff.tag.value.d.ts +15 -16
  40. package/build/const/tiff.tag.value.js +16 -16
  41. package/build/const/tiff.tag.value.js.map +1 -0
  42. package/build/const/tiff.version.d.ts +0 -1
  43. package/build/const/tiff.version.js +1 -1
  44. package/build/const/tiff.version.js.map +1 -0
  45. package/build/index.d.ts +11 -6
  46. package/build/index.js +9 -5
  47. package/build/index.js.map +1 -0
  48. package/build/read/data.view.offset.d.ts +15 -0
  49. package/build/read/data.view.offset.js +19 -0
  50. package/build/read/data.view.offset.js.map +1 -0
  51. package/build/read/tiff.gdal.d.ts +9 -12
  52. package/build/read/tiff.gdal.js +22 -17
  53. package/build/read/tiff.gdal.js.map +1 -0
  54. package/build/read/tiff.ifd.config.d.ts +6 -4
  55. package/build/read/tiff.ifd.config.js +2 -2
  56. package/build/read/tiff.ifd.config.js.map +1 -0
  57. package/build/read/tiff.tag.d.ts +40 -20
  58. package/build/read/tiff.tag.factory.d.ts +16 -0
  59. package/build/read/tiff.tag.factory.js +130 -0
  60. package/build/read/tiff.tag.factory.js.map +1 -0
  61. package/build/read/tiff.tag.js +2 -37
  62. package/build/read/tiff.tag.js.map +1 -0
  63. package/build/read/tiff.value.reader.d.ts +2 -6
  64. package/build/read/tiff.value.reader.js +16 -54
  65. package/build/read/tiff.value.reader.js.map +1 -0
  66. package/build/source.d.ts +5 -0
  67. package/build/source.js +2 -0
  68. package/build/source.js.map +1 -0
  69. package/build/util/bytes.d.ts +17 -0
  70. package/build/util/bytes.js +42 -0
  71. package/build/util/bytes.js.map +1 -0
  72. package/build/util/util.hex.d.ts +2 -3
  73. package/build/util/util.hex.js +4 -5
  74. package/build/util/util.hex.js.map +1 -0
  75. package/build/vector.d.ts +0 -1
  76. package/build/vector.js +1 -1
  77. package/build/vector.js.map +1 -0
  78. package/package.json +25 -30
  79. package/src/__benchmark__/cog.read.benchmark.ts +12 -10
  80. package/src/__benchmark__/source.file.ts +23 -0
  81. package/src/__benchmark__/source.memory.ts +23 -0
  82. package/src/__test__/cog.image.test.ts +188 -197
  83. package/src/__test__/cog.read.test.ts +50 -72
  84. package/src/__test__/example.ts +31 -0
  85. package/src/cog.tiff.image.ts +456 -447
  86. package/src/cog.tiff.ts +142 -145
  87. package/src/const/index.ts +1 -1
  88. package/src/const/tiff.endian.ts +2 -2
  89. package/src/const/tiff.mime.ts +21 -21
  90. package/src/const/tiff.tag.id.ts +157 -156
  91. package/src/const/tiff.tag.value.ts +16 -16
  92. package/src/const/tiff.version.ts +11 -11
  93. package/src/index.ts +11 -5
  94. package/src/read/data.view.offset.ts +23 -0
  95. package/src/read/tiff.gdal.ts +61 -63
  96. package/src/read/tiff.ifd.config.ts +35 -31
  97. package/src/read/tiff.tag.factory.ts +163 -0
  98. package/src/read/tiff.tag.ts +40 -38
  99. package/src/read/tiff.value.reader.ts +25 -73
  100. package/src/source.ts +5 -0
  101. package/src/util/bytes.ts +44 -0
  102. package/src/util/util.hex.ts +5 -7
  103. package/src/vector.ts +5 -5
  104. package/tsconfig.json +8 -8
  105. package/build/__benchmark__/cog.read.benchmark.d.ts.map +0 -1
  106. package/build/__test__/cog.image.test.d.ts.map +0 -1
  107. package/build/__test__/cog.read.test.d.ts.map +0 -1
  108. package/build/cog.tiff.d.ts.map +0 -1
  109. package/build/cog.tiff.image.d.ts.map +0 -1
  110. package/build/const/index.d.ts.map +0 -1
  111. package/build/const/tiff.endian.d.ts.map +0 -1
  112. package/build/const/tiff.mime.d.ts.map +0 -1
  113. package/build/const/tiff.tag.id.d.ts.map +0 -1
  114. package/build/const/tiff.tag.value.d.ts.map +0 -1
  115. package/build/const/tiff.version.d.ts.map +0 -1
  116. package/build/index.d.ts.map +0 -1
  117. package/build/read/tag/__test__/tag.test.d.ts +0 -2
  118. package/build/read/tag/__test__/tag.test.d.ts.map +0 -1
  119. package/build/read/tag/__test__/tag.test.js +0 -23
  120. package/build/read/tag/tiff.tag.base.d.ts +0 -55
  121. package/build/read/tag/tiff.tag.base.d.ts.map +0 -1
  122. package/build/read/tag/tiff.tag.base.js +0 -79
  123. package/build/read/tag/tiff.tag.lazy.d.ts +0 -7
  124. package/build/read/tag/tiff.tag.lazy.d.ts.map +0 -1
  125. package/build/read/tag/tiff.tag.lazy.js +0 -18
  126. package/build/read/tag/tiff.tag.offset.d.ts +0 -21
  127. package/build/read/tag/tiff.tag.offset.d.ts.map +0 -1
  128. package/build/read/tag/tiff.tag.offset.js +0 -54
  129. package/build/read/tag/tiff.tag.static.d.ts +0 -8
  130. package/build/read/tag/tiff.tag.static.d.ts.map +0 -1
  131. package/build/read/tag/tiff.tag.static.js +0 -17
  132. package/build/read/tiff.gdal.d.ts.map +0 -1
  133. package/build/read/tiff.ifd.config.d.ts.map +0 -1
  134. package/build/read/tiff.tag.d.ts.map +0 -1
  135. package/build/read/tiff.value.reader.d.ts.map +0 -1
  136. package/build/source/cog.source.view.d.ts +0 -33
  137. package/build/source/cog.source.view.d.ts.map +0 -1
  138. package/build/source/cog.source.view.js +0 -65
  139. package/build/util/util.hex.d.ts.map +0 -1
  140. package/build/vector.d.ts.map +0 -1
  141. package/src/@types/ieee754.d.ts +0 -18
  142. package/src/read/tag/__test__/tag.test.ts +0 -27
  143. package/src/read/tag/tiff.tag.base.ts +0 -126
  144. package/src/read/tag/tiff.tag.lazy.ts +0 -17
  145. package/src/read/tag/tiff.tag.offset.ts +0 -61
  146. package/src/read/tag/tiff.tag.static.ts +0 -15
  147. package/src/source/cog.source.view.ts +0 -77
@@ -1,214 +1,205 @@
1
- import o from 'ospec';
2
- import * as path from 'path';
3
1
  import { promises as fs } from 'fs';
4
-
5
- import 'source-map-support/register.js';
6
-
7
- import { TestFileChunkSource } from '@chunkd/core/build/__test__/chunk.source.fake.js';
2
+ import assert from 'node:assert';
3
+ import { beforeEach, describe, it } from 'node:test';
4
+ import { TestFileSource } from '../__benchmark__/source.file.js';
5
+ import { SourceMemory } from '../__benchmark__/source.memory.js';
6
+ import { ByteSize } from '../util/bytes.js';
8
7
  import { CogTiff } from '../cog.tiff.js';
9
- import { TiffMimeType } from '../const/index.js';
10
- import { ByteSize, SourceMemory } from '@chunkd/core';
11
- import { fileURLToPath } from 'url';
8
+ import { TiffMimeType } from '../const/tiff.mime.js';
12
9
 
13
- const __dirname = fileURLToPath(import.meta.url);
14
10
  // 900913 properties.
15
11
  const A = 6378137.0;
16
12
  const InitialResolution = (2 * Math.PI * A) / 256;
17
13
 
18
14
  function getResolution(zoom: number): number {
19
- return InitialResolution / 2 ** zoom;
15
+ return InitialResolution / 2 ** zoom;
20
16
  }
21
17
 
22
- o.spec('CogTiled', () => {
23
- const cogSourceFile = new TestFileChunkSource(path.join(__dirname, '../../../data/rgba8_tiled.tiff'));
24
- const cog = new CogTiff(cogSourceFile);
25
-
26
- o.beforeEach(() => cog.init());
27
-
28
- o('should match resolutions to web mercator zoom levels', () => {
29
- for (let i = 0; i < 14; i++) {
30
- o(cog.getImageByResolution(getResolution(i)).id).equals(4);
31
- }
32
-
33
- o(cog.getImageByResolution(getResolution(14)).id).equals(3);
34
- o(cog.getImageByResolution(getResolution(15)).id).equals(2);
35
- o(cog.getImageByResolution(getResolution(16)).id).equals(1);
36
- o(cog.getImageByResolution(getResolution(17)).id).equals(0);
37
- o(cog.getImageByResolution(getResolution(18)).id).equals(0);
38
-
39
- for (let i = 19; i < 32; i++) {
40
- o(cog.getImageByResolution(getResolution(i)).id).equals(0);
41
- }
42
- });
43
-
44
- o('should get origin from all images', () => {
45
- const baseOrigin = cog.images[0].origin;
46
- for (const img of cog.images) {
47
- o(img.origin).deepEquals(baseOrigin);
48
- }
49
- });
50
-
51
- o('should get bounding box from all images', () => {
52
- const baseOrigin = cog.images[0].bbox;
53
- for (const img of cog.images) {
54
- o(img.bbox).deepEquals(baseOrigin);
55
- }
56
- });
57
-
58
- o('should be geolocated', () => {
59
- for (const img of cog.images) o(img.isGeoLocated).equals(true);
60
- });
61
-
62
- o('should scale image resolution for all images', () => {
63
- const [resX, resY, resZ] = cog.images[0].resolution;
64
- for (let i = 0; i < cog.images.length; i++) {
65
- const img = cog.images[i];
66
- const scale = 2 ** i; // This tiff is scaled at a factor of two per zoom level
67
- o(img.resolution).deepEquals([resX * scale, resY * scale, resZ]);
68
- }
69
- });
70
-
71
- o('should have tile information', () => {
72
- const [firstImage] = cog.images;
73
- o(firstImage.stripCount).equals(0);
74
- o(firstImage.isTiled()).equals(true);
75
- });
76
-
77
- o('should hasTile for every tile', async () => {
78
- const [firstImage] = cog.images;
79
-
80
- for (let x = 0; x < firstImage.tileCount.x; x++) {
81
- for (let y = 0; y < firstImage.tileCount.y; y++) {
82
- o(await firstImage.hasTile(x, y)).equals(true);
83
- }
84
- }
85
- });
18
+ describe('CogTiled', () => {
19
+ const cogSourceFile = new TestFileSource(new URL('../../data/rgba8_tiled.tiff', import.meta.url));
20
+ const cog = new CogTiff(cogSourceFile);
21
+
22
+ beforeEach(() => cog.init());
23
+
24
+ it('should match resolutions to web mercator zoom levels', () => {
25
+ for (let i = 0; i < 14; i++) {
26
+ assert.equal(cog.getImageByResolution(getResolution(i)).id, 4);
27
+ }
28
+
29
+ assert.equal(cog.getImageByResolution(getResolution(14)).id, 3);
30
+ assert.equal(cog.getImageByResolution(getResolution(15)).id, 2);
31
+ assert.equal(cog.getImageByResolution(getResolution(16)).id, 1);
32
+ assert.equal(cog.getImageByResolution(getResolution(17)).id, 0);
33
+ assert.equal(cog.getImageByResolution(getResolution(18)).id, 0);
34
+
35
+ for (let i = 19; i < 32; i++) {
36
+ assert.equal(cog.getImageByResolution(getResolution(i)).id, 0);
37
+ }
38
+ });
39
+
40
+ it('should get origin from all images', () => {
41
+ const baseOrigin = cog.images[0].origin;
42
+ for (const img of cog.images) {
43
+ assert.deepEqual(img.origin, baseOrigin);
44
+ }
45
+ });
46
+
47
+ it('should get bounding box from all images', () => {
48
+ const baseOrigin = cog.images[0].bbox;
49
+ for (const img of cog.images) {
50
+ assert.deepEqual(img.bbox, baseOrigin);
51
+ }
52
+ });
53
+
54
+ it('should be geolocated', () => {
55
+ for (const img of cog.images) assert.equal(img.isGeoLocated, true);
56
+ });
57
+
58
+ it('should scale image resolution for all images', () => {
59
+ const [resX, resY, resZ] = cog.images[0].resolution;
60
+ for (let i = 0; i < cog.images.length; i++) {
61
+ const img = cog.images[i];
62
+ const scale = 2 ** i; // This tiff is scaled at a factor of two per zoom level
63
+ assert.deepEqual(img.resolution, [resX * scale, resY * scale, resZ]);
64
+ }
65
+ });
66
+
67
+ it('should have tile information', () => {
68
+ const [firstImage] = cog.images;
69
+ assert.equal(firstImage.stripCount, 0);
70
+ assert.equal(firstImage.isTiled(), true);
71
+ });
72
+
73
+ it('should hasTile for every tile', async () => {
74
+ const [firstImage] = cog.images;
75
+
76
+ for (let x = 0; x < firstImage.tileCount.x; x++) {
77
+ for (let y = 0; y < firstImage.tileCount.y; y++) {
78
+ assert.equal(await firstImage.hasTile(x, y), true);
79
+ }
80
+ }
81
+ });
86
82
  });
87
83
 
88
- o.spec('Cog.Big', () => {
89
- o('should support reading from memory', async () => {
90
- const fullSource = new TestFileChunkSource(path.join(__dirname, '../../../data/sparse.tiff'));
91
- fullSource.chunkSize = 27902;
92
- await fullSource.loadBytes(0, 27902);
93
- const cog = new CogTiff(fullSource);
94
- await cog.init();
95
-
96
- o(fullSource.chunkSize).equals(27902);
97
- o(fullSource.chunks.size).equals(1);
98
- const [firstImage] = cog.images;
99
- o(firstImage.stripCount).equals(0);
100
- o(firstImage.isTiled()).equals(true);
101
-
102
- const img = cog.getImage(4);
103
- o(img.tileCount).deepEquals({ x: 2, y: 2 });
104
- });
105
-
106
- o('should read using a memory source', async () => {
107
- const bytes = await fs.readFile(path.join(__dirname, '../../../data/sparse.tiff'));
108
- const source = new SourceMemory('Sparse.tiff', bytes.buffer);
109
- const cog = new CogTiff(source);
110
- await cog.init();
111
-
112
- o(source.chunkSize).equals(27902);
113
- o(source.chunks.size).equals(1);
114
- const [firstImage] = cog.images;
115
- o(firstImage.stripCount).equals(0);
116
- o(firstImage.isTiled()).equals(true);
117
-
118
- const img = cog.getImage(4);
119
- o(img.tileCount).deepEquals({ x: 2, y: 2 });
120
- });
84
+ describe('Cog.Big', () => {
85
+ it('should support reading from memory', async () => {
86
+ const fullSource = new TestFileSource(new URL('../../data/sparse.tiff', import.meta.url));
87
+
88
+ const cog = new CogTiff(fullSource);
89
+ await cog.init();
90
+
91
+ const [firstImage] = cog.images;
92
+ assert.equal(firstImage.stripCount, 0);
93
+ assert.equal(firstImage.isTiled(), true);
94
+
95
+ const img = cog.images[4];
96
+ assert.deepEqual(img.tileCount, { x: 2, y: 2 });
97
+ });
98
+
99
+ it('should read using a memory source', async () => {
100
+ const bytes = await fs.readFile(new URL('../../data/sparse.tiff', import.meta.url));
101
+ const source = new SourceMemory(bytes.buffer);
102
+ const cog = new CogTiff(source);
103
+ await cog.init();
104
+
105
+ const [firstImage] = cog.images;
106
+ assert.equal(firstImage.stripCount, 0);
107
+ assert.equal(firstImage.isTiled(), true);
108
+
109
+ const img = cog.images[4];
110
+ assert.deepEqual(img.tileCount, { x: 2, y: 2 });
111
+ });
121
112
  });
122
113
 
123
- o.spec('Cog.Sparse', () => {
124
- const cogSourceFile = new TestFileChunkSource(path.join(__dirname, '../../../data/sparse.tiff'));
125
- const cog = new CogTiff(cogSourceFile);
126
- o.beforeEach(() => cog.init(true));
127
-
128
- o('should read metadata', () => {
129
- o(cog.getImage(0).epsg).equals(2193);
130
- });
131
-
132
- o('should be geolocated', () => {
133
- for (const img of cog.images) o(img.isGeoLocated).equals(true);
134
- });
135
-
136
- o('should support sparse cogs', async () => {
137
- const z = 4;
138
- const img = cog.getImage(z);
139
-
140
- const { tileCount } = img;
141
- o(tileCount).deepEquals({ x: 2, y: 2 });
142
-
143
- for (let x = 0; x < tileCount.x; x++) {
144
- for (let y = 0; y < tileCount.y; y++) {
145
- const hasTile = await img.hasTile(x, y);
146
- o(hasTile).equals(false);
147
- const tileXy = await img.getTile(x, y);
148
- const tileXyz = await cog.getTile(x, y, z);
149
- o(tileXy).equals(null)(`Tile x:${x} y:${y} should be empty`);
150
- o(tileXyz).equals(null)(`Tile x:${x} y:${y} z: ${z} should be empty`);
151
- }
152
- }
153
- });
154
-
155
- o('should have ghost options', () => {
156
- o(cog.options.options.size).equals(6);
157
- o(cog.options.tileLeaderByteSize).equals(ByteSize.UInt32);
158
- o(cog.options.isCogOptimized).equals(true);
159
-
160
- const entries = [...cog.options.options.entries()];
161
- o(entries).deepEquals([
162
- ['GDAL_STRUCTURAL_METADATA_SIZE', '000140 bytes'],
163
- ['LAYOUT', 'IFDS_BEFORE_DATA'],
164
- ['BLOCK_ORDER', 'ROW_MAJOR'],
165
- ['BLOCK_LEADER', 'SIZE_AS_UINT4'],
166
- ['BLOCK_TRAILER', 'LAST_4_BYTES_REPEATED'],
167
- ['KNOWN_INCOMPATIBLE_EDITION', 'NO'],
168
- ]);
169
- });
114
+ describe('Cog.Sparse', () => {
115
+ const cogSourceFile = new TestFileSource(new URL('../../data/sparse.tiff', import.meta.url));
116
+ const cog = new CogTiff(cogSourceFile);
117
+
118
+ it('should read metadata', async () => {
119
+ await cog.init();
120
+ assert.equal(cog.images[0].epsg, 2193);
121
+ });
122
+
123
+ it('should be geolocated', () => {
124
+ for (const img of cog.images) assert.equal(img.isGeoLocated, true);
125
+ });
126
+
127
+ it('should support sparse cogs', async () => {
128
+ const z = 4;
129
+ const img = cog.images[z];
130
+
131
+ const { tileCount } = img;
132
+ assert.deepEqual(tileCount, { x: 2, y: 2 });
133
+
134
+ for (let x = 0; x < tileCount.x; x++) {
135
+ for (let y = 0; y < tileCount.y; y++) {
136
+ const hasTile = await img.hasTile(x, y);
137
+ assert.equal(hasTile, false);
138
+ const tileXy = await img.getTile(x, y);
139
+ const tileXyz = await cog.images[z].getTile(x, y);
140
+ assert.equal(tileXy, null, `Tile x:${x} y:${y} should be empty`);
141
+ assert.equal(tileXyz, null, `Tile x:${x} y:${y} z: ${z} should be empty`);
142
+ }
143
+ }
144
+ });
145
+
146
+ it('should have ghost options', () => {
147
+ assert.equal(cog.options?.options.size, 6);
148
+ assert.equal(cog.options?.tileLeaderByteSize, ByteSize.UInt32);
149
+ assert.equal(cog.options?.isCogOptimized, true);
150
+
151
+ const entries = [...(cog.options?.options.entries() ?? [])];
152
+ assert.deepEqual(entries, [
153
+ ['GDAL_STRUCTURAL_METADATA_SIZE', '000140 bytes'],
154
+ ['LAYOUT', 'IFDS_BEFORE_DATA'],
155
+ ['BLOCK_ORDER', 'ROW_MAJOR'],
156
+ ['BLOCK_LEADER', 'SIZE_AS_UINT4'],
157
+ ['BLOCK_TRAILER', 'LAST_4_BYTES_REPEATED'],
158
+ ['KNOWN_INCOMPATIBLE_EDITION', 'NO'],
159
+ ]);
160
+ });
170
161
  });
171
162
 
172
- o.spec('CogStrip', () => {
173
- const cogSourceFile = new TestFileChunkSource(path.join(__dirname, '../../../data/rgba8_strip.tiff'));
174
- const cog = new CogTiff(cogSourceFile);
175
-
176
- o.beforeEach(() => cog.init());
177
-
178
- o('should get origin from all images', () => {
179
- const baseOrigin = cog.images[0].origin;
180
- for (const img of cog.images) {
181
- o(img.origin).deepEquals(baseOrigin);
182
- }
183
- });
184
-
185
- o('should get bounding box from all images', () => {
186
- const baseOrigin = cog.images[0].bbox;
187
- for (const img of cog.images) {
188
- o(img.bbox).deepEquals(baseOrigin);
189
- }
190
- });
191
-
192
- o('should scale image resolution for all images', () => {
193
- const [resX, resY, resZ] = cog.images[0].resolution;
194
- for (let i = 0; i < cog.images.length; i++) {
195
- const img = cog.images[i];
196
- const scale = 2 ** i; // This tiff is scaled at a factor of two per zoom level
197
- o(img.resolution).deepEquals([resX * scale, resY * scale, resZ]);
198
- }
199
- });
200
-
201
- o('should have strip information', async () => {
202
- const [firstImage] = cog.images;
203
- o(firstImage.isTiled()).equals(false);
204
- o(firstImage.stripCount).equals(2);
205
-
206
- const stripA = await firstImage.getStrip(0);
207
- o(stripA?.mimeType).equals(TiffMimeType.WEBP);
208
- o(stripA?.bytes.byteLength).equals(152);
209
-
210
- const stripB = await firstImage.getStrip(1);
211
- o(stripB?.mimeType).equals(TiffMimeType.WEBP);
212
- o(stripB?.bytes.byteLength).equals(152);
213
- });
163
+ describe('CogStrip', () => {
164
+ const cogSourceFile = new TestFileSource(new URL('../../data/rgba8_strip.tiff', import.meta.url));
165
+ const cog = new CogTiff(cogSourceFile);
166
+
167
+ beforeEach(() => cog.init());
168
+
169
+ it('should get origin from all images', () => {
170
+ const baseOrigin = cog.images[0].origin;
171
+ for (const img of cog.images) {
172
+ assert.deepEqual(img.origin, baseOrigin);
173
+ }
174
+ });
175
+
176
+ it('should get bounding box from all images', () => {
177
+ const baseOrigin = cog.images[0].bbox;
178
+ for (const img of cog.images) {
179
+ assert.deepEqual(img.bbox, baseOrigin);
180
+ }
181
+ });
182
+
183
+ it('should scale image resolution for all images', () => {
184
+ const [resX, resY, resZ] = cog.images[0].resolution;
185
+ for (let i = 0; i < cog.images.length; i++) {
186
+ const img = cog.images[i];
187
+ const scale = 2 ** i; // This tiff is scaled at a factor of two per zoom level
188
+ assert.deepEqual(img.resolution, [resX * scale, resY * scale, resZ]);
189
+ }
190
+ });
191
+
192
+ it('should have strip information', async () => {
193
+ const [firstImage] = cog.images;
194
+ assert.equal(firstImage.isTiled(), false);
195
+ assert.equal(firstImage.stripCount, 2);
196
+
197
+ const stripA = await firstImage.getStrip(0);
198
+ assert.equal(stripA?.mimeType, TiffMimeType.Webp);
199
+ assert.equal(stripA?.bytes.byteLength, 152);
200
+
201
+ const stripB = await firstImage.getStrip(1);
202
+ assert.equal(stripB?.mimeType, TiffMimeType.Webp);
203
+ assert.equal(stripB?.bytes.byteLength, 152);
204
+ });
214
205
  });
@@ -1,90 +1,68 @@
1
- import o from 'ospec';
2
- import * as path from 'path';
3
- import 'source-map-support/register.js';
4
-
1
+ import assert from 'node:assert';
2
+ import { describe, it } from 'node:test';
5
3
  import { CogTiff } from '../cog.tiff.js';
6
- import { TiffVersion } from '../const/tiff.version.js';
7
4
  import { TiffMimeType } from '../const/tiff.mime.js';
8
- import { TestFileChunkSource } from '@chunkd/core/build/__test__/chunk.source.fake.js';
9
- import { fileURLToPath } from 'url';
10
-
11
- const __dirname = fileURLToPath(import.meta.url);
12
-
13
- o.spec('CogRead', () => {
14
- // TODO this does not load 100% yet
15
- // o('should read big endian', async () => {
16
- // const source = new TestFileChunkSource(path.join(__dirname, '../../../test/data/be_cog.tif'))
17
- // const tif = new CogTif(source);
18
-
19
- // await tif.init();
5
+ import { TestFileSource } from '../__benchmark__/source.file.js';
6
+ import { TiffVersion } from '../const/tiff.version.js';
20
7
 
21
- // o(source.isLittleEndian).equals(false);
22
- // o(source.version).equals(TiffVersion.Tiff);
23
- // o(tif.images.length).equals(5)
24
- // const [firstTif] = tif.images;
25
- // o(firstTif.isTiled()).equals(true);
26
- //
27
- // // o(firstTif.compression).equals('image/jpeg')
28
- // })
8
+ function validate(tif: CogTiff): void {
9
+ assert.equal(tif.images.length, 5);
29
10
 
30
- function validate(tif: CogTiff): void {
31
- o(tif.images.length).equals(5);
11
+ const [firstTif] = tif.images;
12
+ assert.equal(firstTif.isTiled(), true);
13
+ assert.deepEqual(firstTif.tileSize, { width: 256, height: 256 });
14
+ assert.deepEqual(firstTif.size, { width: 64, height: 64 });
15
+ }
32
16
 
33
- const [firstTif] = tif.images;
34
- o(firstTif.isTiled()).equals(true);
35
- o(firstTif.tileSize).deepEquals({ width: 256, height: 256 });
36
- o(firstTif.size).deepEquals({ width: 64, height: 64 });
37
- }
17
+ describe('CogRead', () => {
18
+ // TODO this does not load 100% yet
19
+ // it('should read big endian', async () => {
20
+ // const source = new TestFileSource(new URL('../../data/big_cog.tiff', import.meta.url));
21
+ // const tiff = new CogTiff(source);
38
22
 
39
- o('should read big tiff', async () => {
40
- const source = new TestFileChunkSource(path.join(__dirname, '../../../data/big_cog.tif'));
41
- const tiff = new CogTiff(source);
23
+ // await tiff.init();
42
24
 
43
- await tiff.init();
25
+ // assert.equal(tiff.isLittleEndian, false);
26
+ // assert.equal(tiff.version, TiffVersion.BigTiff);
27
+ // validate(tiff);
28
+ // });
44
29
 
45
- o(source.isLittleEndian).equals(true);
46
- o(tiff.version).equals(TiffVersion.BigTiff);
47
- validate(tiff);
48
- });
30
+ it('should read big tiff', async () => {
31
+ const source = new TestFileSource(new URL('../../data/big_cog.tiff', import.meta.url));
32
+ const tiff = new CogTiff(source);
49
33
 
50
- o('should read tiff', async () => {
51
- const source = new TestFileChunkSource(path.join(__dirname, '../../../data/cog.tif'));
52
- const tiff = new CogTiff(source);
34
+ await tiff.init();
53
35
 
54
- await tiff.init();
36
+ assert.equal(tiff.isLittleEndian, true);
37
+ assert.equal(tiff.version, TiffVersion.BigTiff);
38
+ validate(tiff);
39
+ });
55
40
 
56
- o(source.isLittleEndian).equals(true);
57
- o(tiff.version).equals(TiffVersion.Tiff);
58
- validate(tiff);
41
+ it('should read tiff', async () => {
42
+ const source = new TestFileSource(new URL('../../data/cog.tiff', import.meta.url));
43
+ const tiff = new CogTiff(source);
59
44
 
60
- const [firstTif] = tiff.images;
61
- o(firstTif.compression).equals(TiffMimeType.JPEG);
62
- });
45
+ await tiff.init();
63
46
 
64
- o('should allow multiple init', async () => {
65
- const source = new TestFileChunkSource(path.join(__dirname, '../../../data/cog.tif'));
66
- const tiff = new CogTiff(source);
47
+ assert.equal(tiff.isLittleEndian, true);
48
+ assert.equal(tiff.version, TiffVersion.Tiff);
49
+ validate(tiff);
67
50
 
68
- o(tiff.isInitialized).equals(false);
69
- await tiff.init();
70
- o(tiff.isInitialized).equals(true);
71
- o(tiff.images.length).equals(5);
51
+ const [firstTif] = tiff.images;
52
+ assert.equal(firstTif.compression, TiffMimeType.Jpeg);
53
+ });
72
54
 
73
- o(tiff.isInitialized).equals(true);
74
- await tiff.init();
75
- o(tiff.images.length).equals(5);
76
- });
55
+ it('should allow multiple init', async () => {
56
+ const source = new TestFileSource(new URL('../../data/cog.tiff', import.meta.url));
57
+ const tiff = new CogTiff(source);
77
58
 
78
- o('should close a source', async () => {
79
- const source = new TestFileChunkSource(path.join(__dirname, '../../../data/cog.tif'));
80
- const tiff = new CogTiff(source);
81
- // Should not close if there is no close
82
- source.close = undefined;
83
- await tiff.close();
59
+ assert.equal(tiff.isInitialized, false);
60
+ await tiff.init();
61
+ assert.equal(tiff.isInitialized, true);
62
+ assert.equal(tiff.images.length, 5);
84
63
 
85
- const closeSpy = o.spy(() => Promise.resolve());
86
- source.close = closeSpy;
87
- await tiff.close();
88
- o(closeSpy.callCount).equals(1);
89
- });
64
+ assert.equal(tiff.isInitialized, true);
65
+ await tiff.init();
66
+ assert.equal(tiff.images.length, 5);
67
+ });
90
68
  });
@@ -0,0 +1,31 @@
1
+ import { SourceHttp } from '@chunkd/source-http';
2
+ import { CogTiff } from '../index.js';
3
+
4
+ async function main(): Promise<void> {
5
+ const source = new SourceHttp('https://example.com/cog.tif');
6
+ const tiff = await CogTiff.create(source);
7
+
8
+ /** Load a specific tile from a specific image */
9
+ const tile = await tiff.images[5].getTile(2, 2);
10
+ if (tile != null) {
11
+ tile.bytes; // Raw image buffer or null if tile doesn't exist
12
+ }
13
+
14
+ /** Load the 5th image in the Tiff */
15
+ const img = tiff.images[5];
16
+ if (img.isTiled()) {
17
+ /** Load tile x:10 y:10 */
18
+ const tile = await img.getTile(10, 10);
19
+ if (tile != null) {
20
+ tile.mimeType; // image/jpeg
21
+ tile.bytes; // Raw image buffer
22
+ }
23
+ }
24
+
25
+ /** Get the origin point of the tiff */
26
+ img.origin;
27
+ /** Bounding box of the tiff */
28
+ img.bbox;
29
+ }
30
+
31
+ main();