@gisatcz/deckgl-geolib 0.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +3 -0
  3. package/dist/cjs/index.js +99799 -18
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/index.min.js +5 -0
  6. package/dist/cjs/index.min.js.map +1 -0
  7. package/dist/cjs/types/cogbitmaplayer/CogBitmapLayer.d.ts +16 -0
  8. package/dist/cjs/types/cogterrainlayer/CogTerrainLayer.d.ts +18 -0
  9. package/dist/cjs/types/cogtiles/cogtiles.d.ts +29 -0
  10. package/dist/cjs/types/geoimage/geoimage.d.ts +49 -0
  11. package/dist/cjs/types/index.d.ts +11 -2
  12. package/dist/cjs/types/utilities/tileurls.d.ts +4 -0
  13. package/dist/esm/index.js +99797 -18
  14. package/dist/esm/index.js.map +1 -1
  15. package/dist/esm/index.min.js +5 -0
  16. package/dist/esm/index.min.js.map +1 -0
  17. package/dist/esm/types/cogbitmaplayer/CogBitmapLayer.d.ts +16 -0
  18. package/dist/esm/types/cogterrainlayer/CogTerrainLayer.d.ts +18 -0
  19. package/dist/esm/types/cogtiles/cogtiles.d.ts +29 -0
  20. package/dist/esm/types/geoimage/geoimage.d.ts +49 -0
  21. package/dist/esm/types/index.d.ts +11 -2
  22. package/dist/esm/types/utilities/tileurls.d.ts +4 -0
  23. package/package.json +42 -36
  24. package/rollup.config.mjs +70 -0
  25. package/src/cogbitmaplayer/CogBitmapLayer.ts +104 -0
  26. package/src/cogbitmaplayer/README.md +52 -0
  27. package/src/cogterrainlayer/CogTerrainLayer.ts +174 -0
  28. package/src/cogterrainlayer/README.md +41 -0
  29. package/src/cogtiles/README.md +72 -0
  30. package/src/cogtiles/cogtiles.ts +355 -0
  31. package/src/cogtiles/lzw.js +256 -0
  32. package/src/geoimage/README.md +110 -0
  33. package/src/geoimage/geoimage.ts +390 -0
  34. package/src/index.ts +11 -0
  35. package/src/utilities/tileurls.ts +21 -0
  36. package/tsconfig.json +3 -0
  37. package/README.md +0 -1
  38. package/dist/cjs/classes/geoImage/GeoImage.d.ts +0 -38
  39. package/dist/cjs/classes/geoImage/index.d.ts +0 -1
  40. package/dist/cjs/classes/geoImage/interface.d.ts +0 -32
  41. package/dist/cjs/classes/index.d.ts +0 -1
  42. package/dist/cjs/hooks/index.d.ts +0 -1
  43. package/dist/cjs/hooks/useGeoData/index.d.ts +0 -1
  44. package/dist/cjs/hooks/useGeoData/useGeoData.d.ts +0 -9
  45. package/dist/cjs/index.d.ts +0 -2
  46. package/dist/cjs/types/classes/geoImage/GeoImage.d.ts +0 -38
  47. package/dist/cjs/types/classes/geoImage/index.d.ts +0 -1
  48. package/dist/cjs/types/classes/geoImage/interface.d.ts +0 -32
  49. package/dist/cjs/types/classes/index.d.ts +0 -1
  50. package/dist/cjs/types/hooks/index.d.ts +0 -1
  51. package/dist/cjs/types/hooks/useGeoData/index.d.ts +0 -1
  52. package/dist/cjs/types/hooks/useGeoData/useGeoData.d.ts +0 -9
  53. package/dist/esm/classes/geoImage/GeoImage.d.ts +0 -38
  54. package/dist/esm/classes/geoImage/index.d.ts +0 -1
  55. package/dist/esm/classes/geoImage/interface.d.ts +0 -32
  56. package/dist/esm/classes/index.d.ts +0 -1
  57. package/dist/esm/hooks/index.d.ts +0 -1
  58. package/dist/esm/hooks/useGeoData/index.d.ts +0 -1
  59. package/dist/esm/hooks/useGeoData/useGeoData.d.ts +0 -9
  60. package/dist/esm/index.d.ts +0 -2
  61. package/dist/esm/types/classes/geoImage/GeoImage.d.ts +0 -38
  62. package/dist/esm/types/classes/geoImage/index.d.ts +0 -1
  63. package/dist/esm/types/classes/geoImage/interface.d.ts +0 -32
  64. package/dist/esm/types/classes/index.d.ts +0 -1
  65. package/dist/esm/types/hooks/index.d.ts +0 -1
  66. package/dist/esm/types/hooks/useGeoData/index.d.ts +0 -1
  67. package/dist/esm/types/hooks/useGeoData/useGeoData.d.ts +0 -9
  68. package/dist/index.d.ts +0 -80
