"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TIFF = void 0; // based on http://www.compix.com/fileformattif.htm // TO-DO: support big-endian as well const fs = require("fs"); const readUInt_1 = require("../readUInt"); // Read IFD (image-file-directory) into a buffer function readIFD(buffer, filepath, isBigEndian) { const ifdOffset = (0, readUInt_1.readUInt)(buffer, 32, 4, isBigEndian); // read only till the end of the file let bufferSize = 1024; const fileSize = fs.statSync(filepath).size; if (ifdOffset + bufferSize > fileSize) { bufferSize = fileSize - ifdOffset - 10; } // populate the buffer const endBuffer = Buffer.alloc(bufferSize); const descriptor = fs.openSync(filepath, 'r'); fs.readSync(descriptor, endBuffer, 0, bufferSize, ifdOffset); fs.closeSync(descriptor); return endBuffer.slice(2); } // TIFF values seem to be messed up on Big-Endian, this helps function readValue(buffer, isBigEndian) { const low = (0, readUInt_1.readUInt)(buffer, 16, 8, isBigEndian); const high = (0, readUInt_1.readUInt)(buffer, 16, 10, isBigEndian); return (high << 16) + low; } // move to the next tag function nextTag(buffer) { if (buffer.length > 24) { return buffer.slice(12); } } // Extract IFD tags from TIFF metadata function extractTags(buffer, isBigEndian) { const tags = {}; let temp = buffer; while (temp && temp.length) { const code = (0, readUInt_1.readUInt)(temp, 16, 0, isBigEndian); const type = (0, readUInt_1.readUInt)(temp, 16, 2, isBigEndian); const length = (0, readUInt_1.readUInt)(temp, 32, 4, isBigEndian); // 0 means end of IFD if (code === 0) { break; } else { // 256 is width, 257 is height // if (code === 256 || code === 257) { if (length === 1 && (type === 3 || type === 4)) { tags[code] = readValue(temp, isBigEndian); } // move to the next tag temp = nextTag(temp); } } return tags; } // Test if the TIFF is Big Endian or Little Endian function determineEndianness(buffer) { const signature = buffer.toString('ascii', 0, 2); if ('II' === signature) { return 'LE'; } else if ('MM' === signature) { return 'BE'; } } const signatures = [ // '492049', // currently not supported '49492a00', '4d4d002a', // Big Endian // '4d4d002a', // BigTIFF > 4GB. currently not supported ]; exports.TIFF = { validate(buffer) { return signatures.includes(buffer.toString('hex', 0, 4)); }, calculate(buffer, filepath) { if (!filepath) { throw new TypeError('Tiff doesn\'t support buffer'); } // Determine BE/LE const isBigEndian = determineEndianness(buffer) === 'BE'; // read the IFD const ifdBuffer = readIFD(buffer, filepath, isBigEndian); // extract the tags from the IFD const tags = extractTags(ifdBuffer, isBigEndian); const width = tags[256]; const height = tags[257]; if (!width || !height) { throw new TypeError('Invalid Tiff. Missing tags'); } return { height, width }; } };