OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 'use strict'; | |
6 | |
7 /* Base class for image metadata parsers that only need to look at a short | |
8 fragment at the start of the file */ | |
9 function SimpleImageParser(parent, type, urlFilter, headerSize) { | |
10 ImageParser.call(this, parent, type, urlFilter); | |
11 this.headerSize = headerSize; | |
12 } | |
13 | |
14 SimpleImageParser.prototype = {__proto__: ImageParser.prototype}; | |
15 | |
16 /** | |
17 * @param {File} file // TODO(JSDOC). | |
18 * @param {Object} metadata // TODO(JSDOC). | |
19 * @param {function(Object)} callback // TODO(JSDOC). | |
20 * @param {function(string)} errorCallback // TODO(JSDOC). | |
21 */ | |
22 SimpleImageParser.prototype.parse = function( | |
23 file, metadata, callback, errorCallback) { | |
24 var self = this; | |
25 util.readFileBytes(file, 0, this.headerSize, | |
26 function(file, br) { | |
27 try { | |
28 self.parseHeader(metadata, br); | |
29 callback(metadata); | |
30 } catch (e) { | |
31 errorCallback(e.toString()); | |
32 } | |
33 }, | |
34 errorCallback); | |
35 }; | |
36 | |
37 | |
38 function PngParser(parent) { | |
39 SimpleImageParser.call(this, parent, 'png', /\.png$/i, 24); | |
40 } | |
41 | |
42 PngParser.prototype = {__proto__: SimpleImageParser.prototype}; | |
43 | |
44 /** | |
45 * @param {Object} metadata // TODO(JSDOC). | |
46 * @param {ByteReader} br // TODO(JSDOC). | |
47 */ | |
48 PngParser.prototype.parseHeader = function(metadata, br) { | |
49 br.setByteOrder(ByteReader.BIG_ENDIAN); | |
50 | |
51 var signature = br.readString(8); | |
52 if (signature != '\x89PNG\x0D\x0A\x1A\x0A') | |
53 throw new Error('Invalid PNG signature: ' + signature); | |
54 | |
55 br.seek(12); | |
56 var ihdr = br.readString(4); | |
57 if (ihdr != 'IHDR') | |
58 throw new Error('Missing IHDR chunk'); | |
59 | |
60 metadata.width = br.readScalar(4); | |
61 metadata.height = br.readScalar(4); | |
62 }; | |
63 | |
64 MetadataDispatcher.registerParserClass(PngParser); | |
65 | |
66 | |
67 function BmpParser(parent) { | |
68 SimpleImageParser.call(this, parent, 'bmp', /\.bmp$/i, 28); | |
69 } | |
70 | |
71 BmpParser.prototype = {__proto__: SimpleImageParser.prototype}; | |
72 | |
73 /** | |
74 * @param {Object} metadata // TODO(JSDOC). | |
75 * @param {ByteReader} br // TODO(JSDOC). | |
76 */ | |
77 BmpParser.prototype.parseHeader = function(metadata, br) { | |
78 br.setByteOrder(ByteReader.LITTLE_ENDIAN); | |
79 | |
80 var signature = br.readString(2); | |
81 if (signature != 'BM') | |
82 throw new Error('Invalid BMP signature: ' + signature); | |
83 | |
84 br.seek(18); | |
85 metadata.width = br.readScalar(4); | |
86 metadata.height = br.readScalar(4); | |
87 }; | |
88 | |
89 MetadataDispatcher.registerParserClass(BmpParser); | |
90 | |
91 | |
92 function GifParser(parent) { | |
93 SimpleImageParser.call(this, parent, 'gif', /\.Gif$/i, 10); | |
94 } | |
95 | |
96 GifParser.prototype = {__proto__: SimpleImageParser.prototype}; | |
97 | |
98 /** | |
99 * @param {Object} metadata // TODO(JSDOC). | |
100 * @param {ByteReader} br // TODO(JSDOC). | |
101 */ | |
102 GifParser.prototype.parseHeader = function(metadata, br) { | |
103 br.setByteOrder(ByteReader.LITTLE_ENDIAN); | |
104 | |
105 var signature = br.readString(6); | |
106 if (!signature.match(/GIF8(7|9)a/)) | |
107 throw new Error('Invalid GIF signature: ' + signature); | |
108 | |
109 metadata.width = br.readScalar(2); | |
110 metadata.height = br.readScalar(2); | |
111 }; | |
112 | |
113 MetadataDispatcher.registerParserClass(GifParser); | |
114 | |
115 | |
116 function WebpParser(parent) { | |
117 SimpleImageParser.call(this, parent, 'webp', /\.webp$/i, 30); | |
118 } | |
119 | |
120 WebpParser.prototype = {__proto__: SimpleImageParser.prototype}; | |
121 | |
122 /** | |
123 * @param {Object} metadata // TODO(JSDOC). | |
124 * @param {ByteReader} br // TODO(JSDOC). | |
125 */ | |
126 WebpParser.prototype.parseHeader = function(metadata, br) { | |
127 br.setByteOrder(ByteReader.LITTLE_ENDIAN); | |
128 | |
129 var riffSignature = br.readString(4); | |
130 if (riffSignature != 'RIFF') | |
131 throw new Error('Invalid RIFF signature: ' + riffSignature); | |
132 | |
133 br.seek(8); | |
134 var webpSignature = br.readString(4); | |
135 if (webpSignature != 'WEBP') | |
136 throw new Error('Invalid WEBP signature: ' + webpSignature); | |
137 | |
138 var chunkFormat = br.readString(4); | |
139 if (chunkFormat != 'VP8 ' && chunkFormat != 'VP8L') | |
140 throw new Error('Invalid chunk format: ' + chunkFormat); | |
141 | |
142 if (chunkFormat == 'VP8 ') { | |
143 // VP8 lossy bitstream format. | |
144 br.seek(23); | |
145 var lossySignature = br.readScalar(2) | (br.readScalar(1) << 16); | |
146 if (lossySignature != 0x2a019d) | |
147 throw new Error('Invalid VP8 lossy bitstream signature: ' + | |
148 lossySignature); | |
149 | |
150 var dimensionBits = br.readScalar(4); | |
151 metadata.width = dimensionBits & 0x3fff; | |
152 metadata.height = (dimensionBits >> 16) & 0x3fff; | |
153 } else { | |
154 // VP8 lossless bitstream format. | |
155 br.seek(20); | |
156 var losslessSignature = br.readScalar(1); | |
157 if (losslessSignature != 0x2f) | |
158 throw new Error('Invalid VP8 lossless bitstream signature: ' + | |
159 losslessSignature); | |
160 | |
161 var dimensionBits = br.readScalar(4); | |
162 metadata.width = (dimensionBits & 0x3fff) + 1; | |
163 metadata.height = ((dimensionBits >> 14) & 0x3fff) + 1; | |
164 } | |
165 }; | |
166 | |
167 MetadataDispatcher.registerParserClass(WebpParser); | |
OLD | NEW |