Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cloud Optimized GeoTIFF (COG) support #875

Open
8 of 14 tasks
sharkAndshark opened this issue Sep 11, 2023 · 12 comments · Fixed by #1590
Open
8 of 14 tasks

Cloud Optimized GeoTIFF (COG) support #875

sharkAndshark opened this issue Sep 11, 2023 · 12 comments · Fixed by #1590
Assignees

Comments

@sharkAndshark
Copy link
Collaborator

sharkAndshark commented Sep 11, 2023

Add support for Cloud Optimized GeoTIFF (COG).

CLI

martin  /path/to/cogs/file.tif  /path/to/directory

Conf file

...
cogs:
  paths:
    # scan this whole dir, matching all *.tif files
    - /dir-path
    # specific cog file will be published as cog source
    - /path/to/file1.tif
  sources:
   # named source matching source name to a single file
    cog-src1:  /path/to/file.tif

It seems that the conf sections about PMTiles and MBTiles are very similar. I don't know maybe we could merge them into a single section?

files:
  paths:
    - /dir1
    - /path/to/file1.ext
  sources:
    source1: /path/to/file.ext

Things to track:

@nyurik
Copy link
Member

nyurik commented Sep 11, 2023

I like the idea, thanks! One aspect that I am not too certain about is combining things into files -- one of highly requested features for files it to serve them from http -- in order words, pmtiles and i suspect COG files will reside in some cloud bucket, and Martin will access them with the HTTP range requests.

This means that we would need to tell the type of that file without relying on file extension. We could try to auto-detect it - e.g. get first few bytes and detect the type, but it won't be relevant to mbtiles, so in short - much easier to keep things clean and separate.

@sharkAndshark
Copy link
Collaborator Author

sharkAndshark commented Sep 14, 2023

@sharkAndshark sharkAndshark self-assigned this Oct 21, 2024
@sharkAndshark
Copy link
Collaborator Author

I've built a simple C# prototype without gdal, and am working on to port it to Rust.
The config would be separated as @nyurik suggested.

@CommanderStorm CommanderStorm changed the title COG support Cloud Optimized GeoTIFF (COG) support Nov 17, 2024
@sharkAndshark
Copy link
Collaborator Author

Tif with Non-Square pixel

Square
On X-Axis Or Y-Axis 1 pixel = 10 meters
Pixel Size = (10.000000000000000,-10.000000000000000)

Non-Square
On X it's 10, On Y it's 11
Pixel Size = (10.000000000000000,-11.000000000000000)

If it's non-square, we should adjust the output PNG size based on the resolution of X or Y and we should tell the user the resolution we picked in our TileJSON.

PseudoCode

let (resolution_x, resolution_y) = get_tiff_resolutions();
let ratio = resolution_x / Math.abs(resolution_y); // we always pick resolution_x as the resolution
let output_tile_size = (tif_tile_size[0], tif_tile_size[1] / ratio);

I'm not sure how often we encounter TIF files with non-square pixels. We will handle this when needed.

@sharkAndshark
Copy link
Collaborator Author

sharkAndshark commented Dec 22, 2024

The tile-schema and tile-json

Clients needs to know the tile-schema(like min_zoom, max_zoom,tile-size, extent, resolutions array...) in tiff file to display them.

We must add these in tile json and it's the most high priority.

And Another to be noted is:

Should we handle the google-schema specially?

The tile-schema could be GoogleMapsCompatible(see gdal doc).

If it's google compatible, Should we do a transformation internally, like if we have 5 layers in a GoogleMapsCompatible tiff file:

Add a google compatible in tile-json when it's tiff file.

{
    ...,
   "min_zoom": 10,
   "max_zoom": 14,
   "googleMapsCompatibled": "true",
    ...
}
sub-file not-specially specially
sub-file 0 user should call /4/x/y user should call /14/x/y
sub-file 1 user should call /3/x/y user should call /13/x/y
.... .... ....

sharkAndshark added a commit that referenced this issue Dec 23, 2024
Try to fix #875 . Still a draft and a lot to discuss and finish.


