Skip to content

Commit e61ad4b

Browse files
committed
added geotiff_no_data and tile_no_data
1 parent 2e2cb8d commit e61ad4b

File tree

4 files changed

+119
-28
lines changed

4 files changed

+119
-28
lines changed

README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ await createTile({
6161
// undefined - same as auto
6262
tile_array_types_strategy: "untyped",
6363

64+
// over-ride default "no data" value in output tile
65+
tile_no_data: 0,
66+
6467
// projection of the tile
6568
// as an EPSG code
6669
tile_srs: 3857,
@@ -76,7 +79,9 @@ await createTile({
7679
tile_resolution: 0.5,
7780

7881
// whether to use overviews if available
79-
use_overview,
82+
// default is true
83+
// setting to false will mean the usage of the highest resolution data
84+
use_overview: false,
8085

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

8792
## advanced usage
88-
### Over-riding geotiff srs
93+
### over-riding geotiff no data value
94+
If for some reason your geotiff has values that should be treated as no data,
95+
but this isn't properly set in the metadata, you can over-ride the no data value
96+
```js
97+
await createTile({
98+
geotiff,
99+
geotiff_no_data: -32767,
100+
// rest is the same
101+
})
102+
```
103+
104+
### over-riding geotiff srs
89105
If for some reason geotiff-tile can't parse the correct projection from your geotiff, you can manually
90106
specify the projection via the geotiff_srs parameter.
91107
```js
@@ -96,7 +112,7 @@ await createTile({
96112
})
97113
```
98114

99-
### Image Pixel Coordinates and Simple SRS
115+
### image pixel coordinates and simple srs
100116
You can also select pixels using a "simple" spatial reference system where the bottom left of your data
101117
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).
102118
```js

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,27 +52,27 @@
5252
"dependencies": {
5353
"geotiff-epsg-code": "^0.3.1",
5454
"geotiff-no-data": "^0.2.0",
55-
"geotiff-read-bbox": "^2.2.0",
56-
"geowarp": "^1.26.1",
55+
"geotiff-read-bbox": "^2.4.0",
56+
"geowarp": "^1.26.2",
5757
"pixel-utils": "^0.9.0",
5858
"proj4": "^2.10.0",
5959
"proj4-fully-loaded": "^0.2.0",
6060
"reproject-bbox": "^0.13.1"
6161
},
6262
"devDependencies": {
63-
"@babel/cli": "^7.23.4",
64-
"@babel/core": "^7.23.7",
63+
"@babel/cli": "^7.23.9",
64+
"@babel/core": "^7.23.9",
6565
"@babel/plugin-transform-export-namespace-from": "^7.23.4",
6666
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
6767
"@babel/preset-typescript": "^7.23.3",
6868
"chroma-js": "^2.4.2",
6969
"envisage": "^0.1.0",
7070
"flug": "^2.7.2",
71-
"geotiff": "^2.1.1",
71+
"geotiff": "^2.1.3",
7272
"rimraf": "^5.0.5",
7373
"snap-bbox": "^0.5.0",
7474
"srvd": "^0.6.0",
75-
"webpack": "^5.89.0",
75+
"webpack": "^5.90.3",
7676
"webpack-cli": "^5.1.4",
7777
"write-image": "^0.2.0"
7878
}

src/index.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export default async function createTile({
1919
debug_level = 0,
2020
density = 100,
2121
geotiff,
22+
geotiff_no_data,
2223
geotiff_srs,
2324
expr: _expr,
2425
// fit = false,
@@ -27,6 +28,7 @@ export default async function createTile({
2728
round,
2829
tile_array_types,
2930
tile_height = 256,
31+
tile_no_data,
3032
tile_srs = 3857, // epsg code of the output tile
3133
tile_array_types_strategy = "auto",
3234
tile_layout = "[band][row,column]",
@@ -44,6 +46,7 @@ export default async function createTile({
4446
debug_level?: number;
4547
density?: number | undefined;
4648
geotiff: any;
49+
geotiff_no_data?: number | undefined;
4750
geotiff_srs?: number | string | undefined;
4851
expr?: ({ pixel }: { pixel: number[] }) => number[];
4952
// fit?: boolean | undefined;
@@ -65,6 +68,7 @@ export default async function createTile({
6568
>
6669
| undefined;
6770
tile_array_types_strategy?: "auto" | "geotiff" | "untyped" | undefined;
71+
tile_no_data?: number | string | undefined;
6872
tile_srs?: number | string;
6973
tile_height: number;
7074
tile_layout?: string;
@@ -168,7 +172,8 @@ export default async function createTile({
168172
// the result from the affine transformation
169173
return {
170174
bbox: bbox_nums,
171-
debugLevel: debug_level,
175+
clamp: true,
176+
debug_level,
172177
srs: "simple",
173178
geotiff,
174179
use_overview,
@@ -178,7 +183,8 @@ export default async function createTile({
178183
} else {
179184
return {
180185
bbox: bbox_in_tile_srs,
181-
debugLevel: debug_level,
186+
clamp: true,
187+
debug_level,
182188
srs: tile_srs,
183189
geotiff,
184190
use_overview,
@@ -277,6 +283,8 @@ export default async function createTile({
277283

278284
const out_srs = tile_srs;
279285

286+
if (typeof geotiff_no_data === "undefined") geotiff_no_data = get_geotiff_no_data_number(image);
287+
280288
const geowarp_options = {
281289
cutline,
282290
cutline_srs,
@@ -289,7 +297,7 @@ export default async function createTile({
289297
// in_geotransform is only necessary if using skewed or rotated in_data
290298
in_geotransform: out_srs === "simple" ? null : readResult.geotransform,
291299
in_layout: "[band][row,column]",
292-
in_no_data: get_geotiff_no_data_number(image),
300+
in_no_data: geotiff_no_data,
293301
in_srs: geotiff_srs,
294302
in_width: readResult.width,
295303
in_height: readResult.height,
@@ -299,6 +307,7 @@ export default async function createTile({
299307
out_bbox: bbox_in_tile_srs_num,
300308
out_height: tile_height,
301309
out_layout: tile_layout,
310+
out_no_data: typeof tile_no_data !== "undefined" ? tile_no_data : typeof geotiff_no_data === "number" ? geotiff_no_data : NaN,
302311
out_pixel_depth: pixel_depth,
303312
out_resolution: typeof tile_resolution === "number" ? [tile_resolution, tile_resolution] : tile_resolution,
304313
out_srs,

test.html

Lines changed: 82 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
<script>
99
window.process = {
1010
env: {
11-
TEST_TIMED: true,
11+
TEST_timed: false,
12+
// TEST_NAME: "geotiff tile (near-vectorize)",
1213
// TEST_NAME: "pulling tile from 4-band Web Mercator GeoTIFF"
14+
// TEST_NAME: "tile greater than extent of source projection",
15+
// TEST_NAME: "clamp"
1316
}
1417
}
1518
</script>
@@ -54,13 +57,12 @@
5457
const url = "./data/umbra_mount_yasur.tiff";
5558
const geotiff = await GeoTIFF.fromUrl(url);
5659
const { height, width, tile } = await geotiff_tile.createTile({
57-
debug_level: 0,
5860
geotiff,
5961

6062
// bbox for https://c.tile.openstreetmap.org/14/15903/9098.png
6163
bbox: [169.43115234375, -19.53908413550933, 169.453125, -19.518375478601566],
6264
bbox_srs: 4326,
63-
debug_level: 10,
65+
debug_level: 0,
6466
expr: ({ pixel }) => [pixel[0], pixel[0], pixel[0]],
6567
method: "near",
6668
pixel_depth: 3,
@@ -69,7 +71,7 @@
6971
tile_layout: "[band][row][column]",
7072
tile_srs: 4326,
7173
tile_width: 512,
72-
timed: true
74+
timed: false
7375
});
7476

7577
eq(tile[0][0].constructor.name, "Array");
@@ -100,7 +102,7 @@
100102
tile_layout: "[band][row][column]",
101103
tile_srs: 3031,
102104
tile_width: 211,
103-
timed: true
105+
timed: false
104106
});
105107

106108
eq(tile[0][0].constructor.name, "Array");
@@ -121,7 +123,7 @@
121123
tile_height: 64,
122124
tile_layout: "[band][row][column]",
123125
tile_width: 64,
124-
timed: true,
126+
timed: false,
125127
});
126128

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

134-
test("pulling empty tile from Harvey COG", async ({ eq }) => {
136+
test("pulling all black empty tile from Harvey COG", async ({ eq }) => {
137+
// this raster uses the color black as no data
135138
const url = "https://storage.googleapis.com/pdd-stac/disasters/hurricane-harvey/0831/20170831_172754_101c_3b_Visual.tif";
136139
const geotiff = await GeoTIFF.fromUrl(url);
137140
const { height, width, tile } = await geotiff_tile.createTile({
138141
geotiff,
139142
// mercator tile at x: 61158, y: 108475, z: 18
143+
// tile is in the "nodata" region of the geotiff
140144
bbox: [-96.01226806640625, 29.616445727622548, -96.01089477539062, 29.61763959537609],
141145
bbox_srs: 4326,
146+
debug_level: 0,
142147
method: "near",
143148
round: false,
144-
timed: true,
149+
timed: false,
145150
tile_height: 256,
146151
tile_layout: "[band][row][column]",
152+
tile_no_data: NaN,
147153
tile_width: 256,
148154
tile_srs: 3857,
149155
use_overview: true
150156
});
157+
console.log("empty tile harvey:", tile);
151158

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

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

@@ -169,7 +178,7 @@
169178
tile_layout: "[band][row][column]",
170179
tile_resolution: 0.25,
171180
tile_width: 512,
172-
timed: true,
181+
timed: false,
173182
turbo: true
174183
});
175184
eq(tile[0][0].constructor.name, "Uint8Array");
@@ -192,7 +201,7 @@
192201
tile_layout: "[band][row][column]",
193202
tile_srs: 4326,
194203
tile_width: 512,
195-
timed: true
204+
timed: false
196205
});
197206
eq(tile[0][0].constructor.name, "Uint8Array");
198207

@@ -226,7 +235,7 @@
226235
tile_layout: "[band][row][column]",
227236
tile_srs: 4326,
228237
tile_width: 512,
229-
timed: true
238+
timed: false
230239
});
231240
eq(tile[0][0].constructor.name, "Uint8Array");
232241

@@ -248,7 +257,7 @@
248257
tile_layout: "[row][column][band]",
249258
tile_srs: 4326,
250259
tile_width: 512,
251-
timed: true
260+
timed: false
252261
});
253262
eq(tile[0][0].constructor.name, "Uint8Array");
254263

@@ -264,7 +273,7 @@
264273
test("geotiff tile (near-vectorize)", async ({ eq }) => {
265274
const geotiff = await GeoTIFF.fromUrl("./data/wildfires.tiff");
266275
const { height, width, tile } = await geotiff_tile.createTile({
267-
debug_level: 2,
276+
debug_level: 0,
268277
geotiff,
269278
bbox: [ -122.0361328125, 40.97989806962013, -121.9921875, 41.0130657870063 ],
270279
bbox_srs: 4326,
@@ -274,8 +283,10 @@
274283
tile_layout: "[band][row][column]",
275284
tile_srs: 4326,
276285
tile_width: 512,
277-
timed: true
286+
timed: false
278287
});
288+
console.log("geotiff tile (near-vectorize)", tile);
289+
279290
eq(tile[0][0].constructor.name, "Uint8Array");
280291

281292
const data = three_to_four_bands({ height, width, tile })
@@ -287,7 +298,7 @@
287298
const geotiff = await GeoTIFF.fromUrl("https://maxar-ard-samples.s3.amazonaws.com/v3/australia_vineyards/50/213133231011/2019-10-07/10500100191CD200-visual.tif");
288299
console.log("geotiff:", geotiff);
289300
const { height, width, tile } = await geotiff_tile.createTile({
290-
debug_level: 2,
301+
debug_level: 0,
291302
geotiff,
292303
bbox: [
293304
12802284.9934276,
@@ -302,7 +313,7 @@
302313
tile_layout: "[band][row][column]",
303314
tile_srs: 3857,
304315
tile_width: 128,
305-
timed: true,
316+
timed: false,
306317
use_overview: true,
307318
turbo: false
308319
});
@@ -314,6 +325,61 @@
314325

315326
displayTile({ tile: data, height, width});
316327
});
328+
329+
test("clamp", async ({ eq }) => {
330+
const geotiff = await GeoTIFF.fromUrl("./data/dom1_32_356_5699_1_nw_2020.tif");
331+
// console.log("geotiff:", geotiff);
332+
const { height, width, tile } = await geotiff_tile.createTile({
333+
debug_level: 0,
334+
geotiff,
335+
bbox: [771265.3262627776, 6698176.788629993, 771402.4894539987, 6698269.944045576],
336+
bbox_srs: 3857,
337+
method: "near-vectorize",
338+
round: true,
339+
tile_height: 60,
340+
tile_layout: "[band][row][column]",
341+
tile_no_data: -32767,
342+
tile_srs: 3857,
343+
tile_width: 60,
344+
timed: false,
345+
use_overview: true,
346+
turbo: false
347+
});
348+
eq(tile[0][0][0], -32767);
349+
eq(tile[0][0].constructor.name, "Float32Array");
350+
eq(tile.length, 1);
351+
352+
console.log("clamp tile:", tile)
353+
const data = three_to_four_bands({ height, width, tile: [tile[0], tile[0], tile[0]] })
354+
355+
displayTile({ tile: data, height, width});
356+
});
357+
358+
test("tile greater than extent of source projection", async ({ eq }) => {
359+
const geotiff = await GeoTIFF.fromUrl("./data/gadas-world.tif");
360+
// console.log("geotiff:", geotiff);
361+
const { height, width, tile } = await geotiff_tile.createTile({
362+
debug_level: 0,
363+
geotiff,
364+
bbox: [-180, -90, 180, 90],
365+
bbox_srs: 4326,
366+
method: "near-vectorize",
367+
round: true,
368+
tile_height: 180,
369+
tile_layout: "[row,column,band]",
370+
tile_srs: 4326,
371+
tile_width: 360,
372+
timed: false,
373+
use_overview: true,
374+
turbo: false
375+
});
376+
eq(tile.slice(0, 4), Uint8Array.from([0, 0, 0, 0]));
377+
eq(tile.length, 259200);
378+
379+
console.log("gadas world tile:", tile);
380+
381+
displayTile({ tile, height, width});
382+
});
317383
</script>
318384
</body>
319385
</html>

0 commit comments

Comments
 (0)