Permalink
Browse files

clean up jpeg code, bring down complexity to 4

  • Loading branch information...
1 parent b99da08 commit 725cd8dcf8cf268d782ceabfb6f3dd48e6a78a38 @netroy netroy committed Oct 11, 2013
Showing with 61 additions and 58 deletions.
  1. +1 −1 .jshintrc
  2. +23 −22 lib/detector.js
  3. +37 −35 lib/types/jpg.js
View
2 .jshintrc
@@ -8,7 +8,7 @@
"indent": 2,
"laxcomma": false,
"maxlen": 72,
- "maxcomplexity": 6,
+ "maxcomplexity": 4,
"maxstatements": 15,
"node": true,
"quotmark": "single",
View
45 lib/detector.js
@@ -8,7 +8,8 @@ function isPSD (buffer) {
var gifRegexp = /^GIF8[7,9]a/;
function isGIF (buffer) {
- return (gifRegexp.test(buffer.toString('ascii', 0, 6)));
+ var signature = buffer.toString('ascii', 0, 6);
+ return (gifRegexp.test(signature));
}
var pngSignature = 'PNG\r\n\u001a\n';
@@ -26,33 +27,33 @@ function isTIFF (buffer) {
return ('49492a00' === hex4 || '4d4d002a' === hex4);
}
+
+// TODO: handle the following as well
+// ffe2 — Canon EOS-1D JPEG
+// ffdb - Samsung D807 JPEG
+// ffe3 — Samsung D500 JPEG
+var validJFIFMarkers = {
+ 'ffe0': '4a46494600', // standard jpeg
+ 'ffe1': '4578696600', // camera jpeg, with EXIF data
+ 'ffe8': '5350494646' // SPIFF jpeg
+};
+
function isJPG (buffer) {
var SOIMarker = buffer.toString('hex', 0, 2);
var JFIFMarker = buffer.toString('hex', 2, 4);
- if ('ffd8' === SOIMarker) {
- var signature = buffer.toString('hex', 6, 11);
-
- // standard jpeg
- if ('ffe0' === JFIFMarker) {
- return '4a46494600' === signature;
- }
-
- // camera jpeg, with EXIF data
- if ('ffe1' === JFIFMarker) {
- return '4578696600' === signature;
- }
+ // not a valid jpeg
+ if ('ffd8' !== SOIMarker) {
+ return false;
+ }
- // SPIFF jpeg
- if ('ffe8' === JFIFMarker) {
- var twelth = buffer.toString('hex', 11, 12);
- return '5350494646' === signature && '00' === twelth;
+ var actual, expected;
+ for (var marker in validJFIFMarkers) {
+ expected = validJFIFMarkers[marker];
+ actual = buffer.toString('hex', 6, 6 + (expected.length / 2));
+ if (marker === JFIFMarker) {
+ return validJFIFMarkers[marker] === actual;
}
-
- // TODO: handle the following as well
- // ffdb - Samsung D807 JPEG
- // dde2 — Canon EOS-1D JPEG
- // ffe3 — Samsung D500 JPEG
}
// not a valid jpeg
View
72 lib/types/jpg.js
@@ -1,46 +1,48 @@
-module.exports = function (buffer) {
-
- var i = 4;
- var len = buffer.length;
-
- // 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.
-
- // read block length of first JPG block
- var currentBlockLength = buffer.readUInt16BE(i);
+// 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 extractSize (buffer, i) {
+ return {
+ 'height' : buffer.readUInt16BE(i),
+ 'width' : buffer.readUInt16BE(i + 2)
+ };
+}
+
+function validateBuffer (buffer, i) {
+ // index should be withing 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');
+ }
+}
- while (i < len) {
+module.exports = function (buffer) {
- i += currentBlockLength;
+ // Skip 5 chars, they are for signature
+ buffer = buffer.slice(4);
- if (i >= len) {
- throw new TypeError('Corrupt JPG, exceeded buffer limits');
- }
+ var i, next;
+ while (buffer.length) {
+ // read length of the next block
+ i = buffer.readUInt16BE(0);
- // every JPG marker starts with 0xFF
- if (buffer[i] !== 0xFF) {
- throw new TypeError('Invalid JPG, marker table corrupted');
- }
+ // ensure correct format
+ validateBuffer(buffer, i);
- // 0xFFC0 is baseline(SOF), 0xFFC2 is progressive(SOF2)
- var next = buffer[i + 1];
+ // 0xFFC0 is baseline(SOF)
+ // 0xFFC2 is progressive(SOF2)
+ next = buffer[i + 1];
if (next === 0xC0 || next === 0xC2) {
- // SOF/SOF2 layout:
- // byte0 = marker (size 16)
- // byte2 = block length (size 16)
- // byte4 = sample precision (size 8)
- // byte5 = height (size 16)
- // byte7 = width (size 16)
- return {
- 'height' : buffer.readUInt16BE(i + 5),
- 'width' : buffer.readUInt16BE(i + 7)
- };
+ return extractSize(buffer, i + 5);
}
- i = i + 2;
- currentBlockLength = buffer.readUInt16BE(i);
+ // move to the next block
+ buffer = buffer.slice(i + 2);
}
throw new TypeError('Invalid JPG, no size found');

0 comments on commit 725cd8d

Please sign in to comment.