@gisatcz/deckgl-geolib 2.4.0 → 2.4.1-dev.1

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/dist/cjs/index.js CHANGED
@@ -447,30 +447,31 @@ function findTagsByName(xml, tagName, options) {
447
447
  return tags;
448
448
  }
449
449
 
450
- const fieldTypes = Object.freeze({
451
- BYTE: 0x0001,
452
- ASCII: 0x0002,
453
- SHORT: 0x0003,
454
- LONG: 0x0004,
455
- RATIONAL: 0x0005,
456
- SBYTE: 0x0006,
457
- UNDEFINED: 0x0007,
458
- SSHORT: 0x0008,
459
- SLONG: 0x0009,
460
- SRATIONAL: 0x000a,
461
- FLOAT: 0x000b,
462
- DOUBLE: 0x000c,
450
+ /** @import {TypedArray} from './geotiff.js' */
451
+ const fieldTypes = {
452
+ BYTE: /** @type {1} */ (0x0001),
453
+ ASCII: /** @type {2} */ (0x0002),
454
+ SHORT: /** @type {3} */ (0x0003),
455
+ LONG: /** @type {4} */ (0x0004),
456
+ RATIONAL: /** @type {5} */ (0x0005),
457
+ SBYTE: /** @type {6} */ (0x0006),
458
+ UNDEFINED: /** @type {7} */ (0x0007),
459
+ SSHORT: /** @type {8} */ (0x0008),
460
+ SLONG: /** @type {9} */ (0x0009),
461
+ SRATIONAL: /** @type {10} */ (0x000a),
462
+ FLOAT: /** @type {11} */ (0x000b),
463
+ DOUBLE: /** @type {12} */ (0x000c),
463
464
  // IFD offset, suggested by https://owl.phy.queensu.ca/~phil/exiftool/standards.html
464
- IFD: 0x000d,
465
+ IFD: /** @type {13} */ (0x000d),
465
466
  // introduced by BigTIFF
466
- LONG8: 0x0010,
467
- SLONG8: 0x0011,
468
- IFD8: 0x0012,
469
- });
467
+ LONG8: /** @type {16} */ (0x0010),
468
+ SLONG8: /** @type {17} */ (0x0011),
469
+ IFD8: /** @type {18} */ (0x0012),
470
+ };
470
471
  /** @typedef {keyof fieldTypes} FieldTypeName */
471
472
  /** @typedef {fieldTypes[keyof typeof fieldTypes]} FieldType */
472
473
  /** @typedef {Record<FieldTypeName, number>} FieldTypeSizes */
