ol 7.0.1-dev.1661646168074 → 7.0.1-dev.1661715723847
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.
- package/package.json +1 -1
- package/source/GeoTIFF.d.ts +28 -7
- package/source/GeoTIFF.d.ts.map +1 -1
- package/source/GeoTIFF.js +221 -103
- package/util.js +1 -1
package/package.json
CHANGED
package/source/GeoTIFF.d.ts
CHANGED
|
@@ -141,9 +141,10 @@ export type Options = {
|
|
|
141
141
|
/**
|
|
142
142
|
* By default, bands from the sources are read as-is. When
|
|
143
143
|
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
|
144
|
-
* convert other color spaces (YCbCr, CMYK) to RGB.
|
|
144
|
+
* convert other color spaces (YCbCr, CMYK) to RGB. Setting the option to `'auto'` will make it so CMYK, YCbCr,
|
|
145
|
+
* CIELab, and ICCLab images will automatically be converted to RGB.
|
|
145
146
|
*/
|
|
146
|
-
convertToRGB?: boolean | undefined;
|
|
147
|
+
convertToRGB?: boolean | "auto" | undefined;
|
|
147
148
|
/**
|
|
148
149
|
* By default, the source data is normalized to values between
|
|
149
150
|
* 0 and 1 with scaling factors based on the raster statistics or `min` and `max` properties of each source.
|
|
@@ -194,9 +195,10 @@ export type Options = {
|
|
|
194
195
|
* another with 1 band, the resulting data tiles will have 5 bands: 3 from the first source, 1 alpha
|
|
195
196
|
* band from the first source, and 1 band from the second source.
|
|
196
197
|
* @property {GeoTIFFSourceOptions} [sourceOptions] Additional options to be passed to [geotiff.js](https://geotiffjs.github.io/geotiff.js/module-geotiff.html)'s `fromUrl` or `fromUrls` methods.
|
|
197
|
-
* @property {
|
|
198
|
+
* @property {true|false|'auto'} [convertToRGB=false] By default, bands from the sources are read as-is. When
|
|
198
199
|
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
|
199
|
-
* convert other color spaces (YCbCr, CMYK) to RGB.
|
|
200
|
+
* convert other color spaces (YCbCr, CMYK) to RGB. Setting the option to `'auto'` will make it so CMYK, YCbCr,
|
|
201
|
+
* CIELab, and ICCLab images will automatically be converted to RGB.
|
|
200
202
|
* @property {boolean} [normalize=true] By default, the source data is normalized to values between
|
|
201
203
|
* 0 and 1 with scaling factors based on the raster statistics or `min` and `max` properties of each source.
|
|
202
204
|
* If instead you want to work with the raw values in a style expression, set this to `false`. Setting this option
|
|
@@ -233,6 +235,11 @@ declare class GeoTIFFSource extends DataTile {
|
|
|
233
235
|
* @private
|
|
234
236
|
*/
|
|
235
237
|
private sourceImagery_;
|
|
238
|
+
/**
|
|
239
|
+
* @type {Array<Array<GeoTIFFImage>>}
|
|
240
|
+
* @private
|
|
241
|
+
*/
|
|
242
|
+
private sourceMasks_;
|
|
236
243
|
/**
|
|
237
244
|
* @type {Array<number>}
|
|
238
245
|
* @private
|
|
@@ -269,9 +276,9 @@ declare class GeoTIFFSource extends DataTile {
|
|
|
269
276
|
*/
|
|
270
277
|
private error_;
|
|
271
278
|
/**
|
|
272
|
-
* @type {
|
|
279
|
+
* @type {true|false|'auto'}
|
|
273
280
|
*/
|
|
274
|
-
|
|
281
|
+
convertToRGB_: true | false | 'auto';
|
|
275
282
|
/**
|
|
276
283
|
* @return {Error} A source loading error. When the source state is `error`, use this function
|
|
277
284
|
* to get more information about the error. To debug a faulty configuration, you may want to use
|
|
@@ -293,7 +300,21 @@ declare class GeoTIFFSource extends DataTile {
|
|
|
293
300
|
* @private
|
|
294
301
|
*/
|
|
295
302
|
private configure_;
|
|
296
|
-
|
|
303
|
+
/**
|
|
304
|
+
* @param {number} z The z tile index.
|
|
305
|
+
* @param {number} x The x tile index.
|
|
306
|
+
* @param {number} y The y tile index.
|
|
307
|
+
* @return {Promise} The composed tile data.
|
|
308
|
+
* @private
|
|
309
|
+
*/
|
|
310
|
+
private loadTile_;
|
|
311
|
+
/**
|
|
312
|
+
* @param {import("../size.js").Size} sourceTileSize The source tile size.
|
|
313
|
+
* @param {Array} sourceSamples The source samples.
|
|
314
|
+
* @return {import("../DataTile.js").Data} The composed tile data.
|
|
315
|
+
* @private
|
|
316
|
+
*/
|
|
317
|
+
private composeTile_;
|
|
297
318
|
}
|
|
298
319
|
import DataTile from "./DataTile.js";
|
|
299
320
|
//# sourceMappingURL=GeoTIFF.d.ts.map
|
package/source/GeoTIFF.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GeoTIFF.d.ts","sourceRoot":"","sources":["GeoTIFF.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"GeoTIFF.d.ts","sourceRoot":"","sources":["GeoTIFF.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAmFc,MAAM;;;;wBACN,MAAM;;;;4BACN,MAAM;;;;6BACN,MAAM;;;;6BACN,MAAM;;;;0BACN,MAAM;;;;2BACN,MAAM;;;;2BACN,MAAM;;sBAIP,OAAO,SAAS,EAAE,OAAO;2BAIzB,OAAO,SAAS,EAAE,YAAY;;;;;wBAK7B,MAAM;;;;wBACN,MAAM;;2BAOP,OAAO,SAAS,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAoO7B,MAAM,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAhB/B;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;GAIG;AACH;IACE;;OAEG;IACH,qBAFW,OAAO,EAyGjB;IA5FC;;;OAGG;IACH,oBAAkC;IAIlC;;;OAGG;IACH,uBAA2C;IAE3C;;;OAGG;IACH,uBAA2C;IAE3C;;;OAGG;IACH,qBAAyC;IAEzC;;;OAGG;IACH,2BAA+C;IAE/C;;;OAGG;IACH,yBAAqB;IAErB;;;OAGG;IACH,sBAAkB;IAElB;;;OAGG;IACH,kBAAc;IAEd;;;OAGG;IACH,mBAA6C;IAE7C;;;OAGG;IACH,kBAAsB;IAEtB;;;OAGG;IACH,eAAkB;IAElB;;OAEG;IACH,eAFU,IAAI,GAAC,KAAK,GAAC,MAAM,CAEuB;IAuBpD;;;;;;;;;;;OAWG;IACH,YAXY,KAAK,CAahB;IAED;;;;;;OAMG;IACH,mBAoOC;IAED;;;;;;OAMG;IACH,kBA6EC;IAED;;;;;OAKG;IACH,qBA4GC;CACF"}
|
package/source/GeoTIFF.js
CHANGED
|
@@ -5,6 +5,7 @@ import DataTile from './DataTile.js';
|
|
|
5
5
|
import TileGrid from '../tilegrid/TileGrid.js';
|
|
6
6
|
import {
|
|
7
7
|
Pool,
|
|
8
|
+
globals as geotiffGlobals,
|
|
8
9
|
fromBlob as tiffFromBlob,
|
|
9
10
|
fromUrl as tiffFromUrl,
|
|
10
11
|
fromUrls as tiffFromUrls,
|
|
@@ -19,6 +20,43 @@ import {clamp} from '../math.js';
|
|
|
19
20
|
import {getCenter, getIntersection} from '../extent.js';
|
|
20
21
|
import {fromCode as unitsFromCode} from '../proj/Units.js';
|
|
21
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Determine if an image type is a mask.
|
|
25
|
+
* See https://www.awaresystems.be/imaging/tiff/tifftags/newsubfiletype.html
|
|
26
|
+
* @param {GeoTIFFImage} image The image.
|
|
27
|
+
* @return {boolean} The image is a mask.
|
|
28
|
+
*/
|
|
29
|
+
function isMask(image) {
|
|
30
|
+
const fileDirectory = image.fileDirectory;
|
|
31
|
+
const type = fileDirectory.NewSubfileType || 0;
|
|
32
|
+
return (type & 4) === 4;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @param {true|false|'auto'} preference The convertToRGB option.
|
|
37
|
+
* @param {GeoTIFFImage} image The image.
|
|
38
|
+
* @return {boolean} Use the `image.readRGB()` method.
|
|
39
|
+
*/
|
|
40
|
+
function readRGB(preference, image) {
|
|
41
|
+
if (!preference) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
if (preference === true) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (image.getSamplesPerPixel() !== 3) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const interpretation = image.fileDirectory.PhotometricInterpretation;
|
|
51
|
+
const interpretations = geotiffGlobals.photometricInterpretations;
|
|
52
|
+
return (
|
|
53
|
+
interpretation === interpretations.CMYK ||
|
|
54
|
+
interpretation === interpretations.YCbCr ||
|
|
55
|
+
interpretation === interpretations.CIELab ||
|
|
56
|
+
interpretation === interpretations.ICCLab
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
22
60
|
/**
|
|
23
61
|
* @typedef {Object} SourceInfo
|
|
24
62
|
* @property {string} [url] URL for the source GeoTIFF.
|
|
@@ -308,9 +346,10 @@ function getMaxForDataType(array) {
|
|
|
308
346
|
* another with 1 band, the resulting data tiles will have 5 bands: 3 from the first source, 1 alpha
|
|
309
347
|
* band from the first source, and 1 band from the second source.
|
|
310
348
|
* @property {GeoTIFFSourceOptions} [sourceOptions] Additional options to be passed to [geotiff.js](https://geotiffjs.github.io/geotiff.js/module-geotiff.html)'s `fromUrl` or `fromUrls` methods.
|
|
311
|
-
* @property {
|
|
349
|
+
* @property {true|false|'auto'} [convertToRGB=false] By default, bands from the sources are read as-is. When
|
|
312
350
|
* reading GeoTIFFs with the purpose of displaying them as RGB images, setting this to `true` will
|
|
313
|
-
* convert other color spaces (YCbCr, CMYK) to RGB.
|
|
351
|
+
* convert other color spaces (YCbCr, CMYK) to RGB. Setting the option to `'auto'` will make it so CMYK, YCbCr,
|
|
352
|
+
* CIELab, and ICCLab images will automatically be converted to RGB.
|
|
314
353
|
* @property {boolean} [normalize=true] By default, the source data is normalized to values between
|
|
315
354
|
* 0 and 1 with scaling factors based on the raster statistics or `min` and `max` properties of each source.
|
|
316
355
|
* If instead you want to work with the raw values in a style expression, set this to `false`. Setting this option
|
|
@@ -363,6 +402,12 @@ class GeoTIFFSource extends DataTile {
|
|
|
363
402
|
*/
|
|
364
403
|
this.sourceImagery_ = new Array(numSources);
|
|
365
404
|
|
|
405
|
+
/**
|
|
406
|
+
* @type {Array<Array<GeoTIFFImage>>}
|
|
407
|
+
* @private
|
|
408
|
+
*/
|
|
409
|
+
this.sourceMasks_ = new Array(numSources);
|
|
410
|
+
|
|
366
411
|
/**
|
|
367
412
|
* @type {Array<number>}
|
|
368
413
|
* @private
|
|
@@ -406,9 +451,9 @@ class GeoTIFFSource extends DataTile {
|
|
|
406
451
|
this.error_ = null;
|
|
407
452
|
|
|
408
453
|
/**
|
|
409
|
-
* @type {
|
|
454
|
+
* @type {true|false|'auto'}
|
|
410
455
|
*/
|
|
411
|
-
this.
|
|
456
|
+
this.convertToRGB_ = options.convertToRGB || false;
|
|
412
457
|
|
|
413
458
|
this.setKey(this.sourceInfo_.map((source) => source.url).join(','));
|
|
414
459
|
|
|
@@ -467,8 +512,22 @@ class GeoTIFFSource extends DataTile {
|
|
|
467
512
|
|
|
468
513
|
const sourceCount = sources.length;
|
|
469
514
|
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
|
470
|
-
const images =
|
|
515
|
+
const images = [];
|
|
516
|
+
const masks = [];
|
|
517
|
+
sources[sourceIndex].forEach((item) => {
|
|
518
|
+
if (isMask(item)) {
|
|
519
|
+
masks.push(item);
|
|
520
|
+
} else {
|
|
521
|
+
images.push(item);
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
|
|
471
525
|
const imageCount = images.length;
|
|
526
|
+
if (masks.length > 0 && masks.length !== imageCount) {
|
|
527
|
+
throw new Error(
|
|
528
|
+
`Expected one mask per image found ${masks.length} masks and ${imageCount} images`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
472
531
|
|
|
473
532
|
let sourceExtent;
|
|
474
533
|
let sourceOrigin;
|
|
@@ -574,6 +633,7 @@ class GeoTIFFSource extends DataTile {
|
|
|
574
633
|
}
|
|
575
634
|
|
|
576
635
|
this.sourceImagery_[sourceIndex] = images.reverse();
|
|
636
|
+
this.sourceMasks_[sourceIndex] = masks.reverse();
|
|
577
637
|
}
|
|
578
638
|
|
|
579
639
|
for (let i = 0, ii = this.sourceImagery_.length; i < ii; ++i) {
|
|
@@ -606,6 +666,10 @@ class GeoTIFFSource extends DataTile {
|
|
|
606
666
|
this.addAlpha_ = true;
|
|
607
667
|
break;
|
|
608
668
|
}
|
|
669
|
+
if (this.sourceMasks_[sourceIndex].length) {
|
|
670
|
+
this.addAlpha_ = true;
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
609
673
|
|
|
610
674
|
const values = nodataValues[sourceIndex];
|
|
611
675
|
|
|
@@ -630,12 +694,11 @@ class GeoTIFFSource extends DataTile {
|
|
|
630
694
|
}
|
|
631
695
|
}
|
|
632
696
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}, 0) + additionalBands;
|
|
697
|
+
let bandCount = this.addAlpha_ ? 1 : 0;
|
|
698
|
+
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
|
699
|
+
bandCount += samplesPerPixel[sourceIndex];
|
|
700
|
+
}
|
|
701
|
+
this.bandCount = bandCount;
|
|
639
702
|
|
|
640
703
|
const tileGrid = new TileGrid({
|
|
641
704
|
extent: extent,
|
|
@@ -650,24 +713,36 @@ class GeoTIFFSource extends DataTile {
|
|
|
650
713
|
|
|
651
714
|
this.setLoader(this.loadTile_.bind(this));
|
|
652
715
|
this.setState('ready');
|
|
716
|
+
|
|
717
|
+
let zoom = 0;
|
|
718
|
+
if (resolutions.length === 1) {
|
|
719
|
+
resolutions = [resolutions[0] * 2, resolutions[0]];
|
|
720
|
+
zoom = 1;
|
|
721
|
+
}
|
|
653
722
|
this.viewResolver({
|
|
723
|
+
showFullExtent: true,
|
|
654
724
|
projection: this.projection,
|
|
655
725
|
resolutions: resolutions,
|
|
656
726
|
center: toUserCoordinate(getCenter(extent), this.projection),
|
|
657
727
|
extent: toUserExtent(extent, this.projection),
|
|
658
|
-
zoom:
|
|
728
|
+
zoom: zoom,
|
|
659
729
|
});
|
|
660
730
|
}
|
|
661
731
|
|
|
732
|
+
/**
|
|
733
|
+
* @param {number} z The z tile index.
|
|
734
|
+
* @param {number} x The x tile index.
|
|
735
|
+
* @param {number} y The y tile index.
|
|
736
|
+
* @return {Promise} The composed tile data.
|
|
737
|
+
* @private
|
|
738
|
+
*/
|
|
662
739
|
loadTile_(z, x, y) {
|
|
663
740
|
const sourceTileSize = this.getTileSize(z);
|
|
664
741
|
const sourceCount = this.sourceImagery_.length;
|
|
665
|
-
const requests = new Array(sourceCount);
|
|
666
|
-
const addAlpha = this.addAlpha_;
|
|
667
|
-
const bandCount = this.bandCount;
|
|
668
|
-
const samplesPerPixel = this.samplesPerPixel_;
|
|
742
|
+
const requests = new Array(sourceCount * 2);
|
|
669
743
|
const nodataValues = this.nodataValues_;
|
|
670
744
|
const sourceInfo = this.sourceInfo_;
|
|
745
|
+
const pool = getWorkerPool();
|
|
671
746
|
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
|
672
747
|
const source = sourceInfo[sourceIndex];
|
|
673
748
|
const resolutionFactor = this.resolutionFactors_[sourceIndex];
|
|
@@ -699,118 +774,161 @@ class GeoTIFFSource extends DataTile {
|
|
|
699
774
|
}
|
|
700
775
|
}
|
|
701
776
|
|
|
702
|
-
|
|
777
|
+
const readOptions = {
|
|
703
778
|
window: pixelBounds,
|
|
704
779
|
width: sourceTileSize[0],
|
|
705
780
|
height: sourceTileSize[1],
|
|
706
781
|
samples: samples,
|
|
707
782
|
fillValue: fillValue,
|
|
708
|
-
pool:
|
|
783
|
+
pool: pool,
|
|
784
|
+
interleave: false,
|
|
785
|
+
};
|
|
786
|
+
if (readRGB(this.convertToRGB_, image)) {
|
|
787
|
+
requests[sourceIndex] = image.readRGB(readOptions);
|
|
788
|
+
} else {
|
|
789
|
+
requests[sourceIndex] = image.readRasters(readOptions);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// requests after `sourceCount` are for mask data (if any)
|
|
793
|
+
const maskIndex = sourceCount + sourceIndex;
|
|
794
|
+
const mask = this.sourceMasks_[sourceIndex][z];
|
|
795
|
+
if (!mask) {
|
|
796
|
+
requests[maskIndex] = Promise.resolve(null);
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
requests[maskIndex] = mask.readRasters({
|
|
801
|
+
window: pixelBounds,
|
|
802
|
+
width: sourceTileSize[0],
|
|
803
|
+
height: sourceTileSize[1],
|
|
804
|
+
samples: [0],
|
|
805
|
+
pool: pool,
|
|
709
806
|
interleave: false,
|
|
710
807
|
});
|
|
711
808
|
}
|
|
712
809
|
|
|
810
|
+
return Promise.all(requests)
|
|
811
|
+
.then(this.composeTile_.bind(this, sourceTileSize))
|
|
812
|
+
.catch(function (error) {
|
|
813
|
+
console.error(error); // eslint-disable-line no-console
|
|
814
|
+
throw error;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* @param {import("../size.js").Size} sourceTileSize The source tile size.
|
|
820
|
+
* @param {Array} sourceSamples The source samples.
|
|
821
|
+
* @return {import("../DataTile.js").Data} The composed tile data.
|
|
822
|
+
* @private
|
|
823
|
+
*/
|
|
824
|
+
composeTile_(sourceTileSize, sourceSamples) {
|
|
825
|
+
const metadata = this.metadata_;
|
|
826
|
+
const sourceInfo = this.sourceInfo_;
|
|
827
|
+
const sourceCount = this.sourceImagery_.length;
|
|
828
|
+
const bandCount = this.bandCount;
|
|
829
|
+
const samplesPerPixel = this.samplesPerPixel_;
|
|
830
|
+
const nodataValues = this.nodataValues_;
|
|
831
|
+
const normalize = this.normalize_;
|
|
832
|
+
const addAlpha = this.addAlpha_;
|
|
833
|
+
|
|
713
834
|
const pixelCount = sourceTileSize[0] * sourceTileSize[1];
|
|
714
835
|
const dataLength = pixelCount * bandCount;
|
|
715
|
-
const normalize = this.normalize_;
|
|
716
|
-
const metadata = this.metadata_;
|
|
717
836
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
data = new Float32Array(dataLength);
|
|
726
|
-
}
|
|
837
|
+
/** @type {Uint8Array|Float32Array} */
|
|
838
|
+
let data;
|
|
839
|
+
if (normalize) {
|
|
840
|
+
data = new Uint8Array(dataLength);
|
|
841
|
+
} else {
|
|
842
|
+
data = new Float32Array(dataLength);
|
|
843
|
+
}
|
|
727
844
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
let min = source.min;
|
|
735
|
-
let max = source.max;
|
|
736
|
-
let gain, bias;
|
|
737
|
-
if (normalize) {
|
|
738
|
-
const stats = metadata[sourceIndex][0];
|
|
739
|
-
if (min === undefined) {
|
|
740
|
-
if (stats && STATISTICS_MINIMUM in stats) {
|
|
741
|
-
min = parseFloat(stats[STATISTICS_MINIMUM]);
|
|
742
|
-
} else {
|
|
743
|
-
min = getMinForDataType(sourceSamples[sourceIndex][0]);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
if (max === undefined) {
|
|
747
|
-
if (stats && STATISTICS_MAXIMUM in stats) {
|
|
748
|
-
max = parseFloat(stats[STATISTICS_MAXIMUM]);
|
|
749
|
-
} else {
|
|
750
|
-
max = getMaxForDataType(sourceSamples[sourceIndex][0]);
|
|
751
|
-
}
|
|
752
|
-
}
|
|
845
|
+
let dataIndex = 0;
|
|
846
|
+
for (let pixelIndex = 0; pixelIndex < pixelCount; ++pixelIndex) {
|
|
847
|
+
let transparent = addAlpha;
|
|
848
|
+
for (let sourceIndex = 0; sourceIndex < sourceCount; ++sourceIndex) {
|
|
849
|
+
const source = sourceInfo[sourceIndex];
|
|
753
850
|
|
|
754
|
-
|
|
755
|
-
|
|
851
|
+
let min = source.min;
|
|
852
|
+
let max = source.max;
|
|
853
|
+
let gain, bias;
|
|
854
|
+
if (normalize) {
|
|
855
|
+
const stats = metadata[sourceIndex][0];
|
|
856
|
+
if (min === undefined) {
|
|
857
|
+
if (stats && STATISTICS_MINIMUM in stats) {
|
|
858
|
+
min = parseFloat(stats[STATISTICS_MINIMUM]);
|
|
859
|
+
} else {
|
|
860
|
+
min = getMinForDataType(sourceSamples[sourceIndex][0]);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (max === undefined) {
|
|
864
|
+
if (stats && STATISTICS_MAXIMUM in stats) {
|
|
865
|
+
max = parseFloat(stats[STATISTICS_MAXIMUM]);
|
|
866
|
+
} else {
|
|
867
|
+
max = getMaxForDataType(sourceSamples[sourceIndex][0]);
|
|
756
868
|
}
|
|
869
|
+
}
|
|
757
870
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
++sampleIndex
|
|
762
|
-
) {
|
|
763
|
-
const sourceValue =
|
|
764
|
-
sourceSamples[sourceIndex][sampleIndex][pixelIndex];
|
|
871
|
+
gain = 255 / (max - min);
|
|
872
|
+
bias = -min * gain;
|
|
873
|
+
}
|
|
765
874
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
875
|
+
for (
|
|
876
|
+
let sampleIndex = 0;
|
|
877
|
+
sampleIndex < samplesPerPixel[sourceIndex];
|
|
878
|
+
++sampleIndex
|
|
879
|
+
) {
|
|
880
|
+
const sourceValue =
|
|
881
|
+
sourceSamples[sourceIndex][sampleIndex][pixelIndex];
|
|
882
|
+
|
|
883
|
+
let value;
|
|
884
|
+
if (normalize) {
|
|
885
|
+
value = clamp(gain * sourceValue + bias, 0, 255);
|
|
886
|
+
} else {
|
|
887
|
+
value = sourceValue;
|
|
888
|
+
}
|
|
772
889
|
|
|
773
|
-
|
|
774
|
-
|
|
890
|
+
if (!addAlpha) {
|
|
891
|
+
data[dataIndex] = value;
|
|
892
|
+
} else {
|
|
893
|
+
let nodata = source.nodata;
|
|
894
|
+
if (nodata === undefined) {
|
|
895
|
+
let bandIndex;
|
|
896
|
+
if (source.bands) {
|
|
897
|
+
bandIndex = source.bands[sampleIndex] - 1;
|
|
775
898
|
} else {
|
|
776
|
-
|
|
777
|
-
if (nodata === undefined) {
|
|
778
|
-
let bandIndex;
|
|
779
|
-
if (source.bands) {
|
|
780
|
-
bandIndex = source.bands[sampleIndex] - 1;
|
|
781
|
-
} else {
|
|
782
|
-
bandIndex = sampleIndex;
|
|
783
|
-
}
|
|
784
|
-
nodata = nodataValues[sourceIndex][bandIndex];
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
const nodataIsNaN = isNaN(nodata);
|
|
788
|
-
if (
|
|
789
|
-
(!nodataIsNaN && sourceValue !== nodata) ||
|
|
790
|
-
(nodataIsNaN && !isNaN(sourceValue))
|
|
791
|
-
) {
|
|
792
|
-
transparent = false;
|
|
793
|
-
data[dataIndex] = value;
|
|
794
|
-
}
|
|
899
|
+
bandIndex = sampleIndex;
|
|
795
900
|
}
|
|
796
|
-
|
|
901
|
+
nodata = nodataValues[sourceIndex][bandIndex];
|
|
797
902
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
if (
|
|
801
|
-
|
|
903
|
+
|
|
904
|
+
const nodataIsNaN = isNaN(nodata);
|
|
905
|
+
if (
|
|
906
|
+
(!nodataIsNaN && sourceValue !== nodata) ||
|
|
907
|
+
(nodataIsNaN && !isNaN(sourceValue))
|
|
908
|
+
) {
|
|
909
|
+
transparent = false;
|
|
910
|
+
data[dataIndex] = value;
|
|
802
911
|
}
|
|
803
|
-
|
|
912
|
+
}
|
|
913
|
+
dataIndex++;
|
|
914
|
+
}
|
|
915
|
+
if (!transparent) {
|
|
916
|
+
const maskIndex = sourceCount + sourceIndex;
|
|
917
|
+
const mask = sourceSamples[maskIndex];
|
|
918
|
+
if (mask && !mask[0][pixelIndex]) {
|
|
919
|
+
transparent = true;
|
|
804
920
|
}
|
|
805
921
|
}
|
|
922
|
+
}
|
|
923
|
+
if (addAlpha) {
|
|
924
|
+
if (!transparent) {
|
|
925
|
+
data[dataIndex] = 255;
|
|
926
|
+
}
|
|
927
|
+
dataIndex++;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
806
930
|
|
|
807
|
-
|
|
808
|
-
})
|
|
809
|
-
.catch(function (error) {
|
|
810
|
-
// output then rethrow
|
|
811
|
-
console.error(error); // eslint-disable-line no-console
|
|
812
|
-
throw error;
|
|
813
|
-
});
|
|
931
|
+
return data;
|
|
814
932
|
}
|
|
815
933
|
}
|
|
816
934
|
|
package/util.js
CHANGED