(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= this.fileDirectory.BitsPerSample.length) { throw new RangeError("Sample index " + i + " is out of range."); } var bits = this.fileDirectory.BitsPerSample[i]; if (bits % 8 !== 0) { throw new Error("Sample bit-width of " + bits + " is not supported."); } return bits / 8; }, getReaderForSample: function getReaderForSample(sampleIndex) { var format = this.fileDirectory.SampleFormat[sampleIndex]; var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex]; switch (format) { case 1: // unsigned integer data switch (bitsPerSample) { case 8: return DataView.prototype.getUint8; case 16: return DataView.prototype.getUint16; case 32: return DataView.prototype.getUint32; } break; case 2: // twos complement signed integer data switch (bitsPerSample) { case 8: return DataView.prototype.getInt8; case 16: return DataView.prototype.getInt16; case 32: return DataView.prototype.getInt32; } break; case 3: switch (bitsPerSample) { case 32: return DataView.prototype.getFloat32; case 64: return DataView.prototype.getFloat64; } break; } }, getArrayForSample: function getArrayForSample(sampleIndex, size) { var format = this.fileDirectory.SampleFormat[sampleIndex]; var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex]; return arrayForType(format, bitsPerSample, size); }, getDecoder: function getDecoder() { return this.decoder; }, /** * Returns the decoded strip or tile. * @param {Number} x the strip or tile x-offset * @param {Number} y the tile y-offset (0 for stripped images) * @param {Number} plane the planar configuration (1: "chunky", 2: "separate samples") * @returns {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array)} */ getTileOrStrip: function getTileOrStrip(x, y, sample, callback) { var numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth()); var numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight()); var index; var tiles = this.tiles; if (this.planarConfiguration === 1) { index = y * numTilesPerRow + x; } else if (this.planarConfiguration === 2) { index = sample * numTilesPerRow * numTilesPerCol + y * numTilesPerRow + x; } if (tiles !== null && index in tiles) { if (callback) { return callback(null, { x: x, y: y, sample: sample, data: tiles[index] }); } return tiles[index]; } else { var offset, byteCount; if (this.isTiled) { offset = this.fileDirectory.TileOffsets[index]; byteCount = this.fileDirectory.TileByteCounts[index]; } else { offset = this.fileDirectory.StripOffsets[index]; byteCount = this.fileDirectory.StripByteCounts[index]; } var slice = this.dataView.buffer.slice(offset, offset + byteCount); if (callback) { return this.getDecoder().decodeBlockAsync(slice, function (error, data) { if (!error && tiles !== null) { tiles[index] = data; } callback(error, { x: x, y: y, sample: sample, data: data }); }); } var block = this.getDecoder().decodeBlock(slice); if (tiles !== null) { tiles[index] = block; } return block; } }, _readRasterAsync: function _readRasterAsync(imageWindow, samples, valueArrays, interleave, callback, callbackError) { var tileWidth = this.getTileWidth(); var tileHeight = this.getTileHeight(); var minXTile = Math.floor(imageWindow[0] / tileWidth); var maxXTile = Math.ceil(imageWindow[2] / tileWidth); var minYTile = Math.floor(imageWindow[1] / tileHeight); var maxYTile = Math.ceil(imageWindow[3] / tileHeight); var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth); var windowWidth = imageWindow[2] - imageWindow[0]; var windowHeight = imageWindow[3] - imageWindow[1]; var bytesPerPixel = this.getBytesPerPixel(); var imageWidth = this.getWidth(); var srcSampleOffsets = []; var sampleReaders = []; for (var i = 0; i < samples.length; ++i) { if (this.planarConfiguration === 1) { srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8); } else { srcSampleOffsets.push(0); } sampleReaders.push(this.getReaderForSample(samples[i])); } var allStacked = false; var unfinishedTiles = 0; var littleEndian = this.littleEndian; var globalError = null; function onTileGot(error, tile) { if (!error) { var dataView = new DataView(tile.data); var firstLine = tile.y * tileHeight; var firstCol = tile.x * tileWidth; var lastLine = (tile.y + 1) * tileHeight; var lastCol = (tile.x + 1) * tileWidth; var sampleIndex = tile.sample; for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) { for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) { var pixelOffset = (y * tileWidth + x) * bytesPerPixel; var value = sampleReaders[_sampleIndex].call(dataView, pixelOffset + srcSampleOffsets[_sampleIndex], littleEndian); var windowCoordinate; if (interleave) { windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth * samples.length + (x + firstCol - imageWindow[0]) * samples.length + _sampleIndex; valueArrays[windowCoordinate] = value; } else { windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth + x + firstCol - imageWindow[0]; valueArrays[_sampleIndex][windowCoordinate] = value; } } } } else { globalError = error; } // check end condition and call callbacks unfinishedTiles -= 1; checkFinished(); } function checkFinished() { if (allStacked && unfinishedTiles === 0) { if (globalError) { callbackError(globalError); } else { callback(valueArrays); } } } for (var yTile = minYTile; yTile <= maxYTile; ++yTile) { for (var xTile = minXTile; xTile <= maxXTile; ++xTile) { for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) { var sample = samples[sampleIndex]; if (this.planarConfiguration === 2) { bytesPerPixel = this.getSampleByteSize(sample); } var _sampleIndex = sampleIndex; unfinishedTiles += 1; this.getTileOrStrip(xTile, yTile, sample, onTileGot); } } } allStacked = true; checkFinished(); }, _readRaster: function _readRaster(imageWindow, samples, valueArrays, interleave, callback, callbackError) { try { var tileWidth = this.getTileWidth(); var tileHeight = this.getTileHeight(); var minXTile = Math.floor(imageWindow[0] / tileWidth); var maxXTile = Math.ceil(imageWindow[2] / tileWidth); var minYTile = Math.floor(imageWindow[1] / tileHeight); var maxYTile = Math.ceil(imageWindow[3] / tileHeight); var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth); var windowWidth = imageWindow[2] - imageWindow[0]; var windowHeight = imageWindow[3] - imageWindow[1]; var bytesPerPixel = this.getBytesPerPixel(); var imageWidth = this.getWidth(); var srcSampleOffsets = []; var sampleReaders = []; for (var i = 0; i < samples.length; ++i) { if (this.planarConfiguration === 1) { srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8); } else { srcSampleOffsets.push(0); } sampleReaders.push(this.getReaderForSample(samples[i])); } for (var yTile = minYTile; yTile < maxYTile; ++yTile) { for (var xTile = minXTile; xTile < maxXTile; ++xTile) { var firstLine = yTile * tileHeight; var firstCol = xTile * tileWidth; var lastLine = (yTile + 1) * tileHeight; var lastCol = (xTile + 1) * tileWidth; for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) { var sample = samples[sampleIndex]; if (this.planarConfiguration === 2) { bytesPerPixel = this.getSampleByteSize(sample); } var tile = new DataView(this.getTileOrStrip(xTile, yTile, sample)); for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) { for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) { var pixelOffset = (y * tileWidth + x) * bytesPerPixel; var value = sampleReaders[sampleIndex].call(tile, pixelOffset + srcSampleOffsets[sampleIndex], this.littleEndian); var windowCoordinate; if (interleave) { windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth * samples.length + (x + firstCol - imageWindow[0]) * samples.length + sampleIndex; valueArrays[windowCoordinate] = value; } else { windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth + x + firstCol - imageWindow[0]; valueArrays[sampleIndex][windowCoordinate] = value; } } } } } } callback(valueArrays); return valueArrays; } catch (error) { return callbackError(error); } }, /** * This callback is called upon successful reading of a GeoTIFF image. The * resulting arrays are passed as a single argument. * @callback GeoTIFFImage~readCallback * @param {(TypedArray|TypedArray[])} array the requested data as a either a * single typed array or a list of * typed arrays, depending on the * 'interleave' option. */ /** * This callback is called upon encountering an error while reading of a * GeoTIFF image * @callback GeoTIFFImage~readErrorCallback * @param {Error} error the encountered error */ /** * Reads raster data from the image. This function reads all selected samples * into separate arrays of the correct type for that sample. When provided, * only a subset of the raster is read for each sample. * * @param {Object} [options] optional parameters * @param {Array} [options.window=whole image] the subset to read data from. * @param {Array} [options.samples=all samples] the selection of samples to read from. * @param {Boolean} [options.interleave=false] whether the data shall be read * in one single array or separate * arrays. * @param {GeoTIFFImage~readCallback} [callback] the success callback. this * parameter is mandatory for * asynchronous decoders (some * compression mechanisms). * @param {GeoTIFFImage~readErrorCallback} [callbackError] the error callback * @returns {(TypedArray|TypedArray[]|null)} in synchonous cases, the decoded * array(s) is/are returned. In * asynchronous cases, nothing is * returned. */ readRasters: function readRasters() /* arguments are read via the 'arguments' object */{ // parse the arguments var options, callback, callbackError; switch (arguments.length) { case 0: break; case 1: if (typeof arguments[0] === "function") { callback = arguments[0]; } else { options = arguments[0]; } break; case 2: if (typeof arguments[0] === "function") { callback = arguments[0]; callbackError = arguments[1]; } else { options = arguments[0]; callback = arguments[1]; } break; case 3: options = arguments[0]; callback = arguments[1]; callbackError = arguments[2]; break; default: throw new Error("Invalid number of arguments passed."); } // set up default arguments options = options || {}; callbackError = callbackError || function (error) { console.error(error); }; var imageWindow = options.window || [0, 0, this.getWidth(), this.getHeight()], samples = options.samples, interleave = options.interleave; // check parameters if (imageWindow[0] < 0 || imageWindow[1] < 0 || imageWindow[2] > this.getWidth() || imageWindow[3] > this.getHeight()) { throw new Error("Select window is out of image bounds."); } else if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) { throw new Error("Invalid subsets"); } var imageWindowWidth = imageWindow[2] - imageWindow[0]; var imageWindowHeight = imageWindow[3] - imageWindow[1]; var numPixels = imageWindowWidth * imageWindowHeight; var i; if (!samples) { samples = []; for (i = 0; i < this.fileDirectory.SamplesPerPixel; ++i) { samples.push(i); } } else { for (i = 0; i < samples.length; ++i) { if (samples[i] >= this.fileDirectory.SamplesPerPixel) { throw new RangeError("Invalid sample index '" + samples[i] + "'."); } } } var valueArrays; if (interleave) { var format = Math.max.apply(null, this.fileDirectory.SampleFormat), bitsPerSample = Math.max.apply(null, this.fileDirectory.BitsPerSample); valueArrays = arrayForType(format, bitsPerSample, numPixels * samples.length); } else { valueArrays = []; for (i = 0; i < samples.length; ++i) { valueArrays.push(this.getArrayForSample(samples[i], numPixels)); } } // start reading data, sync or async var decoder = this.getDecoder(); if (decoder.isAsync()) { if (!callback) { throw new Error("No callback specified for asynchronous raster reading."); } return this._readRasterAsync(imageWindow, samples, valueArrays, interleave, callback, callbackError); } else { callback = callback || function () {}; return this._readRaster(imageWindow, samples, valueArrays, interleave, callback, callbackError); } }, /** * Returns an array of tiepoints. * @returns {Object[]} */ getTiePoints: function getTiePoints() { if (!this.fileDirectory.ModelTiepoint) { return []; } var tiePoints = []; for (var i = 0; i < this.fileDirectory.ModelTiepoint.length; i += 6) { tiePoints.push({ i: this.fileDirectory.ModelTiepoint[i], j: this.fileDirectory.ModelTiepoint[i + 1], k: this.fileDirectory.ModelTiepoint[i + 2], x: this.fileDirectory.ModelTiepoint[i + 3], y: this.fileDirectory.ModelTiepoint[i + 4], z: this.fileDirectory.ModelTiepoint[i + 5] }); } return tiePoints; }, /** * Returns the parsed GDAL metadata items. * @returns {Object} */ getGDALMetadata: function getGDALMetadata() { var metadata = {}; if (!this.fileDirectory.GDAL_METADATA) { return null; } var xmlDom = globals.parseXml(this.fileDirectory.GDAL_METADATA); var result = xmlDom.evaluate("GDALMetadata/Item", xmlDom, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for (var i = 0; i < result.snapshotLength; ++i) { var node = result.snapshotItem(i); metadata[node.getAttribute("name")] = node.textContent; } return metadata; } }; module.exports = GeoTIFFImage; },{"./compression/deflate.js":2,"./compression/lzw.js":3,"./compression/packbits.js":4,"./compression/raw.js":5,"./globals.js":8}],8:[function(require,module,exports){ "use strict"; var fieldTagNames = { // TIFF Baseline 0x013B: 'Artist', 0x0102: 'BitsPerSample', 0x0109: 'CellLength', 0x0108: 'CellWidth', 0x0140: 'ColorMap', 0x0103: 'Compression', 0x8298: 'Copyright', 0x0132: 'DateTime', 0x0152: 'ExtraSamples', 0x010A: 'FillOrder', 0x0121: 'FreeByteCounts', 0x0120: 'FreeOffsets', 0x0123: 'GrayResponseCurve', 0x0122: 'GrayResponseUnit', 0x013C: 'HostComputer', 0x010E: 'ImageDescription', 0x0101: 'ImageLength', 0x0100: 'ImageWidth', 0x010F: 'Make', 0x0119: 'MaxSampleValue', 0x0118: 'MinSampleValue', 0x0110: 'Model', 0x00FE: 'NewSubfileType', 0x0112: 'Orientation', 0x0106: 'PhotometricInterpretation', 0x011C: 'PlanarConfiguration', 0x0128: 'ResolutionUnit', 0x0116: 'RowsPerStrip', 0x0115: 'SamplesPerPixel', 0x0131: 'Software', 0x0117: 'StripByteCounts', 0x0111: 'StripOffsets', 0x00FF: 'SubfileType', 0x0107: 'Threshholding', 0x011A: 'XResolution', 0x011B: 'YResolution', // TIFF Extended 0x0146: 'BadFaxLines', 0x0147: 'CleanFaxData', 0x0157: 'ClipPath', 0x0148: 'ConsecutiveBadFaxLines', 0x01B1: 'Decode', 0x01B2: 'DefaultImageColor', 0x010D: 'DocumentName', 0x0150: 'DotRange', 0x0141: 'HalftoneHints', 0x015A: 'Indexed', 0x015B: 'JPEGTables', 0x011D: 'PageName', 0x0129: 'PageNumber', 0x013D: 'Predictor', 0x013F: 'PrimaryChromaticities', 0x0214: 'ReferenceBlackWhite', 0x0153: 'SampleFormat', 0x0154: 'SMinSampleValue', 0x0155: 'SMaxSampleValue', 0x022F: 'StripRowCounts', 0x014A: 'SubIFDs', 0x0124: 'T4Options', 0x0125: 'T6Options', 0x0145: 'TileByteCounts', 0x0143: 'TileLength', 0x0144: 'TileOffsets', 0x0142: 'TileWidth', 0x012D: 'TransferFunction', 0x013E: 'WhitePoint', 0x0158: 'XClipPathUnits', 0x011E: 'XPosition', 0x0211: 'YCbCrCoefficients', 0x0213: 'YCbCrPositioning', 0x0212: 'YCbCrSubSampling', 0x0159: 'YClipPathUnits', 0x011F: 'YPosition', // EXIF 0x9202: 'ApertureValue', 0xA001: 'ColorSpace', 0x9004: 'DateTimeDigitized', 0x9003: 'DateTimeOriginal', 0x8769: 'Exif IFD', 0x9000: 'ExifVersion', 0x829A: 'ExposureTime', 0xA300: 'FileSource', 0x9209: 'Flash', 0xA000: 'FlashpixVersion', 0x829D: 'FNumber', 0xA420: 'ImageUniqueID', 0x9208: 'LightSource', 0x927C: 'MakerNote', 0x9201: 'ShutterSpeedValue', 0x9286: 'UserComment', // IPTC 0x83BB: 'IPTC', // ICC 0x8773: 'ICC Profile', // XMP 0x02BC: 'XMP', // GDAL 0xA480: 'GDAL_METADATA', 0xA481: 'GDAL_NODATA', // Photoshop 0x8649: 'Photoshop', // GeoTiff 0x830E: 'ModelPixelScale', 0x8482: 'ModelTiepoint', 0x85D8: 'ModelTransformation', 0x87AF: 'GeoKeyDirectory', 0x87B0: 'GeoDoubleParams', 0x87B1: 'GeoAsciiParams' }; var key; var fieldTags = {}; for (key in fieldTagNames) { fieldTags[fieldTagNames[key]] = parseInt(key); } var arrayFields = [fieldTags.BitsPerSample, fieldTags.ExtraSamples, fieldTags.SampleFormat, fieldTags.StripByteCounts, fieldTags.StripOffsets, fieldTags.StripRowCounts, fieldTags.TileByteCounts, fieldTags.TileOffsets]; var fieldTypeNames = { 0x0001: 'BYTE', 0x0002: 'ASCII', 0x0003: 'SHORT', 0x0004: 'LONG', 0x0005: 'RATIONAL', 0x0006: 'SBYTE', 0x0007: 'UNDEFINED', 0x0008: 'SSHORT', 0x0009: 'SLONG', 0x000A: 'SRATIONAL', 0x000B: 'FLOAT', 0x000C: 'DOUBLE' }; var fieldTypes = {}; for (key in fieldTypeNames) { fieldTypes[fieldTypeNames[key]] = parseInt(key); } var 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' }; var geoKeys = {}; for (key in geoKeyNames) { geoKeys[geoKeyNames[key]] = parseInt(key); } var parseXml; // node.js version if (typeof window === "undefined") { parseXml = function parseXml(xmlStr) { // requires xmldom module var DOMParser = require('xmldom').DOMParser; return new DOMParser().parseFromString(xmlStr, "text/xml"); }; } else if (typeof window.DOMParser !== "undefined") { parseXml = function parseXml(xmlStr) { return new window.DOMParser().parseFromString(xmlStr, "text/xml"); }; } else if (typeof window.ActiveXObject !== "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) { parseXml = function parseXml(xmlStr) { var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async = "false"; xmlDoc.loadXML(xmlStr); return xmlDoc; }; } module.exports = { fieldTags: fieldTags, fieldTagNames: fieldTagNames, arrayFields: arrayFields, fieldTypes: fieldTypes, fieldTypeNames: fieldTypeNames, geoKeys: geoKeys, geoKeyNames: geoKeyNames, parseXml: parseXml }; },{"xmldom":"xmldom"}],9:[function(require,module,exports){ "use strict"; var GeoTIFF = require("./geotiff.js"); /** * Main parsing function for GeoTIFF files. * @param {(string|ArrayBuffer)} data Raw data to parse the GeoTIFF from. * @param {Object} [options] further options. * @param {Boolean} [options.cache=false] whether or not decoded tiles shall be cached. * @returns {GeoTIFF} the parsed geotiff file. */ var parse = function parse(data, options) { var rawData, i, strLen, view; if (typeof data === "string" || data instanceof String) { rawData = new ArrayBuffer(data.length * 2); // 2 bytes for each char view = new Uint16Array(rawData); for (i = 0, strLen = data.length; i < strLen; ++i) { view[i] = data.charCodeAt(i); } } else if (data instanceof ArrayBuffer) { rawData = data; } else { throw new Error("Invalid input data given."); } return new GeoTIFF(rawData, options); }; if (typeof module !== "undefined" && typeof module.exports !== "undefined") { module.exports.parse = parse; } if (typeof window !== "undefined") { window["GeoTIFF"] = { parse: parse }; } },{"./geotiff.js":6}]},{},[9]);