UNPKG

tatry

Version:
124 lines (100 loc) 3.23 kB
const { parse } = require('./lame-tiff/file'); module.exports = bounds; 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: 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; }