我在 Node.js 中发现了一个 JPEG 解析函数,我正在尝试将其改编为在浏览器环境中使用。原始代码可以在这里找到。
原始代码使用Node.js的Buffer类。因为我想将它用于浏览器环境,所以我们必须使用
DataView.getUint16(0, false /* big endian */)
而不是 buffer.readUInt16BE(0) /*BE = big endian */
有趣的是,DataView 在 NodeJs 中也可用,因此结果可能是跨环境的。
这是我迄今为止发现的:
j
有助于获得第一次迭代的正确偏移量,因为缓冲区的前 4 个字节被切片: let j=4 // match the buffer slicing above
j+=2; // match the buffer slicing below ( i + 2 )
buffer = buffer.slice(i + 2); // Buffer is sliced of two bytes, 0 offset is now 2 bytes further ?
这是添加日志记录的功能
function calculate (buffer) {
// Skip 4 chars, they are for signature
buffer = buffer.slice(4);
let j=4 // match the buffer slicing above
let aDataView=new DataView(buffer.buffer);
var i, next;
while (buffer.length) {
// read length of the next block
i = buffer.readUInt16BE(0);
console.log("i="+i,"read="+aDataView.getUint16(j,false));
j+=2; // match the buffer slicing below ( i + 2 )
// ensure correct format
validateBuffer(buffer, i);
// 0xFFC0 is baseline standard(SOF)
// 0xFFC1 is baseline optimized(SOF)
// 0xFFC2 is progressive(SOF2)
next = buffer[i + 1];
if (next === 0xC0 || next === 0xC1 || next === 0xC2) {
return extractSize(buffer, i + 5);
}
// move to the next block
buffer = buffer.slice(i + 2);
}
throw new TypeError('Invalid JPG, no size found');
}
此图片的实际结果:
node .\start.js
i=16 read=16 # Seems to be the correct offset
i=91 read=19014 # Wrong offset
i=132 read=18758
到目前为止我的调试步骤是: 从 npm 安装了 buffer-image-size
npm install buffer-image-size --save
start.js写成如下
var sizeOf = require('buffer-image-size');
const fs = require('fs');
fileBuffer = fs.readFileSync("flowers.jpg");
var dimensions = sizeOf(fileBuffer);
console.log(dimensions.width, dimensions.height);
编辑“node_modules uffer-image-size\lib ypes\jpg.js”添加提到的行和日志记录
你有什么提示吗
j
上加 2 并不能帮助获得正确的偏移量。我感谢任何有关解决此问题的见解或指导。谢谢!
是的,避免提前偏移并重新切片缓冲区,这只会让您感到困惑。我会写
function calculate(typedArray) {
const view = new DataView(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength);
let i = 0;
// Skip 4 chars, they are for signature
i += 4;
while (i < view.length) {
// read length of the next block
const blockLen = view.getUint16(i, false /* big endian */);
// ensure correct format
// index should be within buffer limits
if (i + blockLen > view.length) {
throw new TypeError('Corrupt JPG, exceeded buffer limits');
}
// Every JPEG block must begin with a 0xFF
if (view.getUint8(i + blockLen) !== 0xFF) {
throw new TypeError('Invalid JPG, marker table corrupted');
}
// 0xFFC0 is baseline standard(SOF)
// 0xFFC1 is baseline optimized(SOF)
// 0xFFC2 is progressive(SOF2)
const next = view.getUint8(i + blockLen + 1);
if (next === 0xC0 || next === 0xC1 || next === 0xC2) {
return extractSize(view, i + blockLen + 5);
}
// move to the next block
i += blockLen + 2;
}
throw new TypeError('Invalid JPG, no size found');
}