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