81 lines
1.8 KiB
JavaScript
81 lines
1.8 KiB
JavaScript
'use strict';
|
|
|
|
/* eslint-disable no-bitwise */
|
|
/* eslint-disable consistent-return */
|
|
|
|
var str2arr = require('../common').str2arr;
|
|
var sliceEq = require('../common').sliceEq;
|
|
var readUInt16LE = require('../common').readUInt16LE;
|
|
var readUInt32LE = require('../common').readUInt32LE;
|
|
|
|
|
|
var SIG_RIFF = str2arr('RIFF');
|
|
var SIG_WEBPVP8 = str2arr('WEBPVP8');
|
|
|
|
|
|
function parseVP8(data) {
|
|
if (data.length < 16 + 14) return;
|
|
|
|
if (data[16 + 7] !== 0x9D || data[16 + 8] !== 0x01 || data[16 + 9] !== 0x2A) {
|
|
// bad code block signature
|
|
return;
|
|
}
|
|
|
|
return {
|
|
width: readUInt16LE(data, 16 + 10) & 0x3FFF,
|
|
height: readUInt16LE(data, 16 + 12) & 0x3FFF,
|
|
type: 'webp',
|
|
mime: 'image/webp',
|
|
wUnits: 'px',
|
|
hUnits: 'px'
|
|
};
|
|
}
|
|
|
|
|
|
function parseVP8L(data) {
|
|
if (data.length < 16 + 9) return;
|
|
|
|
if (data[16 + 4] !== 0x2F) return;
|
|
|
|
var bits = readUInt32LE(data, 16 + 5);
|
|
|
|
return {
|
|
width: (bits & 0x3FFF) + 1,
|
|
height: ((bits >> 14) & 0x3FFF) + 1,
|
|
type: 'webp',
|
|
mime: 'image/webp',
|
|
wUnits: 'px',
|
|
hUnits: 'px'
|
|
};
|
|
}
|
|
|
|
|
|
function parseVP8X(data) {
|
|
if (data.length < 16 + 14) return;
|
|
|
|
return {
|
|
// TODO: replace with `data.readUIntLE(8, 3) + 1`
|
|
// when 0.10 support is dropped
|
|
width: ((data[16 + 10] << 16) | (data[16 + 9] << 8) | data[16 + 8]) + 1,
|
|
height: ((data[16 + 13] << 16) | (data[16 + 12] << 8) | data[16 + 11]) + 1,
|
|
type: 'webp',
|
|
mime: 'image/webp',
|
|
wUnits: 'px',
|
|
hUnits: 'px'
|
|
};
|
|
}
|
|
|
|
|
|
module.exports = function (data) {
|
|
if (data.length < 16) return;
|
|
|
|
// check /^RIFF....WEBPVP8([ LX])$/ signature
|
|
if (sliceEq(data, 0, SIG_RIFF) && sliceEq(data, 8, SIG_WEBPVP8)) {
|
|
switch (data[15]) {
|
|
case 32/*' '*/: return parseVP8(data);
|
|
case 76/* L */: return parseVP8L(data);
|
|
case 88/* X */: return parseVP8X(data);
|
|
}
|
|
}
|
|
};
|