Skip to content

feat: add experimental cog viewer#169

Open
alukach wants to merge 5 commits intomainfrom
feat/add-experimental-cog-viewer
Open

feat: add experimental cog viewer#169
alukach wants to merge 5 commits intomainfrom
feat/add-experimental-cog-viewer

Conversation

@alukach
Copy link
Contributor

@alukach alukach commented Oct 19, 2025

What I'm changing

Add @bdon's COG viewer (#72 (comment))

How I did it

Right now, we're using this viewer for any file ending in .tif. I feel like the "sniffing" of support for the viewer could be a bit more intelligent, possibly using another viewer if the TIF is not actually COG.

Alternatively, perhaps the https://cogeo.org/viewer/ could support non-cogs?

How you can test it

@vercel
Copy link

vercel bot commented Oct 19, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
source-cooperative Error Error Jan 15, 2026 11:33pm

Review with Vercel Agent

@bdon
Copy link
Contributor

bdon commented Oct 20, 2025

https://data.source.coop/kerner-lab/fields-of-the-world/denmark/s2_images/window_a/g22_00002_10.tif
https://data.source.coop/ausantarctic/ghrsst-mur-v2/2020/12/12/20201212090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1_sea_ice_fraction.tif

These COGs are in geographic CRS (EPSG:4326)

https://data.source.coop/tabaqat/riyadh-sentinel-rgb/Sentinel-2_Satellite_RGB_Riyadh.tif

This COG is in UTM 38N

https://data.source.coop/giswqs/tn-imagery/imagery/AndersonCo_OrthoPan_2ft_2000.tif

This COG is in NAD83

I think our best bet is to use OpenLayers instead of MapLibre, which means introducing a build system to cogeo.org/viewer. I will work on this next, can you please leave this feature branch / deployment open? Thanks!

@bdon
Copy link
Contributor

bdon commented Oct 20, 2025

https://data.source.coop/ausantarctic/ghrsst-mur-v2/2020/12/12/20201212090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1_sea_ice_fraction.tif

It looks like this cog uses ZStandard for compression, which OL's COG implementation does not seem to support yet.

@bdon
Copy link
Contributor

bdon commented Oct 27, 2025

Turns out it is pretty challenging to make a generic COG viewer on the web!

  1. https://data.source.coop/kerner-lab/fields-of-the-world/denmark/s2_images/window_a/g22_00002_10.tif
  2. https://data.source.coop/ausantarctic/ghrsst-mur-v2/2020/12/12/20201212090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1_sea_ice_fraction.tif
  3. https://data.source.coop/tabaqat/riyadh-sentinel-rgb/Sentinel-2_Satellite_RGB_Riyadh.tif
  4. https://data.source.coop/giswqs/tn-imagery/imagery/AndersonCo_OrthoPan_2ft_2000.tif

To summarize:

  • maplibre-cog-protocol - only supports EPSG:3857 projected COGs, which are unlikely to be on Source
  • http://app.geotiff.io/ - (source) - strongest candidate, but seems to not have ZStandard decoding support yet so fails on (2)
  • COG Explorer (source) - on the previous major version of geotiff.js, fails silently on (1) and (2), and (4) gives an error
  • OpenLayers COG support - does not visualize (1) correctly, fails on (2) because of lack of zstd, fails on (4) because lack of transform

@bdon
Copy link
Contributor

bdon commented Oct 27, 2025

For GeoTIFF.io we need to make a build with the latest geotiff.js with ZStandard support through this dependency tree:

@bdon
Copy link
Contributor

bdon commented Oct 27, 2025

I'm falling back to the existing solution which is to use tiles.rdnt.io as a proxy for the MapLibre-powered viewer. This makes rasters 1,3,and 4 show a preview on the deployed featured branch:

CleanShot 2025-10-27 at 16 38 06@2x

GeoTIFF 2 is broken, likely because tiles.rdnt.io or one of its dependencies like marblecutter-virtual needs to be updated to support ZStandard decompression.

I think this is a good interim solution with no marginal additional cost since tiles.rdnt.io has already been running for years with no issues. We can keep an eye on client-side COG viewers and switch to one if it has sufficient projection and compression support (something like https://github.com/Gisat/deck.gl-geotiff) @jedsundwall what do you think about this in the long term?

@jedsundwall
Copy link
Contributor

I'm fine with this for now, but I would prefer that we move to a client-side solution sometime within the next 6 months or so (funding dependent). I anticipate that Source will eventually host a lot of non-geospatial imagery, so I predict that this "imagery viewer" will end up being fairly complicated, sniffing out different kinds of imagery files that can be previewed, and the COG viewer will be one feature among many.

I'm glad tiles.rdnt.io has proven to be so durable, but it's been neglected for years. I have a vague idea of turning tiles.rdnt.io into a service that's integrated into Source, but haven't thought through this enough.

@m-mohr
Copy link

m-mohr commented Oct 28, 2025

This is all very interesting to me, given that STAC Browser used georaster-layer-for-leaflet in the past (with tiles.rdnt.io fallback) and migrated to OpenLayers (without pre-defined fallback yet) where it's also the plan to support generic COGs (although we assume that there's potentially a STAC with additional metadata for visualization). So could potentially make sense to join forces here.

georaster-layer-for-leaflet did a pretty good job in getting a wide variety of COGs visualied nicely by default, but this comes with drawbacks. The resolution sometimes is lacking, but if you set it too high, it gets rather slow due to the way it computes statistics across all pixels on the fly. It also has some reprojection issues (there are various issues posted in stac-layer and stac-browser repositories around this).

