geotiff
Version:
GeoTIFF image decoding in JavaScript
421 lines • 17.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.geoKeys = exports.geoKeyNames = exports.LercAddCompression = exports.LercParameters = exports.ExtraSamplesValues = exports.photometricInterpretations = exports.fieldTagTypes = exports.tagDefinitions = exports.tags = exports.tagDictionary = exports.fieldTypeSizes = exports.fieldTypes = void 0;
exports.getFieldTypeSize = getFieldTypeSize;
exports.registerTag = registerTag;
exports.resolveTag = resolveTag;
exports.getTag = getTag;
/** @import {TypedArray} from './geotiff.js' */
exports.fieldTypes = {
BYTE: /** @type {1} */ (0x0001),
ASCII: /** @type {2} */ (0x0002),
SHORT: /** @type {3} */ (0x0003),
LONG: /** @type {4} */ (0x0004),
RATIONAL: /** @type {5} */ (0x0005),
SBYTE: /** @type {6} */ (0x0006),
UNDEFINED: /** @type {7} */ (0x0007),
SSHORT: /** @type {8} */ (0x0008),
SLONG: /** @type {9} */ (0x0009),
SRATIONAL: /** @type {10} */ (0x000a),
FLOAT: /** @type {11} */ (0x000b),
DOUBLE: /** @type {12} */ (0x000c),
// IFD offset, suggested by https://owl.phy.queensu.ca/~phil/exiftool/standards.html
IFD: /** @type {13} */ (0x000d),
// introduced by BigTIFF
LONG8: /** @type {16} */ (0x0010),
SLONG8: /** @type {17} */ (0x0011),
IFD8: /** @type {18} */ (0x0012),
};
/** @typedef {keyof fieldTypes} FieldTypeName */
/** @typedef {fieldTypes[keyof typeof fieldTypes]} FieldType */
/** @typedef {Record<FieldTypeName, number>} FieldTypeSizes */
exports.fieldTypeSizes = ({
[exports.fieldTypes.BYTE]: 1,
[exports.fieldTypes.ASCII]: 1,
[exports.fieldTypes.SBYTE]: 1,
[exports.fieldTypes.UNDEFINED]: 1,
[exports.fieldTypes.SHORT]: 2,
[exports.fieldTypes.SSHORT]: 2,
[exports.fieldTypes.LONG]: 4,
[exports.fieldTypes.SLONG]: 4,
[exports.fieldTypes.FLOAT]: 4,
[exports.fieldTypes.IFD]: 4,
[exports.fieldTypes.RATIONAL]: 8,
[exports.fieldTypes.SRATIONAL]: 8,
[exports.fieldTypes.DOUBLE]: 8,
[exports.fieldTypes.LONG8]: 8,
[exports.fieldTypes.SLONG8]: 8,
[exports.fieldTypes.IFD8]: 8,
});
/** @typedef {fieldTypeSizes[keyof typeof fieldTypeSizes]} FieldTypeSize */
/**
* Get the byte size for a given field type.
* @param {FieldType} fieldType The TIFF field type constant
* @returns {number} The size in bytes
* @throws {RangeError} If the field type is invalid
*/
function getFieldTypeSize(fieldType) {
const size = exports.fieldTypeSizes[fieldType];
if (size === undefined) {
throw new RangeError(`Invalid field type: ${fieldType}`);
}
return size;
}
/**
* @typedef {Object} TagDictionaryEntry
* @property {number} tag
* @property {string} [name]
* @property {number} [type]
* @property {boolean} [isArray]
* @property {boolean} [eager]
*/
exports.tagDictionary = ({
NewSubfileType: { tag: 254, type: exports.fieldTypes.LONG, eager: true },
SubfileType: { tag: 255, type: exports.fieldTypes.SHORT, eager: true },
ImageWidth: { tag: 256, type: exports.fieldTypes.SHORT, eager: true },
ImageLength: { tag: 257, type: exports.fieldTypes.SHORT, eager: true },
BitsPerSample: { tag: 258, type: exports.fieldTypes.SHORT, isArray: true, eager: true },
Compression: { tag: 259, type: exports.fieldTypes.SHORT, eager: true },
PhotometricInterpretation: { tag: 262, type: exports.fieldTypes.SHORT, eager: true },
Threshholding: { tag: 263, type: exports.fieldTypes.SHORT },
CellWidth: { tag: 264, type: exports.fieldTypes.SHORT },
CellLength: { tag: 265, type: exports.fieldTypes.SHORT },
FillOrder: { tag: 266, type: exports.fieldTypes.SHORT },
DocumentName: { tag: 269, type: exports.fieldTypes.ASCII },
ImageDescription: { tag: 270, type: exports.fieldTypes.ASCII },
Make: { tag: 271, type: exports.fieldTypes.ASCII },
Model: { tag: 272, type: exports.fieldTypes.ASCII },
StripOffsets: { tag: 273, type: exports.fieldTypes.SHORT, isArray: true },
Orientation: { tag: 274, type: exports.fieldTypes.SHORT },
SamplesPerPixel: { tag: 277, type: exports.fieldTypes.SHORT, eager: true },
RowsPerStrip: { tag: 278, type: exports.fieldTypes.SHORT, eager: true },
StripByteCounts: { tag: 279, type: exports.fieldTypes.LONG, isArray: true },
MinSampleValue: { tag: 280, type: exports.fieldTypes.SHORT, isArray: true },
MaxSampleValue: { tag: 281, type: exports.fieldTypes.SHORT, isArray: true },
XResolution: { tag: 282, type: exports.fieldTypes.RATIONAL },
YResolution: { tag: 283, type: exports.fieldTypes.RATIONAL },
PlanarConfiguration: { tag: 284, type: exports.fieldTypes.SHORT, eager: true },
PageName: { tag: 285, type: exports.fieldTypes.ASCII },
XPosition: { tag: 286, type: exports.fieldTypes.RATIONAL },
YPosition: { tag: 287, type: exports.fieldTypes.RATIONAL },
FreeOffsets: { tag: 288, type: exports.fieldTypes.LONG },
FreeByteCounts: { tag: 289, type: exports.fieldTypes.LONG },
GrayResponseUnit: { tag: 290, type: exports.fieldTypes.SHORT },
GrayResponseCurve: { tag: 291, type: exports.fieldTypes.SHORT, isArray: true },
T4Options: { tag: 292, type: exports.fieldTypes.LONG },
T6Options: { tag: 293, type: exports.fieldTypes.LONG },
ResolutionUnit: { tag: 296, type: exports.fieldTypes.SHORT },
PageNumber: { tag: 297, type: exports.fieldTypes.SHORT, isArray: true },
TransferFunction: { tag: 301, type: exports.fieldTypes.SHORT, isArray: true },
Software: { tag: 305, type: exports.fieldTypes.ASCII },
DateTime: { tag: 306, type: exports.fieldTypes.ASCII },
Artist: { tag: 315, type: exports.fieldTypes.ASCII },
HostComputer: { tag: 316, type: exports.fieldTypes.ASCII },
Predictor: { tag: 317, type: exports.fieldTypes.SHORT },
WhitePoint: { tag: 318, type: exports.fieldTypes.RATIONAL, isArray: true },
PrimaryChromaticities: { tag: 319, type: exports.fieldTypes.RATIONAL, isArray: true },
ColorMap: { tag: 320, type: exports.fieldTypes.SHORT, isArray: true },
HalftoneHints: { tag: 321, type: exports.fieldTypes.SHORT, isArray: true },
TileWidth: { tag: 322, type: exports.fieldTypes.SHORT, eager: true },
TileLength: { tag: 323, type: exports.fieldTypes.SHORT, eager: true },
TileOffsets: { tag: 324, type: exports.fieldTypes.LONG, isArray: true },
TileByteCounts: { tag: 325, type: exports.fieldTypes.SHORT, isArray: true },
InkSet: { tag: 332, type: exports.fieldTypes.SHORT },
InkNames: { tag: 333, type: exports.fieldTypes.ASCII },
NumberOfInks: { tag: 334, type: exports.fieldTypes.SHORT },
DotRange: { tag: 336, type: exports.fieldTypes.BYTE, isArray: true },
TargetPrinter: { tag: 337, type: exports.fieldTypes.ASCII },
ExtraSamples: { tag: 338, type: exports.fieldTypes.BYTE, isArray: true, eager: true },
SampleFormat: { tag: 339, type: exports.fieldTypes.SHORT, isArray: true, eager: true },
SMinSampleValue: { tag: 340, isArray: true },
SMaxSampleValue: { tag: 341, isArray: true },
TransferRange: { tag: 342, type: exports.fieldTypes.SHORT, isArray: true },
JPEGProc: { tag: 512, type: exports.fieldTypes.SHORT },
JPEGInterchangeFormat: { tag: 513, type: exports.fieldTypes.LONG },
JPEGInterchangeFormatLngth: { tag: 514, type: exports.fieldTypes.LONG },
JPEGRestartInterval: { tag: 515, type: exports.fieldTypes.SHORT },
JPEGLosslessPredictors: { tag: 517, type: exports.fieldTypes.SHORT, isArray: true },
JPEGPointTransforms: { tag: 518, type: exports.fieldTypes.SHORT, isArray: true },
JPEGQTables: { tag: 519, type: exports.fieldTypes.LONG, isArray: true },
JPEGDCTables: { tag: 520, type: exports.fieldTypes.LONG, isArray: true },
JPEGACTables: { tag: 521, type: exports.fieldTypes.LONG, isArray: true },
YCbCrCoefficients: { tag: 529, type: exports.fieldTypes.RATIONAL, isArray: true },
YCbCrSubSampling: { tag: 530, type: exports.fieldTypes.SHORT, isArray: true },
YCbCrPositioning: { tag: 531, type: exports.fieldTypes.SHORT },
ReferenceBlackWhite: { tag: 532, type: exports.fieldTypes.LONG, isArray: true },
Copyright: { tag: 33432, type: exports.fieldTypes.ASCII },
BadFaxLines: { tag: 326 },
CleanFaxData: { tag: 327 },
ClipPath: { tag: 343 },
ConsecutiveBadFaxLines: { tag: 328 },
Decode: { tag: 433 },
DefaultImageColor: { tag: 434 },
Indexed: { tag: 346 },
JPEGTables: { tag: 347, isArray: true, eager: true },
StripRowCounts: { tag: 559, isArray: true },
SubIFDs: { tag: 330, isArray: true },
XClipPathUnits: { tag: 344 },
YClipPathUnits: { tag: 345 },
ApertureValue: { tag: 37378 },
ColorSpace: { tag: 40961 },
DateTimeDigitized: { tag: 36868 },
DateTimeOriginal: { tag: 36867 },
ExifIFD: { tag: 34665, name: 'Exif IFD', type: exports.fieldTypes.LONG },
ExifVersion: { tag: 36864 },
ExposureTime: { tag: 33434 },
FileSource: { tag: 41728 },
Flash: { tag: 37385 },
FlashpixVersion: { tag: 40960 },
FNumber: { tag: 33437 },
ImageUniqueID: { tag: 42016 },
LightSource: { tag: 37384 },
MakerNote: { tag: 37500 },
ShutterSpeedValue: { tag: 37377 },
UserComment: { tag: 37510 },
IPTC: { tag: 33723 },
CZ_LSMINFO: { tag: 34412 },
ICCProfile: { tag: 34675, name: 'ICC Profile' },
XMP: { tag: 700 },
GDAL_METADATA: { tag: 42112 },
GDAL_NODATA: { tag: 42113, type: exports.fieldTypes.ASCII, eager: true },
Photoshop: { tag: 34377 },
ModelPixelScale: { tag: 33550, type: exports.fieldTypes.DOUBLE, isArray: true, eager: true },
ModelTiepoint: { tag: 33922, type: exports.fieldTypes.DOUBLE, isArray: true, eager: true },
ModelTransformation: { tag: 34264, type: exports.fieldTypes.DOUBLE, isArray: true, eager: true },
GeoKeyDirectory: { tag: 34735, type: exports.fieldTypes.SHORT, isArray: true, eager: true },
GeoDoubleParams: { tag: 34736, type: exports.fieldTypes.DOUBLE, isArray: true, eager: true },
GeoAsciiParams: { tag: 34737, type: exports.fieldTypes.ASCII, eager: true },
LercParameters: { tag: 50674, eager: true },
});
/** @typedef {keyof typeof tagDictionary} TagName */
/** @typedef {typeof tagDictionary[keyof typeof tagDictionary]['tag']} Tag */
/**
* @typedef {Extract<keyof typeof tagDictionary,
* { [K in keyof typeof tagDictionary]: (typeof tagDictionary)[K] extends { eager: true }
* ? K : never }[keyof typeof tagDictionary]>} EagerTagName
*/
/**
* @typedef {Extract<Tag, { [K in keyof typeof tagDictionary]: (typeof tagDictionary)[K] extends { eager: true }
* ? (typeof tagDictionary)[K]['tag'] : never }[keyof typeof tagDictionary]>} EagerTag
*/
/** @typedef {Extract<typeof tagDictionary[keyof typeof tagDictionary], {type: any}>['type']} TagType */
/**
* @template {number} T
* @typedef {T extends 2 ? string : number} GeoTiffPrimitive
*/
/**
* @template {TagName} T
* @typedef {typeof tagDictionary[T]} TagDef
*/
/**
* @typedef {{
* 1: number;
* 2: string;
* 3: number;
* 4: number;
* 5: number;
* 6: number;
* 7: ArrayBuffer;
* 8: number;
* 9: number;
* 10: number;
* 11: number;
* 12: number;
* 16: number;
* 17: number;
* 18: number;
* }} FieldTypeMap
*/
/**
* @template {TagName} T
* @typedef {TagDef<T> extends { isArray: true }
* ? (TagDef<T> extends { type: typeof fieldTypes.DOUBLE } ? number[] :
* TagDef<T> extends { type: typeof fieldTypes.ASCII } ? string[] :
* TagDef<T> extends { type: typeof fieldTypes.BYTE | typeof fieldTypes.SBYTE | typeof fieldTypes.UNDEFINED }
* ? Uint8Array | Int8Array :
* (number[] | TypedArray))
* : (TagDef<T> extends { type: keyof FieldTypeMap } ? FieldTypeMap[TagDef<T>['type']] : any)} TagValue
*/
/**
* Maps tag names to their numeric values
* @type {Record<string, number>}
*/
exports.tags = {};
/**
* Maps tag numbers to their definitions
* @type {Record<number, { tag: number, name: string, type: string|number|undefined, isArray: boolean, eager: boolean }>}
*/
exports.tagDefinitions = {};
/**
* Registers a new field tag
* @param {number} tag the numeric tiff tag
* @param {string} name the name of the tag that will be reported in the IFD
* @param {keyof fieldTypes|number|undefined} type the tags data type
* @param {Boolean} isArray whether the tag is an array
* @param {boolean} [eager=false] whether to eagerly fetch deferred fields.
* When false (default), tags are loaded lazily on-demand.
* When true, all tags are loaded immediately during parsing.
*/
function registerTag(tag, name, type, isArray = false, eager = false) {
exports.tags[name] = tag;
exports.tagDefinitions[tag] = { tag, name, type: typeof type === 'string' ? exports.fieldTypes[type] : type, isArray, eager };
}
for (const [key, value] of Object.entries(exports.tagDictionary)) {
const entry = /** @type {TagDictionaryEntry} */ (value);
registerTag(entry.tag, entry.name || key, entry.type, entry.isArray, entry.eager);
}
/**
* @param {number|string} tagIdentifier The field tag ID or name
* @returns {number} the resolved tag ID
*/
function resolveTag(tagIdentifier) {
if (typeof tagIdentifier === 'number') {
return tagIdentifier;
}
return exports.tags[tagIdentifier];
}
/**
* @param {number|string} tagIdentifier The field tag ID or name
* @returns {{ tag: number, name: string, type: string|number|undefined, isArray: boolean, eager: boolean }} the tag definition
*/
function getTag(tagIdentifier) {
return exports.tagDefinitions[resolveTag(tagIdentifier)];
}
exports.fieldTagTypes = {
256: 'SHORT',
257: 'SHORT',
258: 'SHORT',
259: 'SHORT',
262: 'SHORT',
270: 'ASCII',
271: 'ASCII',
272: 'ASCII',
273: 'LONG',
274: 'SHORT',
277: 'SHORT',
278: 'LONG',
279: 'LONG',
282: 'RATIONAL',
283: 'RATIONAL',
284: 'SHORT',
286: 'SHORT',
287: 'RATIONAL',
296: 'SHORT',
297: 'SHORT',
305: 'ASCII',
306: 'ASCII',
315: 'ASCII',
338: 'SHORT',
339: 'SHORT',
513: 'LONG',
514: 'LONG',
1024: 'SHORT',
1025: 'SHORT',
1026: 'ASCII',
2048: 'SHORT',
2049: 'ASCII',
2052: 'SHORT',
2054: 'SHORT',
2057: 'DOUBLE',
2059: 'DOUBLE',
2060: 'SHORT',
3072: 'SHORT',
3073: 'ASCII',
3076: 'SHORT',
4096: 'SHORT',
4097: 'ASCII',
4099: 'SHORT',
33432: 'ASCII',
33550: 'DOUBLE',
33922: 'DOUBLE',
34264: 'DOUBLE',
34665: 'LONG',
34735: 'SHORT',
34736: 'DOUBLE',
34737: 'ASCII',
42113: 'ASCII',
};
exports.photometricInterpretations = {
WhiteIsZero: 0,
BlackIsZero: 1,
RGB: 2,
Palette: 3,
TransparencyMask: 4,
CMYK: 5,
YCbCr: 6,
CIELab: 8,
ICCLab: 9,
};
exports.ExtraSamplesValues = {
Unspecified: 0,
Assocalpha: 1,
Unassalpha: 2,
};
exports.LercParameters = {
Version: 0,
AddCompression: 1,
};
exports.LercAddCompression = {
None: 0,
Deflate: 1,
Zstandard: 2,
};
exports.geoKeyNames = ({
1024: 'GTModelTypeGeoKey',
1025: 'GTRasterTypeGeoKey',
1026: 'GTCitationGeoKey',
2048: 'GeographicTypeGeoKey',
2049: 'GeogCitationGeoKey',
2050: 'GeogGeodeticDatumGeoKey',
2051: 'GeogPrimeMeridianGeoKey',
2052: 'GeogLinearUnitsGeoKey',
2053: 'GeogLinearUnitSizeGeoKey',
2054: 'GeogAngularUnitsGeoKey',
2055: 'GeogAngularUnitSizeGeoKey',
2056: 'GeogEllipsoidGeoKey',
2057: 'GeogSemiMajorAxisGeoKey',
2058: 'GeogSemiMinorAxisGeoKey',
2059: 'GeogInvFlatteningGeoKey',
2060: 'GeogAzimuthUnitsGeoKey',
2061: 'GeogPrimeMeridianLongGeoKey',
2062: 'GeogTOWGS84GeoKey',
3072: 'ProjectedCSTypeGeoKey',
3073: 'PCSCitationGeoKey',
3074: 'ProjectionGeoKey',
3075: 'ProjCoordTransGeoKey',
3076: 'ProjLinearUnitsGeoKey',
3077: 'ProjLinearUnitSizeGeoKey',
3078: 'ProjStdParallel1GeoKey',
3079: 'ProjStdParallel2GeoKey',
3080: 'ProjNatOriginLongGeoKey',
3081: 'ProjNatOriginLatGeoKey',
3082: 'ProjFalseEastingGeoKey',
3083: 'ProjFalseNorthingGeoKey',
3084: 'ProjFalseOriginLongGeoKey',
3085: 'ProjFalseOriginLatGeoKey',
3086: 'ProjFalseOriginEastingGeoKey',
3087: 'ProjFalseOriginNorthingGeoKey',
3088: 'ProjCenterLongGeoKey',
3089: 'ProjCenterLatGeoKey',
3090: 'ProjCenterEastingGeoKey',
3091: 'ProjCenterNorthingGeoKey',
3092: 'ProjScaleAtNatOriginGeoKey',
3093: 'ProjScaleAtCenterGeoKey',
3094: 'ProjAzimuthAngleGeoKey',
3095: 'ProjStraightVertPoleLongGeoKey',
3096: 'ProjRectifiedGridAngleGeoKey',
4096: 'VerticalCSTypeGeoKey',
4097: 'VerticalCitationGeoKey',
4098: 'VerticalDatumGeoKey',
4099: 'VerticalUnitsGeoKey',
});
/** @typedef {geoKeyNames[keyof typeof geoKeyNames]} GeoKeyName */
/**
* @type {Record<GeoKeyName, number>}
*/
exports.geoKeys = ({});
for (const [key, name] of Object.entries(exports.geoKeyNames)) {
exports.geoKeys[ /** @type {GeoKeyName} */(name)] = parseInt(key, 10);
}
//# sourceMappingURL=globals.js.map
//# sourceMappingURL=globals.js.map