@@ -0,0 +1,110 @@
1
+ # GEOIMAGE
2
+ #### A Javascript library for generating bitmaps out of **geoTIFF** files.
3
+ <img src = "/images/example0crop1.png" width = "100%">
4
+
5
+ ## Features
6
+ #### Color texture generation
7
+ - Create RGB pictures out of RGB geoTIFF data.
8
+ - Generate pictures out of non-RGB geoTIFF data with different processing options.
9
+
10
+ #### Terrain texture generation
11
+ - Generate heightmaps out of single-channel geoTIFF elevation data.
12
+ - The **elevation data** is encoded into the bitmap as [Mapbox Terrain-RGB](https://docs.mapbox.com/data/tilesets/guides/access-elevation-data/#decode-data).
13
+
14
+ #### Data visualisation options
15
+ - Color
16
+ - Transparency
17
+ - Heatmap (custom color scale example [here](../cogbitmaplayer/README.md#custom-heatmap-color-scale))
18
+ - Data slice
19
+ - Automatic data range
20
+ - Manual data range
21
+ - Assign color to specific data value (example [here](../cogbitmaplayer/README.md#assigning-color-to-specific-data-value))
22
+ ## Data processing options
23
+ - `useAutoRange : boolean` - set automatic range of color gradient **(default false)**
24
+ - `useDataForOpacity : boolean` - visualise data with opacity of each pixel according to its value **(default false)**
25
+ - `alpha : number` - visualise data in specific opacity **(if useDataOpacity is false)** **(default 150)**
26
+ - `useHeatMap : boolean` - generate data as a color heatmap **(default true)**
27
+ `useChannel : number | null` - specify a single channel to use **(default null)**
28
+ - `multiplier : number ` - multiplies each value **(default 1.00)**
29
+ - `clipLow : number | null`- generate only data greater than this **(default null)**
30
+
31
+ - `clipHigh : number | null`- generate only data less than this **(default null)**
32
+ - `clippedColor: chroma.Color` - set color for clipped values when using `clipLow` or `clipHigh`, **(default [0, 0, 0, 0])**
33
+ - `colorScale:chroma.Color[]` - array of colors, supports chroma.js color definition such as `'red'`, `[255,0,0]`, `'#FF0000'`, etc. and [Color Brewer pallete names](https://www.datanovia.com/en/wp-content/uploads/dn-tutorials/ggplot2/figures/0101-rcolorbrewer-palette-rcolorbrewer-palettes-colorblind-friendly-1.png) in this format: `chroma.brewer.Greens`
34
+ - `colorScaleValueRange: number[]` - set min and max range values or set any array of values to set exact colors to values, **if useAutoRange is false**, **(default [0,255])**
35
+ - `useColorsBasedOnValues: boolean` - assign pixels colors based on defined data values **(default false)**
36
+ - `colorsBasedOnValues : [number, chroma.Color][]` - array of value-color pairs, used **if useColorsBasedOnValues is true**, supports chroma.js color definition such as `'red'`, `[255,0,0]`, `'#FF0000'`, etc.
37
+ - `unidentifiedColor: chroma.Color` - set color for not identified values **if useColorsBasedOnValues is true**, **(default [0, 0, 0, 0])**
38
+ - `nullColor: chroma.Color` - set color for noData values **(default [0, 0, 0, 0])**
39
+ - `useSingleColor: boolean` - display data values only with single color **(default false)**
40
+ - `color: chroma.Color` - set color when **if useSingleColor is true**, **(default [255, 0, 255, 255])**
41
+
42
+ ## Return options
43
+ **Method returns Image DataUrl**
44
+
45
+ - `getMap(returnFormat : "image" | "terrain", input : string | { width : number, height : number, rasters : any[] }, options?: { opacity : number })`
46
+
47
+ If `returnFormat` = `"image"` - If the input has 3 or 4 color channels, return standard RGB or RGBA image. If the input has 1 channel, data gets processed according to data processing options.
48
+
49
+ If `returnFormat` = `"terrain"` - Ignores all options except `multiplier` and returns [Mapbox Terrain-RGB](https://docs.mapbox.com/data/tilesets/guides/access-elevation-data/#decode-data)
50
+
51
+ ## Basic example
52
+ #### Initialize the library
53
+ ```typescript
54
+ import GeoImage from 'geoimage';
55
+
56
+ const g = new GeoImage();
57
+ ```
58
+ #### Get bitmap
59
+ ```typescript
60
+ const bitmap = await g.getMap("image", 'image.tif');
61
+ ```
62
+ ```typescript
63
+ const bitmap = await g.getMap("image", { width : 512, height : 512, rasters : [[...data]] });
64
+ ```
65
+
66
+
67
+
68
+ #### Get heightmap
69
+
70
+ ```typescript
71
+ const heightmap = await g.getMap("terrain", 'image.tif');
72
+ ```
73
+ ```typescript
74
+ const bitmap = await g.getMap("terrain", { width : 512, height : 512, rasters : [[...data]] });
75
+ ```
76
+
77
+ ## Advanced example
78
+
79
+ ```typescript
80
+ //Import the library and initiate GeoImage object:
81
+ import GeoImage from 'geoimage';
82
+
83
+ const g = new GeoImage();
84
+
85
+ //Single-channel geotiff as a transparent heatmap with auto-rage:
86
+ g.useAutoRange(true);
87
+ g.useHeatMap(true);
88
+ g.alpha(120);
89
+ const firstImage = await g.getMap("image", 'image.tif');
90
+
91
+ //Single-channel geotiff as a transparent heatmap with manual range in meters:
92
+ g.useAutoRange(false);
93
+ g.useDataRange(0,250); //Blue at 0m, red at 250m
94
+ g.useHeatMap(true);
95
+ g.alpha(120);
96
+ const secondImage = await g.getBitmap("image", 'image.tif');
97
+
98
+ //Single-channel geotiff with data as transparency:
99
+ g.useAutoRange(true);
100
+ g.useHeatMap(false);
101
+ g.useDataForOpacity(true);
102
+ const thirdImage = await g.getBitmap("image", 'image.tif');
103
+
104
+ //Single-channel geotiff with data slice from 350m to 360m in custom color:
105
+ g.clipLow(350); //generate only data between 350m and 360m
106
+ g.clipHigh(360);
107
+ g.useHeatMap(false);
108
+ g.color[0,255,100];
109
+ const fourthImage = await g.getBitmap("image", 'image.tif');
110
+ ```
@@ -0,0 +1,390 @@
1
+ /* eslint 'max-len': [1, { code: 105, comments: 999, ignoreStrings: true, ignoreUrls: true }] */
2
+
3
+ // import { ExtentsLeftBottomRightTop } from '@deck.gl/core/utils/positions';
4
+ import { fromArrayBuffer, GeoTIFFImage, TypedArray } from 'geotiff';
5
+ import chroma from 'chroma-js';
6
+
7
+ export type GeoImageOptions = {
8
+ type: 'image' | 'terrain',
9
+ format?: 'uint8' | 'uint16' | 'uint32' |'int8' | 'int16' | 'int32' | 'float32' | 'float64'
10
+ useHeatMap?: boolean,
11
+ useColorsBasedOnValues? : boolean,
12
+ useAutoRange?: boolean,
13
+ useDataForOpacity?: boolean,
14
+ useChannel?: number | null,
15
+ useSingleColor?: boolean,
16
+ clipLow?: number | null,
17
+ clipHigh?: number | null,
18
+ multiplier?: number,
19
+ color?: Array<number> | chroma.Color,
20
+ colorScale?: Array<string> | Array<chroma.Color>,
21
+ colorScaleValueRange?: number[],
22
+ colorsBasedOnValues? : [number|undefined, chroma.Color][],
23
+ alpha?: number,
24
+ noDataValue?: number
25
+ numOfChannels?: number,
26
+ nullColor?: Array<number> | chroma.Color
27
+ unidentifiedColor?: Array<number> | chroma.Color,
28
+ clippedColor?: Array<number> | chroma.Color
29
+ }
30
+
31
+ const DefaultGeoImageOptions: GeoImageOptions = {
32
+ type: 'image',
33
+ format: 'uint8',
34
+ useHeatMap: true,
35
+ useColorsBasedOnValues: false,
36
+ useAutoRange: false,
37
+ useDataForOpacity: false,
38
+ useSingleColor: false,
39
+ clipLow: null,
40
+ clipHigh: null,
41
+ multiplier: 1.0,
42
+ color: [255, 0, 255, 255],
43
+ colorScale: chroma.brewer.YlOrRd,
44
+ colorScaleValueRange: [0, 255],
45
+ colorsBasedOnValues: null,
46
+ alpha: 255,
47
+ useChannel: null,
48
+ noDataValue: undefined,
49
+ numOfChannels: undefined,
50
+ nullColor: [0, 0, 0, 0],
51
+ unidentifiedColor: [0, 0, 0, 0],
52
+ clippedColor: [0, 0, 0, 0],
53
+ };
54
+
55
+ export default class GeoImage {
56
+ data: GeoTIFFImage | undefined;
57
+
58
+ scale = (
59
+ num: number,
60
+ inMin: number,
61
+ inMax: number,
62
+ outMin: number,
63
+ outMax: number,
64
+ ) => ((num - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;
65
+
66
+ async setUrl(url: string) {
67
+ const response = await fetch(url);
68
+ const arrayBuffer = await response.arrayBuffer();
69
+ const tiff = await fromArrayBuffer(arrayBuffer);
70
+
71
+ const data = await tiff.getImage(0);
72
+
73
+ this.data = data;
74
+ }
75
+
76
+ async getMap(
77
+ input: string | {
78
+ width: number,
79
+ height: number,
80
+ rasters: any[]
81
+ },
82
+ options: GeoImageOptions,
83
+ ) {
84
+ const mergedOptions = { ...DefaultGeoImageOptions, ...options };
85
+
86
+ switch (mergedOptions.type) {
87
+ case 'image':
88
+ return this.getBitmap(input, mergedOptions);
89
+ case 'terrain':
90
+ return this.getHeightmap(input, mergedOptions);
91
+ default:
92
+ return null;
93
+ }
94
+ }
95
+
96
+ // GetHeightmap uses only "useChannel" and "multiplier" options
97
+ async getHeightmap(
98
+ input: string | {
99
+ width: number,
100
+ height: number,
101
+ rasters: any[] },
102
+ options: GeoImageOptions,
103
+ ) {
104
+ let rasters = [];
105
+ let width: number;
106
+ let height: number;
107
+
108
+ if (typeof (input) === 'string') {
109
+ await this.setUrl(input);
110
+
111
+ rasters = (await this.data!.readRasters()) as TypedArray[];
112
+ width = this.data!.getWidth();
113
+ height = this.data!.getHeight();
114
+ } else {
115
+ rasters = input.rasters;
116
+ width = input.width;
117
+ height = input.height;
118
+ }
119
+
120
+ let channel = rasters[0];
121
+
122
+ if (options.useChannel != null) {
123
+ if (rasters[options.useChannel]) {
124
+ channel = rasters[options.useChannel];
125
+ }
126
+ }
127
+
128
+ const canvas = document.createElement('canvas');
129
+ canvas.width = width;
130
+ canvas.height = height;
131
+ const c = canvas.getContext('2d');
132
+ const imageData = c!.createImageData(width, height);
133
+
134
+ const channelCount = channel.length / (width * height);
135
+ const s = width * height * 4;
136
+
137
+ let pixel = 0;
138
+ if (options.useChannel != null) {
139
+ pixel = options.useChannel;
140
+ }
141
+
142
+ // console.time("heightmap generated in");
143
+ for (let i = 0; i < s; i += 4) {
144
+ channel[pixel] *= options.multiplier!;
145
+ const multiplied = 100000 + channel[pixel] * 10;
146
+
147
+ imageData.data[i] = Math.trunc(multiplied * 0.00001525878);
148
+ imageData.data[i + 1] = Math.trunc(multiplied * 0.00390625) - imageData.data[i] * 256;
149
+ imageData.data[i + 2] = Math.trunc(multiplied) - imageData.data[i] * 65536
150
+ - imageData.data[i + 1] * 256;
151
+ imageData.data[i + 3] = 255;
152
+
153
+ pixel += channelCount;
154
+ }
155
+
156
+ // console.timeEnd("heightmap generated in");
157
+
158
+ c!.putImageData(imageData, 0, 0);
159
+ const imageUrl = canvas.toDataURL('image/png');
160
+ // console.log('Heightmap generated.');
161
+ return imageUrl;
162
+ }
163
+
164
+ async getBitmap(
165
+ input: string | {
166
+ width: number,
167
+ height: number,
168
+ rasters: any[] },
169
+ options: GeoImageOptions,
170
+ ) {
171
+ // console.time('bitmap-generated-in');
172
+ // const optionsLocal = { ...options };
173
+ const optionsLocal = { ...options };
174
+
175
+ let rasters = [];
176
+ let channels: number;
177
+ let width: number;
178
+ let height: number;
179
+
180
+ if (typeof (input) === 'string') {
181
+ await this.setUrl(input);
182
+ rasters = (await this.data!.readRasters()) as TypedArray[];
183
+ channels = rasters.length;
184
+ width = this.data!.getWidth();
185
+ height = this.data!.getHeight();
186
+ } else {
187
+ rasters = input.rasters;
188
+ channels = rasters.length;
189
+ width = input.width;
190
+ height = input.height;
191
+ }
192
+ // TO DO if alpha is set in options, then apply to entire image
193
+
194
+ const canvas = document.createElement('canvas');
195
+ canvas.width = width;
196
+ canvas.height = height;
197
+ const c = canvas.getContext('2d');
198
+ const imageData: ImageData = c!.createImageData(width, height);
199
+
200
+ let r; let g; let b; let
201
+ a;
202
+ const size = width * height * 4;
203
+
204
+ if (!options.noDataValue) {
205
+ console.log('Missing noData value. Raster might be displayed incorrectly.');
206
+ }
207
+ optionsLocal.unidentifiedColor = this.getColorFromChromaType(optionsLocal.unidentifiedColor);
208
+ optionsLocal.nullColor = this.getColorFromChromaType(optionsLocal.nullColor);
209
+ optionsLocal.clippedColor = this.getColorFromChromaType(optionsLocal.clippedColor);
210
+ optionsLocal.color = this.getColorFromChromaType(optionsLocal.color);
211
+
212
+ // console.log(rasters[0])
213
+ /* console.log("raster 0 length: " + rasters[0].length)
214
+ console.log("image width: " + width)
215
+ console.log("channels: " + channels)
216
+ console.log("format: " + rasters[0].length / (width * height))
217
+ */
218
+
219
+ if (optionsLocal.useChannel == null) {
220
+ if (channels === 1) {
221
+ if (rasters[0].length / (width * height) === 1) {
222
+ const channel = rasters[0];
223
+ // AUTO RANGE
224
+ if (optionsLocal.useAutoRange) {
225
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
226
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
227
+ }
228
+ // SINGLE CHANNEL
229
+ const colorData = this.getColorValue(channel, optionsLocal, size);
230
+ colorData.forEach((value, index) => {
231
+ imageData.data[index] = value;
232
+ });
233
+ }
234
+ if (rasters[0].length / (width * height) === 3) {
235
+ // console.log("geoImage: " + "RGB 1 array of length: " + rasters[0].length);
236
+ let pixel = 0;
237
+ for (let i = 0; i < size; i += 4) {
238
+ imageData.data[i] = rasters[0][pixel += 1];
239
+ imageData.data[i + 1] = rasters[0][pixel += 1];
240
+ imageData.data[i + 2] = rasters[0][pixel += 1];
241
+ imageData.data[i + 3] = optionsLocal.alpha!;
242
+ }
243
+ }
244
+ if (rasters[0].length / (width * height) === 4) {
245
+ // console.log("geoImage: " + "RGBA 1 array");
246
+ rasters[0].forEach((value, index) => {
247
+ imageData.data[index] = value;
248
+ });
249
+ }
250
+ }
251
+ if (channels === 3) {
252
+ // RGB
253
+ let pixel = 0;
254
+ for (let i = 0; i < size; i += 4) {
255
+ r = rasters[0][pixel];
256
+ g = rasters[1][pixel];
257
+ b = rasters[2][pixel];
258
+ a = optionsLocal.alpha!;
259
+
260
+ imageData.data[i] = r;
261
+ imageData.data[i + 1] = g;
262
+ imageData.data[i + 2] = b;
263
+ imageData.data[i + 3] = a;
264
+
265
+ pixel += 1;
266
+ }
267
+ }
268
+ if (channels === 4) {
269
+ // RGBA
270
+ let pixel = 0;
271
+ for (let i = 0; i < size; i += 4) {
272
+ r = rasters[0][pixel];
273
+ g = rasters[1][pixel];
274
+ b = rasters[2][pixel];
275
+ a = optionsLocal.alpha!;
276
+
277
+ imageData.data[i] = r;
278
+ imageData.data[i + 1] = g;
279
+ imageData.data[i + 2] = b;
280
+ imageData.data[i + 3] = a;
281
+
282
+ pixel += 1;
283
+ }
284
+ }
285
+ } else if (optionsLocal.useChannel <= optionsLocal.numOfChannels) {
286
+ let channel = rasters[0];
287
+ if (rasters[optionsLocal.useChannel]) {
288
+ channel = rasters[optionsLocal.useChannel];
289
+ }
290
+ // AUTO RANGE
291
+ if (optionsLocal.useAutoRange) {
292
+ optionsLocal.colorScaleValueRange = this.getMinMax(channel, optionsLocal);
293
+ // console.log('data min: ' + optionsLocal.rangeMin + ', max: ' + optionsLocal.rangeMax);
294
+ }
295
+ const numOfChannels = channel.length / (width * height);
296
+ const colorData = this.getColorValue(channel, optionsLocal, size, numOfChannels);
297
+ colorData.forEach((value, index) => {
298
+ imageData.data[index] = value;
299
+ });
300
+ } else {
301
+ // if user defined channel does not exist --> return greyscale image
302
+ console.log('Defined channel does not exist, displaying only grey values');
303
+ const defaultColorData = this.getDefaultColor(size, optionsLocal.nullColor);
304
+ defaultColorData.forEach((value, index) => {
305
+ imageData.data[index] = value;
306
+ });
307
+ }
308
+ // console.timeEnd('bitmap-generated-in');
309
+
310
+ c!.putImageData(imageData, 0, 0);
311
+ const imageUrl = canvas.toDataURL('image/png');
312
+ // console.log('Bitmap generated.');
313
+ return imageUrl;
314
+ }
315
+
316
+ getMinMax(array, options) {
317
+ let maxValue = options.maxValue ? options.maxValue : Number.MIN_VALUE;
318
+ let minValue = options.minValue ? options.minValue : Number.MAX_VALUE;
319
+ for (let idx = 0; idx < array.length; idx += 1) {
320
+ if (!options.noDataValue || array[idx] !== options.noDataValue) {
321
+ if (array[idx] > maxValue) maxValue = array[idx];
322
+ if (array[idx] < minValue) minValue = array[idx];
323
+ }
324
+ }
325
+ return [minValue, maxValue];
326
+ }
327
+
328
+ getColorValue(dataArray:[], options:GeoImageOptions, arrayLength:number, numOfChannels = 1) {
329
+ const colorScale = chroma.scale(options.colorScale).domain(options.colorScaleValueRange);
330
+ let pixel:number = options.useChannel === null ? 0 : options.useChannel;
331
+ const colorsArray = new Array(arrayLength);
332
+
333
+ // for useColorsBasedOnValues
334
+ const dataValues = options.colorsBasedOnValues ? options.colorsBasedOnValues.map(([first]) => first) : undefined;
335
+ const colorValues = options.colorsBasedOnValues ? options.colorsBasedOnValues.map(([, second]) => [...chroma(second).rgb(), 255]) : undefined;
336
+
337
+ for (let i = 0; i < arrayLength; i += 4) {
338
+ let pixelColor = options.nullColor;
339
+ if (!options.noDataValue || dataArray[pixel] !== options.noDataValue) {
340
+ if (
341
+ (options.clipLow != null && dataArray[pixel] <= options.clipLow)
342
+ || (options.clipHigh != null && dataArray[pixel] >= options.clipHigh)
343
+ ) {
344
+ pixelColor = options.clippedColor;
345
+ } else {
346
+ if (options.useHeatMap) {
347
+ // FIXME
348
+ // eslint-disable-next-line
349
+ pixelColor = [...colorScale(dataArray[pixel]).rgb(), 255];
350
+ }
351
+ if (options.useColorsBasedOnValues) {
352
+ const index = dataValues.indexOf(dataArray[pixel]);
353
+ if (index > -1) {
354
+ pixelColor = colorValues[index];
355
+ } else pixelColor = options.unidentifiedColor;
356
+ }
357
+ if (options.useSingleColor) {
358
+ // FIXME - Is this compatible with chroma.color?
359
+ pixelColor = options.color;
360
+ }
361
+ if (options.useDataForOpacity) {
362
+ // eslint-disable-next-line max-len
363
+ pixelColor[3] = this.scale(dataArray[pixel], options.colorScaleValueRange[0]!, options.colorScaleValueRange.slice(-1)[0]!, 0, 255);
364
+ }
365
+ }
366
+ }
367
+ // FIXME
368
+ // eslint-disable-next-line
369
+ [colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = pixelColor;
370
+
371
+ pixel += numOfChannels;
372
+ }
373
+ return colorsArray;
374
+ }
375
+
376
+ getDefaultColor(size, nullColor) {
377
+ const colorsArray = new Array(size);
378
+ for (let i = 0; i < size; i += 4) {
379
+ [colorsArray[i], colorsArray[i + 1], colorsArray[i + 2], colorsArray[i + 3]] = nullColor;
380
+ }
381
+ return colorsArray;
382
+ }
383
+
384
+ getColorFromChromaType(colorDefinition) {
385
+ if (!Array.isArray(colorDefinition) || colorDefinition.length !== 4) {
386
+ return [...chroma(colorDefinition).rgb(), 255];
387
+ }
388
+ return colorDefinition;
389
+ }
390
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import CogBitmapLayer from './cogbitmaplayer/CogBitmapLayer';
2
+ import CogTerrainLayer from './cogterrainlayer/CogTerrainLayer';
3
+ import cogtiles from './cogtiles/cogtiles';
4
+ import GeoImage from './geoimage/geoimage';
5
+
6
+ export default {
7
+ CogBitmapLayer,
8
+ CogTerrainLayer,
9
+ cogtiles,
10
+ GeoImage,
11
+ };
@@ -0,0 +1,21 @@
1
+ function isTileServiceUrl(url:string) {
2
+ if (url.includes('{x}') && url.includes('{y}') && url.includes('{z}')) {
3
+ return true;
4
+ }
5
+ return false;
6
+ }
7
+
8
+ function isCogUrl(url:string) {
9
+ if (url.includes('.tif') || url.includes('.tiff') || url.includes('.TIF') || url.includes('.TIFF')) {
10
+ return true;
11
+ }
12
+ return false;
13
+ }
14
+
15
+ function getTileUrl(service:string, x:number, y:number, z:number) {
16
+ const url = service.replace('{x}', String(x)).replace('{y}', String(y)).replace('{z}', String(z));
17
+
18
+ return url;
19
+ }
20
+
21
+ export { isTileServiceUrl, isCogUrl, getTileUrl };
package/tsconfig.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ }
package/README.md DELETED
@@ -1 +0,0 @@
1
- # geoimage
@@ -1,38 +0,0 @@
1
- import { GeoTIFFImage } from 'geotiff';
2
- import { IGeoImage } from './interface';
3
- declare class GeoImage implements IGeoImage {
4
- url: string;
5
- origin: number[];
6
- boundingBox: number[];
7
- data: GeoTIFFImage | undefined;
8
- useHeatMap: boolean;
9
- useAutoRange: boolean;
10
- useClip: boolean;
11
- useDataForOpacity: boolean;
12
- rangeMin: number;
13
- rangeMax: number;
14
- clipLow: number;
15
- clipHigh: number;
16
- multiplier: number;
17
- color: number[];
18
- alpha: number;
19
- imageWidth: number;
20
- imageHeight: number;
21
- options: {};
22
- useChannel: number;
23
- scale: (num: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;
24
- getOrigin: () => number[];
25
- getBoundingBox: () => number[];
26
- setUrl(url: string): Promise<void>;
27
- getHeightMap(input: any): Promise<string>;
28
- getBitmap(input: any): Promise<string>;
29
- setDataOpacity(toggle?: boolean): void;
30
- setHeatMap(heat?: boolean): void;
31
- setAutoRange(auto?: boolean): void;
32
- setDataClip(low?: number, high?: number): void;
33
- setDataRange(min?: number, max?: number): void;
34
- setMultiplier(n?: number): void;
35
- setColor(r?: number, g?: number, b?: number): void;
36
- setOpacity(alpha?: number): void;
37
- }
38
- export default GeoImage;
@@ -1 +0,0 @@
1
- export { default } from './GeoImage';
@@ -1,32 +0,0 @@
1
- import { GeoTIFFImage } from 'geotiff';
2
- export interface IGeoImage {
3
- url: string;
4
- origin: number[];
5
- boundingBox: number[];
6
- data: GeoTIFFImage | undefined;
7
- useHeatMap: boolean;
8
- useAutoRange: boolean;
9
- useClip: boolean;
10
- useDataForOpacity: boolean;
11
- rangeMin: number;
12
- rangeMax: number;
13
- clipLow: number;
14
- clipHigh: number;
15
- color: number[];
16
- alpha: number;
17
- imageWidth: number;
18
- imageHeight: number;
19
- setUrl(url: string): Promise<void>;
20
- scale: (num: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;
21
- getOrigin: () => number[];
22
- getBoundingBox: () => number[];
23
- getBitmap(input: any): Promise<string>;
24
- getHeightMap(input: any): Promise<string>;
25
- setDataOpacity(toggle?: boolean): void;
26
- setHeatMap(heat?: boolean): void;
27
- setAutoRange(auto?: boolean): void;
28
- setDataClip(low?: number, high?: number): void;
29
- setDataRange(min?: number, max?: number): void;
30
- setColor(r?: number, g?: number, b?: number): void;
31
- setOpacity(alpha?: number): void;
32
- }
@@ -1 +0,0 @@
1
- export { default as GeoImage } from './geoImage';
@@ -1 +0,0 @@
1
- export { default as useGeoData } from './useGeoData';
@@ -1 +0,0 @@
1
- export { default } from './useGeoData';
@@ -1,9 +0,0 @@
1
- interface IGeo {
2
- image: string;
3
- bbox: Array<Number>;
4
- viewState: any;
5
- heightMap: string;
6
- loaded: boolean;
7
- }
8
- declare const useGeoData: (url: string, useHeightMap: boolean | undefined, opacity: number) => IGeo;
9
- export default useGeoData;
@@ -1,2 +0,0 @@
1
- export * from './classes';
2
- export * from './hooks';
@@ -1,38 +0,0 @@
1
- import { GeoTIFFImage } from 'geotiff';
2
- import { IGeoImage } from './interface';
3
- declare class GeoImage implements IGeoImage {
4
- url: string;
5
- origin: number[];
6
- boundingBox: number[];
7
- data: GeoTIFFImage | undefined;
8
- useHeatMap: boolean;
9
- useAutoRange: boolean;
10
- useClip: boolean;
11
- useDataForOpacity: boolean;
12
- rangeMin: number;
13
- rangeMax: number;
14
- clipLow: number;
15
- clipHigh: number;
16
- multiplier: number;
17
- color: number[];
18
- alpha: number;
19
- imageWidth: number;
20
- imageHeight: number;
21
- options: {};
22
- useChannel: number;
23
- scale: (num: number, inMin: number, inMax: number, outMin: number, outMax: number) => number;
24
- getOrigin: () => number[];
25
- getBoundingBox: () => number[];
26
- setUrl(url: string): Promise<void>;
27
- getHeightMap(input: any): Promise<string>;
28
- getBitmap(input: any): Promise<string>;
29
- setDataOpacity(toggle?: boolean): void;
30
- setHeatMap(heat?: boolean): void;
31
- setAutoRange(auto?: boolean): void;
32
- setDataClip(low?: number, high?: number): void;
33
- setDataRange(min?: number, max?: number): void;
34
- setMultiplier(n?: number): void;
35
- setColor(r?: number, g?: number, b?: number): void;
36
- setOpacity(alpha?: number): void;
37
- }
38
- export default GeoImage;
@@ -1 +0,0 @@
1
- export { default } from './GeoImage';