tatry
Version:
Elevation API server.
122 lines (99 loc) • 3.21 kB
JavaScript
import { parse } from './lame-tiff/file.js';
export default async function bounds(file) {
function convert({ fileDirectory, littleEndian }) {
check(fileDirectory);
const { ImageWidth: width, ImageLength: height } = fileDirectory;
const isTiled = !fileDirectory.StripOffsets;
const tileWidth = isTiled ? fileDirectory.TileWidth : width;
let tileHeight = height;
if (isTiled) {
tileHeight = fileDirectory.tileHeight;
} else if (typeof fileDirectory.RowsPerStrip !== 'undefined') {
tileHeight = Math.min(fileDirectory.RowsPerStrip, height);
}
const { minX, minY, maxX, maxY } = getBoundingBox(fileDirectory);
return {
minX,
maxX,
minY,
maxY,
file,
meta: {
width,
height,
tileWidth,
tileHeight,
tilesPerRow: Math.ceil(width / tileWidth),
tilesPerCol: Math.ceil(height / tileHeight),
littleEndian,
offsets: isTiled ? fileDirectory.TileOffsets : fileDirectory.StripOffsets,
byteCounts: isTiled ? fileDirectory.TileByteCounts : fileDirectory.StripByteCounts,
it: getInverseTransformMatrix(fileDirectory)
}
};
}
const data = await parse(file);
try {
return convert(data);
} catch (e) {
console.error('Invalid file format', file, e.toString());
} finally {
data.fh.close();
}
}
function check(fileDirectory) {
function checkProperty(name, expected) {
if (name in fileDirectory && fileDirectory[name] !== expected) {
throw new Error(`Invalid ${name}: expected: ${expected}, got: ${fileDirectory[name]}`);
}
}
checkProperty('BitsPerSample', 16);
checkProperty('Compression', 1);
checkProperty('SamplesPerPixel', 1);
checkProperty('PlanarConfiguration', 1);
checkProperty('SampleFormat', 2);
}
function getOrigin(fileDirectory) {
const { ModelTiepoint: tp, ModelTransformation: mt } = fileDirectory;
if (tp && tp.length === 6) {
return [tp[3], tp[4], tp[5]];
}
if (mt) {
return [mt[3], mt[7], mt[11]];
}
throw new Error('Cannot calculated origin.');
}
function getResolution(fileDirectory) {
const { ModelPixelScale: ps, ModelTransformation: mt } = fileDirectory;
if (ps) {
return [ps[0], -ps[1], ps[2]];
}
if (mt) {
return [mt[0], mt[5], mt[10]];
}
throw new Error('Cannot calculate resolution.');
}
function getBoundingBox(fileDirectory) {
const origin = getOrigin(fileDirectory);
const resolution = getResolution(fileDirectory);
const x = origin[0];
const width = resolution[0] * fileDirectory.ImageWidth;
const xx = width > 0 ? [x, x + width] : [x + width, x];
const y = origin[1];
const height = resolution[1] * fileDirectory.ImageLength;
const yy = height > 0 ? [y, y + height] : [y + height, y];
return {
minX: xx[0],
minY: yy[0],
maxX: xx[1],
maxY: yy[1]
};
}
function getInverseTransformMatrix(fileDirectory) {
const { ModelPixelScale: scale, ModelTiepoint: tiepoint } = fileDirectory;
const x = tiepoint[3];
const y = tiepoint[4];
const t = [x, scale[0], 0, y, 0, -scale[1]];
const inverse = [-t[0] / t[1], 1 / t[1], 0, -t[3] / t[5], 0, 1 / t[5]];
return inverse;
}