Skip to content

Commit

Permalink
added geotiff_no_data and tile_no_data
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielJDufour committed Feb 25, 2024
1 parent 2e2cb8d commit e61ad4b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 28 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ await createTile({
// undefined - same as auto
tile_array_types_strategy: "untyped",

// over-ride default "no data" value in output tile
tile_no_data: 0,

// projection of the tile
// as an EPSG code
tile_srs: 3857,
Expand All @@ -76,7 +79,9 @@ await createTile({
tile_resolution: 0.5,

// whether to use overviews if available
use_overview,
// default is true
// setting to false will mean the usage of the highest resolution data
use_overview: false,

// optional, default is false
// enable experimental turbocharging via proj-turbo
Expand All @@ -85,7 +90,18 @@ await createTile({
```

## advanced usage
### Over-riding geotiff srs
### over-riding geotiff no data value
If for some reason your geotiff has values that should be treated as no data,
but this isn't properly set in the metadata, you can over-ride the no data value
```js
await createTile({
geotiff,
geotiff_no_data: -32767,
// rest is the same
})
```

### over-riding geotiff srs
If for some reason geotiff-tile can't parse the correct projection from your geotiff, you can manually
specify the projection via the geotiff_srs parameter.
```js
Expand All @@ -96,7 +112,7 @@ await createTile({
})
```

### Image Pixel Coordinates and Simple SRS
### image pixel coordinates and simple srs
You can also select pixels using a "simple" spatial reference system where the bottom left of your data
is the origin [0, 0] and the top-right corner is [width, height]. This is inspired by [Leaflet's Simple CRS](https://leafletjs.com/examples/crs-simple/crs-simple.html).
```js
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,27 +52,27 @@
"dependencies": {
"geotiff-epsg-code": "^0.3.1",
"geotiff-no-data": "^0.2.0",
"geotiff-read-bbox": "^2.2.0",
"geowarp": "^1.26.1",
"geotiff-read-bbox": "^2.4.0",
"geowarp": "^1.26.2",
"pixel-utils": "^0.9.0",
"proj4": "^2.10.0",
"proj4-fully-loaded": "^0.2.0",
"reproject-bbox": "^0.13.1"
},
"devDependencies": {
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.7",
"@babel/cli": "^7.23.9",
"@babel/core": "^7.23.9",
"@babel/plugin-transform-export-namespace-from": "^7.23.4",
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"chroma-js": "^2.4.2",
"envisage": "^0.1.0",
"flug": "^2.7.2",
"geotiff": "^2.1.1",
"geotiff": "^2.1.3",
"rimraf": "^5.0.5",
"snap-bbox": "^0.5.0",
"srvd": "^0.6.0",
"webpack": "^5.89.0",
"webpack": "^5.90.3",
"webpack-cli": "^5.1.4",
"write-image": "^0.2.0"
}
Expand Down
15 changes: 12 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default async function createTile({
debug_level = 0,
density = 100,
geotiff,
geotiff_no_data,
geotiff_srs,
expr: _expr,
// fit = false,
Expand All @@ -27,6 +28,7 @@ export default async function createTile({
round,
tile_array_types,
tile_height = 256,
tile_no_data,
tile_srs = 3857, // epsg code of the output tile
tile_array_types_strategy = "auto",
tile_layout = "[band][row,column]",
Expand All @@ -44,6 +46,7 @@ export default async function createTile({
debug_level?: number;
density?: number | undefined;
geotiff: any;
geotiff_no_data?: number | undefined;
geotiff_srs?: number | string | undefined;
expr?: ({ pixel }: { pixel: number[] }) => number[];
// fit?: boolean | undefined;
Expand All @@ -65,6 +68,7 @@ export default async function createTile({
>
| undefined;
tile_array_types_strategy?: "auto" | "geotiff" | "untyped" | undefined;
tile_no_data?: number | string | undefined;
tile_srs?: number | string;
tile_height: number;
tile_layout?: string;
Expand Down Expand Up @@ -168,7 +172,8 @@ export default async function createTile({
// the result from the affine transformation
return {
bbox: bbox_nums,
debugLevel: debug_level,
clamp: true,
debug_level,
srs: "simple",
geotiff,
use_overview,
Expand All @@ -178,7 +183,8 @@ export default async function createTile({
} else {
return {
bbox: bbox_in_tile_srs,
debugLevel: debug_level,
clamp: true,
debug_level,
srs: tile_srs,
geotiff,
use_overview,
Expand Down Expand Up @@ -277,6 +283,8 @@ export default async function createTile({

const out_srs = tile_srs;

if (typeof geotiff_no_data === "undefined") geotiff_no_data = get_geotiff_no_data_number(image);

const geowarp_options = {
cutline,
cutline_srs,
Expand All @@ -289,7 +297,7 @@ export default async function createTile({
// in_geotransform is only necessary if using skewed or rotated in_data
in_geotransform: out_srs === "simple" ? null : readResult.geotransform,
in_layout: "[band][row,column]",
in_no_data: get_geotiff_no_data_number(image),
in_no_data: geotiff_no_data,
in_srs: geotiff_srs,
in_width: readResult.width,
in_height: readResult.height,
Expand All @@ -299,6 +307,7 @@ export default async function createTile({
out_bbox: bbox_in_tile_srs_num,
out_height: tile_height,
out_layout: tile_layout,
out_no_data: typeof tile_no_data !== "undefined" ? tile_no_data : typeof geotiff_no_data === "number" ? geotiff_no_data : NaN,
out_pixel_depth: pixel_depth,
out_resolution: typeof tile_resolution === "number" ? [tile_resolution, tile_resolution] : tile_resolution,
out_srs,
Expand Down
98 changes: 82 additions & 16 deletions test.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
<script>
window.process = {
env: {
TEST_TIMED: true,
TEST_timed: false,
// TEST_NAME: "geotiff tile (near-vectorize)",
// TEST_NAME: "pulling tile from 4-band Web Mercator GeoTIFF"
// TEST_NAME: "tile greater than extent of source projection",
// TEST_NAME: "clamp"
}
}
</script>
Expand Down Expand Up @@ -54,13 +57,12 @@
const url = "./data/umbra_mount_yasur.tiff";
const geotiff = await GeoTIFF.fromUrl(url);
const { height, width, tile } = await geotiff_tile.createTile({
debug_level: 0,
geotiff,

// bbox for https://c.tile.openstreetmap.org/14/15903/9098.png
bbox: [169.43115234375, -19.53908413550933, 169.453125, -19.518375478601566],
bbox_srs: 4326,
debug_level: 10,
debug_level: 0,
expr: ({ pixel }) => [pixel[0], pixel[0], pixel[0]],
method: "near",
pixel_depth: 3,
Expand All @@ -69,7 +71,7 @@
tile_layout: "[band][row][column]",
tile_srs: 4326,
tile_width: 512,
timed: true
timed: false
});

eq(tile[0][0].constructor.name, "Array");
Expand Down Expand Up @@ -100,7 +102,7 @@
tile_layout: "[band][row][column]",
tile_srs: 3031,
tile_width: 211,
timed: true
timed: false
});

eq(tile[0][0].constructor.name, "Array");
Expand All @@ -121,7 +123,7 @@
tile_height: 64,
tile_layout: "[band][row][column]",
tile_width: 64,
timed: true,
timed: false,
});

eq(tile[0][0].constructor.name, "Uint8Array");
Expand All @@ -131,25 +133,32 @@
displayTile({ tile: data, height, width});
});

test("pulling empty tile from Harvey COG", async ({ eq }) => {
test("pulling all black empty tile from Harvey COG", async ({ eq }) => {
// this raster uses the color black as no data
const url = "https://storage.googleapis.com/pdd-stac/disasters/hurricane-harvey/0831/20170831_172754_101c_3b_Visual.tif";
const geotiff = await GeoTIFF.fromUrl(url);
const { height, width, tile } = await geotiff_tile.createTile({
geotiff,
// mercator tile at x: 61158, y: 108475, z: 18
// tile is in the "nodata" region of the geotiff
bbox: [-96.01226806640625, 29.616445727622548, -96.01089477539062, 29.61763959537609],
bbox_srs: 4326,
debug_level: 0,
method: "near",
round: false,
timed: true,
timed: false,
tile_height: 256,
tile_layout: "[band][row][column]",
tile_no_data: NaN,
tile_width: 256,
tile_srs: 3857,
use_overview: true
});
console.log("empty tile harvey:", tile);

// it's an array because of fill values
eq(tile[0][0].constructor.name, "Uint8Array");
eq(tile[0][0][0], 0);

const data = three_to_four_bands({ height, width, tile })

Expand All @@ -169,7 +178,7 @@
tile_layout: "[band][row][column]",
tile_resolution: 0.25,
tile_width: 512,
timed: true,
timed: false,
turbo: true
});
eq(tile[0][0].constructor.name, "Uint8Array");
Expand All @@ -192,7 +201,7 @@
tile_layout: "[band][row][column]",
tile_srs: 4326,
tile_width: 512,
timed: true
timed: false
});
eq(tile[0][0].constructor.name, "Uint8Array");

Expand Down Expand Up @@ -226,7 +235,7 @@
tile_layout: "[band][row][column]",
tile_srs: 4326,
tile_width: 512,
timed: true
timed: false
});
eq(tile[0][0].constructor.name, "Uint8Array");

Expand All @@ -248,7 +257,7 @@
tile_layout: "[row][column][band]",
tile_srs: 4326,
tile_width: 512,
timed: true
timed: false
});
eq(tile[0][0].constructor.name, "Uint8Array");

Expand All @@ -264,7 +273,7 @@
test("geotiff tile (near-vectorize)", async ({ eq }) => {
const geotiff = await GeoTIFF.fromUrl("./data/wildfires.tiff");
const { height, width, tile } = await geotiff_tile.createTile({
debug_level: 2,
debug_level: 0,
geotiff,
bbox: [ -122.0361328125, 40.97989806962013, -121.9921875, 41.0130657870063 ],
bbox_srs: 4326,
Expand All @@ -274,8 +283,10 @@
tile_layout: "[band][row][column]",
tile_srs: 4326,
tile_width: 512,
timed: true
timed: false
});
console.log("geotiff tile (near-vectorize)", tile);

eq(tile[0][0].constructor.name, "Uint8Array");

const data = three_to_four_bands({ height, width, tile })
Expand All @@ -287,7 +298,7 @@
const geotiff = await GeoTIFF.fromUrl("https://maxar-ard-samples.s3.amazonaws.com/v3/australia_vineyards/50/213133231011/2019-10-07/10500100191CD200-visual.tif");
console.log("geotiff:", geotiff);
const { height, width, tile } = await geotiff_tile.createTile({
debug_level: 2,
debug_level: 0,
geotiff,
bbox: [
12802284.9934276,
Expand All @@ -302,7 +313,7 @@
tile_layout: "[band][row][column]",
tile_srs: 3857,
tile_width: 128,
timed: true,
timed: false,
use_overview: true,
turbo: false
});
Expand All @@ -314,6 +325,61 @@

displayTile({ tile: data, height, width});
});

test("clamp", async ({ eq }) => {
const geotiff = await GeoTIFF.fromUrl("./data/dom1_32_356_5699_1_nw_2020.tif");
// console.log("geotiff:", geotiff);
const { height, width, tile } = await geotiff_tile.createTile({
debug_level: 0,
geotiff,
bbox: [771265.3262627776, 6698176.788629993, 771402.4894539987, 6698269.944045576],
bbox_srs: 3857,
method: "near-vectorize",
round: true,
tile_height: 60,
tile_layout: "[band][row][column]",
tile_no_data: -32767,
tile_srs: 3857,
tile_width: 60,
timed: false,
use_overview: true,
turbo: false
});
eq(tile[0][0][0], -32767);
eq(tile[0][0].constructor.name, "Float32Array");
eq(tile.length, 1);

console.log("clamp tile:", tile)
const data = three_to_four_bands({ height, width, tile: [tile[0], tile[0], tile[0]] })

displayTile({ tile: data, height, width});
});

test("tile greater than extent of source projection", async ({ eq }) => {
const geotiff = await GeoTIFF.fromUrl("./data/gadas-world.tif");
// console.log("geotiff:", geotiff);
const { height, width, tile } = await geotiff_tile.createTile({
debug_level: 0,
geotiff,
bbox: [-180, -90, 180, 90],
bbox_srs: 4326,
method: "near-vectorize",
round: true,
tile_height: 180,
tile_layout: "[row,column,band]",
tile_srs: 4326,
tile_width: 360,
timed: false,
use_overview: true,
turbo: false
});
eq(tile.slice(0, 4), Uint8Array.from([0, 0, 0, 0]));
eq(tile.length, 259200);

console.log("gadas world tile:", tile);

displayTile({ tile, height, width});
});
</script>
</body>
</html>

0 comments on commit e61ad4b

Please sign in to comment.