63 lines
1.5 KiB
JavaScript
63 lines
1.5 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
// NOTE: we only support baseline and progressive JPGs here
|
||
|
// due to the structure of the loader class, we only get a buffer
|
||
|
// with a maximum size of 4096 bytes. so if the SOF marker is outside
|
||
|
// if this range we can't detect the file size correctly.
|
||
|
|
||
|
function isJPG (buffer) { //, filepath
|
||
|
var SOIMarker = buffer.toString('hex', 0, 2);
|
||
|
return ('ffd8' === SOIMarker);
|
||
|
}
|
||
|
|
||
|
function extractSize (buffer, i) {
|
||
|
return {
|
||
|
'height' : buffer.readUInt16BE(i),
|
||
|
'width' : buffer.readUInt16BE(i + 2)
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function validateBuffer (buffer, i) {
|
||
|
// index should be within buffer limits
|
||
|
if (i > buffer.length) {
|
||
|
throw new TypeError('Corrupt JPG, exceeded buffer limits');
|
||
|
}
|
||
|
// Every JPEG block must begin with a 0xFF
|
||
|
if (buffer[i] !== 0xFF) {
|
||
|
throw new TypeError('Invalid JPG, marker table corrupted');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function calculate (buffer) {
|
||
|
|
||
|
// Skip 4 chars, they are for signature
|
||
|
buffer = buffer.slice(4);
|
||
|
|
||
|
var i, next;
|
||
|
while (buffer.length) {
|
||
|
// read length of the next block
|
||
|
i = buffer.readUInt16BE(0);
|
||
|
|
||
|
// ensure correct format
|
||
|
validateBuffer(buffer, i);
|
||
|
|
||
|
// 0xFFC0 is baseline standard(SOF)
|
||
|
// 0xFFC1 is baseline optimized(SOF)
|
||
|
// 0xFFC2 is progressive(SOF2)
|
||
|
next = buffer[i + 1];
|
||
|
if (next === 0xC0 || next === 0xC1 || next === 0xC2) {
|
||
|
return extractSize(buffer, i + 5);
|
||
|
}
|
||
|
|
||
|
// move to the next block
|
||
|
buffer = buffer.slice(i + 2);
|
||
|
}
|
||
|
|
||
|
throw new TypeError('Invalid JPG, no size found');
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
'detect': isJPG,
|
||
|
'calculate': calculate
|
||
|
};
|