- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / file_manager / foreground / js / metadata / image_parsers.js
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);