Skip to content

Commit 6f75540

Browse files
committed
fix #120, fix #116
The change codes are from antimatter15/whammy#70 (comment)
1 parent 5ebb99a commit 6f75540

File tree

1 file changed

+79
-9
lines changed

1 file changed

+79
-9
lines changed

src/statics/lib/whammy.js

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,67 @@ window.Whammy = (function(){
433433
data: VP8,
434434
riff: riff
435435
}
436-
}
436+
} /**
437+
* 读取指定偏移量处的小端模式的32位无符号整数
438+
* @param buffer - 数据缓冲区
439+
* @param offset - 起始偏移量
440+
* @returns 32位无符号整数
441+
*/
442+
function readUint32LittleEndian(buffer, offset) {
443+
let val = parseInt(
444+
buffer
445+
.substr(offset, 4)
446+
.split("")
447+
.map(function(i) {
448+
var unpadded = i.charCodeAt(0).toString(2);
449+
return new Array(8 - unpadded.length + 1).join("0") + unpadded;
450+
})
451+
.reverse() // 注意需要翻转字节序才是小端编码
452+
.join(""),
453+
2
454+
);
455+
return val;
456+
}
457+
458+
/**
459+
* 对于 VP8X,需要提取出其中的 VP8 或 VP8L bit stream chunk。
460+
* 关于 VP8X 格式,参见 Extended file format: https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
461+
* @param buffer VP8X Chunk数据,不含 "VP8X" tag
462+
*/
463+
function extractBitStreamFromVp8x(buffer) {
464+
//console.log("VP8X buffer:", buffer);
465+
466+
/*
467+
跳过以下VP8X头:
468+
32bit VP8X Chunk size
469+
8bit Flags: Rsv I L E X A R
470+
24bit Reserved
471+
24bit Canvas Width Minus One
472+
24bit Canvas Height Minus One
473+
*/
474+
let offset = 4 + 1 + 3 + 3 + 3;
475+
// 搜索第一个"VP8 "或"VP8L" bit stream chunk
476+
while (offset < buffer.length) {
477+
let chunkTag = buffer.substr(offset, 4);
478+
//console.log(`chunkTag: \"${chunkTag}\"`);
479+
offset += 4;
480+
let chunkSize = readUint32LittleEndian(buffer, offset);
481+
//console.log("chunkSize:", chunkSize);
482+
offset += 4;
483+
switch (chunkTag) {
484+
case "VP8 ":
485+
case "VP8L":
486+
const size = buffer.substr(offset - 4, 4);
487+
const body = buffer.substr(offset, chunkSize);
488+
return size + body;
489+
default:
490+
// 跳过不关心的数据块
491+
offset += chunkSize;
492+
break;
493+
}
494+
}
495+
console.error("VP8X format error: missing VP8/VP8L chunk.");
496+
}
437497

438498
// i think i'm going off on a riff by pretending this is some known
439499
// idiom which i'm making a casual and brilliant pun about, but since
@@ -449,17 +509,27 @@ window.Whammy = (function(){
449509
while (offset < string.length) {
450510
var id = string.substr(offset, 4);
451511
chunks[id] = chunks[id] || [];
452-
if (id == 'RIFF' || id == 'LIST') {
453-
var len = parseInt(string.substr(offset + 4, 4).split('').map(function(i){
454-
var unpadded = i.charCodeAt(0).toString(2);
455-
return (new Array(8 - unpadded.length + 1)).join('0') + unpadded
456-
}).join(''),2);
512+
if (id == "RIFF" || id == "LIST") {
513+
var len = readUint32LittleEndian(string, offset + 4)
457514
var data = string.substr(offset + 4 + 4, len);
515+
// console.log(data);
458516
offset += 4 + 4 + len;
459517
chunks[id].push(parseRIFF(data));
460-
} else if (id == 'WEBP') {
461-
// Use (offset + 8) to skip past "VP8 "/"VP8L"/"VP8X" field after "WEBP"
462-
chunks[id].push(string.substr(offset + 8));
518+
} else if (id == "WEBP") {
519+
let vpVersion = string.substr(offset + 4, 4);
520+
switch (vpVersion) {
521+
case "VP8X":
522+
chunks[id].push(extractBitStreamFromVp8x(string.substr(offset + 8)));
523+
break;
524+
case "VP8 ":
525+
case "VP8L":
526+
// Use (offset + 8) to skip past "VP8 " / "VP8L" field after "WEBP"
527+
chunks[id].push(string.substr(offset + 8));
528+
break;
529+
default:
530+
console.error(`not supported webp version: \"${vpVersion}\"`);
531+
break;
532+
}
463533
offset = string.length;
464534
} else {
465535
// Unknown chunk type; push entire payload

0 commit comments

Comments
 (0)