UNPKG

2.48 kBJavaScriptView Raw
1'use strict';
2
3
4var ParserStream = require('../common').ParserStream;
5
6
7// part of parseJpegMarker called after skipping initial FF
8function parseJpegMarker_afterFF(parser, callback) {
9 parser._bytes(1, function (data) {
10 var code = data[0];
11
12 if (code === 0xFF) {
13 // padding byte, skip it
14 parseJpegMarker_afterFF(parser, callback);
15 return;
16 }
17
18 // standalone markers, according to JPEG 1992,
19 // http://www.w3.org/Graphics/JPEG/itu-t81.pdf, see Table B.1
20 if ((0xD0 <= code && code <= 0xD9) || code === 0x01) {
21 callback(code, 0);
22 return;
23 }
24
25 // the rest of the unreserved markers
26 if (0xC0 <= code && code <= 0xFE) {
27 parser._bytes(2, function (length) {
28 callback(code, length.readUInt16BE(0) - 2);
29 });
30 return;
31 }
32
33 // unknown markers
34 callback();
35 });
36}
37
38
39function parseJpegMarker(parser, callback) {
40 parser._bytes(1, function (data) {
41 if (data[0] !== 0xFF) {
42 // not a JPEG marker
43 callback();
44 return;
45 }
46
47 parseJpegMarker_afterFF(parser, callback);
48 });
49}
50
51
52function getJpegSize(parser) {
53 parseJpegMarker(parser, function (code, length) {
54 if (!code || length < 0) {
55 // invalid jpeg
56 parser._skipBytes(Infinity);
57 parser.push(null);
58 return;
59 }
60
61 if (code === 0xD9 /* EOI */ || code === 0xDA /* SOS */) {
62 // end of the datastream
63 parser._skipBytes(Infinity);
64 parser.push(null);
65 return;
66 }
67
68 if (length <= 0) {
69 // e.g. empty comment
70 getJpegSize(parser);
71 return;
72 }
73
74 if (length >= 5 &&
75 (0xC0 <= code && code <= 0xCF) &&
76 code !== 0xC4 && code !== 0xC8 && code !== 0xCC) {
77
78 parser._bytes(length, function (data) {
79 parser._skipBytes(Infinity);
80
81 parser.push({
82 width: data.readUInt16BE(3),
83 height: data.readUInt16BE(1),
84 type: 'jpg',
85 mime: 'image/jpeg',
86 wUnits: 'px',
87 hUnits: 'px'
88 });
89
90 parser.push(null);
91 });
92 return;
93 }
94
95 parser._skipBytes(length, function () {
96 getJpegSize(parser);
97 });
98 });
99}
100
101
102module.exports = function () {
103 var parser = new ParserStream();
104
105 parser._bytes(2, function (data) {
106 if (data[0] !== 0xFF || data[1] !== 0xD8) {
107 // first marker of the file MUST be 0xFFD8
108 parser._skipBytes(Infinity);
109 parser.push(null);
110 return;
111 }
112
113 getJpegSize(parser);
114 });
115
116 return parser;
117};