473
- const fieldTypeSizes = Object.freeze({
474
+ const fieldTypeSizes = /** @type {const} */ ({
474
475
  [fieldTypes.BYTE]: 1,
475
476
  [fieldTypes.ASCII]: 1,
476
477
  [fieldTypes.SBYTE]: 1,
@@ -502,219 +503,196 @@ function getFieldTypeSize(fieldType) {
502
503
  }
503
504
  return size;
504
505
  }
505
- const tagSource = [
506
- { tag: 254, name: 'NewSubfileType', fieldTypes: fieldTypes.LONG },
507
- { tag: 255, name: 'SubfileType', type: fieldTypes.SHORT },
508
- { tag: 256, name: 'ImageWidth', type: fieldTypes.SHORT },
509
- { tag: 257, name: 'ImageLength', type: fieldTypes.SHORT },
510
- {
511
- tag: 258,
512
- name: 'BitsPerSample',
513
- type: fieldTypes.SHORT,
514
- isArray: true,
515
- eager: true,
516
- },
517
- { tag: 259, name: 'Compression', type: fieldTypes.SHORT },
518
- { tag: 262, name: 'PhotometricInterpretation', type: fieldTypes.SHORT },
519
- { tag: 263, name: 'Threshholding', type: fieldTypes.SHORT },
520
- { tag: 264, name: 'CellWidth', type: fieldTypes.SHORT },
521
- { tag: 265, name: 'CellLength', type: fieldTypes.SHORT },
522
- { tag: 266, name: 'FillOrder', type: fieldTypes.SHORT },
523
- { tag: 269, name: 'DocumentName', type: fieldTypes.ASCII },
524
- { tag: 270, name: 'ImageDescription', type: fieldTypes.ASCII },
525
- { tag: 271, name: 'Make', type: fieldTypes.ASCII },
526
- { tag: 272, name: 'Model', type: fieldTypes.ASCII },
527
- { tag: 273, name: 'StripOffsets', type: fieldTypes.SHORT, isArray: true },
528
- { tag: 274, name: 'Orientation', type: fieldTypes.SHORT },
529
- { tag: 277, name: 'SamplesPerPixel', type: fieldTypes.SHORT },
530
- { tag: 278, name: 'RowsPerStrip', type: fieldTypes.SHORT },
531
- { tag: 279, name: 'StripByteCounts', type: fieldTypes.LONG, isArray: true },
532
- { tag: 280, name: 'MinSampleValue', type: fieldTypes.SHORT, isArray: true },
533
- { tag: 281, name: 'MaxSampleValue', type: fieldTypes.SHORT, isArray: true },
534
- { tag: 282, name: 'XResolution', type: fieldTypes.RATIONAL },
535
- { tag: 283, name: 'YResolution', type: fieldTypes.RATIONAL },
536
- { tag: 284, name: 'PlanarConfiguration', fieldTypes: fieldTypes.SHORT },
537
- { tag: 285, name: 'PageName', type: fieldTypes.ASCII },
538
- { tag: 286, name: 'XPosition', type: fieldTypes.RATIONAL },
539
- { tag: 287, name: 'YPosition', type: fieldTypes.RATIONAL },
540
- { tag: 288, name: 'FreeOffsets', type: fieldTypes.LONG },
541
- { tag: 289, name: 'FreeByteCounts', type: fieldTypes.LONG },
542
- { tag: 290, name: 'GrayResponseUnit', type: fieldTypes.SHORT },
543
- {
544
- tag: 291,
545
- name: 'GrayResponseCurve',
546
- type: fieldTypes.SHORT,
547
- isArray: true,
548
- },
549
- { tag: 292, name: 'T4Options', type: fieldTypes.LONG },
550
- { tag: 293, name: 'T6Options', type: fieldTypes.LONG },
551
- { tag: 296, name: 'ResolutionUnit', type: fieldTypes.SHORT },
552
- { tag: 297, name: 'PageNumber', type: fieldTypes.SHORT, isArray: true },
553
- { tag: 301, name: 'TransferFunction', type: fieldTypes.SHORT, isArray: true },
554
- { tag: 305, name: 'Software', type: fieldTypes.ASCII },
555
- { tag: 306, name: 'DateTime', type: fieldTypes.ASCII },
556
- { tag: 315, name: 'Artist', type: fieldTypes.ASCII },
557
- { tag: 316, name: 'HostComputer', type: fieldTypes.ASCII },
558
- { tag: 317, name: 'Predictor', type: fieldTypes.SHORT },
559
- { tag: 318, name: 'WhitePoint', type: fieldTypes.RATIONAL, isArray: true },
560
- {
561
- tag: 319,
562
- name: 'PrimaryChromaticities',
563
- type: fieldTypes.RATIONAL,
564
- isArray: true,
565
- },
566
- { tag: 320, name: 'ColorMap', type: fieldTypes.SHORT, isArray: true },
567
- { tag: 321, name: 'HalftoneHints', type: fieldTypes.SHORT, isArray: true },
568
- { tag: 322, name: 'TileWidth', type: fieldTypes.SHORT },
569
- { tag: 323, name: 'TileLength', type: fieldTypes.SHORT },
570
- { tag: 324, name: 'TileOffsets', type: fieldTypes.LONG, isArray: true },
571
- { tag: 325, name: 'TileByteCounts', type: fieldTypes.SHORT, isArray: true },
572
- { tag: 332, name: 'InkSet', type: fieldTypes.SHORT },
573
- { tag: 333, name: 'InkNames', type: fieldTypes.ASCII },
574
- { tag: 334, name: 'NumberOfInks', type: fieldTypes.SHORT },
575
- { tag: 336, name: 'DotRange', type: fieldTypes.BYTE, isArray: true },
576
- { tag: 337, name: 'TargetPrinter', type: fieldTypes.ASCII },
577
- { tag: 338, name: 'ExtraSamples', type: fieldTypes.BYTE, isArray: true },
578
- {
579
- tag: 339,
580
- name: 'SampleFormat',
581
- type: fieldTypes.SHORT,
582
- isArray: true,
583
- eager: true,
584
- },
585
- { tag: 340, name: 'SMinSampleValue', isArray: true },
586
- { tag: 341, name: 'SMaxSampleValue', isArray: true },
587
- { tag: 342, name: 'TransferRange', type: fieldTypes.SHORT, isArray: true },
588
- { tag: 512, name: 'JPEGProc', type: fieldTypes.SHORT },
589
- { tag: 513, name: 'JPEGInterchangeFormat', type: fieldTypes.LONG },
590
- { tag: 514, name: 'JPEGInterchangeFormatLngth', type: fieldTypes.LONG },
591
- { tag: 515, name: 'JPEGRestartInterval', type: fieldTypes.SHORT },
592
- {
593
- tag: 517,
594
- name: 'JPEGLosslessPredictors',
595
- type: fieldTypes.SHORT,
596
- isArray: true,
597
- },
598
- {
599
- tag: 518,
600
- name: 'JPEGPointTransforms',
601
- type: fieldTypes.SHORT,
602
- isArray: true,
603
- },
604
- { tag: 519, name: 'JPEGQTables', type: fieldTypes.LONG, isArray: true },
605
- { tag: 520, name: 'JPEGDCTables', type: fieldTypes.LONG, isArray: true },
606
- { tag: 521, name: 'JPEGACTables', type: fieldTypes.LONG, isArray: true },
607
- {
608
- tag: 529,
609
- name: 'YCbCrCoefficients',
610
- type: fieldTypes.RATIONAL,
611
- isArray: true,
612
- },
613
- { tag: 530, name: 'YCbCrSubSampling', type: fieldTypes.SHORT, isArray: true },
614
- { tag: 531, name: 'YCbCrPositioning', type: fieldTypes.SHORT },
615
- {
616
- tag: 532,
617
- name: 'ReferenceBlackWhite',
618
- type: fieldTypes.LONG,
619
- isArray: true,
620
- },
621
- { tag: 33432, name: 'Copyright', type: fieldTypes.ASCII },
622
- // TIFF Extended
623
- { tag: 326, name: 'BadFaxLines' },
624
- { tag: 327, name: 'CleanFaxData' },
625
- { tag: 343, name: 'ClipPath' },
626
- { tag: 328, name: 'ConsecutiveBadFaxLines' },
627
- { tag: 433, name: 'Decode' },
628
- { tag: 434, name: 'DefaultImageColor' },
629
- { tag: 346, name: 'Indexed' },
630
- { tag: 347, name: 'JPEGTables', isArray: true, eager: true },
631
- { tag: 559, name: 'StripRowCounts', isArray: true },
632
- { tag: 330, name: 'SubIFDs', isArray: true },
633
- { tag: 344, name: 'XClipPathUnits' },
634
- { tag: 345, name: 'YClipPathUnits' },
635
- // EXIF
636
- { tag: 37378, name: 'ApertureValue' },
637
- { tag: 40961, name: 'ColorSpace' },
638
- { tag: 36868, name: 'DateTimeDigitized' },
639
- { tag: 36867, name: 'DateTimeOriginal' },
640
- { tag: 34665, name: 'Exif IFD', type: fieldTypes.LONG },
641
- { tag: 36864, name: 'ExifVersion' },
642
- { tag: 33434, name: 'ExposureTime' },
643
- { tag: 41728, name: 'FileSource' },
644
- { tag: 37385, name: 'Flash' },
645
- { tag: 40960, name: 'FlashpixVersion' },
646
- { tag: 33437, name: 'FNumber' },
647
- { tag: 42016, name: 'ImageUniqueID' },
648
- { tag: 37384, name: 'LightSource' },
649
- { tag: 37500, name: 'MakerNote' },
650
- { tag: 37377, name: 'ShutterSpeedValue' },
651
- { tag: 37510, name: 'UserComment' },
652
- // IPTC
653
- { tag: 33723, name: 'IPTC' },
654
- // Laser Scanning Microscopy
655
- { tag: 34412, name: 'CZ_LSMINFO' },
656
- // ICC
657
- { tag: 34675, name: 'ICC Profile' },
658
- // XMP
659
- { tag: 700, name: 'XMP' },
660
- // GDAL
661
- { tag: 42112, name: 'GDAL_METADATA' },
662
- { tag: 42113, name: 'GDAL_NODATA', type: fieldTypes.ASCII },
663
- // Photoshop
664
- { tag: 34377, name: 'Photoshop' },
665
- // GeoTiff
666
- {
667
- tag: 33550,
668
- name: 'ModelPixelScale',
669
- type: fieldTypes.DOUBLE,
670
- isArray: true,
671
- eager: true,
672
- },
673
- {
674
- tag: 33922,
675
- name: 'ModelTiepoint',
676
- type: fieldTypes.DOUBLE,
677
- isArray: true,
678
- eager: true,
679
- },
680
- {
681
- tag: 34264,
682
- name: 'ModelTransformation',
683
- type: fieldTypes.DOUBLE,
684
- isArray: true,
685
- eager: true,
686
- },
687
- {
688
- tag: 34735,
689
- name: 'GeoKeyDirectory',
690
- type: fieldTypes.SHORT,
691
- isArray: true,
692
- eager: true,
693
- },
694
- {
695
- tag: 34736,
696
- name: 'GeoDoubleParams',
697
- type: fieldTypes.DOUBLE,
698
- isArray: true,
699
- eager: true,
700
- },
701
- { tag: 34737, name: 'GeoAsciiParams', type: fieldTypes.ASCII, eager: true },
702
- // LERC
703
- { tag: 50674, name: 'LercParameters', eager: true },
704
- ];
506
+ /**
507
+ * @typedef {Object} TagDictionaryEntry
508
+ * @property {number} tag
509
+ * @property {string} [name]
510
+ * @property {number} [type]
511
+ * @property {boolean} [isArray]
512
+ * @property {boolean} [eager]
513
+ */
514
+ const tagDictionary = /** @type {const} */ ({
515
+ NewSubfileType: { tag: 254, type: fieldTypes.LONG, eager: true },
516
+ SubfileType: { tag: 255, type: fieldTypes.SHORT, eager: true },
517
+ ImageWidth: { tag: 256, type: fieldTypes.SHORT, eager: true },
518
+ ImageLength: { tag: 257, type: fieldTypes.SHORT, eager: true },
519
+ BitsPerSample: { tag: 258, type: fieldTypes.SHORT, isArray: true, eager: true },
520
+ Compression: { tag: 259, type: fieldTypes.SHORT, eager: true },
521
+ PhotometricInterpretation: { tag: 262, type: fieldTypes.SHORT, eager: true },
522
+ Threshholding: { tag: 263, type: fieldTypes.SHORT },
523
+ CellWidth: { tag: 264, type: fieldTypes.SHORT },
524
+ CellLength: { tag: 265, type: fieldTypes.SHORT },
525
+ FillOrder: { tag: 266, type: fieldTypes.SHORT },
526
+ DocumentName: { tag: 269, type: fieldTypes.ASCII },
527
+ ImageDescription: { tag: 270, type: fieldTypes.ASCII },
528
+ Make: { tag: 271, type: fieldTypes.ASCII },
529
+ Model: { tag: 272, type: fieldTypes.ASCII },
530
+ StripOffsets: { tag: 273, type: fieldTypes.SHORT, isArray: true },
531
+ Orientation: { tag: 274, type: fieldTypes.SHORT },
532
+ SamplesPerPixel: { tag: 277, type: fieldTypes.SHORT, eager: true },
533
+ RowsPerStrip: { tag: 278, type: fieldTypes.SHORT, eager: true },
534
+ StripByteCounts: { tag: 279, type: fieldTypes.LONG, isArray: true },
535
+ MinSampleValue: { tag: 280, type: fieldTypes.SHORT, isArray: true },
536
+ MaxSampleValue: { tag: 281, type: fieldTypes.SHORT, isArray: true },
537
+ XResolution: { tag: 282, type: fieldTypes.RATIONAL },
538
+ YResolution: { tag: 283, type: fieldTypes.RATIONAL },
539
+ PlanarConfiguration: { tag: 284, type: fieldTypes.SHORT, eager: true },
540
+ PageName: { tag: 285, type: fieldTypes.ASCII },
541
+ XPosition: { tag: 286, type: fieldTypes.RATIONAL },
542
+ YPosition: { tag: 287, type: fieldTypes.RATIONAL },
543
+ FreeOffsets: { tag: 288, type: fieldTypes.LONG },
544
+ FreeByteCounts: { tag: 289, type: fieldTypes.LONG },
545
+ GrayResponseUnit: { tag: 290, type: fieldTypes.SHORT },
546
+ GrayResponseCurve: { tag: 291, type: fieldTypes.SHORT, isArray: true },
547
+ T4Options: { tag: 292, type: fieldTypes.LONG },
548
+ T6Options: { tag: 293, type: fieldTypes.LONG },
549
+ ResolutionUnit: { tag: 296, type: fieldTypes.SHORT },
550
+ PageNumber: { tag: 297, type: fieldTypes.SHORT, isArray: true },
551
+ TransferFunction: { tag: 301, type: fieldTypes.SHORT, isArray: true },
552
+ Software: { tag: 305, type: fieldTypes.ASCII },
553
+ DateTime: { tag: 306, type: fieldTypes.ASCII },
554
+ Artist: { tag: 315, type: fieldTypes.ASCII },
555
+ HostComputer: { tag: 316, type: fieldTypes.ASCII },
556
+ Predictor: { tag: 317, type: fieldTypes.SHORT },
557
+ WhitePoint: { tag: 318, type: fieldTypes.RATIONAL, isArray: true },
558
+ PrimaryChromaticities: { tag: 319, type: fieldTypes.RATIONAL, isArray: true },
559
+ ColorMap: { tag: 320, type: fieldTypes.SHORT, isArray: true },
560
+ HalftoneHints: { tag: 321, type: fieldTypes.SHORT, isArray: true },
561
+ TileWidth: { tag: 322, type: fieldTypes.SHORT, eager: true },
562
+ TileLength: { tag: 323, type: fieldTypes.SHORT, eager: true },
563
+ TileOffsets: { tag: 324, type: fieldTypes.LONG, isArray: true },
564
+ TileByteCounts: { tag: 325, type: fieldTypes.SHORT, isArray: true },
565
+ InkSet: { tag: 332, type: fieldTypes.SHORT },
566
+ InkNames: { tag: 333, type: fieldTypes.ASCII },
567
+ NumberOfInks: { tag: 334, type: fieldTypes.SHORT },
568
+ DotRange: { tag: 336, type: fieldTypes.BYTE, isArray: true },
569
+ TargetPrinter: { tag: 337, type: fieldTypes.ASCII },
570
+ ExtraSamples: { tag: 338, type: fieldTypes.BYTE, isArray: true, eager: true },
571
+ SampleFormat: { tag: 339, type: fieldTypes.SHORT, isArray: true, eager: true },
572
+ SMinSampleValue: { tag: 340, isArray: true },
573
+ SMaxSampleValue: { tag: 341, isArray: true },
574
+ TransferRange: { tag: 342, type: fieldTypes.SHORT, isArray: true },
575
+ JPEGProc: { tag: 512, type: fieldTypes.SHORT },
576
+ JPEGInterchangeFormat: { tag: 513, type: fieldTypes.LONG },
577
+ JPEGInterchangeFormatLngth: { tag: 514, type: fieldTypes.LONG },
578
+ JPEGRestartInterval: { tag: 515, type: fieldTypes.SHORT },
579
+ JPEGLosslessPredictors: { tag: 517, type: fieldTypes.SHORT, isArray: true },
580
+ JPEGPointTransforms: { tag: 518, type: fieldTypes.SHORT, isArray: true },
581
+ JPEGQTables: { tag: 519, type: fieldTypes.LONG, isArray: true },
582
+ JPEGDCTables: { tag: 520, type: fieldTypes.LONG, isArray: true },
583
+ JPEGACTables: { tag: 521, type: fieldTypes.LONG, isArray: true },
584
+ YCbCrCoefficients: { tag: 529, type: fieldTypes.RATIONAL, isArray: true },
585
+ YCbCrSubSampling: { tag: 530, type: fieldTypes.SHORT, isArray: true },
586
+ YCbCrPositioning: { tag: 531, type: fieldTypes.SHORT },
587
+ ReferenceBlackWhite: { tag: 532, type: fieldTypes.LONG, isArray: true },
588
+ Copyright: { tag: 33432, type: fieldTypes.ASCII },
589
+ BadFaxLines: { tag: 326 },
590
+ CleanFaxData: { tag: 327 },
591
+ ClipPath: { tag: 343 },
592
+ ConsecutiveBadFaxLines: { tag: 328 },
593
+ Decode: { tag: 433 },
594
+ DefaultImageColor: { tag: 434 },
595
+ Indexed: { tag: 346 },
596
+ JPEGTables: { tag: 347, isArray: true, eager: true },
597
+ StripRowCounts: { tag: 559, isArray: true },
598
+ SubIFDs: { tag: 330, isArray: true },
599
+ XClipPathUnits: { tag: 344 },
600
+ YClipPathUnits: { tag: 345 },
601
+ ApertureValue: { tag: 37378 },
602
+ ColorSpace: { tag: 40961 },
603
+ DateTimeDigitized: { tag: 36868 },
604
+ DateTimeOriginal: { tag: 36867 },
605
+ ExifIFD: { tag: 34665, name: 'Exif IFD', type: fieldTypes.LONG },
606
+ ExifVersion: { tag: 36864 },
607
+ ExposureTime: { tag: 33434 },
608
+ FileSource: { tag: 41728 },
609
+ Flash: { tag: 37385 },
610
+ FlashpixVersion: { tag: 40960 },
611
+ FNumber: { tag: 33437 },
612
+ ImageUniqueID: { tag: 42016 },
613
+ LightSource: { tag: 37384 },
614
+ MakerNote: { tag: 37500 },
615
+ ShutterSpeedValue: { tag: 37377 },
616
+ UserComment: { tag: 37510 },
617
+ IPTC: { tag: 33723 },
618
+ CZ_LSMINFO: { tag: 34412 },
619
+ ICCProfile: { tag: 34675, name: 'ICC Profile' },
620
+ XMP: { tag: 700 },
621
+ GDAL_METADATA: { tag: 42112 },
622
+ GDAL_NODATA: { tag: 42113, type: fieldTypes.ASCII, eager: true },
623
+ Photoshop: { tag: 34377 },
624
+ ModelPixelScale: { tag: 33550, type: fieldTypes.DOUBLE, isArray: true, eager: true },
625
+ ModelTiepoint: { tag: 33922, type: fieldTypes.DOUBLE, isArray: true, eager: true },
626
+ ModelTransformation: { tag: 34264, type: fieldTypes.DOUBLE, isArray: true, eager: true },
627
+ GeoKeyDirectory: { tag: 34735, type: fieldTypes.SHORT, isArray: true, eager: true },
628
+ GeoDoubleParams: { tag: 34736, type: fieldTypes.DOUBLE, isArray: true, eager: true },
629
+ GeoAsciiParams: { tag: 34737, type: fieldTypes.ASCII, eager: true },
630
+ LercParameters: { tag: 50674, eager: true },
631
+ });
632
+ /** @typedef {keyof typeof tagDictionary} TagName */
633
+ /** @typedef {typeof tagDictionary[keyof typeof tagDictionary]['tag']} Tag */
634
+ /**
635
+ * @typedef {Extract<keyof typeof tagDictionary,
636
+ * { [K in keyof typeof tagDictionary]: (typeof tagDictionary)[K] extends { eager: true }
637
+ * ? K : never }[keyof typeof tagDictionary]>} EagerTagName
638
+ */
639
+ /**
640
+ * @typedef {Extract<Tag, { [K in keyof typeof tagDictionary]: (typeof tagDictionary)[K] extends { eager: true }
641
+ * ? (typeof tagDictionary)[K]['tag'] : never }[keyof typeof tagDictionary]>} EagerTag
642
+ */
643
+ /** @typedef {Extract<typeof tagDictionary[keyof typeof tagDictionary], {type: any}>['type']} TagType */
644
+ /**
645
+ * @template {number} T
646
+ * @typedef {T extends 2 ? string : number} GeoTiffPrimitive
647
+ */
648
+ /**
649
+ * @template {TagName} T
650
+ * @typedef {typeof tagDictionary[T]} TagDef
651
+ */
652
+ /**
653
+ * @typedef {{
654
+ * 1: number;
655
+ * 2: string;
656
+ * 3: number;
657
+ * 4: number;
658
+ * 5: number;
659
+ * 6: number;
660
+ * 7: ArrayBuffer;
661
+ * 8: number;
662
+ * 9: number;
663
+ * 10: number;
664
+ * 11: number;
665
+ * 12: number;
666
+ * 16: number;
667
+ * 17: number;
668
+ * 18: number;
669
+ * }} FieldTypeMap
670
+ */
671
+ /**
672
+ * @template {TagName} T
673
+ * @typedef {TagDef<T> extends { isArray: true }
674
+ * ? (TagDef<T> extends { type: typeof fieldTypes.DOUBLE } ? number[] :
675
+ * TagDef<T> extends { type: typeof fieldTypes.ASCII } ? string[] :
676
+ * TagDef<T> extends { type: typeof fieldTypes.BYTE | typeof fieldTypes.SBYTE | typeof fieldTypes.UNDEFINED }
677
+ * ? Uint8Array | Int8Array :
678
+ * (number[] | TypedArray))
679
+ * : (TagDef<T> extends { type: keyof FieldTypeMap } ? FieldTypeMap[TagDef<T>['type']] : any)} TagValue
680
+ */
705
681
  /**
706
682
  * Maps tag names to their numeric values
683
+ * @type {Record<string, number>}
707
684
  */
708
685
  const tags = {};
709
686
  /**
710
687
  * Maps tag numbers to their definitions
688
+ * @type {Record<number, { tag: number, name: string, type: string|number|undefined, isArray: boolean, eager: boolean }>}
711
689
  */
712
690
  const tagDefinitions = {};
713
691
  /**
714
692
  * Registers a new field tag
715
693
  * @param {number} tag the numeric tiff tag
716
694
  * @param {string} name the name of the tag that will be reported in the IFD
717
- * @param {string|number|undefined} type the tags data type
695
+ * @param {keyof fieldTypes|number|undefined} type the tags data type
718
696
  * @param {Boolean} isArray whether the tag is an array
719
697
  * @param {boolean} [eager=false] whether to eagerly fetch deferred fields.
720
698
  * When false (default), tags are loaded lazily on-demand.
@@ -724,8 +702,9 @@ function registerTag(tag, name, type, isArray = false, eager = false) {
724
702
  tags[name] = tag;
725
703
  tagDefinitions[tag] = { tag, name, type: typeof type === 'string' ? fieldTypes[type] : type, isArray, eager };
726
704
  }
727
- for (const entry of tagSource) {
728
- registerTag(entry.tag, entry.name, entry.type, entry.isArray, entry.eager);
705
+ for (const [key, value] of Object.entries(tagDictionary)) {
706
+ const entry = /** @type {TagDictionaryEntry} */ (value);
707
+ registerTag(entry.tag, entry.name || key, entry.type, entry.isArray, entry.eager);
729
708
  }
730
709
  /**
731
710
  * @param {number|string} tagIdentifier The field tag ID or name
@@ -755,7 +734,7 @@ const LercAddCompression = {
755
734
  Deflate: 1,
756
735
  Zstandard: 2,
757
736
  };
758
- const geoKeyNames = Object.freeze({
737
+ const geoKeyNames = /** @type {const} */ ({
759
738
  1024: 'GTModelTypeGeoKey',
760
739
  1025: 'GTRasterTypeGeoKey',
761
740
  1026: 'GTCitationGeoKey',
@@ -804,15 +783,7 @@ const geoKeyNames = Object.freeze({
804
783
  4098: 'VerticalDatumGeoKey',
805
784
  4099: 'VerticalUnitsGeoKey',
806
785
  });
807
- /** @typedef {geoKeyNames[keyof typeof geoKeyNames]} GeoKeyName */
808
- /**
809
- * @type {Record<GeoKeyName, number>}
810
- */
811
- const geoKeys = /** @type {Record<GeoKeyName, number>} */ ({});
812
- for (const key in geoKeyNames) {
813
- if (geoKeyNames.hasOwnProperty(key)) {
814
- geoKeys[geoKeyNames[key]] = parseInt(key, 10);
815
- }
786
+ for (const [key, name] of Object.entries(geoKeyNames)) {
816
787
  }
817
788
 
818
789
  function fromWhiteIsZero(raster, max) {
@@ -912,39 +883,40 @@ function fromCIELab(cieLabRaster) {
912
883
  return rgbRaster;
913
884
  }
914
885
 
915
- const registry = new Map();
886
+ /** @import BaseDecoder, {BaseDecoderParameters} from "./basedecoder.js" */
916
887
  /**
917
- * @typedef {Object} DecoderParameters
918
- * @property {number} tileWidth
919
- * @property {number} tileHeight
920
- * @property {number} planarConfiguration
921
- * @property {number} bitsPerSample
922
- * @property {number} predictor
888
+ * @typedef {Object} RegistryEntry
889
+ * @property {function():Promise<typeof BaseDecoder>} importFn
890
+ * @property {function(import("../imagefiledirectory.js").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn
891
+ * @property {boolean} preferWorker
923
892
  */
893
+ /** @type {Map<number | undefined, RegistryEntry>} */
894
+ const registry = new Map();
924
895
  /**
925
896
  * Default decoder parameter retrieval function
926
- * @param {import("../imagefiledirectory").ImageFileDirectory} fileDirectory
927
- * @returns {Promise<DecoderParameters>}
897
+ * @param {import("../imagefiledirectory.js").ImageFileDirectory} fileDirectory
898
+ * @returns {Promise<BaseDecoderParameters>}
928
899
  */
929
900
  async function defaultDecoderParameterFn(fileDirectory) {
930
901
  const isTiled = !fileDirectory.hasTag('StripOffsets');
931
- return {
932
- tileWidth: isTiled ? await fileDirectory.loadValue('TileWidth') : await fileDirectory.loadValue('ImageWidth'),
933
- tileHeight: isTiled ? await fileDirectory.loadValue('TileLength') : (await fileDirectory.loadValue('RowsPerStrip') || await fileDirectory.loadValue('ImageLength')),
902
+ return /** @type {BaseDecoderParameters} */ ({
903
+ tileWidth: isTiled
904
+ ? await fileDirectory.loadValue('TileWidth')
905
+ : await fileDirectory.loadValue('ImageWidth'),
906
+ tileHeight: isTiled
907
+ ? await fileDirectory.loadValue('TileLength')
908
+ : (await fileDirectory.loadValue('RowsPerStrip')
909
+ || await fileDirectory.loadValue('ImageLength')),
934
910
  planarConfiguration: await fileDirectory.loadValue('PlanarConfiguration'),
935
911
  bitsPerSample: await fileDirectory.loadValue('BitsPerSample'),
936
912
  predictor: await fileDirectory.loadValue('Predictor') || 1,
937
- };
913
+ });
938
914
  }
939
- /**
940
- * Either a number or undefined.
941
- * @typedef {(number|undefined)} NumberOrUndefined
942
- */
943
915
  /**
944
916
  * Register a decoder for a specific compression method or a range of compressions
945
- * @param {(NumberOrUndefined|(NumberOrUndefined[]))} cases ids of the compression methods to register for
946
- * @param {function():Promise} importFn the function to import the decoder
947
- * @param {function(import("../imagefiledirectory").ImageFileDirectory):Promise} decoderParameterFn
917
+ * @param {(number|undefined|(number|undefined)[])} cases ids of the compression methods to register for
918
+ * @param {function():Promise<typeof BaseDecoder>} importFn the function to import the decoder
919
+ * @param {function(import("../imagefiledirectory.js").ImageFileDirectory):Promise<BaseDecoderParameters>} decoderParameterFn
948
920
  * @param {boolean} preferWorker_ Whether to prefer running the decoder in a worker
949
921
  */
950
922
  function addDecoder(cases, importFn, decoderParameterFn = defaultDecoderParameterFn, preferWorker_ = true) {
@@ -957,27 +929,27 @@ function addDecoder(cases, importFn, decoderParameterFn = defaultDecoderParamete
957
929
  }
958
930
  /**
959
931
  * Get the required decoder parameters for a specific compression method
960
- * @param {NumberOrUndefined} compression
932
+ * @param {number|undefined} compression
961
933
  * @param {import('../imagefiledirectory.js').ImageFileDirectory} fileDirectory
962
934
  */
963
935
  async function getDecoderParameters(compression, fileDirectory) {
964
936
  if (!registry.has(compression)) {
965
937
  throw new Error(`Unknown compression method identifier: ${compression}`);
966
938
  }
967
- const { decoderParameterFn } = registry.get(compression);
939
+ const { decoderParameterFn } = /** @type {RegistryEntry} */ (registry.get(compression));
968
940
  return decoderParameterFn(fileDirectory);
969
941
  }
970
942
  /**
971
943
  * Get a decoder for a specific compression and parameters
972
944
  * @param {number} compression the compression method identifier
973
- * @param {DecoderParameters} decoderParameters the parameters for the decoder
945
+ * @param {BaseDecoderParameters} decoderParameters the parameters for the decoder
974
946
  * @returns {Promise<import('./basedecoder.js').default>}
975
947
  */
976
948
  async function getDecoder(compression, decoderParameters) {
977
949
  if (!registry.has(compression)) {
978
950
  throw new Error(`Unknown compression method identifier: ${compression}`);
979
951
  }
980
- const { importFn } = registry.get(compression);
952
+ const { importFn } = /** @type {RegistryEntry} */ (registry.get(compression));
981
953
  const Decoder = await importFn();
982
954
  return new Decoder(decoderParameters);
983
955
  }
@@ -1004,6 +976,9 @@ const defaultDecoderDefinitions = [
1004
976
  {
1005
977
  cases: 7,
1006
978
  importFn: () => Promise.resolve().then(function () { return jpeg; }).then((m) => m.default),
979
+ /**
980
+ * @param {import("../imagefiledirectory.js").ImageFileDirectory} fileDirectory
981
+ */
1007
982
  decoderParameterFn: async (fileDirectory) => {
1008
983
  return {
1009
984
  ...await defaultDecoderParameterFn(fileDirectory),
@@ -1030,6 +1005,9 @@ const defaultDecoderDefinitions = [
1030
1005
  return m;
1031
1006
  })
1032
1007
  .then((m) => m.default),
1008
+ /**
1009
+ * @param {import("../imagefiledirectory.js").ImageFileDirectory} fileDirectory
1010
+ */
1033
1011
  decoderParameterFn: async (fileDirectory) => {
1034
1012
  return {
1035
1013
  ...await defaultDecoderParameterFn(fileDirectory),
@@ -1051,10 +1029,13 @@ const defaultDecoderDefinitions = [
1051
1029
  {
1052
1030
  cases: 50001,
1053
1031
  importFn: () => Promise.resolve().then(function () { return webimage; }).then((m) => m.default),
1032
+ /**
1033
+ * @param {import("../imagefiledirectory.js").ImageFileDirectory} fileDirectory
1034
+ */
1054
1035
  decoderParameterFn: async (fileDirectory) => {
1055
1036
  return {
1056
1037
  ...await defaultDecoderParameterFn(fileDirectory),
1057
- samplesPerPixel: await fileDirectory.loadValue('SamplesPerPixel') || 4,
1038
+ samplesPerPixel: Number(await fileDirectory.loadValue('SamplesPerPixel')) || 4,
1058
1039
  };
1059
1040
  },
1060
1041
  preferWorker: false,
@@ -1069,17 +1050,23 @@ for (const decoderDefinition of defaultDecoderDefinitions) {
1069
1050
  /**
1070
1051
  * @module resample
1071
1052
  */
1053
+ /**
1054
+ * @param {import("./geotiff.js").TypedArray} array
1055
+ * @param {number} width
1056
+ * @param {number} height
1057
+ * @param {number} [samplesPerPixel=1]
1058
+ */
1072
1059
  function copyNewSize(array, width, height, samplesPerPixel = 1) {
1073
1060
  return new (Object.getPrototypeOf(array).constructor)(width * height * samplesPerPixel);
1074
1061
  }
1075
1062
  /**
1076
1063
  * Resample the input arrays using nearest neighbor value selection.
1077
- * @param {import("./geotiff").TypedArray[]} valueArrays The input arrays to resample
1064
+ * @param {import("./geotiff.js").TypedArray[]} valueArrays The input arrays to resample
1078
1065
  * @param {number} inWidth The width of the input rasters
1079
1066
  * @param {number} inHeight The height of the input rasters
1080
1067
  * @param {number} outWidth The desired width of the output rasters
1081
1068
  * @param {number} outHeight The desired height of the output rasters
1082
- * @returns {import("./geotiff").TypedArray[]} The resampled rasters
1069
+ * @returns {import("./geotiff.js").TypedArray[]} The resampled rasters
1083
1070
  */
1084
1071
  function resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight) {
1085
1072
  const relX = inWidth / outWidth;
@@ -1099,17 +1086,22 @@ function resampleNearest(valueArrays, inWidth, inHeight, outWidth, outHeight) {
1099
1086
  }
1100
1087
  // simple linear interpolation, code from:
1101
1088
  // https://en.wikipedia.org/wiki/Linear_interpolation#Programming_language_support
1089
+ /**
1090
+ * @param {number} v0
1091
+ * @param {number} v1
1092
+ * @param {number} t
1093
+ */
1102
1094
  function lerp(v0, v1, t) {
1103
1095
  return ((1 - t) * v0) + (t * v1);
1104
1096
  }
1105
1097
  /**
1106
1098
  * Resample the input arrays using bilinear interpolation.
1107
- * @param {import("./geotiff").TypedArray[]} valueArrays The input arrays to resample
1099
+ * @param {import("./geotiff.js").TypedArray[]} valueArrays The input arrays to resample
1108
1100
  * @param {number} inWidth The width of the input rasters
1109
1101
  * @param {number} inHeight The height of the input rasters
1110
1102
  * @param {number} outWidth The desired width of the output rasters
1111
1103
  * @param {number} outHeight The desired height of the output rasters
1112
- * @returns {import("./geotiff").TypedArray[]} The resampled rasters
1104
+ * @returns {import("./geotiff.js").TypedArray[]} The resampled rasters
1113
1105
  */
1114
1106
  function resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight) {
1115
1107
  const relX = inWidth / outWidth;
@@ -1138,13 +1130,13 @@ function resampleBilinear(valueArrays, inWidth, inHeight, outWidth, outHeight) {
1138
1130
  }
1139
1131
  /**
1140
1132
  * Resample the input arrays using the selected resampling method.
1141
- * @param {import("./geotiff").TypedArray[]} valueArrays The input arrays to resample
1133
+ * @param {import("./geotiff.js").TypedArray[]} valueArrays The input arrays to resample
1142
1134
  * @param {number} inWidth The width of the input rasters
1143
1135
  * @param {number} inHeight The height of the input rasters
1144
1136
  * @param {number} outWidth The desired width of the output rasters
1145
1137
  * @param {number} outHeight The desired height of the output rasters
1146
1138
  * @param {string} [method = 'nearest'] The desired resampling method
1147
- * @returns {import("./geotiff").TypedArray[]} The resampled rasters
1139
+ * @returns {import("./geotiff.js").TypedArray[]} The resampled rasters
1148
1140
  */
1149
1141
  function resample(valueArrays, inWidth, inHeight, outWidth, outHeight, method = 'nearest') {
1150
1142
  switch (method.toLowerCase()) {
@@ -1159,14 +1151,14 @@ function resample(valueArrays, inWidth, inHeight, outWidth, outHeight, method =
1159
1151
  }
1160
1152
  /**
1161
1153
  * Resample the pixel interleaved input array using nearest neighbor value selection.
1162
- * @param {import("./geotiff").TypedArray} valueArray The input array to resample
1154
+ * @param {import("./geotiff.js").TypedArray} valueArray The input array to resample
1163
1155
  * @param {number} inWidth The width of the input rasters
1164
1156
  * @param {number} inHeight The height of the input rasters
1165
1157
  * @param {number} outWidth The desired width of the output rasters
1166
1158
  * @param {number} outHeight The desired height of the output rasters
1167
1159
  * @param {number} samples The number of samples per pixel for pixel
1168
1160
  * interleaved data
1169
- * @returns {import("./geotiff").TypedArray} The resampled raster
1161
+ * @returns {import("./geotiff.js").TypedArray} The resampled raster
1170
1162
  */
1171
1163
  function resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {
1172
1164
  const relX = inWidth / outWidth;
@@ -1186,14 +1178,14 @@ function resampleNearestInterleaved(valueArray, inWidth, inHeight, outWidth, out
1186
1178
  }
1187
1179
  /**
1188
1180
  * Resample the pixel interleaved input array using bilinear interpolation.
1189
- * @param {import("./geotiff").TypedArray} valueArray The input array to resample
1181
+ * @param {import("./geotiff.js").TypedArray} valueArray The input array to resample
1190
1182
  * @param {number} inWidth The width of the input rasters
1191
1183
  * @param {number} inHeight The height of the input rasters
1192
1184
  * @param {number} outWidth The desired width of the output rasters
1193
1185
  * @param {number} outHeight The desired height of the output rasters
1194
1186
  * @param {number} samples The number of samples per pixel for pixel
1195
1187
  * interleaved data
1196
- * @returns {import("./geotiff").TypedArray} The resampled raster
1188
+ * @returns {import("./geotiff.js").TypedArray} The resampled raster
1197
1189
  */
1198
1190
  function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples) {
1199
1191
  const relX = inWidth / outWidth;
@@ -1222,7 +1214,7 @@ function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, ou
1222
1214
  }
1223
1215
  /**
1224
1216
  * Resample the pixel interleaved input array using the selected resampling method.
1225
- * @param {import("./geotiff").TypedArray} valueArray The input array to resample
1217
+ * @param {import("./geotiff.js").TypedArray} valueArray The input array to resample
1226
1218
  * @param {number} inWidth The width of the input rasters
1227
1219
  * @param {number} inHeight The height of the input rasters
1228
1220
  * @param {number} outWidth The desired width of the output rasters
@@ -1230,7 +1222,7 @@ function resampleBilinearInterleaved(valueArray, inWidth, inHeight, outWidth, ou
1230
1222
  * @param {number} samples The number of samples per pixel for pixel
1231
1223
  * interleaved data
1232
1224
  * @param {string} [method = 'nearest'] The desired resampling method
1233
- * @returns {import("./geotiff").TypedArray} The resampled rasters
1225
+ * @returns {import("./geotiff.js").TypedArray} The resampled rasters
1234
1226
  */
1235
1227
  function resampleInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight, samples, method = 'nearest') {
1236
1228
  switch (method.toLowerCase()) {
@@ -1245,10 +1237,16 @@ function resampleInterleaved(valueArray, inWidth, inHeight, outWidth, outHeight,
1245
1237
  }
1246
1238
 
1247
1239
  /** @module geotiffimage */
1248
- /** @import {DecoderWorker, TypedArray} from "./geotiff" */
1249
- /** @import {ReadRasterResult} from "./geotiff" */
1250
- /** @import {ReadRastersOptions} from "./geotiff" */
1251
- /** @import {ReadRGBOptions} from "./geotiff" */
1240
+ /** @import {DecoderWorker, TypedArray} from "./geotiff.js" */
1241
+ /** @import {ReadRasterResult} from "./geotiff.js" */
1242
+ /** @import {ReadRastersOptions} from "./geotiff.js" */
1243
+ /** @import {ReadRGBOptions} from "./geotiff.js" */
1244
+ /**
1245
+ * @param {Array<number>|TypedArray} array
1246
+ * @param {number} start
1247
+ * @param {number} end
1248
+ * @returns {number}
1249
+ */
1252
1250
  function sum(array, start, end) {
1253
1251
  let s = 0;
1254
1252
  for (let i = start; i < end; ++i) {
@@ -1256,42 +1254,64 @@ function sum(array, start, end) {
1256
1254
  }
1257
1255
  return s;
1258
1256
  }
1259
- function arrayForType(format, bitsPerSample, size) {
1257
+ /**
1258
+ * @param {1|2|3} format
1259
+ * @param {number} bitsPerSample
1260
+ * @param {number|ArrayBufferLike} sizeOrData
1261
+ * @returns {TypedArray}
1262
+ */
1263
+ function arrayForType(format, bitsPerSample, sizeOrData) {
1264
+ let TypedArrayConstructor;
1260
1265
  switch (format) {
1261
1266
  case 1: // unsigned integer data
1262
1267
  if (bitsPerSample <= 8) {
1263
- return new Uint8Array(size);
1268
+ TypedArrayConstructor = Uint8Array;
1264
1269
  }
1265
1270
  else if (bitsPerSample <= 16) {
1266
- return new Uint16Array(size);
1271
+ TypedArrayConstructor = Uint16Array;
1267
1272
  }
1268
1273
  else if (bitsPerSample <= 32) {
1269
- return new Uint32Array(size);
1274
+ TypedArrayConstructor = Uint32Array;
1270
1275
  }
1271
1276
  break;
1272
1277
  case 2: // twos complement signed integer data
1273
1278
  if (bitsPerSample === 8) {
1274
- return new Int8Array(size);
1279
+ TypedArrayConstructor = Int8Array;
1275
1280
  }
1276
1281
  else if (bitsPerSample === 16) {
1277
- return new Int16Array(size);
1282
+ TypedArrayConstructor = Int16Array;
1278
1283
  }
1279
1284
  else if (bitsPerSample === 32) {
1280
- return new Int32Array(size);
1285
+ TypedArrayConstructor = Int32Array;
1281
1286
  }
1282
1287
  break;
1283
1288
  case 3: // floating point data
1284
1289
  switch (bitsPerSample) {
1285
1290
  case 16:
1286
1291
  case 32:
1287
- return new Float32Array(size);
1292
+ TypedArrayConstructor = Float32Array;
1293
+ break;
1288
1294
  case 64:
1289
- return new Float64Array(size);
1295
+ TypedArrayConstructor = Float64Array;
1296
+ break;
1290
1297
  }
1291
1298
  break;
1292
1299
  }
1300
+ if (TypedArrayConstructor) {
1301
+ if (typeof sizeOrData === 'number') {
1302
+ return new TypedArrayConstructor(sizeOrData);
1303
+ }
1304
+ else if (sizeOrData instanceof ArrayBuffer) {
1305
+ return new TypedArrayConstructor(sizeOrData);
1306
+ }
1307
+ }
1293
1308
  throw Error('Unsupported data format/bitsPerSample');
1294
1309
  }
1310
+ /**
1311
+ * @param {1|2|3} format
1312
+ * @param {number} bitsPerSample
1313
+ * @returns {boolean}
1314
+ */
1295
1315
  function needsNormalization(format, bitsPerSample) {
1296
1316
  if ((format === 1 || format === 2) && bitsPerSample <= 32 && bitsPerSample % 8 === 0) {
1297
1317
  return false;
@@ -1301,6 +1321,16 @@ function needsNormalization(format, bitsPerSample) {
1301
1321
  }
1302
1322
  return true;
1303
1323
  }
1324
+ /**
1325
+ * @param {ArrayBufferLike} inBuffer
1326
+ * @param {1|2|3} format
1327
+ * @param {1|2} planarConfiguration
1328
+ * @param {number} samplesPerPixel
1329
+ * @param {number} bitsPerSample
1330
+ * @param {number} tileWidth
1331
+ * @param {number} tileHeight
1332
+ * @returns {ArrayBufferLike}
1333
+ */
1304
1334
  function normalizeArray(inBuffer, format, planarConfiguration, samplesPerPixel, bitsPerSample, tileWidth, tileHeight) {
1305
1335
  // const inByteArray = new Uint8Array(inBuffer);
1306
1336
  const view = new DataView(inBuffer);
@@ -1374,7 +1404,7 @@ function normalizeArray(inBuffer, format, planarConfiguration, samplesPerPixel,
1374
1404
  class GeoTIFFImage {
1375
1405
  /**
1376
1406
  * @constructor
1377
- * @param {import("./imagefiledirectory").ImageFileDirectory} fileDirectory The parsed file directory
1407
+ * @param {import("./imagefiledirectory.js").ImageFileDirectory} fileDirectory The parsed file directory
1378
1408
  * @param {Boolean} littleEndian Whether the file is encoded in little or big endian
1379
1409
  * @param {Boolean} cache Whether or not decoded tiles shall be cached
1380
1410
  * @param {import('./source/basesource.js').BaseSource} source The datasource to read from
@@ -1382,7 +1412,8 @@ class GeoTIFFImage {
1382
1412
  constructor(fileDirectory, littleEndian, cache, source) {
1383
1413
  this.fileDirectory = fileDirectory;
1384
1414
  this.littleEndian = littleEndian;
1385
- this.tiles = cache ? {} : null;
1415
+ /** @type {Array<Promise<ArrayBufferLike>>|null} */
1416
+ this.tiles = cache ? [] : null;
1386
1417
  this.isTiled = !fileDirectory.hasTag('StripOffsets');
1387
1418
  const planarConfiguration = fileDirectory.getValue('PlanarConfiguration') ?? 1;
1388
1419
  if (planarConfiguration !== 1 && planarConfiguration !== 2) {
@@ -1394,7 +1425,7 @@ class GeoTIFFImage {
1394
1425
  }
1395
1426
  /**
1396
1427
  * Returns the associated parsed file directory.
1397
- * @returns {import("./imagefiledirectory").ImageFileDirectory} the parsed file directory
1428
+ * @returns {import("./imagefiledirectory.js").ImageFileDirectory} the parsed file directory
1398
1429
  */
1399
1430
  getFileDirectory() {
1400
1431
  return this.fileDirectory;
@@ -1411,46 +1442,50 @@ class GeoTIFFImage {
1411
1442
  * @returns {Number} the width of the image
1412
1443
  */
1413
1444
  getWidth() {
1414
- return this.fileDirectory.getValue('ImageWidth');
1445
+ return this.fileDirectory.getValue('ImageWidth') || 0;
1415
1446
  }
1416
1447
  /**
1417
1448
  * Returns the height of the image.
1418
1449
  * @returns {Number} the height of the image
1419
1450
  */
1420
1451
  getHeight() {
1421
- return this.fileDirectory.getValue('ImageLength');
1452
+ return this.fileDirectory.getValue('ImageLength') || 0;
1422
1453
  }
1423
1454
  /**
1424
1455
  * Returns the number of samples per pixel.
1425
- * @returns {Number} the number of samples per pixel
1456
+ * @returns {number} the number of samples per pixel
1426
1457
  */
1427
1458
  getSamplesPerPixel() {
1428
- return this.fileDirectory.hasTag('SamplesPerPixel')
1429
- ? this.fileDirectory.getValue('SamplesPerPixel') : 1;
1459
+ return this.fileDirectory.getValue('SamplesPerPixel') ?? 1;
1430
1460
  }
1431
1461
  /**
1432
1462
  * Returns the width of each tile.
1433
- * @returns {Number} the width of each tile
1463
+ * @returns {number} the width of each tile
1434
1464
  */
1435
1465
  getTileWidth() {
1436
- return this.isTiled ? this.fileDirectory.getValue('TileWidth') : this.getWidth();
1466
+ return this.isTiled ? (this.fileDirectory.getValue('TileWidth') || 0) : this.getWidth();
1437
1467
  }
1438
1468
  /**
1439
1469
  * Returns the height of each tile.
1440
- * @returns {Number} the height of each tile
1470
+ * @returns {number} the height of each tile
1441
1471
  */
1442
1472
  getTileHeight() {
1443
1473
  if (this.isTiled) {
1444
- return this.fileDirectory.getValue('TileLength');
1474
+ return this.fileDirectory.getValue('TileLength') || 0;
1445
1475
  }
1446
- if (this.fileDirectory.hasTag('RowsPerStrip')) {
1447
- return Math.min(this.fileDirectory.getValue('RowsPerStrip'), this.getHeight());
1476
+ const rowsPerStrip = this.fileDirectory.hasTag('RowsPerStrip') && this.fileDirectory.getValue('RowsPerStrip');
1477
+ if (rowsPerStrip) {
1478
+ return Math.min(rowsPerStrip, this.getHeight());
1448
1479
  }
1449
1480
  return this.getHeight();
1450
1481
  }
1451
1482
  getBlockWidth() {
1452
1483
  return this.getTileWidth();
1453
1484
  }
1485
+ /**
1486
+ * @param {number} y
1487
+ * @returns {number}
1488
+ */
1454
1489
  getBlockHeight(y) {
1455
1490
  if (this.isTiled || (y + 1) * this.getTileHeight() <= this.getHeight()) {
1456
1491
  return this.getTileHeight();
@@ -1467,22 +1502,32 @@ class GeoTIFFImage {
1467
1502
  getBytesPerPixel() {
1468
1503
  let bytes = 0;
1469
1504
  // this is a short list, so we assume this is already loaded
1470
- for (let i = 0; i < this.fileDirectory.getValue('BitsPerSample').length; ++i) {
1505
+ const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];
1506
+ for (let i = 0; i < bitsPerSample.length; ++i) {
1471
1507
  bytes += this.getSampleByteSize(i);
1472
1508
  }
1473
1509
  return bytes;
1474
1510
  }
1511
+ /**
1512
+ * @param {number} i
1513
+ * @returns {number}
1514
+ */
1475
1515
  getSampleByteSize(i) {
1476
- const bitsPerSample = this.fileDirectory.getValue('BitsPerSample');
1516
+ const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];
1477
1517
  if (i >= bitsPerSample.length) {
1478
1518
  throw new RangeError(`Sample index ${i} is out of range.`);
1479
1519
  }
1480
1520
  return Math.ceil(bitsPerSample[i] / 8);
1481
1521
  }
1522
+ /**
1523
+ * @param {number} sampleIndex
1524
+ * @returns {(this: DataView, byteOffset: number, littleEndian: boolean) => number}
1525
+ */
1482
1526
  getReaderForSample(sampleIndex) {
1483
- const format = this.fileDirectory.hasTag('SampleFormat')
1484
- ? this.fileDirectory.getValue('SampleFormat')[sampleIndex] : 1;
1485
- const bitsPerSample = this.fileDirectory.getValue('BitsPerSample')[sampleIndex];
1527
+ const sampleFormat = this.fileDirectory.getValue('SampleFormat');
1528
+ const format = sampleFormat
1529
+ ? sampleFormat[sampleIndex] : 1;
1530
+ const bitsPerSample = (this.fileDirectory.getValue('BitsPerSample') || [])[sampleIndex];
1486
1531
  switch (format) {
1487
1532
  case 1: // unsigned integer data
1488
1533
  if (bitsPerSample <= 8) {
@@ -1522,26 +1567,32 @@ class GeoTIFFImage {
1522
1567
  throw Error('Unsupported data format/bitsPerSample');
1523
1568
  }
1524
1569
  getSampleFormat(sampleIndex = 0) {
1525
- return this.fileDirectory.hasTag('SampleFormat')
1526
- ? this.fileDirectory.getValue('SampleFormat')[sampleIndex] : 1;
1570
+ const sampleFormat = this.fileDirectory.getValue('SampleFormat');
1571
+ return sampleFormat ? sampleFormat[sampleIndex] : 1;
1527
1572
  }
1528
1573
  getBitsPerSample(sampleIndex = 0) {
1529
- return this.fileDirectory.getValue('BitsPerSample')[sampleIndex];
1574
+ const bitsPerSample = this.fileDirectory.getValue('BitsPerSample');
1575
+ return bitsPerSample ? bitsPerSample[sampleIndex] : 0;
1530
1576
  }
1531
- getArrayForSample(sampleIndex, size) {
1532
- const format = this.getSampleFormat(sampleIndex);
1577
+ /**
1578
+ * @param {number} sampleIndex
1579
+ * @param {number|ArrayBufferLike} sizeOrData
1580
+ * @returns {TypedArray}
1581
+ */
1582
+ getArrayForSample(sampleIndex, sizeOrData) {
1583
+ const format = /** @type {1|2|3} */ (this.getSampleFormat(sampleIndex));
1533
1584
  const bitsPerSample = this.getBitsPerSample(sampleIndex);
1534
- return arrayForType(format, bitsPerSample, size);
1585
+ return arrayForType(format, bitsPerSample, sizeOrData);
1535
1586
  }
1536
1587
  /**
1537
1588
  * Returns the decoded strip or tile.
1538
1589
  * @param {Number} x the strip or tile x-offset
1539
1590
  * @param {Number} y the tile y-offset (0 for stripped images)
1540
1591
  * @param {Number} sample the sample to get for separated samples
1541
- * @param {DecoderWorker|import("./geotiff").BaseDecoder} poolOrDecoder the decoder or decoder pool
1592
+ * @param {DecoderWorker|import("./geotiff.js").BaseDecoder} poolOrDecoder the decoder or decoder pool
1542
1593
  * @param {AbortSignal} [signal] An AbortSignal that may be signalled if the request is
1543
1594
  * to be aborted
1544
- * @returns {Promise.<{x: number, y: number, sample: number, data: ArrayBuffer}>} the decoded strip or tile
1595
+ * @returns {Promise.<{x: number, y: number, sample: number, data: ArrayBufferLike}>} the decoded strip or tile
1545
1596
  */
1546
1597
  async getTileOrStrip(x, y, sample, poolOrDecoder, signal) {
1547
1598
  const numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());
@@ -1560,12 +1611,12 @@ class GeoTIFFImage {
1560
1611
  let offset;
1561
1612
  let byteCount;
1562
1613
  if (this.isTiled) {
1563
- offset = await this.fileDirectory.loadValueIndexed('TileOffsets', index);
1564
- byteCount = await this.fileDirectory.loadValueIndexed('TileByteCounts', index);
1614
+ offset = Number(await this.fileDirectory.loadValueIndexed('TileOffsets', index));
1615
+ byteCount = Number(await this.fileDirectory.loadValueIndexed('TileByteCounts', index));
1565
1616
  }
1566
1617
  else {
1567
- offset = await this.fileDirectory.loadValueIndexed('StripOffsets', index);
1568
- byteCount = await this.fileDirectory.loadValueIndexed('StripByteCounts', index);
1618
+ offset = Number(await this.fileDirectory.loadValueIndexed('StripOffsets', index));
1619
+ byteCount = Number(await this.fileDirectory.loadValueIndexed('StripByteCounts', index));
1569
1620
  }
1570
1621
  if (byteCount === 0) {
1571
1622
  const nPixels = this.getBlockHeight(y) * this.getTileWidth();
@@ -1581,7 +1632,7 @@ class GeoTIFFImage {
1581
1632
  // resolve each request by potentially applying array normalization
1582
1633
  request = (async () => {
1583
1634
  let data = await poolOrDecoder.decode(slice);
1584
- const sampleFormat = this.getSampleFormat();
1635
+ const sampleFormat = /** @type {1|2|3} */ (this.getSampleFormat());
1585
1636
  const bitsPerSample = this.getBitsPerSample();
1586
1637
  if (needsNormalization(sampleFormat, bitsPerSample)) {
1587
1638
  data = normalizeArray(data, sampleFormat, this.planarConfiguration, this.getSamplesPerPixel(), bitsPerSample, this.getTileWidth(), this.getBlockHeight(y));
@@ -1603,11 +1654,11 @@ class GeoTIFFImage {
1603
1654
  /**
1604
1655
  * Internal read function.
1605
1656
  * @private
1606
- * @param {Array} imageWindow The image window in pixel coordinates
1607
- * @param {Array} samples The selected samples (0-based indices)
1657
+ * @param {Array<number>} imageWindow The image window in pixel coordinates
1658
+ * @param {Array<number>} samples The selected samples (0-based indices)
1608
1659
  * @param {TypedArray|TypedArray[]} valueArrays The array(s) to write into
1609
1660
  * @param {boolean|undefined} interleave Whether or not to write in an interleaved manner
1610
- * @param {DecoderWorker|import("./geotiff").BaseDecoder} poolOrDecoder the decoder or decoder pool
1661
+ * @param {DecoderWorker|import("./geotiff.js").BaseDecoder} poolOrDecoder the decoder or decoder pool
1611
1662
  * @param {number} [width] the width of window to be read into
1612
1663
  * @param {number} [height] the height of window to be read into
1613
1664
  * @param {string} [resampleMethod] the resampling method to be used when interpolating
@@ -1626,11 +1677,17 @@ class GeoTIFFImage {
1626
1677
  const maxYTile = Math.min(Math.ceil(imageWindow[3] / tileHeight), Math.ceil(imageHeight / tileHeight));
1627
1678
  const windowWidth = imageWindow[2] - imageWindow[0];
1628
1679
  let bytesPerPixel = this.getBytesPerPixel();
1680
+ /** @type {Array<number>} */
1629
1681
  const srcSampleOffsets = [];
1682
+ /** @type {Array<(this: DataView, byteOffset: number, littleEndian: boolean) => number>} */
1630
1683
  const sampleReaders = [];
1631
1684
  for (let i = 0; i < samples.length; ++i) {
1632
1685
  if (this.planarConfiguration === 1) {
1633
- srcSampleOffsets.push(sum(await this.fileDirectory.loadValue('BitsPerSample'), 0, samples[i]) / 8);
1686
+ const bitsPerSample = await this.fileDirectory.loadValue('BitsPerSample');
1687
+ if (typeof bitsPerSample !== 'object') {
1688
+ throw new Error('Expected BitsPerSample to be an array or typed array.');
1689
+ }
1690
+ srcSampleOffsets.push(sum(bitsPerSample, 0, samples[i]) / 8);
1634
1691
  }
1635
1692
  else {
1636
1693
  srcSampleOffsets.push(0);
@@ -1679,7 +1736,7 @@ class GeoTIFFImage {
1679
1736
  }
1680
1737
  else {
1681
1738
  windowCoordinate = ((y + firstLine - imageWindow[1]) * windowWidth) + x + firstCol - imageWindow[0];
1682
- valueArrays[si][windowCoordinate] = value;
1739
+ /** @type {TypedArray} */ (valueArrays[si])[windowCoordinate] = value;
1683
1740
  }
1684
1741
  }
1685
1742
  }
@@ -1715,12 +1772,12 @@ class GeoTIFFImage {
1715
1772
  /**
1716
1773
  * @overload
1717
1774
  * @param {ReadRastersOptions & {interleave: true}} options optional parameters
1718
- * @returns {Promise<import("./geotiff").TypedArrayWithDimensions>} the decoded arrays as a promise
1775
+ * @returns {Promise<import("./geotiff.js").TypedArrayWithDimensions>} the decoded arrays as a promise
1719
1776
  */
1720
1777
  /**
1721
1778
  * @overload
1722
1779
  * @param {ReadRastersOptions & {interleave: false}} options optional parameters
1723
- * @returns {Promise<import("./geotiff").TypedArrayArrayWithDimensions>} the decoded arrays as a promise
1780
+ * @returns {Promise<import("./geotiff.js").TypedArrayArrayWithDimensions>} the decoded arrays as a promise
1724
1781
  */
1725
1782
  /**
1726
1783
  * @overload
@@ -1730,7 +1787,7 @@ class GeoTIFFImage {
1730
1787
  /**
1731
1788
  * @overload
1732
1789
  * @param {ReadRastersOptions} [options={}] optional parameters
1733
- * @returns {Promise<import("./geotiff").TypedArrayArrayWithDimensions>} the decoded arrays as a promise
1790
+ * @returns {Promise<import("./geotiff.js").TypedArrayArrayWithDimensions>} the decoded arrays as a promise
1734
1791
  */
1735
1792
  /**
1736
1793
  * Reads raster data from the image. This function reads all selected samples
@@ -1768,9 +1825,16 @@ class GeoTIFFImage {
1768
1825
  /** @type {TypedArray|TypedArray[]} */
1769
1826
  let valueArrays;
1770
1827
  if (interleave) {
1771
- const format = this.fileDirectory.hasTag('SampleFormat')
1772
- ? Math.max.apply(null, this.fileDirectory.getValue('SampleFormat')) : 1;
1773
- const bitsPerSample = Math.max.apply(null, this.fileDirectory.getValue('BitsPerSample'));
1828
+ const { fileDirectory } = this;
1829
+ const sampleFormat = fileDirectory.getValue('SampleFormat');
1830
+ const format = sampleFormat
1831
+ ? Math.max.apply(null, Array.from(sampleFormat)) : 1;
1832
+ if (format !== 1 && format !== 2 && format !== 3) {
1833
+ throw new Error('Unsupported sample format for interleaved data. Must be 1, 2, or 3.');
1834
+ }
1835
+ const bitsPerSample_ = fileDirectory.getValue('BitsPerSample');
1836
+ const bitsPerSample = bitsPerSample_
1837
+ ? Math.max.apply(null, Array.from(bitsPerSample_)) : 8;
1774
1838
  valueArrays = arrayForType(format, bitsPerSample, numPixels * samples.length);
1775
1839
  if (fillValue) {
1776
1840
  if (Array.isArray(fillValue)) {
@@ -1803,12 +1867,12 @@ class GeoTIFFImage {
1803
1867
  /**
1804
1868
  * @overload
1805
1869
  * @param {ReadRGBOptions & {interleave: true}} options optional parameters
1806
- * @returns {Promise<import("./geotiff").TypedArrayWithDimensions>} the RGB array as a Promise
1870
+ * @returns {Promise<import("./geotiff.js").TypedArrayWithDimensions>} the RGB array as a Promise
1807
1871
  */
1808
1872
  /**
1809
1873
  * @overload
1810
1874
  * @param {ReadRGBOptions & {interleave: false}} options optional parameters
1811
- * @returns {Promise<import("./geotiff").TypedArrayArrayWithDimensions>} the RGB array as a Promise
1875
+ * @returns {Promise<import("./geotiff.js").TypedArrayArrayWithDimensions>} the RGB array as a Promise
1812
1876
  */
1813
1877
  /**
1814
1878
  * @overload
@@ -1818,7 +1882,7 @@ class GeoTIFFImage {
1818
1882
  /**
1819
1883
  * @overload
1820
1884
  * @param {ReadRGBOptions} [options={}] optional parameters
1821
- * @returns {Promise<import("./geotiff").TypedArrayArrayWithDimensions>} the RGB array as a Promise
1885
+ * @returns {Promise<import("./geotiff.js").TypedArrayArrayWithDimensions>} the RGB array as a Promise
1822
1886
  */
1823
1887
  /**
1824
1888
  * Reads raster data from the image as RGB.
@@ -1841,9 +1905,11 @@ class GeoTIFFImage {
1841
1905
  const pi = this.fileDirectory.getValue('PhotometricInterpretation');
1842
1906
  if (pi === photometricInterpretations.RGB) {
1843
1907
  let s = [0, 1, 2];
1844
- if ((!(this.fileDirectory.getValue('ExtraSamples') === ExtraSamplesValues.Unspecified)) && enableAlpha) {
1908
+ const extraSamples = this.fileDirectory.getValue('ExtraSamples');
1909
+ if (extraSamples && extraSamples[0] !== ExtraSamplesValues.Unspecified && enableAlpha) {
1845
1910
  s = [];
1846
- for (let i = 0; i < this.fileDirectory.getValue('BitsPerSample').length; i += 1) {
1911
+ const bitsPerSample = this.fileDirectory.getValue('BitsPerSample') || [];
1912
+ for (let i = 0; i < bitsPerSample.length; i += 1) {
1847
1913
  s.push(i);
1848
1914
  }
1849
1915
  }
@@ -1898,7 +1964,7 @@ class GeoTIFFImage {
1898
1964
  data = fromBlackIsZero(raster, max);
1899
1965
  break;
1900
1966
  case photometricInterpretations.Palette:
1901
- data = fromPalette(raster, await fileDirectory.loadValue('ColorMap'));
1967
+ data = fromPalette(raster, /** @type {Uint16Array} */ (await fileDirectory.loadValue('ColorMap')));
1902
1968
  break;
1903
1969
  case photometricInterpretations.CMYK:
1904
1970
  data = fromCMYK(raster);
@@ -1925,20 +1991,23 @@ class GeoTIFFImage {
1925
1991
  }
1926
1992
  data = [red, green, blue];
1927
1993
  }
1928
- const dataWithDimensions = /** @type {import("./geotiff").ReadRasterResult} */ (data);
1994
+ const dataWithDimensions = /** @type {import("./geotiff.js").ReadRasterResult} */ (data);
1929
1995
  dataWithDimensions.width = raster.width;
1930
1996
  dataWithDimensions.height = raster.height;
1931
1997
  return dataWithDimensions;
1932
1998
  }
1933
1999
  /**
1934
2000
  * Returns an array of tiepoints.
1935
- * @returns {Promise<Object[]>}
2001
+ * @returns {Promise<Array<{i: number, j: number, k: number, x: number, y: number, z: number}>>} the tiepoints
1936
2002
  */
1937
2003
  async getTiePoints() {
1938
2004
  if (!this.fileDirectory.hasTag('ModelTiepoint')) {
1939
2005
  return [];
1940
2006
  }
1941
2007
  const modelTiePoint = await this.fileDirectory.loadValue('ModelTiepoint');
2008
+ if (typeof modelTiePoint !== 'object') {
2009
+ throw new Error('Expected ModelTiepoint to be an array or typed array.');
2010
+ }
1942
2011
  const tiePoints = [];
1943
2012
  for (let i = 0; i < modelTiePoint.length; i += 6) {
1944
2013
  tiePoints.push({
@@ -1959,14 +2028,16 @@ class GeoTIFFImage {
1959
2028
  * Otherwise only metadata specific to the provided sample will be returned.
1960
2029
  *
1961
2030
  * @param {number|null} [sample=null] The sample index.
1962
- * @returns {Promise<Object>}
2031
+ * @returns {Promise<Record<string, unknown>|null>} The GDAL metadata items
1963
2032
  */
1964
2033
  async getGDALMetadata(sample = null) {
2034
+ /** @type {Record<string, unknown>} */
1965
2035
  const metadata = {};
1966
2036
  if (!this.fileDirectory.hasTag('GDAL_METADATA')) {
1967
2037
  return null;
1968
2038
  }
1969
2039
  const string = await this.fileDirectory.loadValue('GDAL_METADATA');
2040
+ /** @type {Array<{inner: unknown}>} */
1970
2041
  let items = findTagsByName(string, 'Item');
1971
2042
  if (sample === null) {
1972
2043
  items = items.filter((item) => getAttribute(item, 'sample') === undefined);
@@ -1985,10 +2056,10 @@ class GeoTIFFImage {
1985
2056
  * @returns {number|null}
1986
2057
  */
1987
2058
  getGDALNoData() {
1988
- if (!this.fileDirectory.hasTag('GDAL_NODATA')) {
2059
+ const string = this.fileDirectory.hasTag('GDAL_NODATA') && this.fileDirectory.getValue('GDAL_NODATA');
2060
+ if (!string) {
1989
2061
  return null;
1990
2062
  }
1991
- const string = this.fileDirectory.getValue('GDAL_NODATA');
1992
2063
  return Number(string.substring(0, string.length - 1));
1993
2064
  }
1994
2065
  /**
@@ -2077,9 +2148,9 @@ class GeoTIFFImage {
2077
2148
  getBoundingBox(tilegrid = false) {
2078
2149
  const height = this.getHeight();
2079
2150
  const width = this.getWidth();
2080
- if (this.fileDirectory.hasTag('ModelTransformation') && !tilegrid) {
2081
- // eslint-disable-next-line no-unused-vars
2082
- const [a, b, c, d, e, f, g, h] = this.fileDirectory.getValue('ModelTransformation');
2151
+ const modelTransformation = this.fileDirectory.getValue('ModelTransformation');
2152
+ if (modelTransformation && !tilegrid) {
2153
+ const [a, b, , d, e, f, , h] = modelTransformation;
2083
2154
  const corners = [
2084
2155
  [0, 0],
2085
2156
  [0, height],
@@ -2117,12 +2188,20 @@ class GeoTIFFImage {
2117
2188
  }
2118
2189
 
2119
2190
  class DataView64 {
2191
+ /**
2192
+ * @param {ArrayBufferLike} arrayBuffer
2193
+ */
2120
2194
  constructor(arrayBuffer) {
2121
2195
  this._dataView = new DataView(arrayBuffer);
2122
2196
  }
2123
2197
  get buffer() {
2124
2198
  return this._dataView.buffer;
2125
2199
  }
2200
+ /**
2201
+ * @param {number} offset
2202
+ * @param {boolean} littleEndian
2203
+ * @returns {number}
2204
+ */
2126
2205
  getUint64(offset, littleEndian) {
2127
2206
  const left = this.getUint32(offset, littleEndian);
2128
2207
  const right = this.getUint32(offset + 4, littleEndian);
@@ -2142,7 +2221,12 @@ class DataView64 {
2142
2221
  }
2143
2222
  return combined;
2144
2223
  }
2145
- // adapted from https://stackoverflow.com/a/55338384/8060591
2224
+ /**
2225
+ * Adapted from https://stackoverflow.com/a/55338384/8060591
2226
+ * @param {number} offset
2227
+ * @param {boolean} littleEndian
2228
+ * @returns {number}
2229
+ */
2146
2230
  getInt64(offset, littleEndian) {
2147
2231
  let value = 0;
2148
2232
  const isNegative = (this._dataView.getUint8(offset + (littleEndian ? 7 : 0)) & 0x80) > 0;
@@ -2167,36 +2251,85 @@ class DataView64 {
2167
2251
  }
2168
2252
  return value;
2169
2253
  }
2254
+ /**
2255
+ * @param {number} offset
2256
+ * @returns {number}
2257
+ */
2170
2258
  getUint8(offset) {
2171
2259
  return this._dataView.getUint8(offset);
2172
2260
  }
2261
+ /**
2262
+ * @param {number} offset
2263
+ * @returns {number}
2264
+ */
2173
2265
  getInt8(offset) {
2174
2266
  return this._dataView.getInt8(offset);
2175
2267
  }
2268
+ /**
2269
+ * @param {number} offset
2270
+ * @param {boolean} littleEndian
2271
+ * @returns {number}
2272
+ */
2176
2273
  getUint16(offset, littleEndian) {
2177
2274
  return this._dataView.getUint16(offset, littleEndian);
2178
2275
  }
2276
+ /**
2277
+ * @param {number} offset
2278
+ * @param {boolean} littleEndian
2279
+ * @returns {number}
2280
+ */
2179
2281
  getInt16(offset, littleEndian) {
2180
2282
  return this._dataView.getInt16(offset, littleEndian);
2181
2283
  }
2284
+ /**
2285
+ * @param {number} offset
2286
+ * @param {boolean} littleEndian
2287
+ * @returns {number}
2288
+ */
2182
2289
  getUint32(offset, littleEndian) {
2183
2290
  return this._dataView.getUint32(offset, littleEndian);
2184
2291
  }
2292
+ /**
2293
+ * @param {number} offset
2294
+ * @param {boolean} littleEndian
2295
+ * @returns {number}
2296
+ */
2185
2297
  getInt32(offset, littleEndian) {
2186
2298
  return this._dataView.getInt32(offset, littleEndian);
2187
2299
  }
2300
+ /**
2301
+ * @param {number} offset
2302
+ * @param {boolean} littleEndian
2303
+ * @returns {number}
2304
+ */
2188
2305
  getFloat16(offset, littleEndian) {
2189
2306
  return getFloat16(this._dataView, offset, littleEndian);
2190
2307
  }
2308
+ /**
2309
+ * @param {number} offset
2310
+ * @param {boolean} littleEndian
2311
+ * @returns {number}
2312
+ */
2191
2313
  getFloat32(offset, littleEndian) {
2192
2314
  return this._dataView.getFloat32(offset, littleEndian);
2193
2315
  }
2316
+ /**
2317
+ * @param {number} offset
2318
+ * @param {boolean} littleEndian
2319
+ * @returns {number}
2320
+ */
2194
2321
  getFloat64(offset, littleEndian) {
2195
2322
  return this._dataView.getFloat64(offset, littleEndian);
2196
2323
  }
2197
2324
  }
2198
2325
 
2199
2326
  class DataSlice {
2327
+ /**
2328
+ * @param {ArrayBufferLike} arrayBuffer
2329
+ * @param {number} sliceOffset
2330
+ * @param {boolean} littleEndian
2331
+ * @param {boolean} bigTiff
2332
+ */
2200
2333
  constructor(arrayBuffer, sliceOffset, littleEndian, bigTiff) {
2201
2334
  this._dataView = new DataView(arrayBuffer);
2202
2335
  this._sliceOffset = sliceOffset;
@@ -2218,33 +2351,74 @@ class DataSlice {
2218
2351
  get buffer() {
2219
2352
  return this._dataView.buffer;
2220
2353
  }
2354
+ /**
2355
+ * @param {number} offset
2356
+ * @param {number} length
2357
+ * @returns {boolean}
2358
+ */
2221
2359
  covers(offset, length) {
2222
2360
  return this.sliceOffset <= offset && this.sliceTop >= offset + length;
2223
2361
  }
2362
+ /**
2363
+ * @param {number} offset
2364
+ * @returns {number}
2365
+ */
2224
2366
  readUint8(offset) {
2225
2367
  return this._dataView.getUint8(offset - this._sliceOffset);
2226
2368
  }
2369
+ /**
2370
+ * @param {number} offset
2371
+ * @returns {number}
2372
+ */
2227
2373
  readInt8(offset) {
2228
2374
  return this._dataView.getInt8(offset - this._sliceOffset);
2229
2375
  }
2376
+ /**
2377
+ * @param {number} offset
2378
+ * @returns {number}
2379
+ */
2230
2380
  readUint16(offset) {
2231
2381
  return this._dataView.getUint16(offset - this._sliceOffset, this._littleEndian);
2232
2382
  }
2383
+ /**
2384
+ * @param {number} offset
2385
+ * @returns {number}
2386
+ */
2233
2387
  readInt16(offset) {
2234
2388
  return this._dataView.getInt16(offset - this._sliceOffset, this._littleEndian);
2235
2389
  }
2390
+ /**
2391
+ * @param {number} offset
2392
+ * @returns {number}
2393
+ */
2236
2394
  readUint32(offset) {
2237
2395
  return this._dataView.getUint32(offset - this._sliceOffset, this._littleEndian);
2238
2396
  }
2397
+ /**
2398
+ * @param {number} offset
2399
+ * @returns {number}
2400
+ */
2239
2401
  readInt32(offset) {
2240
2402
  return this._dataView.getInt32(offset - this._sliceOffset, this._littleEndian);
2241
2403
  }
2404
+ /**
2405
+ * @param {number} offset
2406
+ * @returns {number}
2407
+ */
2242
2408
  readFloat32(offset) {
2243
2409
  return this._dataView.getFloat32(offset - this._sliceOffset, this._littleEndian);
2244
2410
  }
2411
+ /**
2412
+ * @param {number} offset
2413
+ * @returns {number}
2414
+ */
2245
2415
  readFloat64(offset) {
2246
2416
  return this._dataView.getFloat64(offset - this._sliceOffset, this._littleEndian);
2247
2417
  }
2418
+ /**
2419
+ * @param {number} offset
2420
+ * @returns {number}
2421
+ */
2248
2422
  readUint64(offset) {
2249
2423
  const left = this.readUint32(offset);
2250
2424
  const right = this.readUint32(offset + 4);
@@ -2264,7 +2438,11 @@ class DataSlice {
2264
2438
  }
2265
2439
  return combined;
2266
2440
  }
2267
- // adapted from https://stackoverflow.com/a/55338384/8060591
2441
+ /**
2442
+ * Adapted from https://stackoverflow.com/a/55338384/8060591
2443
+ * @param {number} offset
2444
+ * @returns {number}
2445
+ */
2268
2446
  readInt64(offset) {
2269
2447
  let value = 0;
2270
2448
  const isNegative = (this._dataView.getUint8(offset + (this._littleEndian ? 7 : 0)) & 0x80)
@@ -2290,6 +2468,10 @@ class DataSlice {
2290
2468
  }
2291
2469
  return value;
2292
2470
  }
2471
+ /**
2472
+ * @param {number} offset
2473
+ * @returns {number}
2474
+ */
2293
2475
  readOffset(offset) {
2294
2476
  if (this._bigTiff) {
2295
2477
  return this.readUint64(offset);
@@ -2299,13 +2481,17 @@ class DataSlice {
2299
2481
  }
2300
2482
 
2301
2483
  const CRLFCRLF = '\r\n\r\n';
2302
- /*
2484
+ /**
2303
2485
  * Shim for 'Object.fromEntries'
2486
+ * @template T
2487
+ * @param {Array<[string, T]>} items
2488
+ * @return {Record<string, T>}
2304
2489
  */
2305
2490
  function itemsToObject(items) {
2306
2491
  if (typeof Object.fromEntries !== 'undefined') {
2307
2492
  return Object.fromEntries(items);
2308
2493
  }
2494
+ /** @type {Record<string, T>} */
2309
2495
  const obj = {};
2310
2496
  for (const [key, value] of items) {
2311
2497
  obj[key.toLowerCase()] = value;
@@ -2314,14 +2500,15 @@ function itemsToObject(items) {
2314
2500
  }
2315
2501
  /**
2316
2502
  * Parse HTTP headers from a given string.
2317
- * @param {String} text the text to parse the headers from
2318
- * @returns {Object} the parsed headers with lowercase keys
2503
+ * @param {string} text the text to parse the headers from
2504
+ * @returns {Record<string, string>} the parsed headers with lowercase keys
2319
2505
  */
2320
2506
  function parseHeaders(text) {
2507
+ /** @type {Array<[string, string]>} */
2321
2508
  const items = text
2322
2509
  .split('\r\n')
2323
2510
  .map((line) => {
2324
- const kv = line.split(':').map((str) => str.trim());
2511
+ const kv = /** @type {[string, string]} */ (line.split(':').map((str) => str.trim()));
2325
2512
  kv[0] = kv[0].toLowerCase();
2326
2513
  return kv;
2327
2514
  });
@@ -2329,8 +2516,8 @@ function parseHeaders(text) {
2329
2516
  }
2330
2517
  /**
2331
2518
  * Parse a 'Content-Type' header value to the content-type and parameters
2332
- * @param {string|null} rawContentType the raw string to parse from
2333
- * @returns {{type: string|null, params: Object}}}
2519
+ * @param {string|undefined} rawContentType the raw string to parse from
2520
+ * @returns {{type: string|null, params: Record<string, string>}}
2334
2521
  * the parsed content type with the fields: type and params
2335
2522
  */
2336
2523
  function parseContentType(rawContentType) {
@@ -2338,12 +2525,12 @@ function parseContentType(rawContentType) {
2338
2525
  return { type: null, params: {} };
2339
2526
  }
2340
2527
  const [type, ...rawParams] = rawContentType.split(';').map((s) => s.trim());
2341
- const paramsItems = rawParams.map((param) => param.split('='));
2528
+ const paramsItems = /** @type {Array<[string, string]>} */ (rawParams.map((param) => param.split('=')));
2342
2529
  return { type, params: itemsToObject(paramsItems) };
2343
2530
  }
2344
2531
  /**
2345
2532
  * Parse a 'Content-Range' header value to its start, end, and total parts
2346
- * @param {string|null} rawContentRange the raw string to parse from
2533
+ * @param {string|undefined} rawContentRange the raw string to parse from
2347
2534
  * @returns {{start: number, end: number, total: number}} the parsed parts
2348
2535
  */
2349
2536
  function parseContentRange(rawContentRange) {
@@ -2363,11 +2550,12 @@ function parseContentRange(rawContentRange) {
2363
2550
  * - offset: the offset of the byterange within its originating file
2364
2551
  * - length: the length of the byterange
2365
2552
  * @param {ArrayBuffer} responseArrayBuffer the response to be parsed and split
2366
- * @param {String} boundary the boundary string used to split the sections
2367
- * @returns {Object[]} the parsed byteranges
2553
+ * @param {string} boundary the boundary string used to split the sections
2554
+ * @returns {Array<{headers: Record<string, string>, data: ArrayBuffer, offset: number, length: number, fileSize: number}>}
2555
+ * the parsed byteranges
2368
2556
  */
2369
2557
  function parseByteRanges(responseArrayBuffer, boundary) {
2370
- let offset = null;
2558
+ let offset = -1;
2371
2559
  const decoder = new TextDecoder('ascii');
2372
2560
  const out = [];
2373
2561
  const startBoundary = `--${boundary}`;
@@ -2380,7 +2568,7 @@ function parseByteRanges(responseArrayBuffer, boundary) {
2380
2568
  offset = i;
2381
2569
  }
2382
2570
  }
2383
- if (offset === null) {
2571
+ if (offset === -1) {
2384
2572
  throw new Error('Could not find initial boundary');
2385
2573
  }
2386
2574
  while (offset < responseArrayBuffer.byteLength) {
@@ -2419,29 +2607,31 @@ function parseByteRanges(responseArrayBuffer, boundary) {
2419
2607
  }
2420
2608
 
2421
2609
  /**
2422
- * @typedef Slice
2610
+ * @typedef {Object} Slice
2423
2611
  * @property {number} offset
2424
2612
  * @property {number} length
2425
2613
  */
2614
+ /** @typedef {Slice & {data: ArrayBufferLike}} SliceWithData */
2426
2615
  class BaseSource {
2427
2616
  /**
2428
2617
  * @param {Array<Slice>} slices
2429
2618
  * @param {AbortSignal} [signal]
2430
- * @returns {Promise<*[]>}
2619
+ * @returns {Promise<ArrayBufferLike[]>}
2431
2620
  */
2432
2621
  async fetch(slices, signal) {
2433
- return Promise.all(slices.map((slice) => this.fetchSlice(slice, signal)));
2622
+ return Promise.all(slices.map(async (slice) => (await this.fetchSlice(slice, signal)).data));
2434
2623
  }
2435
2624
  /**
2436
2625
  * @param {Slice} slice
2437
2626
  * @param {AbortSignal} [_signal]
2438
- * @returns {Promise<*>}
2627
+ * @returns {Promise<SliceWithData>}
2439
2628
  */
2440
2629
  async fetchSlice(slice, _signal) {
2441
2630
  throw new Error(`fetching of slice ${slice} not possible, not implemented`);
2442
2631
  }
2443
2632
  /**
2444
2633
  * Returns the filesize if already determined and null otherwise
2634
+ * @returns {number|null}
2445
2635
  */
2446
2636
  get fileSize() {
2447
2637
  return null;
@@ -2735,18 +2925,14 @@ class QuickLRU extends Map {
2735
2925
  }
2736
2926
  }
2737
2927
 
2738
- /*
2928
+ /**
2739
2929
  * Promisified wrapper around 'setTimeout' to allow 'await'
2930
+ * @param {number} [milliseconds]
2931
+ * @returns {Promise<void>}
2740
2932
  */
2741
2933
  async function wait(milliseconds) {
2742
2934
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
2743
2935
  }
2744
- /**
2745
- * @template T,U
2746
- * @param {Iterable<T>} a
2747
- * @param {Iterable<U>} b
2748
- * @returns {Array<[T, U]>}
2749
- */
2750
2936
  function zip(a, b) {
2751
2937
  const A = Array.isArray(a) ? a : Array.from(a);
2752
2938
  const B = Array.isArray(b) ? b : Array.from(b);
@@ -2754,14 +2940,15 @@ function zip(a, b) {
2754
2940
  }
2755
2941
  // Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
2756
2942
  class AbortError extends Error {
2757
- constructor(params) {
2943
+ constructor(...args) {
2758
2944
  // Pass remaining arguments (including vendor specific ones) to parent constructor
2759
- super(params);
2945
+ super(...args);
2760
2946
  // Maintains proper stack trace for where our error was thrown (only available on V8)
2761
2947
  if (Error.captureStackTrace) {
2762
2948
  Error.captureStackTrace(this, AbortError);
2763
2949
  }
2764
2950
  this.name = 'AbortError';
2951
+ this.signal = undefined;
2765
2952
  }
2766
2953
  }
2767
2954
  class CustomAggregateError extends Error {
@@ -2836,7 +3023,7 @@ class BlockedSource extends BaseSource {
2836
3023
  return this.source.fileSize;
2837
3024
  }
2838
3025
  /**
2839
- * @param {import("./basesource").Slice[]} slices
3026
+ * @param {import("./basesource.js").Slice[]} slices
2840
3027
  * @param {AbortSignal} [signal]
2841
3028
  * @return {Promise<ArrayBuffer[]>}
2842
3029
  */
@@ -2918,24 +3105,25 @@ class BlockedSource extends BaseSource {
2918
3105
  if (this.blockIdsToFetch.size > 0) {
2919
3106
  const groups = this.groupBlocks(this.blockIdsToFetch);
2920
3107
  // start requesting slices of data
2921
- const groupRequests = this.source.fetch(groups, signal);
3108
+ const groupRequests = groups.map(async (group) => ({ ...group, ...(await this.source.fetchSlice(group, signal)) }));
2922
3109
  for (let groupIndex = 0; groupIndex < groups.length; ++groupIndex) {
2923
3110
  const group = groups[groupIndex];
2924
3111
  for (const blockId of group.blockIds) {
2925
3112
  // make an async IIFE for each block
2926
3113
  this.blockRequests.set(blockId, (async () => {
2927
3114
  try {
2928
- const response = (await groupRequests)[groupIndex];
3115
+ const response = (await Promise.all(groupRequests))[groupIndex];
2929
3116
  const blockOffset = blockId * this.blockSize;
2930
3117
  const o = blockOffset - response.offset;
2931
3118
  const t = Math.min(o + this.blockSize, response.data.byteLength);
2932
3119
  const data = response.data.slice(o, t);
2933
- const block = new Block(blockOffset, data.byteLength, data);
3120
+ const block = new Block(blockOffset, data.byteLength,
3121
+ /** @type {ArrayBuffer} */ (data));
2934
3122
  this.blockCache.set(blockId, block);
2935
3123
  this.abortedBlockIds.delete(blockId);
2936
3124
  }
2937
3125
  catch (err) {
2938
- if (err.name === 'AbortError') {
3126
+ if (err instanceof AbortError && err.name === 'AbortError') {
2939
3127
  // store the signal here, we need it to determine later if an
2940
3128
  // error was caused by this signal
2941
3129
  err.signal = signal;
@@ -2957,7 +3145,7 @@ class BlockedSource extends BaseSource {
2957
3145
  }
2958
3146
  /**
2959
3147
  *
2960
- * @param {Set} blockIds
3148
+ * @param {Set<number>} blockIds
2961
3149
  * @returns {BlockGroup[]}
2962
3150
  */
2963
3151
  groupBlocks(blockIds) {
@@ -2965,6 +3153,7 @@ class BlockedSource extends BaseSource {
2965
3153
  if (sortedBlockIds.length === 0) {
2966
3154
  return [];
2967
3155
  }
3156
+ /** @type {number[]} */
2968
3157
  let current = [];
2969
3158
  let lastBlockId = null;
2970
3159
  const groups = [];
@@ -2983,7 +3172,7 @@ class BlockedSource extends BaseSource {
2983
3172
  return groups;
2984
3173
  }
2985
3174
  /**
2986
- * @param {import("./basesource").Slice[]} slices
3175
+ * @param {import("./basesource.js").Slice[]} slices
2987
3176
  * @param {Map<number, Block>} blocks
2988
3177
  * @returns {ArrayBuffer[]}
2989
3178
  */
@@ -3043,10 +3232,10 @@ class BaseResponse {
3043
3232
  }
3044
3233
  /**
3045
3234
  * Returns the value of the specified header
3046
- * @param {string} headerName the header name
3047
- * @returns {string|null} the header value
3235
+ * @param {string} _headerName the header name
3236
+ * @returns {string|undefined} the header value
3048
3237
  */
3049
- getHeader(headerName) {
3238
+ getHeader(_headerName) {
3050
3239
  throw new Error('not implemented');
3051
3240
  }
3052
3241
  /**
@@ -3057,15 +3246,16 @@ class BaseResponse {
3057
3246
  }
3058
3247
  }
3059
3248
  class BaseClient {
3249
+ /** @param {string} url */
3060
3250
  constructor(url) {
3061
3251
  this.url = url;
3062
3252
  }
3063
3253
  /**
3064
3254
  * Send a request with the options
3065
- * @param {RequestInit} [options={}]
3255
+ * @param {RequestInit} [_options={}]
3066
3256
  * @returns {Promise<BaseResponse>}
3067
3257
  */
3068
- async request({ headers, signal } = {}) {
3258
+ async request(_options) {
3069
3259
  throw new Error('request is not implemented');
3070
3260
  }
3071
3261
  }
@@ -3084,10 +3274,10 @@ class FetchResponse extends BaseResponse {
3084
3274
  }
3085
3275
  /**
3086
3276
  * @param {string} name
3087
- * @returns {string|null}
3277
+ * @returns {string|undefined}
3088
3278
  */
3089
3279
  getHeader(name) {
3090
- return this.response.headers.get(name);
3280
+ return this.response.headers.get(name) || undefined;
3091
3281
  }
3092
3282
  async getData() {
3093
3283
  const data = this.response.arrayBuffer
@@ -3098,6 +3288,10 @@ class FetchResponse extends BaseResponse {
3098
3288
  }
3099
3289
  }
3100
3290
  class FetchClient extends BaseClient {
3291
+ /**
3292
+ * @param {string} url
3293
+ * @param {RequestCredentials} [credentials]
3294
+ */
3101
3295
  constructor(url, credentials) {
3102
3296
  super(url);
3103
3297
  this.credentials = credentials;
@@ -3128,14 +3322,23 @@ class XHRResponse extends BaseResponse {
3128
3322
  get status() {
3129
3323
  return this.xhr.status;
3130
3324
  }
3325
+ /**
3326
+ * @param {string} name
3327
+ * @returns {string|undefined}
3328
+ */
3131
3329
  getHeader(name) {
3132
- return this.xhr.getResponseHeader(name);
3330
+ return this.xhr.getResponseHeader(name) || undefined;
3133
3331
  }
3134
3332
  async getData() {
3135
3333
  return this.data;
3136
3334
  }
3137
3335
  }
3138
3336
  class XHRClient extends BaseClient {
3337
+ /**
3338
+ * @param {Object<string, string>} headers
3339
+ * @param {AbortSignal} [signal]
3340
+ * @returns {Promise<XHRResponse>}
3341
+ */
3139
3342
  constructRequest(headers, signal) {
3140
3343
  return new Promise((resolve, reject) => {
3141
3344
  const xhr = new XMLHttpRequest();
@@ -3160,7 +3363,7 @@ class XHRClient extends BaseClient {
3160
3363
  }
3161
3364
  });
3162
3365
  }
3163
- async request({ headers = undefined, signal = undefined } = {}) {
3366
+ async request({ headers = {}, signal = undefined } = {}) {
3164
3367
  const response = await this.constructRequest(headers, signal);
3165
3368
  return response;
3166
3369
  }
@@ -3172,6 +3375,7 @@ class HttpResponse extends BaseResponse {
3172
3375
  /**
3173
3376
  * BaseResponse facade for node HTTP/HTTPS API Response
3174
3377
  * @param {import('http').IncomingMessage} response
3378
+ * @param {Promise<ArrayBuffer>} dataPromise
3175
3379
  */
3176
3380
  constructor(response, dataPromise) {
3177
3381
  super();
@@ -3181,8 +3385,13 @@ class HttpResponse extends BaseResponse {
3181
3385
  get status() {
3182
3386
  return /** @type {number} */ (this.response.statusCode);
3183
3387
  }
3388
+ /**
3389
+ * @param {string} name
3390
+ * @returns {string|undefined}
3391
+ */
3184
3392
  getHeader(name) {
3185
- return /** @type {string|null} */ (this.response.headers[name]);
3393
+ const value = this.response.headers[name];
3394
+ return Array.isArray(value) ? value.join(', ') : value;
3186
3395
  }
3187
3396
  async getData() {
3188
3397
  const data = await this.dataPromise;
@@ -3190,11 +3399,17 @@ class HttpResponse extends BaseResponse {
3190
3399
  }
3191
3400
  }
3192
3401
  class HttpClient extends BaseClient {
3402
+ /** @param {string} url */
3193
3403
  constructor(url) {
3194
3404
  super(url);
3195
3405
  this.parsedUrl = fs.parse(this.url);
3196
3406
  this.httpApi = (this.parsedUrl.protocol === 'http:' ? fs : fs);
3197
3407
  }
3408
+ /**
3409
+ * @param {Object<string, string>} headers
3410
+ * @param {AbortSignal} [signal]
3411
+ * @returns {Promise<HttpResponse>}
3412
+ */
3198
3413
  constructRequest(headers, signal) {
3199
3414
  return new Promise((resolve, reject) => {
3200
3415
  const request = this.httpApi.get({
@@ -3202,6 +3417,7 @@ class HttpClient extends BaseClient {
3202
3417
  headers,
3203
3418
  }, (response) => {
3204
3419
  const dataPromise = new Promise((resolveData) => {
3420
+ /** @type {Uint8Array[]} */
3205
3421
  const chunks = [];
3206
3422
  // collect chunks
3207
3423
  response.on('data', (chunk) => {
@@ -3225,7 +3441,7 @@ class HttpClient extends BaseClient {
3225
3441
  }
3226
3442
  });
3227
3443
  }
3228
- async request({ headers = undefined, signal = undefined } = {}) {
3444
+ async request({ headers = {}, signal = undefined } = {}) {
3229
3445
  const response = await this.constructRequest(headers, signal);
3230
3446
  return response;
3231
3447
  }
@@ -3234,7 +3450,7 @@ class HttpClient extends BaseClient {
3234
3450
  /** @import { RemoteSourceOptions, BlockedSourceOptions } from '../geotiff.js' */
3235
3451
  class RemoteSource extends BaseSource {
3236
3452
  /**
3237
- * @param {import("../geotiff").BaseClient} client
3453
+ * @param {import("../geotiff.js").BaseClient} client
3238
3454
  * @param {RemoteSourceOptions} options
3239
3455
  */
3240
3456
  constructor(client, { headers, maxRanges = 0, allowFullFile } = {}) {
@@ -3248,24 +3464,29 @@ class RemoteSource extends BaseSource {
3248
3464
  /**
3249
3465
  * @param {import('./basesource.js').Slice[]} slices
3250
3466
  * @param {AbortSignal} [signal]
3251
- * @returns {Promise<*[]>}
3467
+ * @returns {Promise<ArrayBufferLike[]>}
3252
3468
  */
3253
3469
  async fetch(slices, signal) {
3254
3470
  // if we allow multi-ranges, split the incoming request into that many sub-requests
3255
3471
  // and join them afterwards
3256
3472
  if (this.maxRanges >= slices.length) {
3257
- return this.fetchSlices(slices, signal);
3473
+ return this.fetchSlices(slices, signal).then((results) => results.map((r) => r.data));
3258
3474
  }
3259
3475
  else if (this.maxRanges > 0 && slices.length > 1) ;
3260
3476
  // otherwise make a single request for each slice
3261
- return Promise.all(slices.map((slice) => this.fetchSlice(slice, signal)));
3477
+ return Promise.all(slices.map(async (slice) => (await this.fetchSlice(slice, signal)).data));
3262
3478
  }
3479
+ /**
3480
+ * @param {Array<import('./basesource.js').Slice>} slices
3481
+ * @param {AbortSignal} [signal]
3482
+ * @returns {Promise<Array<import('./basesource.js').SliceWithData>>}
3483
+ */
3263
3484
  async fetchSlices(slices, signal) {
3264
3485
  const response = await this.client.request({
3265
3486
  headers: {
3266
3487
  ...this.headers,
3267
3488
  Range: `bytes=${slices
3268
- .map(({ offset, length }) => `${offset}-${offset + length}`)
3489
+ .map(({ offset, length }) => `${offset}-${offset + length - 1}`)
3269
3490
  .join(',')}`,
3270
3491
  },
3271
3492
  signal,
@@ -3283,10 +3504,11 @@ class RemoteSource extends BaseSource {
3283
3504
  const data = await response.getData();
3284
3505
  const { start, end, total } = parseContentRange(response.getHeader('content-range'));
3285
3506
  this._fileSize = total || null;
3507
+ /** @type {import('./basesource.js').SliceWithData[]} */
3286
3508
  const first = [{
3287
3509
  data,
3288
3510
  offset: start,
3289
- length: end - start,
3511
+ length: end + 1 - start,
3290
3512
  }];
3291
3513
  if (slices.length > 1) {
3292
3514
  // we requested more than one slice, but got only the first
@@ -3311,12 +3533,17 @@ class RemoteSource extends BaseSource {
3311
3533
  }];
3312
3534
  }
3313
3535
  }
3536
+ /**
3537
+ * @param {import('./basesource.js').Slice} slice
3538
+ * @param {AbortSignal} [signal]
3539
+ * @returns {Promise<import('./basesource.js').SliceWithData>}
3540
+ */
3314
3541
  async fetchSlice(slice, signal) {
3315
3542
  const { offset, length } = slice;
3316
3543
  const response = await this.client.request({
3317
3544
  headers: {
3318
3545
  ...this.headers,
3319
- Range: `bytes=${offset}-${offset + length}`,
3546
+ Range: `bytes=${offset}-${offset + length - 1}`,
3320
3547
  },
3321
3548
  signal,
3322
3549
  });
@@ -3357,7 +3584,7 @@ class RemoteSource extends BaseSource {
3357
3584
  * @returns {BaseSource}
3358
3585
  */
3359
3586
  function maybeWrapInBlockedSource(source, { blockSize, cacheSize }) {
3360
- if (blockSize === null) {
3587
+ if (blockSize === undefined) {
3361
3588
  return source;
3362
3589
  }
3363
3590
  return new BlockedSource(source, { blockSize, cacheSize });
@@ -3408,17 +3635,30 @@ function makeRemoteSource(url, { forceXHR = false, ...clientOptions } = {}) {
3408
3635
  }
3409
3636
 
3410
3637
  class ArrayBufferSource extends BaseSource {
3638
+ /**
3639
+ * @param {ArrayBuffer} arrayBuffer
3640
+ */
3411
3641
  constructor(arrayBuffer) {
3412
3642
  super();
3413
3643
  this.arrayBuffer = arrayBuffer;
3414
3644
  }
3645
+ /**
3646
+ * @param {import('./basesource.js').Slice} slice
3647
+ * @param {AbortSignal} [signal]
3648
+ * @returns {Promise<import('./basesource.js').SliceWithData>}
3649
+ */
3415
3650
  fetchSlice(slice, signal) {
3416
3651
  if (signal && signal.aborted) {
3417
3652
  throw new AbortError('Request aborted');
3418
3653
  }
3419
- return this.arrayBuffer.slice(slice.offset, slice.offset + slice.length);
3654
+ return Promise.resolve({
3655
+ data: this.arrayBuffer.slice(slice.offset, slice.offset + slice.length),
3656
+ offset: slice.offset,
3657
+ length: slice.length,
3658
+ });
3420
3659
  }
3421
3660
  }
3661
+ /** @param {ArrayBuffer} arrayBuffer */
3422
3662
  function makeBufferSource(arrayBuffer) {
3423
3663
  return new ArrayBufferSource(arrayBuffer);
3424
3664
  }
@@ -3516,6 +3756,17 @@ function getDataSliceReader(dataSlice, fieldType) {
3516
3756
  * @param {true} isArray - Whether to always return an array (vs single value)
3517
3757
  * @returns {import('./geotiff.js').TypedArray|Array<number>} The decoded value(s)
3518
3758
  */
3759
+ /**
3760
+ * @overload
3761
+ * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array
3762
+ * @param {Function} readMethod - DataView read method (e.g., getUint16)
3763
+ * @param {DataSlice} dataSlice - Source data slice
3764
+ * @param {number} fieldType - TIFF field type constant
3765
+ * @param {number} count - Number of values to read
3766
+ * @param {number} offset - Byte offset to start reading
3767
+ * @param {boolean} [isArray] - Whether to always return an array (vs single value)
3768
+ * @returns {import('./geotiff.js').TypedArray|Array<number>|string|number} The decoded value(s)
3769
+ */
3519
3770
  /**
3520
3771
  * Reads field values from a DataSlice.
3521
3772
  * @param {import('./geotiff.js').TypedArray|Array<number>|null} outValues - Optional pre-allocated output array
@@ -3640,9 +3891,11 @@ class DeferredArray {
3640
3891
  class ImageFileDirectory {
3641
3892
  /**
3642
3893
  * Create an ImageFileDirectory.
3643
- * @param {Map} actualizedFields the file directory, mapping tag names to values
3644
- * @param {Map} deferredFields the deferred fields, mapping tag names to async functions
3645
- * @param {Map} deferredArrays the deferred arrays, mapping tag names to DeferredArray objects
3894
+ * @param {Map<string|number, number|string|Array<number|string>>} actualizedFields the file directory,
3895
+ * mapping tag names to values
3896
+ * @param {Map<string|number, Function>} deferredFields the deferred fields, mapping tag names to async functions
3897
+ * @param {Map<string|number, DeferredArray>} deferredArrays the deferred arrays, mapping tag names to
3898
+ * DeferredArray objects
3646
3899
  * @param {number} nextIFDByteOffset the byte offset to the next IFD
3647
3900
  */
3648
3901
  constructor(actualizedFields, deferredFields, deferredArrays, nextIFDByteOffset) {
@@ -3653,7 +3906,7 @@ class ImageFileDirectory {
3653
3906
  this.nextIFDByteOffset = nextIFDByteOffset;
3654
3907
  }
3655
3908
  /**
3656
- * @param {number|string} tagIdentifier The field tag ID or name
3909
+ * @param {import('./globals.js').TagName|number} tagIdentifier The field tag ID or name
3657
3910
  * @returns {boolean} whether the field exists (actualized or deferred)
3658
3911
  */
3659
3912
  hasTag(tagIdentifier) {
@@ -3662,8 +3915,11 @@ class ImageFileDirectory {
3662
3915
  }
3663
3916
  /**
3664
3917
  * Synchronously retrieves the value for a given tag. If it is deferred, an error is thrown.
3665
- * @param {number|string} tagIdentifier The field tag ID or name
3666
- * @returns the field value, or undefined if it does not exist
3918
+ * @template {import('./globals.js').EagerTagName | import('./globals.js').EagerTag} [T=any]
3919
+ * @param {T} tagIdentifier The field tag ID or name
3920
+ * @returns {T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any}
3921
+ * the field value,
3922
+ * or undefined if it does not exist
3667
3923
  * @throws {Error} If the tag is deferred and requires asynchronous loading
3668
3924
  */
3669
3925
  getValue(tagIdentifier) {
@@ -3674,25 +3930,27 @@ class ImageFileDirectory {
3674
3930
  throw new Error(`Field '${tagName}' (${tag}) is deferred. Use loadValue() to load it asynchronously.`);
3675
3931
  }
3676
3932
  if (!this.actualizedFields.has(tag)) {
3677
- return undefined;
3933
+ return /** @type {any} */ (undefined);
3678
3934
  }
3679
- return this.actualizedFields.get(tag);
3935
+ return /** @type {any} */ (this.actualizedFields.get(tag));
3680
3936
  }
3681
3937
  /**
3682
3938
  * Retrieves the value for a given tag. If it is deferred, it will be loaded first.
3683
- * @param {number|string} tagIdentifier The field tag ID or name
3684
- * @returns the field value, or undefined if it does not exist
3939
+ * @template {import('./globals.js').TagName} [T=any]
3940
+ * @param {T|number} tagIdentifier The field tag ID or name
3941
+ * @returns {Promise<T extends import('./globals.js').TagName ? (import('./globals.js').TagValue<T> | undefined) : any>}
3942
+ * the field value, or undefined if it does not exist
3685
3943
  */
3686
3944
  async loadValue(tagIdentifier) {
3687
3945
  const tag = resolveTag(tagIdentifier);
3688
3946
  if (this.actualizedFields.has(tag)) {
3689
- return this.actualizedFields.get(tag);
3947
+ return /** @type {any} */ (this.actualizedFields.get(tag));
3690
3948
  }
3691
3949
  if (this.deferredFieldsBeingResolved.has(tag)) {
3692
- return this.deferredFieldsBeingResolved.get(tag);
3950
+ return /** @type {any} */ (this.deferredFieldsBeingResolved.get(tag));
3693
3951
  }
3694
- if (this.deferredFields.has(tag)) {
3695
- const loaderFn = this.deferredFields.get(tag);
3952
+ const loaderFn = this.deferredFields.get(tag);
3953
+ if (loaderFn) {
3696
3954
  this.deferredFields.delete(tag);
3697
3955
  // Set promise BEFORE starting async work to prevent race conditions
3698
3956
  const valuePromise = (async () => {
@@ -3706,32 +3964,35 @@ class ImageFileDirectory {
3706
3964
  }
3707
3965
  })();
3708
3966
  this.deferredFieldsBeingResolved.set(tag, valuePromise);
3709
- return valuePromise;
3967
+ return /** @type {any} */ (valuePromise);
3710
3968
  }
3711
- if (this.deferredArrays.has(tag)) {
3712
- const deferredArray = this.deferredArrays.get(tag);
3713
- return deferredArray.loadAll();
3969
+ const deferredArray = this.deferredArrays.get(tag);
3970
+ if (deferredArray) {
3971
+ return /** @type {any} */ (deferredArray.loadAll());
3714
3972
  }
3715
- return undefined;
3973
+ return /** @type {any} */ (undefined);
3716
3974
  }
3717
3975
  /**
3718
3976
  * Retrieves the value at a given index for a tag that is an array. If it is deferred, it will be loaded first.
3719
3977
  * @param {number|string} tagIdentifier The field tag ID or name
3720
3978
  * @param {number} index The index within the array
3721
- * @returns the field value at the given index, or undefined if it does not exist
3979
+ * @returns {Promise<number|string|bigint|undefined>} the field value at the given index, or undefined if it does not exist
3722
3980
  */
3723
3981
  async loadValueIndexed(tagIdentifier, index) {
3724
3982
  const tag = resolveTag(tagIdentifier);
3725
3983
  if (this.actualizedFields.has(tag)) {
3726
3984
  const value = this.actualizedFields.get(tag);
3727
- return value[index];
3985
+ return /** @type {any} */ (value)[index];
3728
3986
  }
3729
3987
  else if (this.deferredArrays.has(tag)) {
3730
- const deferredArray = this.deferredArrays.get(tag);
3988
+ const deferredArray = /** @type {DeferredArray} */ (this.deferredArrays.get(tag));
3731
3989
  return deferredArray.get(index);
3732
3990
  }
3733
3991
  else if (this.hasTag(tag)) {
3734
- return (await this.loadValue(tag))[index];
3992
+ const value = await this.loadValue(tag);
3993
+ if (value && typeof value !== 'number') {
3994
+ return value[index];
3995
+ }
3735
3996
  }
3736
3997
  return undefined;
3737
3998
  }
@@ -3751,8 +4012,8 @@ class ImageFileDirectory {
3751
4012
  /** @type {Partial<Record<import('./globals.js').GeoKeyName, *>>} */
3752
4013
  const geoKeyDirectory = {};
3753
4014
  for (let i = 4; i <= rawGeoKeyDirectory[3] * 4; i += 4) {
3754
- const key = geoKeyNames[rawGeoKeyDirectory[i]];
3755
- const location = rawGeoKeyDirectory[i + 1] || null;
4015
+ const key = ( /** @type {Record<number, import('./globals.js').GeoKeyName>} */(geoKeyNames))[rawGeoKeyDirectory[i]];
4016
+ const location = /** @type {import('./globals.js').EagerTag} */ (rawGeoKeyDirectory[i + 1]) || null;
3756
4017
  const count = rawGeoKeyDirectory[i + 2];
3757
4018
  const offset = rawGeoKeyDirectory[i + 3];
3758
4019
  let value = null;
@@ -3779,9 +4040,10 @@ class ImageFileDirectory {
3779
4040
  return geoKeyDirectory;
3780
4041
  }
3781
4042
  toObject() {
4043
+ /** @type {Record<string, unknown>} */
3782
4044
  const obj = {};
3783
4045
  for (const [tag, value] of this.actualizedFields.entries()) {
3784
- const tagDefinition = tagDefinitions[tag];
4046
+ const tagDefinition = typeof tag === 'number' ? tagDefinitions[tag] : undefined;
3785
4047
  const tagName = tagDefinition ? tagDefinition.name : `Tag${tag}`;
3786
4048
  obj[tagName] = value;
3787
4049
  }
@@ -3905,6 +4167,10 @@ class ImageFileDirectoryParser {
3905
4167
  }
3906
4168
  }
3907
4169
 
4170
+ /**
4171
+ * @param {Uint8Array|Uint16Array|Uint32Array} row
4172
+ * @param {number} stride
4173
+ */
3908
4174
  function decodeRowAcc(row, stride) {
3909
4175
  let length = row.length - stride;
3910
4176
  let offset = 0;
@@ -3916,6 +4182,11 @@ function decodeRowAcc(row, stride) {
3916
4182
  length -= stride;
3917
4183
  } while (length > 0);
3918
4184
  }
4185
+ /**
4186
+ * @param {Uint8Array} row
4187
+ * @param {number} stride
4188
+ * @param {number} bytesPerSample
4189
+ */
3919
4190
  function decodeRowFloatingPoint(row, stride, bytesPerSample) {
3920
4191
  let index = 0;
3921
4192
  let count = row.length;
@@ -3934,6 +4205,15 @@ function decodeRowFloatingPoint(row, stride, bytesPerSample) {
3934
4205
  }
3935
4206
  }
3936
4207
  }
4208
+ /**
4209
+ * @param {ArrayBufferLike} block
4210
+ * @param {number} predictor
4211
+ * @param {number} width
4212
+ * @param {number} height
4213
+ * @param {number[]} bitsPerSample
4214
+ * @param {number} planarConfiguration
4215
+ * @returns
4216
+ */
3937
4217
  function applyPredictor(block, predictor, width, height, bitsPerSample, planarConfiguration) {
3938
4218
  if (!predictor || predictor === 1) {
3939
4219
  return block;
@@ -3978,21 +4258,41 @@ function applyPredictor(block, predictor, width, height, bitsPerSample, planarCo
3978
4258
  return block;
3979
4259
  }
3980
4260
 
4261
+ /**
4262
+ * @typedef {Object} BaseDecoderParameters
4263
+ * @property {number} tileWidth
4264
+ * @property {number} tileHeight
4265
+ * @property {number} predictor
4266
+ * @property {number|number[]|import('../geotiff.js').TypedArray} bitsPerSample
4267
+ * @property {number} planarConfiguration
4268
+ * @property {number} [samplesPerPixel]
4269
+ */
3981
4270
  class BaseDecoder {
4271
+ /**
4272
+ * @param {BaseDecoderParameters} parameters
4273
+ */
3982
4274
  constructor(parameters) {
3983
4275
  this.parameters = parameters;
3984
4276
  }
3985
4277
  /**
3986
4278
  * @abstract
4279
+ * @param {ArrayBufferLike} _buffer
4280
+ * @returns {Promise<ArrayBufferLike>|ArrayBufferLike}
3987
4281
  */
3988
4282
  decodeBlock(_buffer) {
3989
4283
  throw new Error('decodeBlock not implemented');
3990
4284
  }
4285
+ /**
4286
+ * @param {ArrayBufferLike} buffer
4287
+ * @returns {Promise<ArrayBufferLike>}
4288
+ */
3991
4289
  async decode(buffer) {
3992
4290
  const decoded = await this.decodeBlock(buffer);
3993
4291
  const { tileWidth, tileHeight, predictor, bitsPerSample, planarConfiguration, } = this.parameters;
3994
4292
  if (predictor !== 1) {
3995
- return applyPredictor(decoded, predictor, tileWidth, tileHeight, bitsPerSample, planarConfiguration);
4293
+ const isBitsPerSampleArray = Array.isArray(bitsPerSample) || ArrayBuffer.isView(bitsPerSample);
4294
+ const adaptedBitsPerSample = isBitsPerSampleArray ? Array.from(bitsPerSample) : [bitsPerSample];
4295
+ return applyPredictor(decoded, predictor, tileWidth, tileHeight, adaptedBitsPerSample, planarConfiguration);
3996
4296
  }
3997
4297
  return decoded;
3998
4298
  }
@@ -4018,6 +4318,43 @@ class BaseDecoder {
4018
4318
  * `TypedArray[] & { height: number; width: number}`
4019
4319
  * @typedef {TypedArray[] & Dimensions} TypedArrayArrayWithDimensions
4020
4320
  */
4321
+ /**
4322
+ * @typedef {Object} GeotiffWriterMetadata
4323
+ * @property {number | number[]} [ImageWidth]
4324
+ * @property {number | number[]} [ImageLength]
4325
+ * @property {number} [width]
4326
+ * @property {number} [height]
4327
+ * @property {number | number[]} [BitsPerSample]
4328
+ * @property {number | number[]} [Compression]
4329
+ * @property {number | number[]} [PlanarConfiguration]
4330
+ * @property {number | number[]} [ExtraSamples]
4331
+ * @property {number | number[]} [PhotometricInterpretation]
4332
+ * @property {number | number[]} [SamplesPerPixel]
4333
+ * @property {number | number[]} [StripByteCounts]
4334
+ * @property {number[]} [ModelPixelScale]
4335
+ * @property {number[]} [ModelTransformation]
4336
+ * @property {number[]} [ModelTiepoint]
4337
+ * @property {number[]} [GeoKeyDirectory]
4338
+ * @property {string} [GeoAsciiParams]
4339
+ * @property {number[]} [GeoDoubleParams]
4340
+ * @property {number | number[]} [Orientation]
4341
+ * @property {number | number[]} [ResolutionUnit]
4342
+ * @property {number | number[]} [XPosition]
4343
+ * @property {number | number[]} [YPosition]
4344
+ * @property {number | number[]} [RowsPerStrip]
4345
+ * @property {number[]} [SampleFormat]
4346
+ * @property {number | number[]} [TileWidth]
4347
+ * @property {number | number[]} [TileLength]
4348
+ * @property {number[]} [TileOffsets]
4349
+ * @property {number[]} [TileByteCounts]
4350
+ * @property {string} [GDAL_NODATA]
4351
+ * @property {number | number[]} [GeographicTypeGeoKey]
4352
+ * @property {number | number[]} [ProjectedCSTypeGeoKey]
4353
+ * @property {string} [GeogCitationGeoKey]
4354
+ * @property {string} [GTCitationGeoKey]
4355
+ * @property {number | number[]} [GTModelTypeGeoKey]
4356
+ * @property {number | number[]} [GTRasterTypeGeoKey]
4357
+ */
4021
4358
  /**
4022
4359
  * The autogenerated docs are a little confusing here. The effective type is:
4023
4360
  *
@@ -4029,7 +4366,7 @@ class BaseDecoder {
4029
4366
  * Use the {@link Pool.bindParameters} method to get a decoder worker for
4030
4367
  * a specific compression and its parameters.
4031
4368
  *
4032
- * @property {(buffer: ArrayBuffer) => Promise<ArrayBuffer>} decode
4369
+ * @property {(buffer: ArrayBufferLike) => Promise<ArrayBufferLike>} decode
4033
4370
  * A function that takes a compressed buffer and returns a promise resolving to the decoded buffer.
4034
4371
  */
4035
4372
  /**
@@ -4068,12 +4405,12 @@ class BaseDecoder {
4068
4405
  */
4069
4406
  /**
4070
4407
  * @typedef {Object} BlockedSourceOptions
4071
- * @property {number|null} [blockSize=null] Block size for a BlockedSource.
4408
+ * @property {number} [blockSize] Block size for a BlockedSource.
4072
4409
  * @property {number} [cacheSize=100] The number of blocks to cache.
4073
4410
  */
4074
4411
  /**
4075
4412
  * @typedef {Object} RemoteSourceOptions
4076
- * @property {Object} [headers={}] Additional headers to add to each request
4413
+ * @property {Record<string, string>} [headers={}] Additional headers to add to each request
4077
4414
  * @property {number} [maxRanges=0] Maximum number of ranges to request in a single HTTP request. 0 means no multi-range requests.
4078
4415
  * @property {boolean} [allowFullFile=false] Whether to allow full file responses when requesting ranges
4079
4416
  * @property {boolean} [forceXHR=false] When the Fetch API would be used, force using XMLHttpRequest instead.
@@ -4094,7 +4431,7 @@ class BaseDecoder {
4094
4431
  * @returns {TypedArray|Array<number>|string}
4095
4432
  */
4096
4433
  function getValues(dataSlice, fieldType, count, offset) {
4097
- /** @type {TypedArray|Array|null} */
4434
+ /** @type {TypedArray|Array<number>|null} */
4098
4435
  let values = null;
4099
4436
  let readMethod = null;
4100
4437
  const fieldTypeLength = getFieldTypeSize(fieldType);
@@ -4157,27 +4494,23 @@ function getValues(dataSlice, fieldType, count, offset) {
4157
4494
  throw new RangeError(`Invalid field type: ${fieldType}`);
4158
4495
  }
4159
4496
  // normal fields
4160
- if (!(fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL)) {
4497
+ {
4161
4498
  for (let i = 0; i < count; ++i) {
4162
4499
  values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));
4163
4500
  }
4164
4501
  }
4165
- else { // RATIONAL or SRATIONAL
4166
- for (let i = 0; i < count; i += 2) {
4167
- values[i] = readMethod.call(dataSlice, offset + (i * fieldTypeLength));
4168
- values[i + 1] = readMethod.call(dataSlice, offset + ((i * fieldTypeLength) + 4));
4169
- }
4170
- }
4171
- if (fieldType === fieldTypes.ASCII) {
4502
+ {
4172
4503
  return new TextDecoder('utf-8').decode(/** @type {Uint8Array} */ (values));
4173
4504
  }
4174
- return values;
4175
4505
  }
4176
4506
  /**
4177
4507
  * Error class for cases when an IFD index was requested, that does not exist
4178
4508
  * in the file.
4179
4509
  */
4180
4510
  class GeoTIFFImageIndexError extends Error {
4511
+ /**
4512
+ * @param {number} index
4513
+ */
4181
4514
  constructor(index) {
4182
4515
  super(`No image at index ${index}`);
4183
4516
  this.index = index;
@@ -4262,7 +4595,7 @@ class GeoTIFFBase {
4262
4595
  const image = await this.getImage(i);
4263
4596
  const subfileType = image.fileDirectory.getValue('SubfileType');
4264
4597
  const newSubfileType = image.fileDirectory.getValue('NewSubfileType');
4265
- if (i === 0 || subfileType === 2 || newSubfileType & 1) {
4598
+ if (i === 0 || subfileType === 2 || (newSubfileType || 0) & 1) {
4266
4599
  allImages.push(image);
4267
4600
  }
4268
4601
  }
@@ -4322,9 +4655,16 @@ class GeoTIFF extends GeoTIFFBase {
4322
4655
  this.bigTiff = bigTiff;
4323
4656
  this.firstIFDOffset = firstIFDOffset;
4324
4657
  this.cache = options.cache || false;
4658
+ /** @type {Array<Promise<import('./imagefiledirectory.js').ImageFileDirectory> | undefined>} */
4325
4659
  this.ifdRequests = [];
4660
+ /** @type {Record<string, unknown>|null} */
4326
4661
  this.ghostValues = null;
4327
4662
  }
4663
+ /**
4664
+ * @param {number} offset
4665
+ * @param {number} [size]
4666
+ * @returns {Promise<DataSlice>}
4667
+ */
4328
4668
  async getSlice(offset, size) {
4329
4669
  const fallbackSize = this.bigTiff ? 4048 : 1024;
4330
4670
  return new DataSlice((await this.source.fetch([{
@@ -4332,6 +4672,10 @@ class GeoTIFF extends GeoTIFFBase {
4332
4672
  length: typeof size !== 'undefined' ? size : fallbackSize,
4333
4673
  }]))[0], offset, this.littleEndian, this.bigTiff);
4334
4674
  }
4675
+ /**
4676
+ * @param {number} index
4677
+ * @return {Promise<import('./imagefiledirectory.js').ImageFileDirectory>}
4678
+ */
4335
4679
  async requestIFD(index) {
4336
4680
  // see if we already have that IFD index requested.
4337
4681
  if (this.ifdRequests[index]) {
@@ -4362,7 +4706,11 @@ class GeoTIFF extends GeoTIFFBase {
4362
4706
  // if the previous IFD was loaded, we can finally fetch the one we are interested in.
4363
4707
  // we need to wrap this in an IIFE, otherwise this.ifdRequests[index] would be delayed
4364
4708
  this.ifdRequests[index] = (async () => {
4365
- const previousIfd = await this.ifdRequests[index - 1];
4709
+ const previousPromise = this.ifdRequests[index - 1];
4710
+ if (!previousPromise) {
4711
+ throw new Error('Previous IFD request missing');
4712
+ }
4713
+ const previousIfd = await previousPromise;
4366
4714
  if (previousIfd.nextIFDByteOffset === 0) {
4367
4715
  throw new GeoTIFFImageIndexError(index);
4368
4716
  }
@@ -4407,11 +4755,11 @@ class GeoTIFF extends GeoTIFFBase {
4407
4755
  /**
4408
4756
  * Get the values of the COG ghost area as a parsed map.
4409
4757
  * See https://gdal.org/drivers/raster/cog.html#header-ghost-area for reference
4410
- * @returns {Promise<Object>} the parsed ghost area or null, if no such area was found
4758
+ * @returns {Promise<Record<string, unknown>|null>} the parsed ghost area or null, if no such area was found
4411
4759
  */
4412
4760
  async getGhostValues() {
4413
4761
  const offset = this.bigTiff ? 16 : 8;
4414
- if (this.ghostValues) {
4762
+ if (this.ghostValues !== null) {
4415
4763
  return this.ghostValues;
4416
4764
  }
4417
4765
  const detectionString = 'GDAL_STRUCTURAL_METADATA_SIZE=';
@@ -4425,15 +4773,16 @@ class GeoTIFF extends GeoTIFFBase {
4425
4773
  slice = await this.getSlice(offset, metadataSize);
4426
4774
  }
4427
4775
  const fullString = getValues(slice, fieldTypes.ASCII, metadataSize, offset);
4428
- /** @type {Object} */
4429
- this.ghostValues = {};
4776
+ /** @type {Record<string, unknown>} */
4777
+ const ghostValues = {};
4430
4778
  fullString
4431
4779
  .split('\n')
4432
4780
  .filter((line) => line.length > 0)
4433
4781
  .map((line) => line.split('='))
4434
4782
  .forEach(([key, value]) => {
4435
- this.ghostValues[key] = value;
4783
+ ghostValues[key] = value;
4436
4784
  });
4785
+ this.ghostValues = ghostValues;
4437
4786
  }
4438
4787
  return this.ghostValues;
4439
4788
  }
@@ -4448,7 +4797,7 @@ class GeoTIFF extends GeoTIFFBase {
4448
4797
  static async fromSource(source, options, signal) {
4449
4798
  const headerData = (await source.fetch([{ offset: 0, length: 1024 }], signal))[0];
4450
4799
  const dataView = new DataView64(headerData);
4451
- const BOM = dataView.getUint16(0, 0);
4800
+ const BOM = dataView.getUint16(0, false);
4452
4801
  let littleEndian;
4453
4802
  if (BOM === 0x4949) {
4454
4803
  littleEndian = true;
@@ -4519,6 +4868,7 @@ async function fromArrayBuffer(arrayBuffer, signal) {
4519
4868
  const DefaultGeoImageOptions = {
4520
4869
  // --- Shared / Data ---
4521
4870
  type: 'image',
4871
+ blockSize: 65536,
4522
4872
  format: undefined,
4523
4873
  useChannel: null,
4524
4874
  useChannelIndex: null,
@@ -5908,36 +6258,57 @@ class CogTiles {
5908
6258
  bounds = [0, 0, 0, 0];
5909
6259
  geo = new GeoImage();
5910
6260
  options;
6261
+ // Cache GeoTIFFImage Promises by index to prevent redundant HTTP requests from geotiff 3.0.4+ eager loading
6262
+ // Stores Promises (not resolved values) so concurrent requests share the same getImage() call
6263
+ imageCache = new Map();
6264
+ // Store initialization promise to prevent concurrent duplicate initializations
6265
+ initializePromise;
5911
6266
  constructor(options) {
5912
6267
  this.options = { ...CogTilesGeoImageOptionsDefaults, ...options };
5913
6268
  }
5914
6269
  async initializeCog(url) {
6270
+ // Return existing initialization promise if already in progress (prevents concurrent duplicates)
6271
+ if (this.initializePromise)
6272
+ return this.initializePromise;
5915
6273
  if (this.cog)
5916
- return; // Prevent re-initialization on the same instance
5917
- try {
5918
- this.cog = await fromUrl(url);
5919
- const image = await this.cog.getImage();
5920
- const fileDirectory = image.fileDirectory;
5921
- this.cogOrigin = image.getOrigin();
5922
- this.options.noDataValue ??= await this.getNoDataValue(image);
5923
- this.options.format ??= await this.getDataTypeFromTags(fileDirectory);
5924
- this.options.numOfChannels = fileDirectory.getValue('SamplesPerPixel');
5925
- this.options.planarConfig = fileDirectory.getValue('PlanarConfiguration');
5926
- [this.cogZoomLookup, this.cogResolutionLookup] = await this.buildCogZoomResolutionLookup(this.cog);
5927
- this.tileSize = image.getTileWidth();
5928
- // 1. Validation: Ensure the image is tiled
5929
- if (!this.tileSize || !image.getTileHeight()) {
5930
- throw new Error('GeoTIFF Error: The provided image is not tiled. '
5931
- + 'Please use "rio cogeo create --web-optimized" to fix this.');
5932
- }
5933
- this.zoomRange = this.calculateZoomRange(this.tileSize, image.getResolution()[0], await this.cog.getImageCount());
5934
- this.bounds = this.calculateBoundsAsLatLon(image.getBoundingBox());
5935
- }
5936
- catch (error) {
5937
- /* eslint-disable no-console */
5938
- console.error(`[CogTiles] Failed to initialize COG from ${url}:`, error);
5939
- throw error;
5940
- }
6274
+ return;
6275
+ this.initializePromise = (async () => {
6276
+ try {
6277
+ // fromUrl's type declaration only exposes RemoteSourceOptions, but the implementation
6278
+ // also accepts BlockedSourceOptions (forwarded to makeFetchSource internally).
6279
+ // Explicitly enabling BlockedSource restores the block-level LRU cache that was
6280
+ // accidentally active in geotiff 3.0.3 (due to a null vs undefined bug there).
6281
+ // blockSize defaults to 65536 (64KB) and can be tuned via GeoImageOptions.
6282
+ const blockSize = this.options.blockSize ?? 65536;
6283
+ this.cog = await fromUrl(url, { blockSize });
6284
+ const imagePromise = this.cog.getImage();
6285
+ this.imageCache.set(0, imagePromise); // Cache base image (index 0) to avoid re-fetching during getTileFromImage
6286
+ const image = await imagePromise;
6287
+ const fileDirectory = image.fileDirectory;
6288
+ this.cogOrigin = image.getOrigin();
6289
+ this.options.noDataValue ??= await this.getNoDataValue(image);
6290
+ this.options.format ??= await this.getDataTypeFromTags(fileDirectory);
6291
+ this.options.numOfChannels = fileDirectory.getValue('SamplesPerPixel');
6292
+ this.options.planarConfig = fileDirectory.getValue('PlanarConfiguration');
6293
+ [this.cogZoomLookup, this.cogResolutionLookup] = await this.buildCogZoomResolutionLookup(this.cog);
6294
+ this.tileSize = image.getTileWidth();
6295
+ // 1. Validation: Ensure the image is tiled
6296
+ if (!this.tileSize || !image.getTileHeight()) {
6297
+ throw new Error('GeoTIFF Error: The provided image is not tiled. '
6298
+ + 'Please use "rio cogeo create --web-optimized" to fix this.');
6299
+ }
6300
+ this.zoomRange = this.calculateZoomRange(this.tileSize, image.getResolution()[0], await this.cog.getImageCount());
6301
+ this.bounds = this.calculateBoundsAsLatLon(image.getBoundingBox());
6302
+ }
6303
+ catch (error) {
6304
+ // Reset initialization promise on error so retry can be attempted
6305
+ this.initializePromise = undefined;
6306
+ /* eslint-disable no-console */
6307
+ console.error(`[CogTiles] Failed to initialize COG from ${url}:`, error);
6308
+ throw error;
6309
+ }
6310
+ })();
6311
+ return this.initializePromise;
5941
6312
  }
5942
6313
  getZoomRange() {
5943
6314
  return this.zoomRange;
@@ -6042,7 +6413,13 @@ class CogTiles {
6042
6413
  }
6043
6414
  async getTileFromImage(tileX, tileY, zoom, fetchSize) {
6044
6415
  const imageIndex = this.getImageIndexForZoomLevel(zoom);
6045
- const targetImage = await this.cog.getImage(imageIndex);
6416
+ // Cache Promises to share in-flight requests across concurrent tiles at the same overview
6417
+ let imagePromise = this.imageCache.get(imageIndex);
6418
+ if (!imagePromise) {
6419
+ imagePromise = this.cog.getImage(imageIndex);
6420
+ this.imageCache.set(imageIndex, imagePromise);
6421
+ }
6422
+ const targetImage = await imagePromise;
6046
6423
  // --- STEP 1: CALCULATE BOUNDS IN METERS ---
6047
6424
  // 2. Get COG Metadata (image = COG)
6048
6425
  const imageResolution = this.cogResolutionLookup[imageIndex];
@@ -6533,11 +6910,21 @@ class CogTerrainLayer extends core.CompositeLayer {
6533
6910
  terrainUrl = '';
6534
6911
  async initializeState(context) {
6535
6912
  super.initializeState(context);
6913
+ const terrainCogTiles = this.props.cogTiles || new CogTiles(this.props.terrainOptions);
6536
6914
  this.setState({
6537
- terrainCogTiles: this.props.cogTiles || new CogTiles(this.props.terrainOptions),
6915
+ terrainCogTiles,
6538
6916
  initialized: false,
6539
6917
  });
6540
- await this.init(this.terrainUrl);
6918
+ // Only initialize if not already done (e.g., provided cogTiles instance may be pre-initialized)
6919
+ if (!terrainCogTiles.cog) {
6920
+ await this.init();
6921
+ }
6922
+ else {
6923
+ // CogTiles already initialized; just extract zoom range and mark ready
6924
+ const zoomRange = terrainCogTiles.getZoomRange();
6925
+ const [minZoom, maxZoom] = zoomRange;
6926
+ this.setState({ initialized: true, minZoom, maxZoom });
6927
+ }
6541
6928
  }
6542
6929
  async init() {
6543
6930
  await this.state.terrainCogTiles.initializeCog(this.props.elevationData);
@@ -6716,6 +7103,7 @@ class CogTerrainLayer extends core.CompositeLayer {
6716
7103
  }
6717
7104
 
6718
7105
  class RawDecoder extends BaseDecoder {
7106
+ /** @param {ArrayBuffer} buffer */
6719
7107
  decodeBlock(buffer) {
6720
7108
  return buffer;
6721
7109
  }
@@ -6730,6 +7118,12 @@ const MIN_BITS = 9;
6730
7118
  const CLEAR_CODE = 256; // clear code
6731
7119
  const EOI_CODE = 257; // end of information
6732
7120
  const MAX_BYTELENGTH = 12;
7121
+ /**
7122
+ * @param {Uint8Array} array
7123
+ * @param {number} position
7124
+ * @param {number} length
7125
+ * @returns {number}
7126
+ */
6733
7127
  function getByte(array, position, length) {
6734
7128
  const d = position % 8;
6735
7129
  const a = Math.floor(position / 8);
@@ -6757,12 +7151,21 @@ function getByte(array, position, length) {
6757
7151
  }
6758
7152
  return chunks;
6759
7153
  }
7154
+ /**
7155
+ * @template T
7156
+ * @param {Array<T>} dest
7157
+ * @param {Array<T>} source
7158
+ * @returns {Array<T>}
7159
+ */
6760
7160
  function appendReversed(dest, source) {
6761
7161
  for (let i = source.length - 1; i >= 0; i--) {
6762
7162
  dest.push(source[i]);
6763
7163
  }
6764
7164
  return dest;
6765
7165
  }
7166
+ /**
7167
+ * @param {ArrayBuffer} input
7168
+ */
6766
7169
  function decompress(input) {
6767
7170
  const dictionaryIndex = new Uint16Array(4093);
6768
7171
  const dictionaryChar = new Uint8Array(4093);
@@ -6777,17 +7180,23 @@ function decompress(input) {
6777
7180
  dictionaryLength = 258;
6778
7181
  byteLength = MIN_BITS;
6779
7182
  }
7183
+ /** @param {Uint8Array} array */
6780
7184
  function getNext(array) {
6781
7185
  const byte = getByte(array, position, byteLength);
6782
7186
  position += byteLength;
6783
7187
  return byte;
6784
7188
  }
7189
+ /**
7190
+ * @param {number} i
7191
+ * @param {number} c
7192
+ */
6785
7193
  function addToDictionary(i, c) {
6786
7194
  dictionaryChar[dictionaryLength] = c;
6787
7195
  dictionaryIndex[dictionaryLength] = i;
6788
7196
  dictionaryLength++;
6789
7197
  return dictionaryLength - 1;
6790
7198
  }
7199
+ /** @param {number} n */
6791
7200
  function getDictionaryReversed(n) {
6792
7201
  const rev = [];
6793
7202
  for (let i = n; i !== 4096; i = dictionaryIndex[i]) {
@@ -6822,10 +7231,15 @@ function decompress(input) {
6822
7231
  else if (code < dictionaryLength) {
6823
7232
  const val = getDictionaryReversed(code);
6824
7233
  appendReversed(result, val);
6825
- addToDictionary(oldCode, val[val.length - 1]);
7234
+ if (oldCode !== undefined) {
7235
+ addToDictionary(oldCode, val[val.length - 1]);
7236
+ }
6826
7237
  oldCode = code;
6827
7238
  }
6828
7239
  else {
7240
+ if (oldCode === undefined) {
7241
+ throw new Error(`Invalid LZW code: ${code} with no previous code`);
7242
+ }
6829
7243
  const oldVal = getDictionaryReversed(oldCode);
6830
7244
  if (!oldVal) {
6831
7245
  throw new Error(`Bogus entry. Not in dictionary, ${oldCode} / ${dictionaryLength}, position: ${position}`);
@@ -6848,6 +7262,7 @@ function decompress(input) {
6848
7262
  return new Uint8Array(result);
6849
7263
  }
6850
7264
  class LZWDecoder extends BaseDecoder {
7265
+ /** @param {ArrayBuffer} buffer */
6851
7266
  decodeBlock(buffer) {
6852
7267
  return decompress(buffer).buffer;
6853
7268
  }
@@ -6906,6 +7321,33 @@ const dctSqrt2 = 5793; // sqrt(2)
6906
7321
  const dctSqrt1d2 = 2896; // sqrt(2) / 2
6907
7322
  /** @typedef {(number|HuffmanNode)[]} HuffmanNode */
6908
7323
  /** @typedef {{children: HuffmanNode, index: number}} Code */
7324
+ /**
7325
+ * @typedef {Object} JpegComponent
7326
+ * @property {number} h
7327
+ * @property {number} v
7328
+ * @property {number} [quantizationIdx]
7329
+ * @property {Int32Array} [quantizationTable]
7330
+ * @property {number} blocksPerLine
7331
+ * @property {number} blocksPerColumn
7332
+ * @property {Int32Array[][]} blocks
7333
+ * @property {HuffmanNode} [huffmanTableDC]
7334
+ * @property {HuffmanNode} [huffmanTableAC]
7335
+ * @property {number} [pred]
7336
+ */
7337
+ /**
7338
+ * @typedef {Object} JpegFrame
7339
+ * @property {boolean} extended
7340
+ * @property {boolean} progressive
7341
+ * @property {number} precision
7342
+ * @property {number} scanLines
7343
+ * @property {number} samplesPerLine
7344
+ * @property {Object.<string, JpegComponent>} components
7345
+ * @property {number[]} componentsOrder
7346
+ * @property {number} maxH
7347
+ * @property {number} maxV
7348
+ * @property {number} mcusPerLine
7349
+ * @property {number} mcusPerColumn
7350
+ */
6909
7351
  /**
6910
7352
  * @param {Uint8Array<ArrayBuffer>} codeLengths
6911
7353
  * @param {Uint8Array<ArrayBuffer>} values
@@ -6955,8 +7397,25 @@ function buildHuffmanTable(codeLengths, values) {
6955
7397
  }
6956
7398
  return code[0].children;
6957
7399
  }
7400
+ /**
7401
+ * @param {Uint8Array} data
7402
+ * @param {number} initialOffset
7403
+ * @param {JpegFrame} frame
7404
+ * @param {JpegComponent[]} components
7405
+ * @param {number} resetInterval
7406
+ * @param {number} spectralStart
7407
+ * @param {number} spectralEnd
7408
+ * @param {number} successivePrev
7409
+ * @param {number} successive
7410
+ */
6958
7411
  function decodeScan(data, initialOffset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
6959
7412
  const { mcusPerLine, progressive } = frame;
7413
+ if (components.length > 1 && (mcusPerLine === undefined || frame.mcusPerColumn === undefined)) {
7414
+ throw new Error('Missing MCU dimensions');
7415
+ }
7416
+ if (components.length === 1 && (components[0].blocksPerLine === undefined || components[0].blocksPerColumn === undefined)) {
7417
+ throw new Error('Missing block dimensions');
7418
+ }
6960
7419
  const startOffset = initialOffset;
6961
7420
  let offset = initialOffset;
6962
7421
  let bitsData = 0;
@@ -6977,20 +7436,26 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
6977
7436
  bitsCount = 7;
6978
7437
  return bitsData >>> 7;
6979
7438
  }
7439
+ /** @param {HuffmanNode|undefined} tree */
6980
7440
  function decodeHuffman(tree) {
7441
+ if (!tree) {
7442
+ throw new Error('Huffman table not found');
7443
+ }
6981
7444
  let node = tree;
6982
7445
  let bit;
6983
7446
  while ((bit = readBit()) !== null) { // eslint-disable-line no-cond-assign
6984
- node = node[bit];
6985
- if (typeof node === 'number') {
6986
- return node;
7447
+ const next = node[bit];
7448
+ if (typeof next === 'number') {
7449
+ return next;
6987
7450
  }
6988
- if (typeof node !== 'object') {
7451
+ if (typeof next !== 'object') {
6989
7452
  throw new Error('invalid huffman sequence');
6990
7453
  }
7454
+ node = next;
6991
7455
  }
6992
7456
  return null;
6993
7457
  }
7458
+ /** @param {number} initialLength */
6994
7459
  function receive(initialLength) {
6995
7460
  let length = initialLength;
6996
7461
  let n = 0;
@@ -7004,6 +7469,7 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7004
7469
  }
7005
7470
  return n;
7006
7471
  }
7472
+ /** @param {number} length */
7007
7473
  function receiveAndExtend(length) {
7008
7474
  const n = receive(length);
7009
7475
  if (n === undefined) {
@@ -7014,9 +7480,22 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7014
7480
  }
7015
7481
  return n + (-1 << length) + 1;
7016
7482
  }
7483
+ /**
7484
+ * @param {JpegComponent} component
7485
+ * @param {Int32Array} zz
7486
+ */
7017
7487
  function decodeBaseline(component, zz) {
7018
7488
  const t = decodeHuffman(component.huffmanTableDC);
7489
+ if (t === null) {
7490
+ throw new Error('Huffman error');
7491
+ }
7019
7492
  const diff = t === 0 ? 0 : receiveAndExtend(t);
7493
+ if (diff === undefined) {
7494
+ throw new Error('Unexpected end of stream');
7495
+ }
7496
+ if (component.pred === undefined) {
7497
+ component.pred = 0;
7498
+ }
7020
7499
  component.pred += diff;
7021
7500
  zz[0] = component.pred;
7022
7501
  let k = 1;
@@ -7036,25 +7515,51 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7036
7515
  else {
7037
7516
  k += r;
7038
7517
  const z = dctZigZag[k];
7039
- zz[z] = receiveAndExtend(s);
7518
+ const val = receiveAndExtend(s);
7519
+ if (val === undefined) {
7520
+ throw new Error('Unexpected end of stream');
7521
+ }
7522
+ zz[z] = val;
7040
7523
  k++;
7041
7524
  }
7042
7525
  }
7043
7526
  }
7527
+ /**
7528
+ * @param {JpegComponent} component
7529
+ * @param {Int32Array} zz
7530
+ */
7044
7531
  function decodeDCFirst(component, zz) {
7045
7532
  const t = decodeHuffman(component.huffmanTableDC);
7533
+ if (t === null) {
7534
+ throw new Error('Huffman error');
7535
+ }
7046
7536
  const value = receiveAndExtend(t);
7047
7537
  if (value === undefined) {
7048
7538
  throw new Error('Unexpected end of data in DC coefficient decoding');
7049
7539
  }
7050
7540
  const diff = t === 0 ? 0 : (value << successive);
7541
+ if (component.pred === undefined) {
7542
+ component.pred = 0;
7543
+ }
7051
7544
  component.pred += diff;
7052
7545
  zz[0] = component.pred;
7053
7546
  }
7054
- function decodeDCSuccessive(component, zz) {
7055
- zz[0] |= readBit() << successive;
7547
+ /**
7548
+ * @param {JpegComponent} _
7549
+ * @param {Int32Array} zz
7550
+ */
7551
+ function decodeDCSuccessive(_, zz) {
7552
+ const bit = readBit();
7553
+ if (bit === null) {
7554
+ throw new Error('Unexpected end of data in DC coefficient decoding');
7555
+ }
7556
+ zz[0] |= bit << successive;
7056
7557
  }
7057
7558
  let eobrun = 0;
7559
+ /**
7560
+ * @param {JpegComponent} component
7561
+ * @param {Int32Array} zz
7562
+ */
7058
7563
  function decodeACFirst(component, zz) {
7059
7564
  if (eobrun > 0) {
7060
7565
  eobrun--;
@@ -7093,7 +7598,12 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7093
7598
  }
7094
7599
  }
7095
7600
  let successiveACState = 0;
7601
+ /** @type {number} */
7096
7602
  let successiveACNextValue;
7603
+ /**
7604
+ * @param {JpegComponent} component
7605
+ * @param {Int32Array} zz
7606
+ */
7097
7607
  function decodeACSuccessive(component, zz) {
7098
7608
  let k = spectralStart;
7099
7609
  const e = spectralEnd;
@@ -7127,7 +7637,11 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7127
7637
  if (s !== 1) {
7128
7638
  throw new Error('invalid ACn encoding');
7129
7639
  }
7130
- successiveACNextValue = receiveAndExtend(s);
7640
+ const nextVal = receiveAndExtend(s);
7641
+ if (nextVal === undefined) {
7642
+ throw new Error('Unexpected end of data in AC coefficient decoding');
7643
+ }
7644
+ successiveACNextValue = nextVal;
7131
7645
  successiveACState = r ? 2 : 3;
7132
7646
  }
7133
7647
  continue; // eslint-disable-line no-continue
@@ -7135,7 +7649,11 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7135
7649
  case 1: // skipping r zero items
7136
7650
  case 2:
7137
7651
  if (zz[z]) {
7138
- zz[z] += (readBit() << successive) * direction;
7652
+ const bit = readBit();
7653
+ if (bit === null) {
7654
+ throw new Error('Unexpected end of data in AC coefficient decoding');
7655
+ }
7656
+ zz[z] += (bit << successive) * direction;
7139
7657
  }
7140
7658
  else {
7141
7659
  r--;
@@ -7146,7 +7664,11 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7146
7664
  break;
7147
7665
  case 3: // set value for a zero item
7148
7666
  if (zz[z]) {
7149
- zz[z] += (readBit() << successive) * direction;
7667
+ const bit = readBit();
7668
+ if (bit === null) {
7669
+ throw new Error('Unexpected end of data in AC coefficient decoding');
7670
+ }
7671
+ zz[z] += (bit << successive) * direction;
7150
7672
  }
7151
7673
  else {
7152
7674
  zz[z] = successiveACNextValue << successive;
@@ -7155,7 +7677,11 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7155
7677
  break;
7156
7678
  case 4: // eob
7157
7679
  if (zz[z]) {
7158
- zz[z] += (readBit() << successive) * direction;
7680
+ const bit = readBit();
7681
+ if (bit === null) {
7682
+ throw new Error('Unexpected end of data in AC coefficient decoding');
7683
+ }
7684
+ zz[z] += (bit << successive) * direction;
7159
7685
  }
7160
7686
  break;
7161
7687
  }
@@ -7168,16 +7694,34 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7168
7694
  }
7169
7695
  }
7170
7696
  }
7697
+ /**
7698
+ * @param {JpegComponent} component
7699
+ * @param {function} decodeFunction
7700
+ * @param {number} mcu
7701
+ * @param {number} row
7702
+ * @param {number} col
7703
+ */
7171
7704
  function decodeMcu(component, decodeFunction, mcu, row, col) {
7172
7705
  const mcuRow = (mcu / mcusPerLine) | 0;
7173
7706
  const mcuCol = mcu % mcusPerLine;
7174
7707
  const blockRow = (mcuRow * component.v) + row;
7175
7708
  const blockCol = (mcuCol * component.h) + col;
7709
+ if (!component.blocks) {
7710
+ throw new Error('Missing blocks');
7711
+ }
7176
7712
  decodeFunction(component, component.blocks[blockRow][blockCol]);
7177
7713
  }
7714
+ /**
7715
+ * @param {JpegComponent} component
7716
+ * @param {function} decodeFunction
7717
+ * @param {number} mcu
7718
+ */
7178
7719
  function decodeBlock(component, decodeFunction, mcu) {
7179
7720
  const blockRow = (mcu / component.blocksPerLine) | 0;
7180
7721
  const blockCol = mcu % component.blocksPerLine;
7722
+ if (!component.blocks) {
7723
+ throw new Error('Missing blocks');
7724
+ }
7181
7725
  decodeFunction(component, component.blocks[blockRow][blockCol]);
7182
7726
  }
7183
7727
  const componentsLength = components.length;
@@ -7254,9 +7798,15 @@ function decodeScan(data, initialOffset, frame, components, resetInterval, spect
7254
7798
  }
7255
7799
  return offset - startOffset;
7256
7800
  }
7257
- function buildComponentData(frame, component) {
7801
+ /**
7802
+ * @param {JpegComponent} component
7803
+ */
7804
+ function buildComponentData(component) {
7258
7805
  const lines = [];
7259
7806
  const { blocksPerLine, blocksPerColumn } = component;
7807
+ if (!blocksPerLine || !blocksPerColumn || !component.blocks) {
7808
+ throw new Error('Missing component data');
7809
+ }
7260
7810
  const samplesPerLine = blocksPerLine << 3;
7261
7811
  const R = new Int32Array(64);
7262
7812
  const r = new Uint8Array(64);
@@ -7265,8 +7815,16 @@ function buildComponentData(frame, component) {
7265
7815
  // "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
7266
7816
  // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
7267
7817
  // 988-991.
7818
+ /**
7819
+ * @param {Int32Array} zz
7820
+ * @param {Uint8Array} dataOut
7821
+ * @param {Int32Array} dataIn
7822
+ */
7268
7823
  function quantizeAndInverse(zz, dataOut, dataIn) {
7269
7824
  const qt = component.quantizationTable;
7825
+ if (!qt) {
7826
+ throw new Error('No quantization table found');
7827
+ }
7270
7828
  let v0;
7271
7829
  let v1;
7272
7830
  let v2;
@@ -7445,14 +8003,21 @@ class JpegStreamReader {
7445
8003
  constructor() {
7446
8004
  this.jfif = null;
7447
8005
  this.adobe = null;
8006
+ /** @type {number} */
8007
+ this.resetInterval = 0;
8008
+ /** @type {Int32Array[]} */
7448
8009
  this.quantizationTables = [];
8010
+ /** @type {HuffmanNode[]} */
7449
8011
  this.huffmanTablesAC = [];
8012
+ /** @type {HuffmanNode[]} */
7450
8013
  this.huffmanTablesDC = [];
8014
+ /** @type {JpegFrame[]} */
7451
8015
  this.frames = [];
7452
8016
  }
7453
8017
  resetFrames() {
7454
8018
  this.frames = [];
7455
8019
  }
8020
+ /** @param {Uint8Array} data */
7456
8021
  parse(data) {
7457
8022
  let offset = 0;
7458
8023
  // const { length } = data;
@@ -7467,6 +8032,7 @@ class JpegStreamReader {
7467
8032
  offset += array.length;
7468
8033
  return array;
7469
8034
  }
8035
+ /** @param {JpegFrame} frame */
7470
8036
  function prepareComponents(frame) {
7471
8037
  let maxH = 0;
7472
8038
  let maxV = 0;
@@ -7593,15 +8159,21 @@ class JpegStreamReader {
7593
8159
  case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)
7594
8160
  case 0xFFC2: { // SOF2 (Start of Frame, Progressive DCT)
7595
8161
  readUint16(); // skip data length
8162
+ /** @type {JpegFrame} */
7596
8163
  const frame = {
7597
8164
  extended: (fileMarker === 0xFFC1),
7598
8165
  progressive: (fileMarker === 0xFFC2),
7599
8166
  precision: data[offset++],
7600
8167
  scanLines: readUint16(),
7601
8168
  samplesPerLine: readUint16(),
8169
+ /** @type {Object.<string, JpegComponent>} */
7602
8170
  components: {},
7603
- /** @type {any[]} */
8171
+ /** @type {number[]} */
7604
8172
  componentsOrder: [],
8173
+ maxH: 0,
8174
+ maxV: 0,
8175
+ mcusPerLine: 0,
8176
+ mcusPerColumn: 0,
7605
8177
  };
7606
8178
  const componentsCount = data[offset++];
7607
8179
  let componentId;
@@ -7617,6 +8189,9 @@ class JpegStreamReader {
7617
8189
  h,
7618
8190
  v,
7619
8191
  quantizationIdx: qId,
8192
+ blocksPerLine: 0,
8193
+ blocksPerColumn: 0,
8194
+ blocks: [],
7620
8195
  };
7621
8196
  offset += 3;
7622
8197
  }
@@ -7701,11 +8276,17 @@ class JpegStreamReader {
7701
8276
  for (let i = 0; i < this.frames.length; i++) {
7702
8277
  const cp = this.frames[i].components;
7703
8278
  for (const j of Object.keys(cp)) {
7704
- cp[j].quantizationTable = this.quantizationTables[cp[j].quantizationIdx];
7705
- delete cp[j].quantizationIdx;
8279
+ const qIdx = cp[j].quantizationIdx;
8280
+ if (typeof qIdx === 'number') {
8281
+ cp[j].quantizationTable = this.quantizationTables[qIdx];
8282
+ delete cp[j].quantizationIdx;
8283
+ }
7706
8284
  }
7707
8285
  }
7708
8286
  const frame = frames[0];
8287
+ if (!frame.maxH || !frame.maxV) {
8288
+ throw new Error('Invalid frame dimensions');
8289
+ }
7709
8290
  const { components, componentsOrder } = frame;
7710
8291
  const outComponents = [];
7711
8292
  const width = frame.samplesPerLine;
@@ -7713,7 +8294,7 @@ class JpegStreamReader {
7713
8294
  for (let i = 0; i < componentsOrder.length; i++) {
7714
8295
  const component = components[componentsOrder[i]];
7715
8296
  outComponents.push({
7716
- lines: buildComponentData(frame, component),
8297
+ lines: buildComponentData(component),
7717
8298
  scaleX: component.h / frame.maxH,
7718
8299
  scaleY: component.v / frame.maxV,
7719
8300
  });
@@ -7733,6 +8314,9 @@ class JpegStreamReader {
7733
8314
  }
7734
8315
  }
7735
8316
  class JpegDecoder extends BaseDecoder {
8317
+ /**
8318
+ * @param {import('./basedecoder.js').BaseDecoderParameters & { JPEGTables?: Uint8Array }} parameters
8319
+ */
7736
8320
  constructor(parameters) {
7737
8321
  super(parameters);
7738
8322
  this.reader = new JpegStreamReader();
@@ -7740,6 +8324,7 @@ class JpegDecoder extends BaseDecoder {
7740
8324
  this.reader.parse(parameters.JPEGTables);
7741
8325
  }
7742
8326
  }
8327
+ /** @param {ArrayBuffer} buffer */
7743
8328
  decodeBlock(buffer) {
7744
8329
  this.reader.resetFrames();
7745
8330
  this.reader.parse(new Uint8Array(buffer));
@@ -10988,6 +11573,7 @@ const { inflate} = inflate_1$1;
10988
11573
  var inflate_1 = inflate;
10989
11574
 
10990
11575
  class DeflateDecoder extends BaseDecoder {
11576
+ /** @param {ArrayBuffer} buffer */
10991
11577
  decodeBlock(buffer) {
10992
11578
  return inflate_1(new Uint8Array(buffer)).buffer;
10993
11579
  }
@@ -10999,6 +11585,7 @@ var deflate = /*#__PURE__*/Object.freeze({
10999
11585
  });
11000
11586
 
11001
11587
  class PackbitsDecoder extends BaseDecoder {
11588
+ /** @param {ArrayBuffer} buffer */
11002
11589
  decodeBlock(buffer) {
11003
11590
  const dataView = new DataView(buffer);
11004
11591
  const out = [];
@@ -13446,23 +14033,33 @@ let ZSTDDecoder$1 = class ZSTDDecoder {
13446
14033
  // wasm:begin
13447
14034
  const wasm$1 = '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AikACDcACCAHIDo3AAAgEUEZSA0BIARBGGohBANAIAIpABAhOiAEIAIpABg3AAggBCA6NwAAIAIpACAhOiAEIAIpACg3ABggBCA6NwAQIAJBIGohAiAEQSBqIgQgCkkNAAsMAQsCQAJAIAUoAswCIhEgBUHgAWogJUEHcUEMbGoiDygCACICaiIHIBxLDQAgCSAPKAIEIgogAmoiBmogG0sNACAGQSBqIBQgCWtNDQELIAUgDygCCDYCoAEgBSAPKQIANwOYASAJIBQgBUGYAWogBUHMAmogHCALIBcgIhAgIQYMAQsgAiAJaiEEIA8oAgghFSARKQAAITogCSARKQAINwAIIAkgOjcAAAJAIAJBEUkNACARKQAQITogCSARKQAYNwAYIAkgOjcAECACQRBrQRFIDQAgEUEQaiECIAlBIGohEgNAIAIpABAhOiASIAIpABg3AAggEiA6NwAAIAIpACAhOiASIAIpACg3ABggEiA6NwAQIAJBIGohAiASQSBqIhIgBEkNAAsLIAQgFWshAiAFIAc2AswCIAQgC2sgFUkEQCAVIAQgF2tLDQwgIiAiIAIgC2siD2oiByAKak8EQCAKRQ0CIAQgByAK/AoAAAwCC0EAIA9rIgIEQCAEIAcgAvwKAAALIAogD2ohCiAEIA9rIQQgCyECCyAVQRBPBEAgAikAACE6IAQgAikACDcACCAEIDo3AAAgCkERSA0BIAQgCmohByAEQRBqIQQDQCACKQAQITogBCACKQAYNwAIIAQgOjcAACACKQAgITogBCACKQAoNwAYIAQgOjcAECACQSBqIQIgBEEgaiIEIAdJDQALDAELAkAgFUEHTQRAIAQgAi0AADoAACAEIAItAAE6AAEgBCACLQACOgACIAQgAi0AAzoAAyAEIAIgFUECdCIHQeAaaigCAGoiAigAADYABCACIAdBgBtqKAIAayECDAELIAQgAikAADcAAAsgCkEJSQ0AIAQgCmohDyAEQQhqIgcgAkEIaiICa0EPTARAA0AgByACKQAANwAAIAJBCGohAiAHQQhqIgcgD0kNAAwCCwALIAIpAAAhOiAHIAIpAAg3AAggByA6NwAAIApBGUgNACAEQRhqIQQDQCACKQAQITogBCACKQAYNwAIIAQgOjcAACACKQAgITogBCACKQAoNwAYIAQgOjcAECACQSBqIQIgBEEgaiIEIA9JDQALCyAGQYh/SwRAIAYhAwwLCyAFQeABaiAlQQdxQQxsaiICIA02AgggAiAMNgIEIAIgEDYCAAsgBiAJaiEJICVBAWohJSAQIC1qIAxqIS0MAQsLIAUoArABIAUoArQBRw0HIAUoAqwBQSBHDQcgDiAoayEQA0ACQCAOIBBMBEBBACECA0AgAkEDRg0CIDIgAkECdCIDaiADICZqKAIANgIAIAJBAWohAgwACwALIAVB4AFqIBBBB3FBDGxqIQoCfwJAIAgoAoTsAUECRgRAIAUoAswCIg8gCigCACIEaiIHIAgoAoDsASICSwRAIAIgD0cEQCACIA9rIgIgFCAJa0sNCyAJIA8gAhAfIAogBCACayIENgIAIAIgCWohCQsgBSAWNgLMAiAIQQA2AoTsAQJAAkACQCAEQYCABEoNACAJIAooAgQiDSAEaiIGaiAbSw0AIAZBIGogFCAJa00NAQsgBSAKKAIINgJQIAUgCikCADcDSCAJIBQgBUHIAGogBUHMAmogGSALIBcgIhAgIQYMAQsgBCAWaiEHIAQgCWohDCAKKAIIIQogFikAACE6IAkgFikACDcACCAJIDo3AAACQCAEQRFJDQAgHikAACE6IAkgHikACDcAGCAJIDo3ABAgBEEQa0ERSA0AIAlBIGohAiAeIQQDQCAEKQAQITogAiAEKQAYNwAIIAIgOjcAACAEKQAgITogAiAEKQAoNwAYIAIgOjcAECAEQSBqIQQgAkEgaiICIAxJDQALCyAMIAprIQIgBSAHNgLMAiAMIAtrIApJBEAgCiAMIBdrSw0PICIgIiACIAtrIgdqIgQgDWpPBEAgDUUNAiAMIAQgDfwKAAAMAgtBACAHayICBEAgDCAEIAL8CgAACyAHIA1qIQ0gDCAHayEMIAshAgsgCkEQTwRAIAIpAAAhOiAMIAIpAAg3AAggDCA6NwAAIA1BEUgNASAMIA1qIQcgDEEQaiEEA0AgAikAECE6IAQgAikAGDcACCAEIDo3AAAgAikAICE6IAQgAikAKDcAGCAEIDo3ABAgAkEgaiECIARBIGoiBCAHSQ0ACwwBCwJAIApBB00EQCAMIAItAAA6AAAgDCACLQABOgABIAwgAi0AAjoAAiAMIAItAAM6AAMgDCACIApBAnQiBEHgGmooAgBqIgIoAAA2AAQgAiAEQYAbaigCAGshAgwBCyAMIAIpAAA3AAALIA1BCUkNACAMIA1qIQcgDEEIaiIEIAJBCGoiAmtBD0wEQANAIAQgAikAADcAACACQQhqIQIgBEEIaiIEIAdJDQAMAgsACyACKQAAITogBCACKQAINwAIIAQgOjcAACANQRlIDQAgDEEYaiEEA0AgAikAECE6IAQgAikAGDcACCAEIDo3AAAgAikAICE6IAQgAikAKDcAGCAEIDo3ABAgAkEgaiECIARBIGoiBCAHSQ0ACwsgBkGJf08EQCAGIQMMDgsgGSEcIAYgCWoMAwsgB0EgayECAkACQCAHIBxLDQAgCSAKKAIEIhIgBGoiDGogAksNACAMQSBqIBQgCWtNDQELIAUgCigCCDYCYCAFIAopAgA3A1ggCSAUIAIgBUHYAGogBUHMAmogHCALIBcgIhAhIQwMAgsgBCAJaiEGIAooAgghCiAPKQAAITogCSAPKQAINwAIIAkgOjcAAAJAIARBEUkNACAPKQAQITogCSAPKQAYNwAYIAkgOjcAECAEQRBrQRFIDQAgD0EQaiECIAlBIGohBANAIAIpABAhOiAEIAIpABg3AAggBCA6NwAAIAIpACAhOiAEIAIpACg3ABggBCA6NwAQIAJBIGohAiAEQSBqIgQgBkkNAAsLIAYgCmshAiAFIAc2AswCIAYgC2sgCkkEQCAKIAYgF2tLDQ0gIiAiIAIgC2siB2oiBCASak8EQCASRQ0DIAYgBCAS/AoAAAwDC0EAIAdrIgIEQCAGIAQgAvwKAAALIAcgEmohEiAGIAdrIQYgCyECCyAKQRBPBEAgAikAACE6IAYgAikACDcACCAGIDo3AAAgEkERSA0CIAYgEmohByAGQRBqIQQDQCACKQAQITogBCACKQAYNwAIIAQgOjcAACACKQAgITogBCACKQAoNwAYIAQgOjcAECACQSBqIQIgBEEgaiIEIAdJDQALDAILAkAgCkEHTQRAIAYgAi0AADoAACAGIAItAAE6AAEgBiACLQACOgACIAYgAi0AAzoAAyAGIAIgCkECdCIEQeAaaigCAGoiAigAADYABCACIARBgBtqKAIAayECDAELIAYgAikAADcAAAsgEkEJSQ0BIAYgEmohByAGQQhqIgQgAkEIaiICa0EPTARAA0AgBCACKQAANwAAIAJBCGohAiAE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';
13448
14035
 
14036
+ /**
14037
+ * @typedef {import('./basedecoder.js').BaseDecoderParameters & { LercParameters?: any }} LercDecoderParameters
14038
+ */
13449
14039
  const zstd$2 = new ZSTDDecoder$1();
13450
14040
  class LercDecoder extends BaseDecoder {
14041
+ /**
14042
+ * @param {ArrayBufferLike} buffer
14043
+ * @returns {ArrayBufferLike}
14044
+ */
13451
14045
  decodeBlock(buffer) {
13452
- const addCompression = this.parameters.LercParameters[LercParameters.AddCompression];
14046
+ const params = /** @type {LercDecoderParameters} */ (this.parameters);
14047
+ const addCompression = params.LercParameters?.[LercParameters.AddCompression];
14048
+ /** @type {ArrayBufferLike} */
14049
+ let decoded = buffer;
13453
14050
  switch (addCompression) {
13454
14051
  case LercAddCompression.None:
13455
14052
  break;
13456
14053
  case LercAddCompression.Deflate:
13457
- buffer = inflate_1(new Uint8Array(buffer)).buffer; // eslint-disable-line no-param-reassign, prefer-destructuring
14054
+ decoded = inflate_1(new Uint8Array(decoded)).buffer;
13458
14055
  break;
13459
14056
  case LercAddCompression.Zstandard:
13460
- buffer = zstd$2.decode(new Uint8Array(buffer)).buffer; // eslint-disable-line no-param-reassign, prefer-destructuring
14057
+ decoded = zstd$2.decode(new Uint8Array(decoded)).buffer;
13461
14058
  break;
13462
14059
  default:
13463
14060
  throw new Error(`Unsupported LERC additional compression method identifier: ${addCompression}`);
13464
14061
  }
13465
- const lercResult = Lerc.decode(buffer, { returnPixelInterleavedDims: this.parameters.planarConfiguration === 1 });
14062
+ const lercResult = Lerc.decode(decoded, { returnPixelInterleavedDims: this.parameters.planarConfiguration === 1 });
13466
14063
  const lercData = lercResult.pixels[0];
13467
14064
  return lercData.buffer;
13468
14065
  }
@@ -13638,8 +14235,9 @@ const wasm = 'AGFzbQEAAAABpgEVYAF/AGADf39/AX9gA39/fwBgAX8Bf2AFf39/f38Bf2ACf38AYA
13638
14235
 
13639
14236
  const zstd = new ZSTDDecoder();
13640
14237
  class ZstdDecoder extends BaseDecoder {
14238
+ /** @param {ArrayBuffer} buffer */
13641
14239
  decodeBlock(buffer) {
13642
- return zstd.decode(new Uint8Array(buffer)).buffer;
14240
+ return /** @type {ArrayBuffer} */ (zstd.decode(new Uint8Array(buffer)).buffer);
13643
14241
  }
13644
14242
  }
13645
14243
 
@@ -13656,6 +14254,9 @@ var zstd$1 = /*#__PURE__*/Object.freeze({
13656
14254
  * formats like WebP when supported.
13657
14255
  */
13658
14256
  class WebImageDecoder extends BaseDecoder {
14257
+ /**
14258
+ * @param {import('./basedecoder.js').BaseDecoderParameters} parameters
14259
+ */
13659
14260
  constructor(parameters) {
13660
14261
  super(parameters);
13661
14262
  if (typeof createImageBitmap === 'undefined') {
@@ -13665,6 +14266,7 @@ class WebImageDecoder extends BaseDecoder {
13665
14266
  throw new Error('Cannot decode WebImage as neither `document` nor `OffscreenCanvas` is not available');
13666
14267
  }
13667
14268
  }
14269
+ /** @param {ArrayBuffer} buffer */
13668
14270
  async decodeBlock(buffer) {
13669
14271
  const blob = new Blob([buffer]);
13670
14272
  const imageBitmap = await createImageBitmap(blob);