index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. var fs = require('fs');
  3. var path = require('path');
  4. var detector = require('./detector');
  5. var handlers = {};
  6. var types = require('./types');
  7. // load all available handlers
  8. types.forEach(function (type) {
  9. handlers[type] = require('./types/' + type);
  10. });
  11. // Maximum buffer size, with a default of 128 kilobytes.
  12. // TO-DO: make this adaptive based on the initial signature of the image
  13. var MaxBufferSize = 128*1024;
  14. function lookup (buffer, filepath) {
  15. // detect the file type.. don't rely on the extension
  16. var type = detector(buffer, filepath);
  17. // find an appropriate handler for this file type
  18. if (type in handlers) {
  19. var size = handlers[type].calculate(buffer, filepath);
  20. if (size !== false) {
  21. size.type = type;
  22. return size;
  23. }
  24. }
  25. // throw up, if we don't understand the file
  26. throw new TypeError('unsupported file type: ' + type + ' (file: ' + filepath + ')');
  27. }
  28. function asyncFileToBuffer (filepath, callback) {
  29. // open the file in read only mode
  30. fs.open(filepath, 'r', function (err, descriptor) {
  31. if (err) { return callback(err); }
  32. var size = fs.fstatSync(descriptor).size;
  33. if (size <= 0){return callback(new Error("File size is not greater than 0 —— " + filepath)); }
  34. var bufferSize = Math.min(size, MaxBufferSize);
  35. var buffer = new Buffer(bufferSize);
  36. // read first buffer block from the file, asynchronously
  37. fs.read(descriptor, buffer, 0, bufferSize, 0, function (err) {
  38. if (err) { return callback(err); }
  39. // close the file, we are done
  40. fs.close(descriptor, function (err) {
  41. callback(err, buffer);
  42. });
  43. });
  44. });
  45. }
  46. function syncFileToBuffer (filepath) {
  47. // read from the file, synchronously
  48. var descriptor = fs.openSync(filepath, 'r');
  49. var size = fs.fstatSync(descriptor).size;
  50. var bufferSize = Math.min(size, MaxBufferSize);
  51. var buffer = new Buffer(bufferSize);
  52. fs.readSync(descriptor, buffer, 0, bufferSize, 0);
  53. fs.closeSync(descriptor);
  54. return buffer;
  55. }
  56. /**
  57. * @params input - buffer or relative/absolute path of the image file
  58. * @params callback - optional function for async detection
  59. */
  60. module.exports = function (input, callback) {
  61. // Handle buffer input
  62. if (Buffer.isBuffer(input)) {
  63. return lookup(input);
  64. }
  65. // input should be a string at this point
  66. if (typeof input !== 'string') {
  67. throw new TypeError('invalid invocation');
  68. }
  69. // resolve the file path
  70. var filepath = path.resolve(input);
  71. if (typeof callback === 'function') {
  72. asyncFileToBuffer(filepath, function (err, buffer) {
  73. if (err) { return callback(err); }
  74. // return the dimensions
  75. var dimensions;
  76. try {
  77. dimensions = lookup(buffer, filepath);
  78. } catch (e) {
  79. err = e;
  80. }
  81. callback(err, dimensions);
  82. });
  83. } else {
  84. var buffer = syncFileToBuffer(filepath);
  85. return lookup(buffer, filepath);
  86. }
  87. };
  88. module.exports.types = types;