diff --git a/README.md b/README.md index f5122ac..faa85f3 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Get Statistics from a Large GeoTIFF while Using a Low Amount of Memory I wanted to load a Landsat scene into geotiff.io, but my Chromebook couldn't load all the values into memory in order to calculate the minimum and maximum. This package was created, in order to enable people on low-memory devices to iteratively loop over pixel values in a GeoTIFF image and calculate aggregate statistics like minimum and maximum. # usage +## downloaded GeoTIFF ```javascript const { readFileSync } = require('fs'); const { fromArrayBuffer } = require('geotiff'); @@ -22,6 +23,23 @@ console.log(results); // { bands: [{ min: 0, max: 62196 }] } ``` +## remote Cloud Optimized GeoTIFF +For large Cloud Optimized GeoTIFFs, it is recommended to calculate statistics from the overview file instead of the raw full-resolution GeoTIFF. Calculating from the overview file will be roughly 10x faster than the full-resolution GeoTIFF. +```javascript +const { fromUrls } = require('geotiff'); +const { getStats } = require('geotiff-stats'); + + +const folder_url = "https://landsat-pds.s3.amazonaws.com/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1"; +const geotiff_url = folder_url + "/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF"; +const overview_url = folder_url + "/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF.ovr"; +const geotiff = await fromUrls(geotiff_url, [overview_url]); +const image = await geotiff.getImage(1); // grabs the overview file +const results = await getStats(image); +console.log(results); +// { bands: [{ min: 0, max: 25977 }] } +``` + # accessing data from a specific band getStats returns an object with the max and min for each band. You can access the max for the 3rd band (index of 2) with the following: `results.bands[2].max` diff --git a/index.js b/index.js index 67ee585..9dd1641 100644 --- a/index.js +++ b/index.js @@ -19,9 +19,12 @@ async function getStats(image, debug){ if (debug) console.log("numBands:", numBands); const tileWidth = image.getTileWidth(); + if (debug) console.log("tileWidth:", tileWidth); + const tileHeight = image.getTileHeight(); let bytesPerPixel = image.getBytesPerPixel(); + if (debug) console.log("bytesPerPixel:", bytesPerPixel); const srcSampleOffsets = []; const sampleReaders = []; @@ -35,13 +38,17 @@ async function getStats(image, debug){ } const numTilesPerRow = Math.ceil(image.getWidth() / image.getTileWidth()); + if (debug) console.log("numTilesPerRow:", numTilesPerRow); const numTilesPerCol = Math.ceil(image.getHeight() / image.getTileHeight()); + if (debug) console.log("numTilesPerCol:", numTilesPerCol); const noDataValue = fd.GDAL_NODATA ? parseFloat(fd.GDAL_NODATA) : null; + if (debug) console.log("noDataValue:", noDataValue); const bandResults = []; for (let bandIndex = 0; bandIndex < numBands; bandIndex++) { + if (debug) console.log("bandIndex:", bandIndex); let min = undefined; let max = undefined; diff --git a/test/test.js b/test/test.js index 86dab4a..53758f8 100644 --- a/test/test.js +++ b/test/test.js @@ -1,6 +1,6 @@ const { expect } = require('chai'); const { readFileSync } = require('fs'); -const { fromArrayBuffer } = require('geotiff'); +const { fromArrayBuffer, fromUrls } = require('geotiff'); const { getStats } = require('../index.js'); const SECONDS_TO_MILLISECONDS = 1000; @@ -42,12 +42,26 @@ describe("GeoTIFF.js Test Data", function() { }); describe("Landsat Data", function() { - this.timeout(5 * SECONDS_TO_MILLISECONDS); - it('should get stats for Landsat Scene', async function() { + it('should get stats for downloaded Landsat Scene', async function() { + this.timeout(20 * SECONDS_TO_MILLISECONDS); const { bands } = await getStatsFromFilepath('./test/data/LC80120312013106LGN01_B6.tif'); expect(bands[0].min).to.equal(0); expect(bands[0].max).to.equal(62196); }); + it('should get stats for online Landsat Scene with overview file', async function() { + this.timeout(20 * SECONDS_TO_MILLISECONDS); + const debug = false; + const folder_url = "https://landsat-pds.s3.amazonaws.com/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1"; + const geotiff_url = folder_url + "/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF"; + const overview_url = folder_url + "/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF.ovr"; + const geotiff = await fromUrls(geotiff_url, [overview_url]); + if (debug) console.log("geotiff.overviewFiles:", geotiff.overviewFiles); + const image = await geotiff.getImage(1); + if (debug) console.log("image:", image); + const { bands } = await getStats(image, debug); + expect(bands[0].min).to.equal(0); + expect(bands[0].max).to.equal(25977); + }); }); describe("GHSL Data", function() {