Load GeoTIFF/COG(Cloud optimized GeoTIFF) on Cesium
- Three band rendering.
- Multi mode color rendering.
- Support identify TIFF value with cartographic position.
- WebGL accelerated rendering.
- Band calculation.
- Support nearest neighbor and bilinear interpolation resampling methods.
- [experimental] Support any projected TIFF .
#npm
npm install --save tiff-imagery-provider
#yarn
yarn add tiff-imagery-provider
#pnpm
pnpm add tiff-imagery-provider
Basic
import { Viewer } from "cesium";
import TIFFImageryProvider from 'tiff-imagery-provider';
const cesiumViewer = new Viewer("cesiumContainer");
const provider = await TIFFImageryProvider.fromUrl('https://oin-hotosm.s3.amazonaws.com/56f9b5a963ebf4bc00074e70/0/56f9c2d42b67227a79b4faec.tif');
cesiumViewer.imageryLayers.addImageryProvider(provider);
You can also use the New keyword to create a new TIFFimageryProvider, which was deprecated after cesium@1.104+
const provider = new TIFFImageryProvider({
url: YOUR_TIFF_URL,
});
provider.readyPromise.then(() => {
cesiumViewer.imageryLayers.addImageryProvider(provider);
})
Experimental If TIFF's projection is not EPSG:4326 or EPSG:3857, you can pass the projFunc
to handle the projection
import proj4 from 'proj4';
TIFFImageryProvider.fromUrl(YOUR_TIFF_URL, {
projFunc: (code) => {
if (code === 32760) {
proj4.defs("EPSG:32760", "+proj=utm +zone=60 +south +datum=WGS84 +units=m +no_defs +type=crs");
return {
project: proj4("EPSG:4326", "EPSG:32760").forward,
unproject: proj4("EPSG:4326", "EPSG:32760").inverse
}
}
}
});
Band calculation
// NDVI
TIFFImageryProvider.fromUrl(YOUR_TIFF_URL, {
renderOptions: {
single: {
colorScale: 'rainbow',
domain: [-1, 1],
expression: '(b1 - b2) / (b1 + b2)'
}
}
});
Custom colors
TIFFImageryProvider.fromUrl(YOUR_TIFF_URL, {
renderOptions: {
single: {
"colors": [
[1, "rgb(154, 206, 127)"],
[2, "rgb(163, 214, 245)"],
[3, "rgb(255, 251, 177)"],
[4, "rgb(193, 114, 97)"],
[5, "rgb(220, 100, 120)"],
[6, "rgb(49, 173, 105)"]
],
type: "discrete",
useRealValue: true // use real value in colors stops
}
}
});
class TIFFImageryProvider {
ready: boolean;
readyPromise: Promise<void>
bands: Record<number, {
min: number;
max: number;
}>;
origin: number[];
reverseY: boolean;
samples: number;
constructor(options: TIFFImageryProviderOptions & {
/**
* @deprecated
* Deprecated after cesium@1.104+, you can use fromUrl instead
* @example
* const provider = await TIFFImageryProvider.fromUrl(url)
*/
url?: string | File | Blob;
});
get isDestroyed(): boolean;
destroy(): void;
static fromUrl(url: string | File | Blob, options?: TIFFImageryProviderOptions): Promise<TIFFImageryProvider>;
}
interface TIFFImageryProviderOptions {
requestOptions?: {
/** defaults to false */
forceXHR?: boolean;
headers?: Record<string, any>;
credentials?: boolean;
/** defaults to 0 */
maxRanges?: number;
/** defaults to false */
allowFullFile?: boolean;
[key: string]: any;
};
credit?: string;
tileSize?: number;
maximumLevel?: number;
minimumLevel?: number;
enablePickFeatures?: boolean;
hasAlphaChannel?: boolean;
renderOptions?: TIFFImageryProviderRenderOptions;
/**
* If TIFF's projection is not EPSG:4326 or EPSG:3857, you can pass the ``projFunc`` to handle the projection
* @experimental
*/
projFunc?: (code: number) => {
/** projection function, convert [lon, lat] position to [x, y] */
project: ((pos: number[]) => number[]);
/** unprojection function, convert [x, y] position to [lon, lat] */
unproject: ((pos: number[]) => number[]);
} | undefined;
/** cache size, defaults to 100 */
cacheSize?: number;
/** resample web worker pool size, defaults to the number of CPUs available. When this parameter is `null` or 0, then the resampling will be done in the main thread. */
workerPoolSize?: number;
}
type TIFFImageryProviderRenderOptions = {
/** nodata value, default read from tiff meta */
nodata?: number;
/** Only valid for three band rendering, defaults to { 'black': 'transparent' } */
colorMapping?: Record<string, string>;
/** try to render multi band cog to RGB, priority 1 */
convertToRGB?: boolean;
/** priority 2 */
multi?: MultiBandRenderOptions;
/** priority 3 */
single?: SingleBandRenderOptions;
/** resample method, defaults to nearest */
resampleMethod?: 'bilinear' | 'nearest';
}
interface SingleBandRenderOptions {
/** band index start from 1, defaults to 1 */
band?: number;
/**
* The color scale image to use.
*/
colorScaleImage?: HTMLCanvasElement | HTMLImageElement;
/**
* The name of a named color scale to use.
*/
colorScale?: ColorScaleNames;
/** custom interpolate colors, [stopValue(0 - 1), color] or [color], if the latter, means equal distribution
* @example
* [[0, 'red'], [0.6, 'green'], [1, 'blue']]
*/
colors?: [number, string][] | string[];
/** Determine whether to use the true value range for custom color ranges, defaults to false */
useRealValue?: boolean;
/** defaults to continuous */
type?: 'continuous' | 'discrete';
/**
* The value domain to scale the color.
*/
domain?: [number, number];
/**
* Range of values that will be rendered, values outside of the range will be transparent.
*/
displayRange?: [number, number];
/**
* Set if displayRange should be used.
*/
applyDisplayRange?: boolean;
/**
* Whether or not values below the domain shall be clamped.
*/
clampLow?: boolean;
/**
* Whether or not values above the domain shall be clamped (if not defined defaults to clampLow value).
*/
clampHigh?: boolean;
/**
* Sets a mathematical expression to be evaluated on the plot. Expression can contain mathematical operations with integer/float values, band identifiers or GLSL supported functions with a single parameter.
* Supported mathematical operations are: add '+', subtract '-', multiply '*', divide '/', power '**', unary plus '+a', unary minus '-a'.
* Useful GLSL functions are for example: radians, degrees, sin, asin, cos, acos, tan, atan, log2, log, sqrt, exp2, exp, abs, sign, floor, ceil, fract.
* Don't forget to set the domain parameter!
* @example
* '-2 * sin(3.1415 - b1) ** 2'
* '(b1 - b2) / (b1 + b2)'
*/
expression?: string;
}
interface MultiBandRenderOptions {
/** Band value starts from 1 */
r?: {
band: number;
min?: number;
max?: number;
};
g?: {
band: number;
min?: number;
max?: number;
};
b?: {
band: number;
min?: number;
max?: number;
};
}
/** see https://observablehq.com/@d3/color-schemes */
type ColorScaleNames = 'viridis' | 'inferno' | 'turbo' | 'rainbow' | 'jet' | 'hsv' | 'hot' | 'cool' | 'spring' | 'summer' | 'autumn' | 'winter' | 'bone' | 'copper' | 'greys' | 'ylgnbu' | 'greens' | 'ylorrd' | 'bluered' | 'rdbu' | 'picnic' | 'portland' | 'blackbody' | 'earth' | 'electric' | 'magma' | 'plasma' | 'redblue' | 'coolwarm' | 'diverging_1' | 'diverging_2' | 'blackwhite' | 'twilight' | 'twilight_shifted';
Launch the app in the demo folder, and then visit http://localhost:3000/
pnpm install
cd example
pnpm dev
- GPU speed up calculation
- More efficient tile request method