@cogeotiff/cli 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 (74) hide show
  1. package/CHANGELOG.md +10 -485
  2. package/README.md +26 -34
  3. package/bin/cogeotiff.js +1 -2
  4. package/build/action.util.d.ts +2 -8
  5. package/build/action.util.js +7 -18
  6. package/build/action.util.js.map +1 -0
  7. package/build/bin.d.ts +1 -0
  8. package/build/bin.js +13 -0
  9. package/build/bin.js.map +1 -0
  10. package/build/cli.table.d.ts +0 -1
  11. package/build/cli.table.js +9 -4
  12. package/build/cli.table.js.map +1 -0
  13. package/build/commands/dump.d.ts +27 -0
  14. package/build/commands/dump.js +132 -0
  15. package/build/commands/dump.js.map +1 -0
  16. package/build/commands/info.d.ts +19 -0
  17. package/build/commands/info.js +185 -0
  18. package/build/commands/info.js.map +1 -0
  19. package/build/common.d.ts +16 -0
  20. package/build/common.js +19 -0
  21. package/build/common.js.map +1 -0
  22. package/build/fs.d.ts +6 -0
  23. package/build/fs.js +17 -0
  24. package/build/fs.js.map +1 -0
  25. package/build/index.d.ts +57 -2
  26. package/build/index.js +11 -8
  27. package/build/index.js.map +1 -0
  28. package/build/log.d.ts +11 -0
  29. package/build/log.js +37 -0
  30. package/build/log.js.map +1 -0
  31. package/build/util.bytes.d.ts +0 -1
  32. package/build/util.bytes.js +1 -1
  33. package/build/util.bytes.js.map +1 -0
  34. package/build/util.tile.d.ts +2 -3
  35. package/build/util.tile.js +20 -18
  36. package/build/util.tile.js.map +1 -0
  37. package/package.json +37 -37
  38. package/src/action.util.ts +22 -37
  39. package/src/bin.ts +14 -0
  40. package/src/cli.table.ts +27 -27
  41. package/src/commands/dump.ts +156 -0
  42. package/src/commands/info.ts +199 -0
  43. package/src/common.ts +20 -0
  44. package/src/fs.ts +18 -0
  45. package/src/index.ts +10 -7
  46. package/src/log.ts +43 -0
  47. package/src/util.bytes.ts +6 -6
  48. package/src/util.tile.ts +33 -33
  49. package/tsconfig.json +8 -8
  50. package/build/action.dump.tile.d.ts +0 -24
  51. package/build/action.dump.tile.d.ts.map +0 -1
  52. package/build/action.dump.tile.js +0 -194
  53. package/build/action.info.d.ts +0 -10
  54. package/build/action.info.d.ts.map +0 -1
  55. package/build/action.info.js +0 -183
  56. package/build/action.tile.d.ts +0 -9
  57. package/build/action.tile.d.ts.map +0 -1
  58. package/build/action.tile.js +0 -64
  59. package/build/action.util.d.ts.map +0 -1
  60. package/build/cli.cog.info.d.ts +0 -9
  61. package/build/cli.cog.info.d.ts.map +0 -1
  62. package/build/cli.cog.info.js +0 -42
  63. package/build/cli.log.d.ts +0 -3
  64. package/build/cli.log.d.ts.map +0 -1
  65. package/build/cli.log.js +0 -4
  66. package/build/cli.table.d.ts.map +0 -1
  67. package/build/index.d.ts.map +0 -1
  68. package/build/util.bytes.d.ts.map +0 -1
  69. package/build/util.tile.d.ts.map +0 -1
  70. package/src/action.dump.tile.ts +0 -240
  71. package/src/action.info.ts +0 -205
  72. package/src/action.tile.ts +0 -76
  73. package/src/cli.cog.info.ts +0 -45
  74. package/src/cli.log.ts +0 -4
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.log.d.ts","sourceRoot":"","sources":["../src/cli.log.ts"],"names":[],"mappings":";AAGA,eAAO,MAAM,MAAM,qDAAiE,CAAC"}
package/build/cli.log.js DELETED
@@ -1,4 +0,0 @@
1
- import pino from 'pino';
2
- import { PrettyTransform } from 'pretty-json-log';
3
- export const logger = process.stdout.isTTY ? pino(PrettyTransform.stream()) : pino();
4
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmxvZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jbGkubG9nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUN4QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFbEQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBpbm8gZnJvbSAncGlubyc7XG5pbXBvcnQgeyBQcmV0dHlUcmFuc2Zvcm0gfSBmcm9tICdwcmV0dHktanNvbi1sb2cnO1xuXG5leHBvcnQgY29uc3QgbG9nZ2VyID0gcHJvY2Vzcy5zdGRvdXQuaXNUVFkgPyBwaW5vKFByZXR0eVRyYW5zZm9ybS5zdHJlYW0oKSkgOiBwaW5vKCk7XG4iXX0=
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.table.d.ts","sourceRoot":"","sources":["../src/cli.table.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY,CAAC,CAAC;IACpB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC/C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC;CACjC;AAED,qBAAa,QAAQ,CAAC,CAAC;IACnB,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAM;IAC/B,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI;IAIlC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,UAAU,SAAK,GAAG,MAAM,EAAE;CAa9C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gCAAgC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.bytes.d.ts","sourceRoot":"","sources":["../src/util.bytes.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"util.tile.d.ts","sourceRoot":"","sources":["../src/util.tile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAgB,MAAM,iBAAiB,CAAC;AAGxD,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAU7B;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUzF;AAED,wBAAsB,SAAS,CAC3B,GAAG,EAAE,OAAO,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,IAAI,CAAC,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC,CASf"}
@@ -1,240 +0,0 @@
1
- import { CogTiff, TiffVersion } from '@cogeotiff/core';
2
- import { CommandLineAction, CommandLineIntegerParameter, CommandLineStringParameter } from '@rushstack/ts-command-line';
3
- import c from 'ansi-colors';
4
- import { promises as fs } from 'fs';
5
- import * as path from 'path';
6
- import { ActionUtil, CliResultMap } from './action.util.js';
7
- import { logger as CliLogger } from './cli.log.js';
8
- import { toByteSizeString } from './util.bytes.js';
9
- import { getTileName, writeTile } from './util.tile.js';
10
- import PLimit from 'p-limit';
11
- import { ChunkSourceBase } from '@chunkd/core';
12
- import pino from 'pino';
13
-
14
- const Rad2Deg = 180 / Math.PI;
15
- const A = 6378137.0; // 900913 properties.
16
- function toLatLng(x: number, y: number): [number, number] {
17
- return [(x * Rad2Deg) / A, (Math.PI * 0.5 - 2.0 * Math.atan(Math.exp(-y / A))) * Rad2Deg];
18
- }
19
-
20
- const TileQueue = PLimit(25);
21
-
22
- export interface GeoJsonPolygon {
23
- type: 'Feature';
24
- geometry: {
25
- type: 'Polygon';
26
- coordinates: [[[number, number], [number, number], [number, number], [number, number], [number, number]]];
27
- };
28
- properties: Record<string, unknown>;
29
- }
30
-
31
- function makePolygon(xMin: number, yMin: number, xMax: number, yMax: number): GeoJsonPolygon {
32
- const [lngMin, latMin] = toLatLng(xMin, yMin);
33
- const [lngMax, latMax] = toLatLng(xMax, yMax);
34
-
35
- return {
36
- type: 'Feature',
37
- properties: {},
38
- geometry: {
39
- type: 'Polygon',
40
- coordinates: [
41
- [
42
- [lngMin, latMin],
43
- [lngMin, latMax],
44
- [lngMax, latMax],
45
- [lngMax, latMin],
46
- [lngMin, latMin],
47
- ],
48
- ],
49
- },
50
- };
51
- }
52
-
53
- export class ActionDumpTile extends CommandLineAction {
54
- private file: CommandLineStringParameter | null = null;
55
- private imageIndex: CommandLineIntegerParameter | null = null;
56
- private output: CommandLineStringParameter | null = null;
57
- private outputCount = 0;
58
- private logger: pino.Logger;
59
-
60
- public constructor() {
61
- super({
62
- actionName: 'dump',
63
- summary: 'Dump tiles from a COG',
64
- documentation: 'Stuff',
65
- });
66
- this.logger = CliLogger.child({ action: 'tile' });
67
- }
68
-
69
- // TODO this only works for WSG84
70
- async dumpBounds(tif: CogTiff, output: string, index: number): Promise<void> {
71
- this.logger.info({ index }, 'CreateTileBounds');
72
- const img = tif.getImage(index);
73
- if (!img.isTiled() || !img.isGeoLocated) return;
74
-
75
- const features: GeoJsonPolygon[] = [];
76
- const featureCollection = {
77
- type: 'FeatureCollection',
78
- features,
79
- };
80
-
81
- const tileCount = img.tileCount;
82
- const tileInfo = img.tileSize;
83
- const tileSize = img.size;
84
-
85
- const firstImage = tif.images[0];
86
- const firstTileSize = firstImage.size;
87
- const origin = firstImage.origin;
88
- const resolution = firstImage.resolution;
89
-
90
- const xScale = (resolution[0] * firstTileSize.width) / tileSize.width;
91
- const yScale = (resolution[1] * firstTileSize.height) / tileSize.height;
92
-
93
- for (let y = 0; y < tileCount.y; y++) {
94
- const yMax = origin[1] + y * tileInfo.height * yScale;
95
- const yMin = yMax + tileInfo.height * yScale;
96
- for (let x = 0; x < tileCount.x; x++) {
97
- const xMin = origin[0] + x * tileInfo.width * xScale;
98
- const xMax = xMin + tileInfo.width * xScale;
99
- features.push(makePolygon(xMin, yMin, xMax, yMax));
100
- }
101
- }
102
-
103
- await fs.writeFile(path.join(output, `i${index}.bounds.geojson`), JSON.stringify(featureCollection, null, 2));
104
- }
105
-
106
- async dumpIndex(tif: CogTiff, output: string, index: number): Promise<void> {
107
- this.logger.info({ index }, 'CreateIndexHtml');
108
- const img = tif.getImage(index);
109
- if (!img.isTiled()) {
110
- return;
111
- }
112
-
113
- const { tileCount, tileSize } = img;
114
-
115
- const styles = `<style>.c { min-width: ${tileSize.width}px; min-height: ${tileSize.height}px }</style>`;
116
-
117
- const html = ['<html>', styles];
118
- for (let y = 0; y < tileCount.y; y++) {
119
- html.push('\t<div style="display:flex;">');
120
- for (let x = 0; x < tileCount.x; x++) {
121
- const tile = await tif.getTile(x, y, index);
122
- if (tile == null) {
123
- html.push(`\t\t<div class="c"></div>`);
124
- continue;
125
- }
126
-
127
- html.push(`\t\t<img class="c" src="./${getTileName(tile.mimeType, index, x, y)}" >`);
128
- }
129
-
130
- html.push('\t</div>');
131
- }
132
- html.push('</html>');
133
- await fs.writeFile(path.join(output, 'index.html'), html.join('\n'));
134
- }
135
-
136
- async dumpTiles(tif: CogTiff, output: string, index: number): Promise<void> {
137
- const promises: Promise<void>[] = [];
138
- const img = tif.getImage(index);
139
- if (!img.isTiled()) {
140
- return;
141
- }
142
-
143
- this.logger.info({ ...img.tileSize, ...img.tileCount }, 'TileInfo');
144
- const tileCount = img.tileCount;
145
-
146
- // Load all offsets in
147
- await img.tileOffset.load();
148
-
149
- for (let x = 0; x < tileCount.x; x++) {
150
- for (let y = 0; y < tileCount.y; y++) {
151
- const promise = TileQueue(() => writeTile(tif, x, y, index, output, this.logger));
152
- promises.push(promise);
153
- this.outputCount++;
154
- }
155
- }
156
-
157
- await Promise.all(promises);
158
- }
159
-
160
- async onExecute(): Promise<void> {
161
- if (
162
- this.imageIndex == null ||
163
- this.imageIndex.value == null ||
164
- this.output == null ||
165
- this.output.value == null
166
- ) {
167
- return;
168
- }
169
- this.outputCount = 0;
170
-
171
- const { tif } = await ActionUtil.getCogSource(this.file);
172
- const index = this.imageIndex.value;
173
- if (index == null || index > tif.images.length - 1 || index < -1) {
174
- this.renderHelpText();
175
- throw Error(`Invalid index level "${index}" must be between 0 - ${tif.images.length - 1}`);
176
- }
177
-
178
- const img = tif.getImage(index);
179
- if (!img.isTiled()) {
180
- throw Error('Tif file is not tiled.');
181
- }
182
-
183
- const output = path.join(this.output.value, `i${index}`);
184
- await fs.mkdir(output, { recursive: true });
185
-
186
- await this.dumpTiles(tif, output, index);
187
- await this.dumpIndex(tif, output, index);
188
- await this.dumpBounds(tif, this.output.value, index);
189
-
190
- const source = tif.source as ChunkSourceBase;
191
- const chunkIds = [...(source.chunks as Map<unknown, unknown>).values()];
192
- const result: CliResultMap[] = [
193
- {
194
- keys: [
195
- { key: 'Tiff type', value: `${TiffVersion[tif.version]} (v${String(tif.version)})` },
196
- { key: 'Chunk size', value: toByteSizeString(tif.source.chunkSize) },
197
- {
198
- key: 'Bytes read',
199
- value:
200
- `${toByteSizeString(chunkIds.length * tif.source.chunkSize)} ` +
201
- `(${chunkIds.length} Chunk${chunkIds.length === 1 ? '' : 's'})`,
202
- },
203
- ],
204
- },
205
- {
206
- title: 'Output',
207
- keys: [{ key: 'Images', value: this.outputCount }],
208
- },
209
- ];
210
- const msg = ActionUtil.formatResult(`${c.bold('COG File Info')} - ${c.bold(tif.source.uri)}`, result);
211
- console.log(msg.join('\n'));
212
- return Promise.resolve();
213
- }
214
-
215
- protected onDefineParameters(): void {
216
- this.file = this.defineStringParameter({
217
- argumentName: 'FILE',
218
- parameterLongName: '--file',
219
- parameterShortName: '-f',
220
- description: 'cog file to access',
221
- required: true,
222
- });
223
-
224
- this.imageIndex = this.defineIntegerParameter({
225
- argumentName: 'IMAGE',
226
- parameterShortName: '-i',
227
- parameterLongName: '--image',
228
- description: 'Image id to export (starting from 0)',
229
- required: true,
230
- });
231
-
232
- this.output = this.defineStringParameter({
233
- argumentName: 'OUTPUT',
234
- parameterShortName: '-o',
235
- parameterLongName: '--output',
236
- description: 'Where to store the output',
237
- required: true,
238
- });
239
- }
240
- }
@@ -1,205 +0,0 @@
1
- import { ChunkSourceBase } from '@chunkd/core';
2
- import { CogTiffImage, TiffTag, TiffTagGeo, TiffVersion } from '@cogeotiff/core';
3
- import { CommandLineAction, CommandLineFlagParameter, CommandLineStringParameter } from '@rushstack/ts-command-line';
4
- import c from 'ansi-colors';
5
- import { ActionUtil, CliResultMap } from './action.util.js';
6
- import { CliTable } from './cli.table.js';
7
- import { toByteSizeString } from './util.bytes.js';
8
-
9
- function formatTag(tagId: TiffTag | TiffTagGeo, tagName: string, tagValue: any): { key: string; value: string } {
10
- const key = `${String(tagId).padEnd(7, ' ')} ${String(tagName).padEnd(20)}`;
11
-
12
- if (Array.isArray(tagValue)) {
13
- return { key, value: tagValue.slice(0, 250).join(', ') };
14
- }
15
- return { key, value: String(tagValue).substr(0, 1024) };
16
- }
17
-
18
- function round(num: number): number {
19
- const opt = 10 ** 4;
20
- return Math.floor(num * opt) / opt;
21
- }
22
-
23
- const TiffImageInfoTable = new CliTable<CogTiffImage>();
24
- TiffImageInfoTable.add({ name: 'Id', width: 4, get: (i, index) => String(index) });
25
- TiffImageInfoTable.add({ name: 'Size', width: 20, get: (i) => `${i.size.width}x${i.size.height}` });
26
- TiffImageInfoTable.add({
27
- name: 'Tile Size',
28
- width: 20,
29
- get: (i) => `${i.tileCount.x}x${i.tileCount.y}`,
30
- enabled: (i) => i.isTiled(),
31
- });
32
- TiffImageInfoTable.add({
33
- name: 'Tile Count',
34
- width: 20,
35
- get: (i) => `${i.tileCount.x * i.tileCount.y}`,
36
- enabled: (i) => i.isTiled(),
37
- });
38
- TiffImageInfoTable.add({
39
- name: 'Strip Count',
40
- width: 20,
41
- get: (i) => `${i.tags.get(TiffTag.StripOffsets)?.dataCount}`,
42
- enabled: (i) => !i.isTiled(),
43
- });
44
- TiffImageInfoTable.add({
45
- name: 'Resolution',
46
- width: 20,
47
- get: (i) => `${round(i.resolution[0])}`,
48
- enabled: (i) => i.isGeoLocated,
49
- });
50
-
51
- // Show compression only if it varies between images
52
- TiffImageInfoTable.add({
53
- name: 'Compression',
54
- width: 20,
55
- get: (i) => i.compression,
56
- enabled: (i) => {
57
- const formats = new Set();
58
- i.tif.images.forEach((f) => formats.add(f.compression));
59
- return formats.size > 1;
60
- },
61
- });
62
-
63
- /**
64
- * Parse out the GDAL Metadata to be more friendly to read
65
- *
66
- * TODO using a XML Parser will make this even better
67
- * @param img
68
- */
69
- function parseGdalMetadata(img: CogTiffImage): string[] | null {
70
- const metadata = img.value(TiffTag.GDAL_METADATA);
71
- if (typeof metadata !== 'string') return null;
72
- if (!metadata.startsWith('<GDALMetadata>')) return null;
73
- return metadata
74
- .replace('<GDALMetadata>\n', '')
75
- .replace('</GDALMetadata>\n', '')
76
- .replace('\n\x00', '')
77
- .split('\n')
78
- .map((c) => c.trim());
79
- }
80
-
81
- export class ActionCogInfo extends CommandLineAction {
82
- private file?: CommandLineStringParameter;
83
- private tags?: CommandLineFlagParameter;
84
- private tagsAll?: CommandLineFlagParameter;
85
-
86
- public constructor() {
87
- super({
88
- actionName: 'info',
89
- summary: 'Shows info about a COG',
90
- documentation: '',
91
- });
92
- }
93
-
94
- async onExecute(): Promise<void> {
95
- const { tif } = await ActionUtil.getCogSource(this.file);
96
- const [firstImage] = tif.images;
97
-
98
- await firstImage.loadGeoTiffTags();
99
-
100
- const source = tif.source as ChunkSourceBase;
101
- const chunkIds = [...(source.chunks as Map<unknown, unknown>).values()];
102
-
103
- const imageInfo = '\n' + TiffImageInfoTable.print(tif.images, '\t\t').join('\n');
104
-
105
- const gdalMetadata = parseGdalMetadata(firstImage);
106
- const ghostOptions = [...tif.options.options.entries()];
107
-
108
- const isGeoLocated = firstImage.isGeoLocated;
109
-
110
- const result: CliResultMap[] = [
111
- {
112
- keys: [
113
- { key: 'Tiff type', value: `${TiffVersion[tif.version]} (v${String(tif.version)})` },
114
- { key: 'Chunk size', value: toByteSizeString(tif.source.chunkSize) },
115
- {
116
- key: 'Bytes read',
117
- value: `${toByteSizeString(chunkIds.length * tif.source.chunkSize)} (${chunkIds.length} Chunk${
118
- chunkIds.length === 1 ? '' : 's'
119
- })`,
120
- },
121
- ],
122
- },
123
- {
124
- title: 'Images',
125
- keys: [
126
- { key: 'Compression', value: firstImage.compression },
127
- isGeoLocated ? { key: 'Origin', value: firstImage.origin.map(round).join(', ') } : null,
128
- isGeoLocated ? { key: 'Resolution', value: firstImage.resolution.map(round).join(', ') } : null,
129
- isGeoLocated ? { key: 'BoundingBox', value: firstImage.bbox.map(round).join(', ') } : null,
130
- firstImage.epsg
131
- ? { key: 'EPSG', value: `EPSG:${firstImage.epsg} (https://epsg.io/${firstImage.epsg})` }
132
- : null,
133
- { key: 'Info', value: imageInfo },
134
- ],
135
- },
136
- {
137
- title: 'GDAL',
138
- keys: [
139
- { key: 'COG optimized', value: tif.options.isCogOptimized },
140
- tif.options.isBroken ? { key: 'COG broken', value: tif.options.isBroken } : null,
141
- ghostOptions.length > 0
142
- ? {
143
- key: 'Ghost Options',
144
- value: '\n' + ghostOptions.map((c) => `\t\t${c[0]} = ${c[1]}`).join('\n'),
145
- }
146
- : null,
147
- gdalMetadata
148
- ? {
149
- key: 'Metadata',
150
- value: '\n' + gdalMetadata.map((c) => `\t\t${c}`).join('\n'),
151
- }
152
- : null,
153
- ],
154
- },
155
- ];
156
-
157
- if (this.tags?.value || this.tagsAll?.value) {
158
- for (const img of tif.images) {
159
- const tiffTags = [...img.tags.keys()];
160
- result.push({
161
- title: `Image: ${img.id} - Tiff tags`,
162
- keys: tiffTags.map((tagId) => formatTag(tagId, TiffTag[tagId], img.value(tagId))),
163
- });
164
- await img.loadGeoTiffTags();
165
- if (img.tagsGeo) {
166
- const tiffTagsGeo = [...img.tagsGeo.keys()];
167
- result.push({
168
- title: `Image: ${img.id} - Geo Tiff tags`,
169
- keys: tiffTagsGeo.map((tagId) => formatTag(tagId, TiffTagGeo[tagId], img.valueGeo(tagId))),
170
- });
171
- }
172
- if (!this.tagsAll?.value) {
173
- break;
174
- }
175
- }
176
- }
177
-
178
- const msg = ActionUtil.formatResult(`${c.bold('COG File Info')} - ${c.bold(tif.source.uri)}`, result);
179
- console.log(msg.join('\n'));
180
- }
181
-
182
- protected onDefineParameters(): void {
183
- this.file = this.defineStringParameter({
184
- argumentName: 'FILE',
185
- parameterLongName: '--file',
186
- parameterShortName: '-f',
187
- description: 'cog file to access',
188
- required: true,
189
- });
190
-
191
- this.tags = this.defineFlagParameter({
192
- parameterLongName: '--tags',
193
- parameterShortName: '-t',
194
- description: 'Dump tiff tags',
195
- required: false,
196
- });
197
-
198
- this.tagsAll = this.defineFlagParameter({
199
- parameterLongName: '--tags-all',
200
- parameterShortName: '-T',
201
- description: 'Dump tiff tags for all images',
202
- required: false,
203
- });
204
- }
205
- }
@@ -1,76 +0,0 @@
1
- import { TiffVersion } from '@cogeotiff/core';
2
- import { CommandLineAction, CommandLineStringParameter } from '@rushstack/ts-command-line';
3
- import c from 'ansi-colors';
4
- import { ChunkSourceBase } from '@chunkd/core';
5
- import { ActionUtil, CliResultMap } from './action.util.js';
6
- import { logger as Logger } from './cli.log.js';
7
- import { toByteSizeString } from './util.bytes.js';
8
- import { writeTile } from './util.tile.js';
9
-
10
- export class ActionTile extends CommandLineAction {
11
- private file: CommandLineStringParameter | null = null;
12
- private xyz: CommandLineStringParameter | null = null;
13
-
14
- public constructor() {
15
- super({
16
- actionName: 'tile',
17
- summary: 'Fetch a specific tile from a COG',
18
- documentation: '',
19
- });
20
- }
21
-
22
- async onExecute(): Promise<void> {
23
- const logger = Logger.child({ action: 'tile' });
24
-
25
- // abstract
26
- const { tif } = await ActionUtil.getCogSource(this.file);
27
- if (this.xyz == null || this.xyz.value == null) {
28
- throw new Error('XYZ was not defined');
29
- }
30
-
31
- const [x, y, z] = this.xyz.value.split(',').map((c) => parseInt(c));
32
- if (isNaN(x) || isNaN(y) || isNaN(z)) {
33
- throw new Error('Invalid XYZ, format: "X,Y,Z"');
34
- }
35
-
36
- await writeTile(tif, x, y, z, '.', logger);
37
- const source = tif.source as ChunkSourceBase;
38
- const chunkIds = [...(source.chunks as Map<unknown, unknown>).values()];
39
-
40
- const result: CliResultMap[] = [
41
- {
42
- keys: [
43
- { key: 'Tiff type', value: `${TiffVersion[tif.version]} (v${String(tif.version)})` },
44
- { key: 'Chunk size', value: toByteSizeString(tif.source.chunkSize) },
45
- {
46
- key: 'Bytes read',
47
- value: `${toByteSizeString(chunkIds.length * tif.source.chunkSize)} (${chunkIds.length} Chunk${
48
- chunkIds.length === 1 ? '' : 's'
49
- })`,
50
- },
51
- ],
52
- },
53
- ];
54
-
55
- const msg = ActionUtil.formatResult(`${c.bold('COG File Info')} - ${c.bold(tif.source.uri)}`, result);
56
- console.log(msg.join('\n'));
57
- }
58
-
59
- protected onDefineParameters(): void {
60
- // abstract
61
- this.file = this.defineStringParameter({
62
- argumentName: 'FILE',
63
- parameterLongName: '--file',
64
- parameterShortName: '-f',
65
- description: 'cog file to access',
66
- required: true,
67
- });
68
-
69
- this.xyz = this.defineStringParameter({
70
- argumentName: 'XYZ',
71
- parameterLongName: '--xyz',
72
- description: '"X,Y,Z" of the tile to fetch',
73
- required: true,
74
- });
75
- }
76
- }
@@ -1,45 +0,0 @@
1
- import { CommandLineFlagParameter, CommandLineParser } from '@rushstack/ts-command-line';
2
- import { ActionDumpTile } from './action.dump.tile.js';
3
- import { ActionCogInfo } from './action.info.js';
4
- import { ActionTile } from './action.tile.js';
5
- import { logger } from './cli.log.js';
6
-
7
- export class CogInfoCommandLine extends CommandLineParser {
8
- verbose?: CommandLineFlagParameter;
9
- extraVerbose?: CommandLineFlagParameter;
10
-
11
- constructor() {
12
- super({
13
- toolFilename: 'coginfo',
14
- toolDescription: 'Cloud optimized geotiff utilities',
15
- });
16
-
17
- this.addAction(new ActionDumpTile());
18
- this.addAction(new ActionCogInfo());
19
- this.addAction(new ActionTile());
20
- }
21
-
22
- protected onExecute(): Promise<void> {
23
- if (this.verbose?.value) {
24
- logger.level = 'info';
25
- } else if (this.extraVerbose?.value) {
26
- logger.level = 'trace';
27
- } else {
28
- logger.level = 'warn';
29
- }
30
-
31
- return super.onExecute();
32
- }
33
- protected onDefineParameters(): void {
34
- this.verbose = this.defineFlagParameter({
35
- parameterLongName: '--verbose',
36
- parameterShortName: '-v',
37
- description: 'Show extra logging detail',
38
- });
39
- this.extraVerbose = this.defineFlagParameter({
40
- parameterLongName: '--vv',
41
- parameterShortName: '-V',
42
- description: 'Show extra extra logging detail',
43
- });
44
- }
45
- }
package/src/cli.log.ts DELETED
@@ -1,4 +0,0 @@
1
- import pino from 'pino';
2
- import { PrettyTransform } from 'pretty-json-log';
3
-
4
- export const logger = process.stdout.isTTY ? pino(PrettyTransform.stream()) : pino();