shift73k/assets_old/node_modules/image-size/lib/types/tiff.js

118 lines
2.8 KiB
JavaScript

'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
};