123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- 'use strict';
- // based on http://www.compix.com/fileformattif.htm
- // TO-DO: support big-endian as well
- var fs = require('fs');
- var readUInt = require('../readUInt');
- function isTIFF (buffer) {
- var hex4 = buffer.toString('hex', 0, 4);
- return ('49492a00' === hex4 || '4d4d002a' === hex4);
- }
- // Read IFD (image-file-directory) into a buffer
- function readIFD (buffer, filepath, isBigEndian) {
- var ifdOffset = readUInt(buffer, 32, 4, isBigEndian);
- // read only till the end of the file
- var bufferSize = 1024;
- var fileSize = fs.statSync(filepath).size;
- if (ifdOffset + bufferSize > fileSize) {
- bufferSize = fileSize - ifdOffset - 10;
- }
- // populate the buffer
- var endBuffer = new Buffer(bufferSize);
- var descriptor = fs.openSync(filepath, 'r');
- fs.readSync(descriptor, endBuffer, 0, bufferSize, ifdOffset);
- // var ifdLength = readUInt(endBuffer, 16, 0, isBigEndian);
- var ifdBuffer = endBuffer.slice(2); //, 2 + 12 * ifdLength);
- return ifdBuffer;
- }
- // TIFF values seem to be messed up on Big-Endian, this helps
- function readValue (buffer, isBigEndian) {
- var low = readUInt(buffer, 16, 8, isBigEndian);
- var high = 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) {
- var tags = {};
- var code, type, length;
- while (buffer && buffer.length) {
- code = readUInt(buffer, 16, 0, isBigEndian);
- type = readUInt(buffer, 16, 2, isBigEndian);
- length = readUInt(buffer, 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(buffer, isBigEndian);
- }
- // move to the next tag
- buffer = nextTag(buffer);
- }
- }
- return tags;
- }
- // Test if the TIFF is Big Endian or Little Endian
- function determineEndianness (buffer) {
- var signature = buffer.toString('ascii', 0, 2);
- if ('II' === signature) {
- return 'LE';
- } else if ('MM' === signature) {
- return 'BE';
- }
- }
- function calculate (buffer, filepath) {
- if (!filepath) {
- throw new TypeError('Tiff doesn\'t support buffer');
- }
- // Determine BE/LE
- var isBigEndian = determineEndianness(buffer) === 'BE';
- // read the IFD
- var ifdBuffer = readIFD(buffer, filepath, isBigEndian);
- // extract the tags from the IFD
- var tags = extractTags(ifdBuffer, isBigEndian);
- var width = tags[256];
- var height = tags[257];
- if (!width || !height) {
- throw new TypeError('Invalid Tiff, missing tags');
- }
- return {
- 'width': width,
- 'height': height
- };
- }
- module.exports = {
- 'detect': isTIFF,
- 'calculate': calculate
- };
|