geotiffjs / geotiff.js

geotiff.js is a small library to parse TIFF files for visualization or analysis. It is written in pure JavaScript, and is usable in both the browser and node.js applications.
https://geotiffjs.github.io/
MIT License
878 stars 183 forks source link

Support for scale and offset #222

Open bertcoerver opened 3 years ago

bertcoerver commented 3 years ago

Given an GeoTIFF like the one below, is it possible with Geotiff.js to somehow get the scale and offset factors that are defined inside the file at the band-level? For now I'm hardcoding the scale-factors into my code, but it would be convenient if I could read them from the geotiffs themselves (or even better if geotiff.js would already apply them to the data, like for example QGIS is doing).

Driver: GTiff/GeoTIFF
Files: /Users/hmcoerver/Library/Mobile Documents/com~apple~CloudDocs/GitHub/map-tile-rnd/cogs/web/data/api/cog/gfs/2021020718/precip.cog.tif
Size is 294, 209
Coordinate System is:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
Origin = (106.000000000000000,-55.750000000000000)
Pixel Size = (0.249149659863946,0.248803827751196)
Metadata:
  AREA_OR_POINT=Area
Image Structure Metadata:
  COMPRESSION=DEFLATE
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  ( 106.0000000, -55.7500000) (106d 0' 0.00"E, 55d45' 0.00"S)
Lower Left  ( 106.0000000,  -3.7500000) (106d 0' 0.00"E,  3d45' 0.00"S)
Upper Right ( 179.2500000, -55.7500000) (179d15' 0.00"E, 55d45' 0.00"S)
Lower Right ( 179.2500000,  -3.7500000) (179d15' 0.00"E,  3d45' 0.00"S)
Center      ( 142.6250000, -29.7500000) (142d37'30.00"E, 29d45' 0.00"S)
Band 1 Block=256x256 Type=Int16, ColorInterp=Gray
  Description = precip_2021-02-07T18
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
Band 2 Block=256x256 Type=Int16, ColorInterp=Undefined
  Description = precip_2021-02-07T21
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
Band 3 Block=256x256 Type=Int16, ColorInterp=Undefined
  Description = precip_2021-02-08T00
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
           .
           .
           .
Band 79 Block=256x256 Type=Int16, ColorInterp=Undefined
  Description = precip_2021-02-17T12
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
Band 80 Block=256x256 Type=Int16, ColorInterp=Undefined
  Description = precip_2021-02-17T15
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
Band 81 Block=256x256 Type=Int16, ColorInterp=Undefined
  Description = precip_2021-02-17T18
  NoData Value=-9999
  Overviews: 147x105, 74x53, 37x27, 19x14, 10x7, 5x4
  Offset: 0,   Scale:0.01
tschaub commented 3 years ago

I'd be curious to see if you find this in the GDAL tagged metadata.

const image = geotiff.getImage(0);
console.log(image.getGDALMetadata());

Also worth trying with a specific band (e.g. image.getGDALMetadata(1));

If your data is available that others can access it, that would make it easier to figure out what is possible.

constantinius commented 3 years ago

As far as I can tell, GDAL uses this tag https://www.awaresystems.be/imaging/tiff/tifftags/gdal_metadata.html with OFFSET and SCALE XML tags. So it should be possible to get those values for each band and multiply the result.

I'm thinking of doing this inside of readRasters directly, controlled with a parameter.

tschaub commented 3 years ago

I'm thinking of doing this inside of readRasters directly, controlled with a parameter.

The nodata values might complicate this story.

zakjan commented 3 years ago

Can nodata be converted to NaN / user-defined value (for non-float bands) automatically?