picture-dimensionjs
Version:
picture-dimensionjs
184 lines (183 loc) • 5.96 kB
JavaScript
// 读取数据大小
var blockSize = 64;
var IMAGE_HEAD_SIGS = {
GIF: [0x47, 0x49, 0x46],
PNG: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],
JPG: [0xff, 0xd8, 0xff, 0xe0],
BMP: [0x42, 0x4d]
};
function readUint32BE(bytes, start) {
var uarr = new Uint32Array(1);
uarr[0] = (bytes[start + 0] & 0xFF) << 24;
uarr[0] = uarr[0] | ((bytes[start + 1] & 0xFF) << 16);
uarr[0] = uarr[0] | ((bytes[start + 2] & 0xFF) << 8);
uarr[0] = uarr[0] | (bytes[start + 3] & 0xFF);
return uarr[0];
}
function readUint16BE(bytes, start) {
var uarr = new Uint32Array(1);
uarr[0] = (bytes[start + 0] & 0xFF) << 8;
uarr[0] = uarr[0] | (bytes[start + 1] & 0xFF);
return uarr[0];
}
//LE [0x01,0x02,0x03,0x04] -> 0x04030201
function readUint32LE(bytes, start) {
var uarr = new Uint32Array(1);
uarr[0] = (bytes[start + 3] & 0xFF) << 24;
uarr[0] = uarr[0] | ((bytes[start + 2] & 0xFF) << 16);
uarr[0] = uarr[0] | ((bytes[start + 1] & 0xFF) << 8);
uarr[0] = uarr[0] | (bytes[start + 0] & 0xFF);
return uarr[0];
}
function readUint16LE(bytes, start) {
var uarr = new Uint32Array(1);
uarr[0] = (bytes[start + 1] & 0xFF) << 8;
uarr[0] = uarr[0] | (bytes[start + 0] & 0xFF);
return uarr[0];
}
function readBlob(input, offset, end) {
return new Promise(function (resole, reject) {
var fr = new FileReader();
fr.onload = function () {
var result = fr.result;
if (result) {
return resole(new Uint8Array(result));
}
resole(null);
};
fr.onerror = reject;
// 读取数据
fr.readAsArrayBuffer(input.slice(offset, end));
});
}
function readJPG(input, bufferOffset, bytes, dim, byteOffset) {
if (byteOffset === void 0) { byteOffset = 0; }
var offset = 0;
var M_SOF0 = 0xC0; /* Start Of Frame N */
var M_SOF1 = 0xC1; /* N indicates which compression process */
var M_SOF2 = 0xC2; /* Only SOF0-SOF2 are now in common use */
var M_SOF3 = 0xC3;
var M_SOF5 = 0xC5; /* NB: codes C4 and CC are NOT SOF markers */
var M_SOF6 = 0xC6;
var M_SOF7 = 0xC7;
var M_SOF9 = 0xC9;
var M_SOF10 = 0xCA;
var M_SOF11 = 0xCB;
var M_SOF13 = 0xCD;
var M_SOF14 = 0xCE;
var M_SOF15 = 0xCF;
outer: for (var i = byteOffset; i < bytes.length; i++) {
if (bytes[i] === 0xFF) {
// 判断当前是否是最后一个区间
if (i + 1 === bytes.length) {
offset = i;
break;
}
switch (bytes[i + 1]) {
case M_SOF0:
case M_SOF1:
case M_SOF2:
case M_SOF3:
case M_SOF5:
case M_SOF6:
case M_SOF7:
case M_SOF9:
case M_SOF10:
case M_SOF11:
case M_SOF13:
case M_SOF14:
case M_SOF15:
{
if (bytes.length > i + 9) {
//高在前,宽在后。
dim.width = readUint16BE(bytes, i + 7);
dim.height = readUint16BE(bytes, i + 5);
offset = 0;
break outer;
}
offset = i;
break outer;
}
default:
offset = i;
break;
}
}
else {
offset = i;
}
}
if (offset === 0) {
return Promise.resolve(dim);
}
var end = Math.min(input.size, bufferOffset + blockSize);
if (bufferOffset === end) {
return Promise.resolve(dim);
}
return readBlob(input, bufferOffset, end).then(function (chunk) {
if (!chunk) {
return dim;
}
var sub = bytes.subarray(offset);
var n = new Uint8Array(sub.length + chunk.length);
n.set(sub);
n.set(chunk, sub.length);
return readJPG(input, end, n, dim);
});
}
/**
* 分析文件数据
* @param input
* @param dim
* @param offset 偏移量
*/
function read(input, dim, offset) {
if (offset === void 0) { offset = 0; }
var end = Math.min(input.size, offset + blockSize);
if (offset === end) {
return Promise.resolve(dim);
}
return readBlob(input, offset, end).then(function (bytes) {
if (!bytes) {
return dim;
}
// png
if (bytes.slice(0, 8).toString() === IMAGE_HEAD_SIGS.PNG.toString()) {
dim.ext = "PNG";
dim.width = readUint32BE(bytes, 16);
dim.height = readUint32BE(bytes, 20);
return dim;
// bmp
}
else if (bytes.slice(0, 2).toString() === IMAGE_HEAD_SIGS.BMP.toString()) {
//虽然格式为4字节,这里只取2字节,确保height为正数。为负数时,图像为倒置图像。
dim.ext = "BMP";
dim.height = readUint16LE(bytes, 22);
dim.width = readUint16LE(bytes, 18);
return dim;
// gif
}
else if (bytes.slice(0, 3).toString() === IMAGE_HEAD_SIGS.GIF.toString()) {
dim.ext = 'GIF';
dim.width = readUint16LE(bytes, 6);
dim.height = readUint16LE(bytes, 8);
// return { width, height }
return dim;
// jpg
}
else if (bytes.slice(0, 4).toString() === IMAGE_HEAD_SIGS.JPG.toString()) {
dim.ext = "JPG";
return readJPG(input, end, bytes, dim, 0);
}
else {
return dim;
}
});
}
export default function dimensions(input) {
var dim = { ext: "", width: NaN, height: NaN };
if (input.size === 0) {
return Promise.resolve(dim);
}
return read(input, dim);
}