image-in-browser
Version:
Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)
256 lines • 6.7 kB
JavaScript
import { readUshort, readUint, readUTF8, writeUint, writeUshort, writeUTF8, sizeUTF8, } from './bin.js';
import { inflate as f_inflate, deflateRaw as f_deflateRaw } from './f.js';
const crc = {
table: (function () {
const tab = new Uint32Array(256);
for (let n = 0; n < 256; n++) {
let c = n;
for (let k = 0; k < 8; k++) {
if (c & 1)
c = 0xedb88320 ^ (c >>> 1);
else
c >>>= 1;
}
tab[n] = c;
}
return tab;
})(),
update: function (c, buf, off, len) {
for (let i = 0; i < len; i++)
c = crc.table[(c ^ buf[off + i]) & 0xff] ^ (c >>> 8);
return c;
},
crc: function (b, o, l) {
return crc.update(0xffffffff, b, o, l) ^ 0xffffffff;
},
};
function _readLocal(data, o, out, csize, usize, onlyNames) {
const rUs = readUshort;
const rUi = readUint;
const sign = rUi(data, o);
o += 4;
const ver = rUs(data, o);
o += 2;
const gpflg = rUs(data, o);
o += 2;
const cmpr = rUs(data, o);
o += 2;
const time = rUi(data, o);
o += 4;
const crc32 = rUi(data, o);
o += 4;
o += 8;
const nlen = rUs(data, o);
o += 2;
const elen = rUs(data, o);
o += 2;
const name = readUTF8(data, o, nlen);
o += nlen;
o += elen;
if (onlyNames) {
out[name] = { size: usize, csize: csize };
return;
}
const file = new Uint8Array(data.buffer, o);
if (cmpr === 0)
out[name] = new Uint8Array(file.buffer.slice(o, o + csize));
else if (cmpr === 8) {
const buf = new Uint8Array(usize);
inflateRaw(file, buf);
out[name] = buf;
}
else
throw new Error(`unknown compression method: ${cmpr}`);
}
function _noNeed(fn) {
var _a;
const ext = (_a = fn.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
return 'png,jpg,jpeg,zip'.indexOf(ext !== null && ext !== void 0 ? ext : '') !== -1;
}
function _writeHeader(data, o, p, obj, t, roff) {
const wUi = writeUint;
const wUs = writeUshort;
const file = obj.file;
wUi(data, o, t === 0 ? 0x04034b50 : 0x02014b50);
o += 4;
if (t === 1)
o += 2;
wUs(data, o, 20);
o += 2;
wUs(data, o, 0);
o += 2;
wUs(data, o, obj.cpr ? 8 : 0);
o += 2;
wUi(data, o, 0);
o += 4;
wUi(data, o, obj.crc);
o += 4;
wUi(data, o, file.length);
o += 4;
wUi(data, o, obj.usize);
o += 4;
wUs(data, o, sizeUTF8(p));
o += 2;
wUs(data, o, 0);
o += 2;
if (t === 1) {
o += 2;
o += 2;
o += 6;
wUi(data, o, roff);
o += 4;
}
const nlen = writeUTF8(data, o, p);
o += nlen;
if (t === 0) {
data.set(file, o);
o += file.length;
}
return o;
}
function _adler(data, o, len) {
let a = 1;
let b = 0;
let off = o;
const end = o + len;
while (off < end) {
const eend = Math.min(off + 5552, end);
while (off < eend) {
a += data[off++];
b += a;
}
a %= 65521;
b %= 65521;
}
return (b << 16) | a;
}
export function parse(buf, onlyNames) {
const rUs = readUshort;
const rUi = readUint;
let o = 0;
const out = {};
const data = new Uint8Array(buf);
let eocd = data.length - 4;
while (rUi(data, eocd) !== 0x06054b50)
eocd--;
o = eocd;
o += 4;
o += 4;
const cnu = rUs(data, o);
o += 2;
const cnt = rUs(data, o);
o += 2;
const csize = rUi(data, o);
o += 4;
const coffs = rUi(data, o);
o += 4;
o = coffs;
for (let i = 0; i < cnu; i++) {
const sign = rUi(data, o);
o += 4;
o += 4;
o += 4;
o += 4;
const crc32 = rUi(data, o);
o += 4;
const csize = rUi(data, o);
o += 4;
const usize = rUi(data, o);
o += 4;
const nl = rUs(data, o);
const el = rUs(data, o + 2);
const cl = rUs(data, o + 4);
o += 6;
o += 8;
const roff = rUi(data, o);
o += 4;
o += nl + el + cl;
_readLocal(data, roff, out, csize, usize, onlyNames);
}
return out;
}
export function encode(obj, noCmpr) {
if (noCmpr === undefined)
noCmpr = false;
let tot = 0;
const wUi = writeUint;
const wUs = writeUshort;
const zpd = {};
for (const p in obj) {
const cpr = !_noNeed(p) && !noCmpr;
const buf = obj[p];
const _crc = crc.crc(buf, 0, buf.length);
zpd[p] = {
cpr: cpr,
usize: buf.length,
crc: _crc,
file: cpr ? deflateRaw(buf) : buf,
};
}
for (const p in zpd)
tot += zpd[p].file.length + 30 + 46 + 2 * sizeUTF8(p);
tot += 22;
const data = new Uint8Array(tot);
let o = 0;
const fof = [];
for (const p in zpd) {
const file = zpd[p];
fof.push(o);
o = _writeHeader(data, o, p, file, 0);
}
let i = 0;
const ioff = o;
for (const p in zpd) {
const file = zpd[p];
fof.push(o);
o = _writeHeader(data, o, p, file, 1, fof[i++]);
}
const csize = o - ioff;
wUi(data, o, 0x06054b50);
o += 4;
o += 4;
wUs(data, o, i);
o += 2;
wUs(data, o, i);
o += 2;
wUi(data, o, csize);
o += 4;
wUi(data, o, ioff);
o += 4;
o += 2;
return data.buffer;
}
export function deflateRaw(data, opts) {
if (opts === undefined)
opts = { level: 6 };
const buf = new Uint8Array(50 + Math.floor(data.length * 1.1));
const off = f_deflateRaw(data, buf, 0, opts.level);
return new Uint8Array(buf.buffer, 0, off);
}
export function deflate(data, opts) {
if (opts === undefined)
opts = { level: 6 };
let off = 0;
const buf = new Uint8Array(50 + Math.floor(data.length * 1.1));
buf[off] = 120;
buf[off + 1] = 156;
off += 2;
off = f_deflateRaw(data, buf, off, opts.level);
const crc = _adler(data, 0, data.length);
buf[off + 0] = (crc >>> 24) & 255;
buf[off + 1] = (crc >>> 16) & 255;
buf[off + 2] = (crc >>> 8) & 255;
buf[off + 3] = (crc >>> 0) & 255;
return new Uint8Array(buf.buffer, 0, off + 4);
}
export function inflate(file, buf) {
const CMF = file[0];
const FLG = file[1];
const CM = CMF & 15;
const CINFO = CMF >>> 4;
return inflateRaw(new Uint8Array(file.buffer, file.byteOffset + 2, file.length - 6), buf);
}
export function inflateRaw(file, buf) {
return f_inflate(file, buf);
}
//# sourceMappingURL=packer.js.map