Compare commits

...

8 Commits

7 changed files with 99 additions and 32 deletions

View File

@ -14,7 +14,12 @@ npm install --save terrain50-cli
-----
## v1.8 (unreleased)
## v1.9 (unreleased)
- `identify`: Add value range to output
- `clamp`: add new subcommand
## v1.8
- Add global `--log-level` argument
- `image`: Add `--boundaries` argument

View File

@ -2,7 +2,7 @@
> CLI for parsing Ordnance Survey Digital Elevation Model files
This is the CLI for the sister [`terrain50`](https://www.npmjs.com/package/terrain50) library on npm for parsing Ordnance Survey DEM files I also implemented.
This is the CLI for the sister [`terrain50`](https://www.npmjs.com/package/terrain50) library on npm for parsing Ordnance Survey DEM files in the [ASCII Esri Grid format](https://en.wikipedia.org/wiki/Esri_grid) I also implemented.
- **Current version:** ![current npm version - see the GitHub releases](https://img.shields.io/npm/v/terrain50-cli)
- **Changelog:** https://github.com/sbrl/terrain50-cli/blob/master/Changelog.md
@ -17,7 +17,7 @@ npm install terrain50-cli --global
## Usage
The command-line interface works on a subcommand-based system using [`applause-cli`](https://npmjs.org/packages/applause-cli) (another package of mine).
The command-line interface works on a subcommand-based system using [`applause-cli`](https://npmjs.org/package/applause-cli) (another package of mine).
Display the usage information like this:

48
package-lock.json generated
View File

@ -1,19 +1,19 @@
{
"name": "terrain50-cli",
"version": "1.7.0",
"version": "1.8.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.6.6",
"version": "1.8.0",
"license": "MPL-2.0",
"dependencies": {
"@iarna/toml": "^2.2.5",
"applause-cli": "^1.5.1",
"chroma-js": "^2.1.0",
"image-encode": "^1.3.0",
"image-encode": "^1.3.1",
"nexline": "^1.2.2",
"terrain50": "^1.9.7"
"terrain50": "^1.10.0"
},
"bin": {
"terrain50": "src/index.mjs"
@ -177,15 +177,15 @@
}
},
"node_modules/image-encode": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/image-encode/-/image-encode-1.3.0.tgz",
"integrity": "sha512-2SzuDscMQGK38jGiVMSuygquz2z3DnW4Smget/LipWfqvEnc7+L/qbaQAPDtzi9hsHqKpGGU22SUjl6G8TprJg==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/image-encode/-/image-encode-1.3.1.tgz",
"integrity": "sha512-XlDSaqGFrW0Rn08fxJM725+h9Hfx/D9u1RVMP8IrcSRN5Ib74UgVf7yuzoS8YAxKc6HqQ8bhDSvy+rIzCUoAYg==",
"dependencies": {
"bmp-js": "^0.1.0",
"image-palette": "^2.0.1",
"image-type": "^3.0.0",
"is-plain-obj": "^1.1.0",
"jpeg-js": "^0.3.4",
"jpeg-js": "^0.4.1",
"next-pow-2": "^1.0.0",
"object-assign": "^4.1.1",
"omggif": "^1.0.9",
@ -261,9 +261,9 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"node_modules/jpeg-js": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz",
"integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ=="
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz",
"integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q=="
},
"node_modules/jsonfile": {
"version": "4.0.0",
@ -414,9 +414,9 @@
}
},
"node_modules/terrain50": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.9.7.tgz",
"integrity": "sha512-wE7w4GgRkQn8qvOrja6F4enZBfbb0ONMY2FmpeZQZTWFH6Ga5qmsSnObwTUH2k43qguz0LZ2sOeZL4GPolHy9Q==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.10.0.tgz",
"integrity": "sha512-gP03fb44f0WSvzHXp4ZEUj1imQKxVqvTV/3oKFl0+ireFcG7yFIFjUyGm6vG/MMTevcoeAAZdNpqrIPBJNylQQ==",
"dependencies": {
"nexline": "^1.2.2",
"nnng": "^1.0.0"
@ -738,15 +738,15 @@
}
},
"image-encode": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/image-encode/-/image-encode-1.3.0.tgz",
"integrity": "sha512-2SzuDscMQGK38jGiVMSuygquz2z3DnW4Smget/LipWfqvEnc7+L/qbaQAPDtzi9hsHqKpGGU22SUjl6G8TprJg==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/image-encode/-/image-encode-1.3.1.tgz",
"integrity": "sha512-XlDSaqGFrW0Rn08fxJM725+h9Hfx/D9u1RVMP8IrcSRN5Ib74UgVf7yuzoS8YAxKc6HqQ8bhDSvy+rIzCUoAYg==",
"requires": {
"bmp-js": "^0.1.0",
"image-palette": "^2.0.1",
"image-type": "^3.0.0",
"is-plain-obj": "^1.1.0",
"jpeg-js": "^0.3.4",
"jpeg-js": "^0.4.1",
"next-pow-2": "^1.0.0",
"object-assign": "^4.1.1",
"omggif": "^1.0.9",
@ -810,9 +810,9 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
"jpeg-js": {
"version": "0.3.7",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz",
"integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ=="
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.3.tgz",
"integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q=="
},
"jsonfile": {
"version": "4.0.0",
@ -939,9 +939,9 @@
}
},
"terrain50": {
"version": "1.9.7",
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.9.7.tgz",
"integrity": "sha512-wE7w4GgRkQn8qvOrja6F4enZBfbb0ONMY2FmpeZQZTWFH6Ga5qmsSnObwTUH2k43qguz0LZ2sOeZL4GPolHy9Q==",
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/terrain50/-/terrain50-1.10.0.tgz",
"integrity": "sha512-gP03fb44f0WSvzHXp4ZEUj1imQKxVqvTV/3oKFl0+ireFcG7yFIFjUyGm6vG/MMTevcoeAAZdNpqrIPBJNylQQ==",
"requires": {
"nexline": "^1.2.2",
"nnng": "^1.0.0"

View File

@ -1,6 +1,6 @@
{
"name": "terrain50-cli",
"version": "1.7.0",
"version": "1.8.0",
"description": "CLI for parsing Ordnance Survey Digital Elevation Model files",
"main": "src/index.mjs",
"scripts": {
@ -17,7 +17,8 @@
"elevation",
"model",
"parsing",
"cli"
"cli",
"esri"
],
"author": "Starbeamrainbowlabs",
"license": "MPL-2.0",
@ -35,9 +36,9 @@
"@iarna/toml": "^2.2.5",
"applause-cli": "^1.5.1",
"chroma-js": "^2.1.0",
"image-encode": "^1.3.0",
"image-encode": "^1.3.1",
"nexline": "^1.2.2",
"terrain50": "^1.9.7"
"terrain50": "^1.10.0"
},
"bin": {
"terrain50": "src/index.mjs"

View File

@ -0,0 +1,36 @@
"use strict";
import fs from 'fs';
import l from '../../Helpers/Log.mjs';
import a from '../../Helpers/Ansi.mjs';
import Terrain50 from 'terrain50';
export default async function(settings) {
if(typeof settings.cli.input !== "string") {
l.error("Error: No input file specified (try --filename path/to/heightmap.asc)");
process.exit(1);
}
if(typeof settings.cli.output !== "string") {
l.error("Error: No output file specified (try --filename path/to/output.asc)");
process.exit(1);
}
l.log(`Reading input files`);
let heightmap = Terrain50.Parse(await fs.promises.readFile(settings.cli.input, "utf-8"));
if(typeof settings.cli.min == "number") {
l.log(`Clamping values to a minimum of ${a.hicol}${settings.cli.min}${a.reset}`);
heightmap.min_value = settings.cli.min;
l.log(`done`);
}
if(typeof settings.cli.max == "number") {
l.log(`Clamping values to a maximum of ${a.hicol}${settings.cli.max}${a.reset}`);
heightmap.max_value = settings.cli.max;
l.log(`done`);
}
l.log(`Writing result to disk`);
await heightmap.serialise(fs.createWriteStream(settings.cli.output));
l.log(`Trimming complete!`);
}

View File

@ -0,0 +1,25 @@
description = "Clamp data values (but not NODATA values) to a given minimum and maximum."
[[arguments]]
name = "input"
description = "The input Terrain50 file to operate on"
# default_value = ""
type = "string"
[[arguments]]
name = "output"
description = "The filepath to write the output to"
# default_value = ""
type = "string"
[[arguments]]
name = "min"
description = "The minimum value to clamp to. If not specified, values will not be clamped to a minimum."
# default_value = ""
type = "float"
[[arguments]]
name = "max"
description = "The maximum value to clamp to. If not specified, values will not be clamped to a maximum."
# default_value = ""
type = "float"

View File

@ -14,10 +14,10 @@ function summarise_obj(obj) {
if(typeof obj.meta.NODATA_value !== "undefined")
console.log(`NODATA value: ${obj.meta.NODATA_value}`);
console.log(`Metadata keys: ${Object.keys(obj.meta).join(", ")}`);
console.log(`Value range (excluding NODATA values): ${obj.min_value} - ${obj.max_value}`);
}
export default async function(settings) {
let iterator = null;
switch(settings.cli.mode) {
case "single":
let obj = Terrain50.Parse(