I have a collection of 50 COGs in NZTM projection. The COGs are aligned in a seamless grid. I'd like to use these COGs in a similar method to mosaicJSON on like a VRT online, wherein, I can make single call to a JSON type docoument and load the COGs at once.

I am using OpenLayers and can easily get an individual COG to work well using the GeoTIFF and TileLayer modules. The COGs are served statically via S3.

I'd like to use something like the tileJSON or mosaicJSON formats to bring these COGs together to act as a single unit.  I might be wrong, but I am thinking that while tileJSON can use custom projection, a GeoTIFF cannot be used in the document.  The mosaicJSON would be the tool for this, yes?; but this seems to not allow for a projection other than 3857.

I know there must be a way to get around this, but I cannot seem to figure out how.  Using OpenLayers, I did run a test in using tileJSON and the GeoTIFF link and it looks like I do get a return from the TIFF, however nothing is returned to the screen. Regardless, my assumption is tileJSON cannot be used in this manner but it was worth a shot.

Here is the experiment using one COG as an example:

import './style.css';
import {Map, View} from 'ol';
import TileLayer from 'ol/layer/WebGLTile';
import GeoTIFF from 'ol/source/GeoTIFF';
import proj4 from 'proj4';
import {register} from 'ol/proj/proj4';
import {get as getProjection} from 'ol/proj';
import {fromLonLat} from 'ol/proj';
import TileJSON from 'ol/source/TileJSON';

// set NZTM projection 
proj4.defs("EPSG:2193","+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
const nztmProjection = getProjection('EPSG:2193');

//  NZTM tile matrix origin, resolution and matrixId definitions.
const origin = [-1000000, 10000000];
const resolutions = [
const matrixIds = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

var nztmTileJSON = {
   "tilejson": "2.0.0",
   "name": "compositing",
   "description": "Trying tileJSON with COG",
   "version": "1.0.0",
   "attribution": "TBD",
   "scheme": "tms",
   "tiles": [
   "minzoom": 6,
   "maxzoom": 10,
   "projected_bounds": [ 827933.23, 3729820.29, 3195373.59, 7039943.58 ],
   "center": origin,
   "crs": "EPSG:2193",
   "projection": "+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
   "scales": resolutions,

// cog file loads
const cog = new TileLayer({
   source: new TileJSON({
     tileJSON: nztmTileJSON,
     crossOrigin: 'anonymous',

// draw map
const map = new Map ({
  layers: [cog],
  target: 'map',
  view: new View({
    projection: nztmProjection,
    center: fromLonLat([176.0,-38.68], nztmProjection),
    zoom: 6,
    maxZoom: 6,
    minZoom: 10,
    resolutions: resolutions,
    matrixIds: matrixIds,
    constrainResolution: true,
    smoothResolutionConstraint: true

Does anyone know of a good example of how to do a mosaicJSON with a custom projection that works through OpenLayers or how to use the tileJSON format with GeoTIFF in OpenLayers? Preferably, this would be done without Lamda in the mix. Maybe there is even some way to leverage WMTS?

  • GeoTIFFs should be able to locate themselves codesandbox.io/s/cog-forked-0is04r?file=/main.js Are you trying to get something like openlayers.org/en/latest/examples/cog-pyramid.html by parsing the grid from a json? Or like deploy-preview-13654--ol-site.netlify.app/en/latest/examples/…? (but without reprojection as that is not yet in a release).
    – Mike
    Aug 18, 2022 at 9:23
  • Thanks for the response @Mike. Much appreciated for the examples too. I think I will edit my question to be more clear. My issue is that I have about 50 COGs that make up a seamless grid and I want to be able to make a call to the 50 COGs at once to make seamless map in browser and I want to do this in NZTM.
    – Ian R.
    Aug 18, 2022 at 9:44
  • I'm not sure of the purpose of a TileJSON, that is usually used for sources with {z}, {x} and {y} placeholders in the urls, or how a 17 level grid relates to just 50 files. If you have 50 COGs arranged in a grid (is it 5 x 10 single level?) which is aligned with the projection you could use sourcesFromTileGrid as in openlayers.org/en/latest/examples/cog-pyramid.html You will some means of associating the x and y coordinates of the grid to the COG urls.
    – Mike
    Aug 18, 2022 at 11:55
  • Thanks for the suggestion on the cog pyramid @Mike. I am looking into this now. The use of tileJSON in the example is just a demonstration of the functionality I am looking for. Basically a doc like a JSON where the "rules" could be developed and give me a single point of entry to all the COGs. Thanks to your example, I did find I can easily leverage TileLayer like const fullCOG = new TileLayer({ sources: [cogSourceHM, cogSourceHN] }). This gets me closer. I can go back an optimize the size of the COGs to work with this method. Example up in a bit. Thanks again.
    – Ian R.
    Aug 18, 2022 at 22:08

1 Answer 1


Not the ideal VRT solution, but the workaround to load multiple urls.:

// URL to COG tile
const urls = [

function getSourceURLs(urls) {
  var urlArray = [];
  urls.forEach(address => urlArray.push(
    new GeoTIFF({
        sources: [
            tileSize: 256,
        convertToRGB: true,
        interpolate: false,
    return urlArray

const cog = new TileLayer({
  crossOrigin: 'anonymous',
  sources: getSourceURLs(urls)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.