'use strict'; var fs = require('fs'); var path = require('path'); var detector = require('./detector'); var handlers = {}; var types = require('./types'); // load all available handlers types.forEach(function (type) { handlers[type] = require('./types/' + type); }); // Maximum buffer size, with a default of 128 kilobytes. // TO-DO: make this adaptive based on the initial signature of the image var MaxBufferSize = 128*1024; function lookup (buffer, filepath) { // detect the file type.. don't rely on the extension var type = detector(buffer, filepath); // find an appropriate handler for this file type if (type in handlers) { var size = handlers[type].calculate(buffer, filepath); if (size !== false) { size.type = type; return size; } } // throw up, if we don't understand the file throw new TypeError('unsupported file type'); } function asyncFileToBuffer (filepath, callback) { // open the file in read only mode fs.open(filepath, 'r', function (err, descriptor) { if (err) { return callback(err); } var size = fs.fstatSync(descriptor).size; var bufferSize = Math.min(size, MaxBufferSize); var buffer = new Buffer(bufferSize); // read first buffer block from the file, asynchronously fs.read(descriptor, buffer, 0, bufferSize, 0, function (err) { if (err) { return callback(err); } // close the file, we are done fs.close(descriptor, function (err) { callback(err, buffer); }); }); }); } function syncFileToBuffer (filepath) { // read from the file, synchronously var descriptor = fs.openSync(filepath, 'r'); var size = fs.fstatSync(descriptor).size; var bufferSize = Math.min(size, MaxBufferSize); var buffer = new Buffer(bufferSize); fs.readSync(descriptor, buffer, 0, bufferSize, 0); fs.closeSync(descriptor); return buffer; } /** * @params input - buffer or relative/absolute path of the image file * @params callback - optional function for async detection */ module.exports = function (input, callback) { // Handle buffer input if (Buffer.isBuffer(input)) { return lookup(input); } // input should be a string at this point if (typeof input !== 'string') { throw new TypeError('invalid invocation'); } // resolve the file path var filepath = path.resolve(input); if (typeof callback === 'function') { asyncFileToBuffer(filepath, function (err, buffer) { if (err) { return callback(err); } // return the dimensions var dimensions; try { dimensions = lookup(buffer, filepath); } catch (e) { err = e; } callback(err, dimensions); }); } else { var buffer = syncFileToBuffer(filepath); return lookup(buffer, filepath); } }; module.exports.types = types;