- [ ] Remote file on like S3. We will make it in next PRs. Let's make
this PR just a basic start.
- [x] Made the padded part transparent
- [x] Made the [gdal
nodata](https://gdal.org/en/stable/drivers/raster/gtiff.html#nodata-value)
transparent
- [x] Add tests
- [x] Add doc
- [x] Support rgb/rgba u8 tif tiled image. We will do others in next PRs
and leave this PR simple.

## Color types and bits per smaple
|colory type|bits per sample|supported|status|
|----|----|----|----|
|rgb/rgba|8|✅||
|rgb/rgba|16/32...|🛠️|working on, will be added in next PRs|
|gray|8/16/32...|🛠️|working on, will be added in next PRs|

## Comporession
The crate we used support these methods.
| Compression Format | tiff crate(This PR based on this) | GDAL creation
optinos |
|--------------------|------------------|----------------|
| None               | ✓                | ✓              |
| LZW                | ✓                | ✓ (gdal default)             |
| JPEG               |                  | ✓              |
| Deflate            | ✓                | ✓              |
| ZSTD               |                  | ✓              |
| WEBP               |                  | ✓              |
| LERC               |                  | ✓              |
| LERC_DEFLATE       |                  | ✓              |
| LERC_ZSTD          |                  | ✓              |
| LZMA               |                  | ✓              |
| PackBits | ✓ | Not sure but couldn't find this on gdal doc |

## Some terms and ref links
[7.1.2 Tiles in COG
spec](https://docs.ogc.org/is/21-026/21-026.html#_tiles)
[Tiff 6.0 spec page
67](https%3A%2F%2Fwww.itu.int%2Fitudoc%2Fitu-t%2Fcom16%2Ftiff-fx%2Fdocs%2Ftiff6.pdf)
[Chapter 4 of COG
spec](https://docs.ogc.org/is/21-026/21-026.html#_terms_and_definitions)

## Tile and padding
> In the context for a TIFF file, Tiling is a strategy for dividing the
content in the TIFF file differently than using the classical Strips.
Tiles, as defined in the TIFF version 6.0 specification, can be mapped
to the ones defined in the OGC Two Dimensional Tile Matrix Set Standard
(2D-TMS). For example in 2D-TMS, the TIFF 6.0 forces all tiles to be of
the same size. This is possible with the introduction of the concept of
padding: if necessary extra blank rows or columns are added to the
right-most and bottom-most tile to make them the same shape as other
tiles. However, the naming of the TIFF tags used version 6.0 and the
property names used in the 2D-TMS differ. The following table provides a
mapping between the two standards.

| OGC 2D-TMS | TIFF v. 6.0 | Definition |

|---------------|--------------|-------------------------------------------------|
| TileWidth | TileWidth | The tile width in pixels. The number of
columns in each tile |
| TileHeight | TileLength | The tile height in pixels. The number of
rows in each tile |
| MatrixWidth | TilesAcross | Number of tiles in the width direction |
| MatrixHeight | TilesDown | Number of tiles in the height direction

---------

Co-authored-by: Yuri Astrakhan <[email protected]>
@sharkAndshark sharkAndshark reopened this Dec 30, 2024
@sharkAndshark
Copy link
Collaborator Author

sharkAndshark commented Jan 3, 2025

I find a better subfiles organization description: https://docs.ogc.org/per/21-025.html#toc33 @nyurik @CommanderStorm

@sharkAndshark
Copy link
Collaborator Author

sharkAndshark commented Jan 3, 2025

And a tool to help view the internal details of a tiff file, exiftool. The output of this tools is really helpful.

sudo apt update
sudo apt install libimage-exiftool-perl
exiftool ./rgba_u8_nodata.tiff  -a -U  -g1

@sheecegardezi
Copy link

Some refs:

* [TIFF spec](https://download.osgeo.org/libtiff/doc/TIFF6.pdf)

* [The BigTIFF File Format](https://www.awaresystems.be/imaging/tiff/bigtiff.html)

* [GeoTIFF spec](https://docs.ogc.org/is/19-008r4/19-008r4.html)

* [COG spec](https://github.com/cogeotiff/cog-spec/blob/master/spec.md)

* [COG format details](https://gdal.org/drivers/raster/cog.html#file-format-details)

* [How to recognize a COG and how to create a proper one](https://cogeotiff.github.io/rio-cogeo/Is_it_a_COG/)

* [cogdumper of mapbox](https://github.com/mapbox/COGDumper/blob/master/cogdumper/cog_tiles.py)

none of these actually define COG data format the spec seem incomplete

@sheecegardezi
Copy link

I think i have created valid cog with alpha channel and 8 bit:

gdalwarp -of cog -dstalpha -srcnodata 0  -ot BYTE -b 1 -b 2 -b 3  -overwrite -multi --config GDAL_CACHEMAX 9000 -wm 9000 -co BLOCKSIZE=256 -co BIGTIFF=YES -co COMPRESS=DEFLATE -co PREDICTOR=YES -co NUM_THREADS=ALL_CPUS data.tif cog.tif

I dont think martin support serving COG:

docker run --rm -it -p 3000:3000 -v "$(pwd):/workspace" ghcr.io/maplibre/martin /workspace/cog.tif
[2025-01-25T12:12:21Z INFO  martin] Starting Martin v0.14.2
[2025-01-25T12:12:21Z INFO  martin] Config file is not specified, auto-detecting sources
[2025-01-25T12:12:21Z ERROR martin] Unrecognizable connection strings: ["/workspace/cog.tif"]

Is it possible to get a sample cog that martin supports:

@CommanderStorm
Copy link
Collaborator

CommanderStorm commented Jan 25, 2025

@sheecegardezi you are not running a martin version with basic COG support.
If you want to use this feature, you will have to go nightly and use the :main tag.

See this issue for further context:

@sheecegardezi
Copy link

sheecegardezi commented Jan 25, 2025

@CommanderStorm thanks for picking that up! I just tested it works like a charm with nightly build.

For completeness following worked:

gdalwarp -t_srs EPSG:3857 -of cog -dstalpha -srcnodata 0  -ot BYTE -b 1 -b 2 -b 3  -overwrite -multi --config GDAL_CACHEMAX 9000 -wm 9000 -co BLOCKSIZE=256 -co BIGTIFF=YES -co COMPRESS=DEFLATE -co PREDICTOR=2 -co LEVEL=9 -co NUM_THREADS=ALL_CPUS data.tif cog.tif
docker run --rm -it -p 3000:3000 -v "$(pwd):/workspace" ghcr.io/maplibre/martin:main /workspace/cog.tif

@sharkAndshark
Copy link
Collaborator Author

I will add tile schema of COG to tile json. It's not convenient for clients to load COG without it. Traveling, I will be back next day.

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 a pull request may close this issue.

4 participants