So the decision was to migrate to OpenLayers as it's WebGL-based and thus faster, but has some issues with specific COGs. The examples above are nice to have for testing purposes. I'll take those into testing in STAC Browser (ol-stac) and see how far I can get.

I'm wondering how difficult it would be to add ZStandard support, given there is a zstd JS library (I think?). I'm also facing some issues in OL that I'm still investigating, e.g. openlayers/openlayers#17153 - It would be interesting to understand more about why the examples that error in OL do actually error so that it can be investigated further. Could e.g. the issue 4 be solved by loading the projection dynamically, similar to the given OL issue? Why is 1 not visualizing? Is it potentially an issue with min/max values for stretching? Would be great to get the issues into the OL issue tracker with a repro for testing.

Full list of issues that I encountered over time: https://github.com/openlayers/openlayers/issues?q=is%3Aissue%20state%3Aopen%20author%3Am-mohr ;-)

Edit: for zstd we probably just need an updated release? geotiffjs/geotiff.js#451

@kylebarron
Copy link

In case it's relevant, I'm actively prototyping generic client-side COG rendering in deck.gl (which could be integrated into a Maplibre visualization) but I don't have any specific timelines to share at this time.

bdon added a commit to bdon/source.coop that referenced this pull request Nov 14, 2025
@kylebarron
Copy link

I'm using these above COG urls as test images for https://github.com/developmentseed/deck.gl-raster.

  1. data.source.coop/kerner-lab/fields-of-the-world/denmark/s2_images/window_a/g22_00002_10.tif

This is a 16-bit, 4-band image with a Photometric Interpretation defined in the image as BlackIsZero (i.e. grayscale). And the GDAL_METADATA TIFF tag contains this XML:

<GDALMetadata>
  <Item name="DESCRIPTION" sample="0" role="description">B04</Item>
  <Item name="DESCRIPTION" sample="1" role="description">B03</Item>
  <Item name="DESCRIPTION" sample="2" role="description">B02</Item>
  <Item name="DESCRIPTION" sample="3" role="description">B08</Item>
</GDALMetadata>

How should a COG library render this, with no external information?

We know separately that this image has R, G, B, NIR bands, but there's no way to know that from the included metadata.

As of now this renders as transparent in deck.gl-raster, because the 4th band is set as the alpha.

If I hard-code the alpha to 1 (opaque), then the image still looks black because it's 16 bit input and linear rescaling is applied.

Without fetching the entire image ahead of time, we have no information about dataset min/max and have no good priors for rescaling.

  1. data.source.coop/ausantarctic/ghrsst-mur-v2/2020/12/12/20201212090000-JPL-L4_GHRSST-SSTfnd-MUR-GLOB-v02.0-fv04.1_sea_ice_fraction.tif

This also failed for me because it uses ZSTD compression. It turns out I was using latest geotiff stable version, which was released two years ago. ZSTD is only included on 2.1.4-beta.1.

I tried to load the image with 2.1.4-beta.1 and got an internal error:
image

Someone might need to create an issue on geotiff.js for that.

@jedsundwall
Copy link
Contributor

@kylebarron glad you could use TIFFs in Source to test out your viewer. To be clear, are you saying that these TIFFs are malformed? That is, their inability to render is a function of how they're encoded?

@alukach @bdon I feel like we need to create a generic TIFF viewer (see #203) that can render COGs if and when it encounters valid COGs. We're likely to get a lot of TIFF files that aren't necessarily geospatial in the future. Curious to get your take on how an intelligent in-browser TIFF viewer might work.

## What I'm changing

Add `#iframe=true` to COG viewer to hide parts of the UI. 

## How you can test it

The embedded COG preview should appear. In this state it should be good
enough for most COGs on source that don't use zstd compression.
@kylebarron
Copy link

@kylebarron glad you could use TIFFs in Source to test out your viewer. To be clear, are you saying that these TIFFs are malformed? That is, their inability to render is a function of how they're encoded?

I'm not sure I'm saying they're malformed as much as lamenting that there isn't always enough information stored just in the COG itself to really render data in the way that users would expect.

This is partially why STAC exists, to include the extra metadata not in the COG itself that describes how you might want to render the data.

In effect this means that if you want an excellent COG viewer, you also need to give the users the ability to change the default rendering behavior for the cases when the users know more about the data than is stored in the file itself.

@alukach @bdon I feel like we need to create a generic TIFF viewer (see #203) that can render COGs if and when it encounters valid COGs. We're likely to get a lot of TIFF files that aren't necessarily geospatial in the future. Curious to get your take on how an intelligent in-browser TIFF viewer might work.

FWIW you could use deck.gl / deck.gl-raster for non-geospatial image rendering too if you wanted. deck.gl supports non-geospatial viewports and cameras as well. That would let you use the same GPU rendering setup (arbitrary math in GPU shaders) as deck.gl-raster for generic TIFF data.

@bdon
Copy link
Contributor

bdon commented Feb 5, 2026

We could extend the cog-basic example to support loading from a URL hash param easily like with PMTiles: developmentseed/deck.gl-raster#219

@bdon
Copy link
Contributor

bdon commented Feb 6, 2026

Put the generic URL hash param loading in a branch here: https://github.com/cogeotiff/www.cogeo.org/tree/deckgl-cog-viewer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants