Closed Pomax closed 1 year ago
Here's what I generally do.
First off the goal is to get the actual pixel coordinates for the raster, for the desired coordinates.
So, GeoTIFFImage
has a geoKeys
property (https://geotiffjs.github.io/geotiff.js/module-geotiffimage-GeoTIFFImage.html).
This provides the projection information. There is potentially a lot of stuff there...You can skip the headache of dealing with complicated projections by using a couple libraries:
geotiff-geokeys-to-proj4
https://github.com/matafokka/geotiff-geokeys-to-proj4
And then, of course, feeding that into proj4js
http://proj4js.org/
Using those libraries, set up the projection object...
import proj4 from 'proj4';
import * as geokeysToProj4 from "geotiff-geokeys-to-proj4";
...
const image = await <your geotiff object>.getImage();
const geoKeys = image.getGeoKeys();
const projObj = geokeysToProj4.toProj4( geokeys );
const projection = proj4( `WGS84`, projObj.proj4 );
Get the x and y pixel coordinates from the lat/lng...
const width = image.getWidth();
const height = image.getHeight();
const [ originX, originY ] = image.getOrigin();
const [ xSize, ySize ] = image.getResolution();
const uWidth = xSize * width;
const uHeight = ySize * height;
const { x, y } = projection.forward( {
x: <your longitude>,
y: <your latitude>
} );
const percentX = ( x - originX ) / uWidth;
const percentY = ( y - originY ) / uHeight;
const pixelX = Math.floor( width * percentX );
const pixelY = Math.floor( height * percentY );
Now you have two options. You can either read a window that is one pixel in size, or you can read the raw data array. If you're going to be querying a lot of data points a loop, the raw data array will be faster.
const [ value ] = await <your geotiff object>.readRasters( {
interleave: true,
window: [ pixelX, pixelY, pixelX + 1, pixelY + 1],
samples: [ 0 ]
} );
or...
Get your DEM data as a 1d array...
const data = await <your geotiff object>.readRasters( {
interleave: true,
samples: [ 0 ]
} );
Convert the x and y pixels into an array index...
const val = data[width * pixelY + pixelX];
Hope this helps or gives you some ideas. This was transcribed from a project that is a couple years old so apologies if it doesn't work out of the box but should get you on the right track.
While useful "for me", the main reason I filed this issue is to get examples added to the README.md, or linked from the README.md - a library without examples is an incomplete library.
That's a separate project. Not "examples of how to use this library, and the functions it supports, in this library's own docs".
@Pomax
Thanks for the feedback!
It was a deliberate choice to not include coordinate transformation as part of the library, so this is why it is not shipped with proj or an alternative. It is meant as a low level reader of TIFF raster data.
The problem is that in many cases you have a straightforward way to get from pixel/line to geo coordinates, but in many cases it is not. Think of SAR files with GCPs instead of a transformation matrix. geotiff.js is not GDAL for the web.
However I agree to the fact that the Readme could get a brushup on that exact topic. Since you already delved into the topic, would you be willing to contribute a small section to get raster values of a specific location (also maybe even using proj)?
Ah, I see! That might actually be good to call out (more?) explicitly in the readme, since you can read tiff tags with any tif parser (it's the "t" in tiff, after all =D), so when I found "geotiff" I assumed it was more specifically geared towards not needing to write your own "value for geo coordinate" (even if there's the option to do all the low level stuff if you really need that) =)
I can give that section a shot, I'm currently using node-tiff to get elevation data out of the ALOS World3D dataset, which is probably one of the easier datasets to work with, but I'd probably end up writing an example that would work with any tiff parser, rather than geotiff specifically, so if that's fine I can write something up.
Thanks @Pomax, this is very much appreciated
I've filed a PR with some example code and guide text, feel free to massage that into whatever you feel makes the most sense for inclusion =)
I dug through https://geotiffjs.github.io/geotiff.js/ but I can't for the life of me figure how, after loading in a DSM tif, I can actually resolve GPS coordinates to elevation pixels, and vice versa. I can resolve the file directory and see my tile file uses WGS84, but I can't see anything that lets me use that to turn lat/long into 2d y/x indices. For instance, using
gdal-async
or the like (which requires having gdal installed, and that's exactly what we're trying to avoid =) we can use something as simple as the following:I don't see how to do the same thing using geotiff. How does one actually use this to get elevation data?