Comparing version
{ | ||
"name": "upng-js", | ||
"description": "Small, fast and advanced PNG / APNG encoder and decoder", | ||
"version": "2.0.0", | ||
"version": "2.1.0", | ||
"homepage": "https://github.com/photopea/UPNG.js", | ||
@@ -6,0 +6,0 @@ "author": "photopea (https://github.com/photopea)", |
@@ -7,3 +7,3 @@ # UPNG.js | ||
* [UPNG.Photopea.com](http://upng.photopea.com) - a separate minifier app, that uses UPNG.js | ||
* Support us by [making a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ivan%2ekuckir%40gmail%2ecom&lc=CZ&item_name=UPNG%2ejs¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). | ||
* Support us by [making a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ivan%40kuckir%2ecom&lc=CZ&item_name=UPNG%2ejs¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). | ||
@@ -10,0 +10,0 @@ Download and include the `UPNG.js` file in your code, or get it from NPM: |
830
UPNG.js
@@ -0,1 +1,2 @@ | ||
;(function(){ | ||
@@ -10,3 +11,5 @@ var UPNG = {}; | ||
(function(UPNG, pako){ | ||
@@ -53,6 +56,8 @@ | ||
var rs = UPNG._bin.readUshort; | ||
//console.log(ctype, depth); | ||
if (ctype==6) { // RGB + alpha | ||
var qarea = area<<2; | ||
if(depth== 8) for(var i=0; i<qarea;i++) { bf[i] = data[i]; /*if((i&3)==3) bf[i]=255;*/ } | ||
if(depth== 8) for(var i=0; i<qarea;i++) { bf[i] = data[i]; /*if((i&3)==3 && data[i]!=0) bf[i]=255;*/ } | ||
if(depth==16) for(var i=0; i<qarea;i++) { bf[i] = data[i<<1]; } | ||
@@ -70,2 +75,3 @@ } | ||
var p=out.tabs["PLTE"], ap=out.tabs["tRNS"], tl=ap?ap.length:0; | ||
//console.log(p, ap); | ||
if(depth==1) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w; | ||
@@ -97,381 +103,4 @@ for(var i=0; i<w; i++) { var qi=(t0+i)<<2, j=((data[s0+(i>>3)]>>(7-((i&7)<<0)))& 1), cj=3*j; bf[qi]=p[cj]; bf[qi+1]=p[cj+1]; bf[qi+2]=p[cj+2]; bf[qi+3]=(j<tl)?ap[j]:255; } | ||
UPNG.encode = function(bufs, w, h, ps, dels) | ||
{ | ||
if(ps==null) ps=0; | ||
var data = new Uint8Array(bufs[0].byteLength*bufs.length+100); | ||
var wr=[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; | ||
for(var i=0; i<8; i++) data[i]=wr[i]; | ||
var offset = 8, bin = UPNG._bin, crc = UPNG.crc.crc, wUi = bin.writeUint, wUs = bin.writeUshort, wAs = bin.writeASCII; | ||
var nimg = UPNG.encode.compressPNG(bufs, w, h, ps); | ||
wUi(data,offset, 13); offset+=4; | ||
wAs(data,offset,"IHDR"); offset+=4; | ||
wUi(data,offset,w); offset+=4; | ||
wUi(data,offset,h); offset+=4; | ||
data[offset] = nimg.depth; offset++; // depth | ||
data[offset] = nimg.ctype; offset++; // ctype | ||
data[offset] = 0; offset++; // compress | ||
data[offset] = 0; offset++; // filter | ||
data[offset] = 0; offset++; // interlace | ||
wUi(data,offset,crc(data,offset-17,17)); offset+=4; // crc | ||
// 9 bytes to say, that it is sRGB | ||
wUi(data,offset, 1); offset+=4; | ||
wAs(data,offset,"sRGB"); offset+=4; | ||
data[offset] = 1; offset++; | ||
wUi(data,offset,crc(data,offset-5,5)); offset+=4; // crc | ||
var anim = bufs.length>1; | ||
if(anim) { | ||
wUi(data,offset, 8); offset+=4; | ||
wAs(data,offset,"acTL"); offset+=4; | ||
wUi(data,offset, bufs.length); offset+=4; | ||
wUi(data,offset, 0); offset+=4; | ||
wUi(data,offset,crc(data,offset-12,12)); offset+=4; // crc | ||
} | ||
if(nimg.ctype==3) { | ||
var dl = nimg.plte.length; | ||
wUi(data,offset, dl*3); offset+=4; | ||
wAs(data,offset,"PLTE"); offset+=4; | ||
for(var i=0; i<dl; i++){ | ||
var ti=i*3, c=nimg.plte[i], r=(c)&255, g=(c>>8)&255, b=(c>>16)&255; | ||
data[offset+ti+0]=r; data[offset+ti+1]=g; data[offset+ti+2]=b; | ||
} | ||
offset+=dl*3; | ||
wUi(data,offset,crc(data,offset-dl*3-4,dl*3+4)); offset+=4; // crc | ||
if(nimg.gotAlpha) { | ||
wUi(data,offset, dl); offset+=4; | ||
wAs(data,offset,"tRNS"); offset+=4; | ||
for(var i=0; i<dl; i++) data[offset+i]=(nimg.plte[i]>>24)&255; | ||
offset+=dl; | ||
wUi(data,offset,crc(data,offset-dl-4,dl+4)); offset+=4; // crc | ||
} | ||
} | ||
var fi = 0; | ||
for(var j=0; j<nimg.frames.length; j++) | ||
{ | ||
var fr = nimg.frames[j]; | ||
if(anim) { | ||
wUi(data,offset, 26); offset+=4; | ||
wAs(data,offset,"fcTL"); offset+=4; | ||
wUi(data, offset, fi++); offset+=4; | ||
wUi(data, offset, fr.rect.width ); offset+=4; | ||
wUi(data, offset, fr.rect.height); offset+=4; | ||
wUi(data, offset, fr.rect.x); offset+=4; | ||
wUi(data, offset, fr.rect.y); offset+=4; | ||
wUs(data, offset, dels[j]); offset+=2; | ||
wUs(data, offset, 1000); offset+=2; | ||
data[offset] = fr.dispose; offset++; // dispose | ||
data[offset] = fr.blend ; offset++; // blend | ||
wUi(data,offset,crc(data,offset-30,30)); offset+=4; // crc | ||
} | ||
var imgd = fr.cimg, dl = imgd.length; | ||
wUi(data,offset, dl+(j==0?0:4)); offset+=4; | ||
var ioff = offset; | ||
wAs(data,offset,(j==0)?"IDAT":"fdAT"); offset+=4; | ||
if(j!=0) { wUi(data, offset, fi++); offset+=4; } | ||
for(var i=0; i<dl; i++) data[offset+i] = imgd[i]; | ||
offset += dl; | ||
wUi(data,offset,crc(data,ioff,offset-ioff)); offset+=4; // crc | ||
} | ||
wUi(data,offset, 0); offset+=4; | ||
wAs(data,offset,"IEND"); offset+=4; | ||
wUi(data,offset,crc(data,offset-4,4)); offset+=4; // crc | ||
return data.buffer.slice(0,offset); | ||
} | ||
UPNG.encode.compressPNG = function(bufs, w, h, ps) | ||
{ | ||
var out = UPNG.encode.compress(bufs, w, h, ps, false); | ||
for(var i=0; i<bufs.length; i++) { | ||
var frm = out.frames[i], nw=frm.rect.width, nh=frm.rect.height, bpl=frm.bpl, bpp=frm.bpp; | ||
var fdata = new Uint8Array(nh*bpl+nh); | ||
frm.cimg = UPNG.encode._filterZero(frm.img,nh,bpp,bpl,fdata); | ||
} | ||
return out; | ||
} | ||
UPNG.encode.compress = function(bufs, w, h, ps, forGIF) | ||
{ | ||
if(ps!=0) bufs = UPNG.quantize(bufs, ps-1, forGIF); | ||
var ctype = 6, depth = 8, plte=[0], bpp = 4; | ||
var gotAlpha=false, cmap={}; cmap[0]=0; | ||
for(var j=0; j<bufs.length; j++) // when not quantized, other frames can contain colors, that are not in an initial frame | ||
{ | ||
var img = new Uint8Array(bufs[j]), img32 = new Uint32Array(img.buffer); | ||
var pr32 = (j==0 ? null : new Uint32Array(bufs[j-1])); | ||
for(var i=0; i<img.length; i+=4) { | ||
var c = img32[i>>2]; if((j==0 || c!=pr32[i>>2]) && plte.length<600 && cmap[c]==null) { cmap[c]=plte.length; plte.push(c); } | ||
gotAlpha = gotAlpha || (img[i+3]!=255); | ||
} | ||
} | ||
var brute = forGIF; | ||
if(!gotAlpha) brute = false; //console.log(gotAlpha, brute); | ||
var cc=plte.length; //console.log(cc); | ||
if(cc<=256) { | ||
if(cc<= 2) depth=1; else if(cc<= 4) depth=2; else if(cc<=16) depth=4; else depth=8; | ||
if(forGIF) depth=8; | ||
gotAlpha = true; | ||
} | ||
var frms = []; | ||
for(var j=0; j<bufs.length; j++) | ||
{ | ||
var cimg = new Uint8Array(bufs[j]), cimg32 = new Uint32Array(cimg.buffer); | ||
var nx=0, ny=0, nw=w, nh=h, blend=0; | ||
if(j!=0 && !brute) { | ||
var tlim = (forGIF || j==1 || frms[frms.length-2].dispose==2)?1:2, tstp = 0, tarea = 1e9; | ||
for(var it=0; it<tlim; it++) | ||
{ | ||
var pimg = new Uint8Array(bufs[j-1-it]), p32 = new Uint32Array(bufs[j-1-it]); | ||
var mix=w,miy=h,max=-1,may=-1; | ||
for(var y=0; y<h; y++) for(var x=0; x<w; x++) { | ||
var i = y*w+x; | ||
if(cimg32[i]!=p32[i]) { | ||
if(x<mix) mix=x; if(x>max) max=x; | ||
if(y<miy) miy=y; if(y>may) may=y; | ||
} | ||
} | ||
var sarea = (max==-1) ? 1 : (max-mix+1)*(may-miy+1); | ||
if(sarea<tarea) { | ||
tarea = sarea; tstp = it; | ||
if(max==-1) { nx=ny=0; nw=nh=1; } | ||
else { nx = mix; ny = miy; nw = max-mix+1; nh = may-miy+1; } | ||
} | ||
} | ||
var pimg = new Uint8Array(bufs[j-1-tstp]); | ||
if(tstp==1) frms[frms.length-1].dispose = 2; | ||
var nimg = new Uint8Array(nw*nh*4), nimg32 = new Uint32Array(nimg.buffer); | ||
UPNG. _copyTile(pimg,w,h, nimg,nw,nh, -nx,-ny, 0); | ||
if(UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 3)) { | ||
UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 2); blend = 1; | ||
} | ||
else { | ||
UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 0); blend = 0; | ||
} | ||
cimg = nimg; cimg32 = new Uint32Array(cimg.buffer); | ||
} | ||
var bpl = 4*nw; | ||
if(cc<=256) { | ||
bpl = Math.ceil(depth*nw/8); | ||
var nimg = new Uint8Array(bpl*nh); | ||
for(var y=0; y<nh; y++) { var i=y*bpl, ii=y*nw; | ||
if(depth==1) for(var x=0; x<nw; x++) nimg[i+(x>>3)] |= (cmap[cimg32[ii+x]]<<(7-(x&7) )); | ||
if(depth==2) for(var x=0; x<nw; x++) nimg[i+(x>>2)] |= (cmap[cimg32[ii+x]]<<(6-(x&3)*2)); | ||
if(depth==4) for(var x=0; x<nw; x++) nimg[i+(x>>1)] |= (cmap[cimg32[ii+x]]<<(4-(x&1)*4)); | ||
if(depth==8) for(var x=0; x<nw; x++) nimg[i+ x ] = cmap[cimg32[ii+x]]; | ||
} | ||
cimg=nimg; ctype=3; bpp=1; | ||
} | ||
else if(gotAlpha==false && bufs.length==1) { // some next "reduced" frames may contain alpha for blending | ||
var nimg = new Uint8Array(nw*nh*3), area=nw*nh; | ||
for(var i=0; i<area; i++) { var ti=i*3, qi=i*4; nimg[ti]=cimg[qi]; nimg[ti+1]=cimg[qi+1]; nimg[ti+2]=cimg[qi+2]; } | ||
cimg=nimg; ctype=2; bpp=3; bpl=3*nw; | ||
} | ||
frms.push({rect:{x:nx,y:ny,width:nw,height:nh}, img:cimg, bpl:bpl, bpp:bpp, blend:blend, dispose:brute?1:0}); | ||
} | ||
return {ctype:ctype, depth:depth, plte:plte, gotAlpha:gotAlpha, frames:frms }; | ||
} | ||
UPNG.encode._filterZero = function(img,h,bpp,bpl,data) | ||
{ | ||
var fls = []; | ||
for(var t=0; t<5; t++) { if(h*bpl>500000 && (t==2 || t==3 || t==4)) continue; | ||
for(var y=0; y<h; y++) UPNG.encode._filterLine(data, img, y, bpl, bpp, t); | ||
fls.push(pako["deflate"](data)); if(bpp==1) break; | ||
} | ||
var ti, tsize=1e9; | ||
for(var i=0; i<fls.length; i++) if(fls[i].length<tsize) { ti=i; tsize=fls[i].length; } | ||
return fls[ti]; | ||
} | ||
UPNG.encode._filterLine = function(data, img, y, bpl, bpp, type) | ||
{ | ||
var i = y*bpl, di = i+y, paeth = UPNG.decode._paeth | ||
data[di]=type; di++; | ||
if(type==0) for(var x=0; x<bpl; x++) data[di+x] = img[i+x]; | ||
else if(type==1) { | ||
for(var x= 0; x<bpp; x++) data[di+x] = img[i+x]; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]-img[i+x-bpp]+256)&255; | ||
} | ||
else if(y==0) { | ||
for(var x= 0; x<bpp; x++) data[di+x] = img[i+x]; | ||
if(type==2) for(var x=bpp; x<bpl; x++) data[di+x] = img[i+x]; | ||
if(type==3) for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x] - (img[i+x-bpp]>>1) +256)&255; | ||
if(type==4) for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x] - paeth(img[i+x-bpp], 0, 0) +256)&255; | ||
} | ||
else { | ||
if(type==2) { for(var x= 0; x<bpl; x++) data[di+x] = (img[i+x]+256 - img[i+x-bpl])&255; } | ||
if(type==3) { for(var x= 0; x<bpp; x++) data[di+x] = (img[i+x]+256 - (img[i+x-bpl]>>1))&255; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]+256 - ((img[i+x-bpl]+img[i+x-bpp])>>1))&255; } | ||
if(type==4) { for(var x= 0; x<bpp; x++) data[di+x] = (img[i+x]+256 - paeth(0, img[i+x-bpl], 0))&255; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]+256 - paeth(img[i+x-bpp], img[i+x-bpl], img[i+x-bpp-bpl]))&255; } | ||
} | ||
} | ||
UPNG.crc = { | ||
table : ( function() { | ||
var tab = new Uint32Array(256); | ||
for (var n=0; n<256; n++) { | ||
var c = n; | ||
for (var k=0; k<8; k++) { | ||
if (c & 1) c = 0xedb88320 ^ (c >>> 1); | ||
else c = c >>> 1; | ||
} | ||
tab[n] = c; } | ||
return tab; })(), | ||
update : function(c, buf, off, len) { | ||
for (var i=0; i<len; i++) c = UPNG.crc.table[(c ^ buf[off+i]) & 0xff] ^ (c >>> 8); | ||
return c; | ||
}, | ||
crc : function(b,o,l) { return UPNG.crc.update(0xffffffff,b,o,l) ^ 0xffffffff; } | ||
} | ||
UPNG.quantize = function(bufs, ps, roundAlpha) | ||
{ | ||
var imgs = []; | ||
for(var i=0; i<bufs.length; i++) imgs.push(UPNG.quantize.alphaMul(new Uint8Array(bufs[i]), roundAlpha)); | ||
var nimg = imgs[0]; | ||
var area=nimg.length>>2; | ||
var plte=[], used=[], pr=0, plim = Math.max(100, 10*ps); | ||
while(true) { | ||
used=[]; plte=[]; | ||
var msk = 0xff - ((1<<pr)-1), add = ((1<<pr))>>1; | ||
for(var i=0; i<area; i++) { var qi=i<<2; var r=nimg[qi],g=nimg[qi+1],b=nimg[qi+2],a=nimg[qi+3]; | ||
var nr=(r&msk)+add, ng=(g&msk)+add, nb=(b&msk)+add, na=(a&msk)+add, key=(na<<24)|(nb<<16)|(ng<<8)|nr; | ||
if(used[key]) { var pv=plte[used[key]]; pv.occ++; } | ||
else { used[key]=plte.length; plte.push( {occ:1, r:nr,g:ng,b:nb,a:na} ); } | ||
if(plte.length>plim) break; | ||
} | ||
if(plte.length>plim) { pr++; continue; } | ||
break; | ||
} | ||
if(pr==0 && plte.length<=ps) return bufs; | ||
plte.sort(function(a,b) {return b.occ-a.occ;}); | ||
ps = Math.min(ps, plte.length); | ||
var nplte = new Uint8Array(ps*4); | ||
for(var i=0; i<ps; i++) { var qi=i<<2,c=plte[i]; nplte[qi]=c.r; nplte[qi+1]=c.g; nplte[qi+2]=c.b; nplte[qi+3]=c.a; } | ||
plte = nplte; //*/ | ||
var icnt = Math.max(1, Math.min(10, Math.floor(1024/ps))); | ||
var pind = new Uint16Array(area); | ||
for(var it=0; it<icnt; it++) | ||
{ | ||
UPNG.quantize.kMeans(nimg, plte, pind, ps, true); | ||
} | ||
UPNG.quantize.applyPalette(nimg, plte, pind); | ||
// remap remaining frames according to palette | ||
for(var i=1; i<imgs.length; i++) { | ||
UPNG.quantize.kMeans(imgs[i], plte, pind, ps, false); // "classify" into pind | ||
UPNG.quantize.applyPalette(imgs[i], plte, pind); // remap according to pind | ||
} | ||
//UPNG.quantize.dither(nimg, w,h, pind,plte, ps); // I think that (current) dithering is not worth it | ||
for(var i=0; i<bufs.length; i++) imgs[i] = imgs[i].buffer; | ||
return imgs; | ||
} | ||
UPNG.quantize.alphaMul = function(img, roundA) { | ||
var nimg = new Uint8Array(img.length), area = img.length>>2; | ||
for(var i=0; i<area; i++) { | ||
var qi=i<<2, ia=img[qi+3]; | ||
if(roundA) ia = ((ia<128))?0:255; | ||
var a = ia*(1/255); | ||
nimg[qi+0] = img[qi+0]*a; nimg[qi+1] = img[qi+1]*a; nimg[qi+2] = img[qi+2]*a; nimg[qi+3] = ia; | ||
} | ||
return nimg; | ||
} | ||
UPNG.quantize.applyPalette = function(nimg, plte, pind) | ||
{ | ||
var area = pind.length, rnd=Math.round; | ||
for(var i=0; i<area; i++) { | ||
var qi=i<<2, ci=pind[i], qci=ci<<2, ia = plte[qci+3]==0 ? 0 : 255/plte[qci+3]; | ||
nimg[qi+0] = rnd(plte[qci+0]*ia); nimg[qi+1] = rnd(plte[qci+1]*ia); nimg[qi+2] = rnd(plte[qci+2]*ia); nimg[qi+3] = plte[qci+3]; | ||
} | ||
} | ||
UPNG.quantize.kMeans = function(nimg, plte, pind, ps, update) | ||
{ | ||
var area = pind.length, rnd=Math.round, edist=UPNG.quantize.dist; | ||
var ndst=new Uint32Array(ps), nind=new Uint32Array(ps ); // for each color, find the nearest color (in palette) | ||
for(var i=0; i<ps; i++) { var qi=i<<2; | ||
var r=plte[qi], g=plte[qi+1], b=plte[qi+2], a=plte[qi+3]; | ||
var ci=0; cd=1e9; | ||
for(var j=0; j<ps; j++) { if(j==i) continue; | ||
var dst = edist(r,g,b,a,plte,j<<2); | ||
if(dst<cd) { ci=j; cd=dst; } | ||
} | ||
ndst[i]=cd; nind[i]=ci; | ||
} | ||
var hist=new Uint32Array(ps), nplt=new Uint32Array(ps*4); // classify each pixel | ||
for(var i=0; i<area; i++) { var qi=i<<2; | ||
var r=nimg[qi], g=nimg[qi+1], b=nimg[qi+2], a=nimg[qi+3]; | ||
var ci=0, cd=1e9; | ||
ci=pind[i]; cd=edist(r,g,b,a,plte,ci<<2); if(cd<=(ndst[ci]>>1)) {} else | ||
for(var j=0; j<ps; j++) { | ||
var dst = edist(r,g,b,a,plte,j<<2); | ||
if(dst<cd) { ci=j; cd=dst; | ||
if(dst<=(ndst[ci]>>1)) break; | ||
var dst = edist(r,g,b,a,plte,nind[j]<<2); | ||
if(dst<=(ndst[ci]>>1)) { ci=nind[j]; break; } | ||
} | ||
} | ||
pind[i]=ci; hist[ci]++; var qci=ci<<2; | ||
nplt[qci]+=r; nplt[qci+1]+=g; nplt[qci+2]+=b; nplt[qci+3]+=a; | ||
} | ||
if(update) // update palette | ||
for(var i=0; i<ps; i++) { var qi=i<<2, den=1/hist[i]; | ||
plte[qi]=rnd(nplt[qi]*den); plte[qi+1]=rnd(nplt[qi+1]*den); plte[qi+2]=rnd(nplt[qi+2]*den); plte[qi+3]=rnd(nplt[qi+3]*den); | ||
} | ||
} | ||
UPNG.quantize.dist = function(r,g,b,a,ba,bi) | ||
{ | ||
var pr=ba[bi], pg=ba[bi+1], pb=ba[bi+2], pa=ba[bi+3]; | ||
return (pr-r)*(pr-r)+(pg-g)*(pg-g)+(pb-b)*(pb-b)+(pa-a)*(pa-a); | ||
} | ||
UPNG.quantize.dither = function(nimg, w, h, pind, plte, ps) | ||
{ | ||
var err = new Float32Array(w*h*4), i16 = 1/16; | ||
var edist = UPNG.quantize.dist, round=Math.round, qw=w<<2; | ||
for(var y=0; y<h; y++) | ||
for(var x=0; x<w; x++) { | ||
var i = y*w+x, qi=i<<2; | ||
for(var j=0; j<4; j++) err[qi+j] = Math.max(-8, Math.min(8, err[qi+j])); | ||
var r=round(nimg[qi]+err[qi]), g=round(nimg[qi+1]+err[qi+1]), b=round(nimg[qi+2]+err[qi+2]), a=round(nimg[qi+3]+err[qi+3]); | ||
var ci=0, cd=1e9; | ||
for(var j=0; j<ps; j++) { | ||
var dst = edist(r,g,b,a,plte,j<<2); | ||
if(dst<cd) { ci=j; cd=dst; } | ||
} | ||
pind[i]=ci; | ||
var ciq = ci<<2; | ||
var dr=r-plte[ciq], dg=g-plte[ciq+1], db=b-plte[ciq+2], da=a-plte[ciq+3]; | ||
err[qi +4+0] += (7*dr*i16); err[qi +4+1] += (7*dg*i16); err[qi +4+2] += (7*db*i16); err[qi +4+3] += (7*da*i16); | ||
err[qi+qw-4+0] += (3*dr*i16); err[qi+qw-4+1] += (3*dg*i16); err[qi+qw-4+2] += (3*db*i16); err[qi+qw-4+3] += (3*da*i16); | ||
err[qi+qw +0] += (5*dr*i16); err[qi+qw +1] += (5*dg*i16); err[qi+qw +2] += (5*db*i16); err[qi+qw +3] += (5*da*i16); | ||
err[qi+qw+4+0] += (1*dr*i16); err[qi+qw+4+1] += (1*dg*i16); err[qi+qw+4+2] += (1*db*i16); err[qi+qw+4+3] += (1*da*i16); | ||
} | ||
} | ||
UPNG.decode = function(buff) | ||
@@ -483,4 +112,7 @@ { | ||
var fd, foff = 0; // frames | ||
var mgck = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; | ||
for(var i=0; i<8; i++) if(data[i]!=mgck[i]) throw "The input is not a PNG file!"; | ||
while(true) | ||
while(offset<data.length) | ||
{ | ||
@@ -568,3 +200,3 @@ var len = bin.readUint(data, offset); offset += 4; | ||
} | ||
else { log("unknown chunk type", type, len); } | ||
//else { log("unknown chunk type", type, len); } | ||
offset += len; | ||
@@ -757,3 +389,439 @@ var crc = bin.readUint(data, offset); offset += 4; | ||
UPNG.encode = function(bufs, w, h, ps, dels, forbidPlte) | ||
{ | ||
if(ps==null) ps=0; | ||
if(forbidPlte==null) forbidPlte = false; | ||
var data = new Uint8Array(bufs[0].byteLength*bufs.length+100); | ||
var wr=[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; | ||
for(var i=0; i<8; i++) data[i]=wr[i]; | ||
var offset = 8, bin = UPNG._bin, crc = UPNG.crc.crc, wUi = bin.writeUint, wUs = bin.writeUshort, wAs = bin.writeASCII; | ||
var nimg = UPNG.encode.compressPNG(bufs, w, h, ps, forbidPlte); | ||
wUi(data,offset, 13); offset+=4; | ||
wAs(data,offset,"IHDR"); offset+=4; | ||
wUi(data,offset,w); offset+=4; | ||
wUi(data,offset,h); offset+=4; | ||
data[offset] = nimg.depth; offset++; // depth | ||
data[offset] = nimg.ctype; offset++; // ctype | ||
data[offset] = 0; offset++; // compress | ||
data[offset] = 0; offset++; // filter | ||
data[offset] = 0; offset++; // interlace | ||
wUi(data,offset,crc(data,offset-17,17)); offset+=4; // crc | ||
// 9 bytes to say, that it is sRGB | ||
wUi(data,offset, 1); offset+=4; | ||
wAs(data,offset,"sRGB"); offset+=4; | ||
data[offset] = 1; offset++; | ||
wUi(data,offset,crc(data,offset-5,5)); offset+=4; // crc | ||
var anim = bufs.length>1; | ||
if(anim) { | ||
wUi(data,offset, 8); offset+=4; | ||
wAs(data,offset,"acTL"); offset+=4; | ||
wUi(data,offset, bufs.length); offset+=4; | ||
wUi(data,offset, 0); offset+=4; | ||
wUi(data,offset,crc(data,offset-12,12)); offset+=4; // crc | ||
} | ||
if(nimg.ctype==3) { | ||
var dl = nimg.plte.length; | ||
wUi(data,offset, dl*3); offset+=4; | ||
wAs(data,offset,"PLTE"); offset+=4; | ||
for(var i=0; i<dl; i++){ | ||
var ti=i*3, c=nimg.plte[i], r=(c)&255, g=(c>>8)&255, b=(c>>16)&255; | ||
data[offset+ti+0]=r; data[offset+ti+1]=g; data[offset+ti+2]=b; | ||
} | ||
offset+=dl*3; | ||
wUi(data,offset,crc(data,offset-dl*3-4,dl*3+4)); offset+=4; // crc | ||
if(nimg.gotAlpha) { | ||
wUi(data,offset, dl); offset+=4; | ||
wAs(data,offset,"tRNS"); offset+=4; | ||
for(var i=0; i<dl; i++) data[offset+i]=(nimg.plte[i]>>24)&255; | ||
offset+=dl; | ||
wUi(data,offset,crc(data,offset-dl-4,dl+4)); offset+=4; // crc | ||
} | ||
} | ||
var fi = 0; | ||
for(var j=0; j<nimg.frames.length; j++) | ||
{ | ||
var fr = nimg.frames[j]; | ||
if(anim) { | ||
wUi(data,offset, 26); offset+=4; | ||
wAs(data,offset,"fcTL"); offset+=4; | ||
wUi(data, offset, fi++); offset+=4; | ||
wUi(data, offset, fr.rect.width ); offset+=4; | ||
wUi(data, offset, fr.rect.height); offset+=4; | ||
wUi(data, offset, fr.rect.x); offset+=4; | ||
wUi(data, offset, fr.rect.y); offset+=4; | ||
wUs(data, offset, dels[j]); offset+=2; | ||
wUs(data, offset, 1000); offset+=2; | ||
data[offset] = fr.dispose; offset++; // dispose | ||
data[offset] = fr.blend ; offset++; // blend | ||
wUi(data,offset,crc(data,offset-30,30)); offset+=4; // crc | ||
} | ||
var imgd = fr.cimg, dl = imgd.length; | ||
wUi(data,offset, dl+(j==0?0:4)); offset+=4; | ||
var ioff = offset; | ||
wAs(data,offset,(j==0)?"IDAT":"fdAT"); offset+=4; | ||
if(j!=0) { wUi(data, offset, fi++); offset+=4; } | ||
for(var i=0; i<dl; i++) data[offset+i] = imgd[i]; | ||
offset += dl; | ||
wUi(data,offset,crc(data,ioff,offset-ioff)); offset+=4; // crc | ||
} | ||
wUi(data,offset, 0); offset+=4; | ||
wAs(data,offset,"IEND"); offset+=4; | ||
wUi(data,offset,crc(data,offset-4,4)); offset+=4; // crc | ||
return data.buffer.slice(0,offset); | ||
} | ||
UPNG.encode.compressPNG = function(bufs, w, h, ps, forbidPlte) | ||
{ | ||
var out = UPNG.encode.compress(bufs, w, h, ps, false, forbidPlte); | ||
for(var i=0; i<bufs.length; i++) { | ||
var frm = out.frames[i], nw=frm.rect.width, nh=frm.rect.height, bpl=frm.bpl, bpp=frm.bpp; | ||
var fdata = new Uint8Array(nh*bpl+nh); | ||
frm.cimg = UPNG.encode._filterZero(frm.img,nh,bpp,bpl,fdata); | ||
} | ||
return out; | ||
} | ||
UPNG.encode.compress = function(bufs, w, h, ps, forGIF, forbidPlte) | ||
{ | ||
if(forbidPlte==null) forbidPlte = false; | ||
var ctype = 6, depth = 8, bpp = 4, alphaAnd=255 | ||
for(var j=0; j<bufs.length; j++) { // when not quantized, other frames can contain colors, that are not in an initial frame | ||
var img = new Uint8Array(bufs[j]), ilen = img.length; | ||
for(var i=0; i<ilen; i+=4) alphaAnd &= img[i+3]; | ||
} | ||
var gotAlpha = (alphaAnd)!=255; | ||
var cmap={}, plte=[]; if(bufs.length!=0) { cmap[0]=0; plte.push(0); if(ps!=0) ps--; } | ||
if(ps!=0) { | ||
var qres = UPNG.quantize(bufs, ps, forGIF); bufs = qres.bufs; | ||
for(var i=0; i<qres.plte.length; i++) { var c=qres.plte[i].est.rgba; if(cmap[c]==null) { cmap[c]=plte.length; plte.push(c); } } | ||
} | ||
else { | ||
// what if ps==0, but there are <=256 colors? we still need to detect, if the palette could be used | ||
for(var j=0; j<bufs.length; j++) { // when not quantized, other frames can contain colors, that are not in an initial frame | ||
var img32 = new Uint32Array(bufs[j]), ilen = img32.length; | ||
for(var i=0; i<ilen; i++) { | ||
var c = img32[i]; | ||
if((i<w || (c!=img32[i-1] && c!=img32[i-w])) && cmap[c]==null) { cmap[c]=plte.length; plte.push(c); if(plte.length>=300) break; } | ||
} | ||
} | ||
} | ||
var brute = gotAlpha ? forGIF : false; // brute : frames can only be copied, not "blended" | ||
var cc=plte.length; //console.log(cc); | ||
if(cc<=256 && forbidPlte==false) { | ||
if(cc<= 2) depth=1; else if(cc<= 4) depth=2; else if(cc<=16) depth=4; else depth=8; | ||
if(forGIF) depth=8; | ||
gotAlpha = true; | ||
} | ||
var frms = []; | ||
for(var j=0; j<bufs.length; j++) | ||
{ | ||
var cimg = new Uint8Array(bufs[j]), cimg32 = new Uint32Array(cimg.buffer); | ||
var nx=0, ny=0, nw=w, nh=h, blend=0; | ||
if(j!=0 && !brute) { | ||
var tlim = (forGIF || j==1 || frms[frms.length-2].dispose==2)?1:2, tstp = 0, tarea = 1e9; | ||
for(var it=0; it<tlim; it++) | ||
{ | ||
var pimg = new Uint8Array(bufs[j-1-it]), p32 = new Uint32Array(bufs[j-1-it]); | ||
var mix=w,miy=h,max=-1,may=-1; | ||
for(var y=0; y<h; y++) for(var x=0; x<w; x++) { | ||
var i = y*w+x; | ||
if(cimg32[i]!=p32[i]) { | ||
if(x<mix) mix=x; if(x>max) max=x; | ||
if(y<miy) miy=y; if(y>may) may=y; | ||
} | ||
} | ||
var sarea = (max==-1) ? 1 : (max-mix+1)*(may-miy+1); | ||
if(sarea<tarea) { | ||
tarea = sarea; tstp = it; | ||
if(max==-1) { nx=ny=0; nw=nh=1; } | ||
else { nx = mix; ny = miy; nw = max-mix+1; nh = may-miy+1; } | ||
} | ||
} | ||
var pimg = new Uint8Array(bufs[j-1-tstp]); | ||
if(tstp==1) frms[frms.length-1].dispose = 2; | ||
var nimg = new Uint8Array(nw*nh*4), nimg32 = new Uint32Array(nimg.buffer); | ||
UPNG. _copyTile(pimg,w,h, nimg,nw,nh, -nx,-ny, 0); | ||
if(UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 3)) { | ||
UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 2); blend = 1; | ||
} | ||
else { | ||
UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 0); blend = 0; | ||
} | ||
cimg = nimg; cimg32 = new Uint32Array(cimg.buffer); | ||
} | ||
var bpl = 4*nw; | ||
if(cc<=256 && forbidPlte==false) { | ||
bpl = Math.ceil(depth*nw/8); | ||
var nimg = new Uint8Array(bpl*nh); | ||
for(var y=0; y<nh; y++) { var i=y*bpl, ii=y*nw; | ||
if (depth==8) for(var x=0; x<nw; x++) nimg[i+(x) ] = (cmap[cimg32[ii+x]] ); | ||
else if(depth==4) for(var x=0; x<nw; x++) nimg[i+(x>>1)] |= (cmap[cimg32[ii+x]]<<(4-(x&1)*4)); | ||
else if(depth==2) for(var x=0; x<nw; x++) nimg[i+(x>>2)] |= (cmap[cimg32[ii+x]]<<(6-(x&3)*2)); | ||
else if(depth==1) for(var x=0; x<nw; x++) nimg[i+(x>>3)] |= (cmap[cimg32[ii+x]]<<(7-(x&7)*1)); | ||
} | ||
cimg=nimg; ctype=3; bpp=1; | ||
} | ||
else if(gotAlpha==false && bufs.length==1) { // some next "reduced" frames may contain alpha for blending | ||
var nimg = new Uint8Array(nw*nh*3), area=nw*nh; | ||
for(var i=0; i<area; i++) { var ti=i*3, qi=i*4; nimg[ti]=cimg[qi]; nimg[ti+1]=cimg[qi+1]; nimg[ti+2]=cimg[qi+2]; } | ||
cimg=nimg; ctype=2; bpp=3; bpl=3*nw; | ||
} | ||
frms.push({rect:{x:nx,y:ny,width:nw,height:nh}, img:cimg, bpl:bpl, bpp:bpp, blend:blend, dispose:brute?1:0}); | ||
} | ||
return {ctype:ctype, depth:depth, plte:plte, gotAlpha:gotAlpha, frames:frms }; | ||
} | ||
UPNG.encode._filterZero = function(img,h,bpp,bpl,data) | ||
{ | ||
var fls = []; | ||
for(var t=0; t<5; t++) { if(h*bpl>500000 && (t==2 || t==3 || t==4)) continue; | ||
for(var y=0; y<h; y++) UPNG.encode._filterLine(data, img, y, bpl, bpp, t); | ||
fls.push(pako["deflate"](data)); if(bpp==1) break; | ||
} | ||
var ti, tsize=1e9; | ||
for(var i=0; i<fls.length; i++) if(fls[i].length<tsize) { ti=i; tsize=fls[i].length; } | ||
return fls[ti]; | ||
} | ||
UPNG.encode._filterLine = function(data, img, y, bpl, bpp, type) | ||
{ | ||
var i = y*bpl, di = i+y, paeth = UPNG.decode._paeth | ||
data[di]=type; di++; | ||
if(type==0) for(var x=0; x<bpl; x++) data[di+x] = img[i+x]; | ||
else if(type==1) { | ||
for(var x= 0; x<bpp; x++) data[di+x] = img[i+x]; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]-img[i+x-bpp]+256)&255; | ||
} | ||
else if(y==0) { | ||
for(var x= 0; x<bpp; x++) data[di+x] = img[i+x]; | ||
if(type==2) for(var x=bpp; x<bpl; x++) data[di+x] = img[i+x]; | ||
if(type==3) for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x] - (img[i+x-bpp]>>1) +256)&255; | ||
if(type==4) for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x] - paeth(img[i+x-bpp], 0, 0) +256)&255; | ||
} | ||
else { | ||
if(type==2) { for(var x= 0; x<bpl; x++) data[di+x] = (img[i+x]+256 - img[i+x-bpl])&255; } | ||
if(type==3) { for(var x= 0; x<bpp; x++) data[di+x] = (img[i+x]+256 - (img[i+x-bpl]>>1))&255; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]+256 - ((img[i+x-bpl]+img[i+x-bpp])>>1))&255; } | ||
if(type==4) { for(var x= 0; x<bpp; x++) data[di+x] = (img[i+x]+256 - paeth(0, img[i+x-bpl], 0))&255; | ||
for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]+256 - paeth(img[i+x-bpp], img[i+x-bpl], img[i+x-bpp-bpl]))&255; } | ||
} | ||
} | ||
UPNG.crc = { | ||
table : ( function() { | ||
var tab = new Uint32Array(256); | ||
for (var n=0; n<256; n++) { | ||
var c = n; | ||
for (var k=0; k<8; k++) { | ||
if (c & 1) c = 0xedb88320 ^ (c >>> 1); | ||
else c = c >>> 1; | ||
} | ||
tab[n] = c; } | ||
return tab; })(), | ||
update : function(c, buf, off, len) { | ||
for (var i=0; i<len; i++) c = UPNG.crc.table[(c ^ buf[off+i]) & 0xff] ^ (c >>> 8); | ||
return c; | ||
}, | ||
crc : function(b,o,l) { return UPNG.crc.update(0xffffffff,b,o,l) ^ 0xffffffff; } | ||
} | ||
UPNG.quantize = function(bufs, ps, roundAlpha) | ||
{ | ||
var imgs = [], totl = 0; | ||
for(var i=0; i<bufs.length; i++) { imgs.push(UPNG.encode.alphaMul(new Uint8Array(bufs[i]), roundAlpha)); totl+=bufs[i].byteLength; } | ||
var nimg = new Uint8Array(totl), nimg32 = new Uint32Array(nimg.buffer), noff=0; | ||
for(var i=0; i<imgs.length; i++) { | ||
var img = imgs[i], il = img.length; | ||
for(var j=0; j<il; j++) nimg[noff+j] = img[j]; | ||
noff += il; | ||
} | ||
var root = {i0:0, i1:nimg.length, bst:null, est:null, tdst:0, left:null, right:null }; // basic statistic, extra statistic | ||
root.bst = UPNG.quantize.stats( nimg,root.i0, root.i1 ); root.est = UPNG.quantize.estats( root.bst ); | ||
var leafs = [root]; | ||
while(leafs.length<ps) | ||
{ | ||
var maxL = 0, mi=0; | ||
for(var i=0; i<leafs.length; i++) if(leafs[i].est.L > maxL) { maxL=leafs[i].est.L; mi=i; } | ||
if(maxL<1e-3) break; | ||
var node = leafs[mi]; | ||
var s0 = UPNG.quantize.splitPixels(nimg,nimg32, node.i0, node.i1, node.est.e, node.est.eMq255); | ||
var ln = {i0:node.i0, i1:s0, bst:null, est:null, tdst:0, left:null, right:null }; ln.bst = UPNG.quantize.stats( nimg, ln.i0, ln.i1 ); | ||
ln.est = UPNG.quantize.estats( ln.bst ); | ||
var rn = {i0:s0, i1:node.i1, bst:null, est:null, tdst:0, left:null, right:null }; rn.bst = {R:[], m:[], N:node.bst.N-ln.bst.N}; | ||
for(var i=0; i<16; i++) rn.bst.R[i] = node.bst.R[i]-ln.bst.R[i]; | ||
for(var i=0; i< 4; i++) rn.bst.m[i] = node.bst.m[i]-ln.bst.m[i]; | ||
rn.est = UPNG.quantize.estats( rn.bst ); | ||
node.left = ln; node.right = rn; | ||
leafs[mi]=ln; leafs.push(rn); | ||
} | ||
leafs.sort(function(a,b) { return b.bst.N-a.bst.N; }); | ||
for(var ii=0; ii<imgs.length; ii++) { | ||
var planeDst = UPNG.quantize.planeDst; | ||
var sb = new Uint8Array(imgs[ii].buffer), tb = new Uint32Array(imgs[ii].buffer), len = sb.length; | ||
var stack = [], si=0; | ||
for(var i=0; i<len; i+=4) { | ||
var r=sb[i]*(1/255), g=sb[i+1]*(1/255), b=sb[i+2]*(1/255), a=sb[i+3]*(1/255); | ||
// exact, but too slow :( | ||
//var nd = UPNG.quantize.getNearest(root, r, g, b, a); | ||
var nd = root; | ||
while(nd.left) nd = (planeDst(nd.est,r,g,b,a)<=0) ? nd.left : nd.right; | ||
tb[i>>2] = nd.est.rgba; | ||
} | ||
imgs[ii]=tb.buffer; | ||
} | ||
return { bufs:imgs, plte:leafs }; | ||
} | ||
UPNG.quantize.getNearest = function(nd, r,g,b,a) | ||
{ | ||
if(nd.left==null) { nd.tdst = UPNG.quantize.dist(nd.est.q,r,g,b,a); return nd; } | ||
var planeDst = UPNG.quantize.planeDst(nd.est,r,g,b,a); | ||
var node0 = nd.left, node1 = nd.right; | ||
if(planeDst>0) { node0=nd.right; node1=nd.left; } | ||
var ln = UPNG.quantize.getNearest(node0, r,g,b,a); | ||
if(ln.tdst<=planeDst*planeDst) return ln; | ||
var rn = UPNG.quantize.getNearest(node1, r,g,b,a); | ||
return rn.tdst<ln.tdst ? rn : ln; | ||
} | ||
UPNG.quantize.planeDst = function(est, r,g,b,a) { var e = est.e; return e[0]*r + e[1]*g + e[2]*b + e[3]*a - est.eMq; } | ||
UPNG.quantize.dist = function(q, r,g,b,a) { var d0=r-q[0], d1=g-q[1], d2=b-q[2], d3=a-q[3]; return d0*d0+d1*d1+d2*d2+d3*d3; } | ||
UPNG.quantize.splitPixels = function(nimg, nimg32, i0, i1, e, eMq) | ||
{ | ||
var vecDot = UPNG.quantize.vecDot; | ||
i1-=4; | ||
var shfs = 0; | ||
while(i0<i1) | ||
{ | ||
while(vecDot(nimg, i0, e)<=eMq) i0+=4; | ||
while(vecDot(nimg, i1, e)> eMq) i1-=4; | ||
if(i0>=i1) break; | ||
var t = nimg32[i0>>2]; nimg32[i0>>2] = nimg32[i1>>2]; nimg32[i1>>2]=t; | ||
i0+=4; i1-=4; | ||
} | ||
while(vecDot(nimg, i0, e)>eMq) i0-=4; | ||
return i0+4; | ||
} | ||
UPNG.quantize.vecDot = function(nimg, i, e) | ||
{ | ||
return nimg[i]*e[0] + nimg[i+1]*e[1] + nimg[i+2]*e[2] + nimg[i+3]*e[3]; | ||
} | ||
UPNG.quantize.stats = function(nimg, i0, i1){ | ||
var R = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; | ||
var m = [0,0,0,0]; | ||
var N = (i1-i0)>>2; | ||
for(var i=i0; i<i1; i+=4) | ||
{ | ||
var r = nimg[i]*(1/255), g = nimg[i+1]*(1/255), b = nimg[i+2]*(1/255), a = nimg[i+3]*(1/255); | ||
//var r = nimg[i], g = nimg[i+1], b = nimg[i+2], a = nimg[i+3]; | ||
m[0]+=r; m[1]+=g; m[2]+=b; m[3]+=a; | ||
R[ 0] += r*r; R[ 1] += r*g; R[ 2] += r*b; R[ 3] += r*a; | ||
R[ 5] += g*g; R[ 6] += g*b; R[ 7] += g*a; | ||
R[10] += b*b; R[11] += b*a; | ||
R[15] += a*a; | ||
} | ||
R[4]=R[1]; R[8]=R[2]; R[12]=R[3]; R[9]=R[6]; R[13]=R[7]; R[14]=R[11]; | ||
return {R:R, m:m, N:N}; | ||
} | ||
UPNG.quantize.estats = function(stats){ | ||
var R = stats.R, m = stats.m, N = stats.N; | ||
var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], iN = (N==0 ? 0 : 1/N); | ||
var Rj = [ | ||
R[ 0] - m0*m0*iN, R[ 1] - m0*m1*iN, R[ 2] - m0*m2*iN, R[ 3] - m0*m3*iN, | ||
R[ 4] - m1*m0*iN, R[ 5] - m1*m1*iN, R[ 6] - m1*m2*iN, R[ 7] - m1*m3*iN, | ||
R[ 8] - m2*m0*iN, R[ 9] - m2*m1*iN, R[10] - m2*m2*iN, R[11] - m2*m3*iN, | ||
R[12] - m3*m0*iN, R[13] - m3*m1*iN, R[14] - m3*m2*iN, R[15] - m3*m3*iN | ||
]; | ||
var A = Rj, M = UPNG.M4; | ||
var b = [0.5,0.5,0.5,0.5], mi = 0, tmi = 0; | ||
if(N!=0) | ||
for(var i=0; i<10; i++) { | ||
b = M.multVec(A, b); tmi = Math.sqrt(M.dot(b,b)); b = M.sml(1/tmi, b); | ||
if(Math.abs(tmi-mi)<1e-9) break; mi = tmi; | ||
} | ||
//b = [0,0,1,0]; mi=N; | ||
var q = [m0*iN, m1*iN, m2*iN, m3*iN]; | ||
var eMq255 = M.dot(M.sml(255,q),b); | ||
var ia = (q[3]<0.001) ? 0 : 1/q[3]; | ||
return { Cov:Rj, q:q, e:b, L:mi, eMq255:eMq255, eMq : M.dot(b,q), | ||
rgba: (((Math.round(255*q[3])<<24) | (Math.round(255*q[2]*ia)<<16) | (Math.round(255*q[1]*ia)<<8) | (Math.round(255*q[0]*ia)<<0))>>>0) }; | ||
} | ||
UPNG.M4 = { | ||
multVec : function(m,v) { | ||
return [ | ||
m[ 0]*v[0] + m[ 1]*v[1] + m[ 2]*v[2] + m[ 3]*v[3], | ||
m[ 4]*v[0] + m[ 5]*v[1] + m[ 6]*v[2] + m[ 7]*v[3], | ||
m[ 8]*v[0] + m[ 9]*v[1] + m[10]*v[2] + m[11]*v[3], | ||
m[12]*v[0] + m[13]*v[1] + m[14]*v[2] + m[15]*v[3] | ||
]; | ||
}, | ||
dot : function(x,y) { return x[0]*y[0]+x[1]*y[1]+x[2]*y[2]+x[3]*y[3]; }, | ||
sml : function(a,y) { return [a*y[0],a*y[1],a*y[2],a*y[3]]; } | ||
} | ||
UPNG.encode.alphaMul = function(img, roundA) { | ||
var nimg = new Uint8Array(img.length), area = img.length>>2; | ||
for(var i=0; i<area; i++) { | ||
var qi=i<<2, ia=img[qi+3]; | ||
if(roundA) ia = ((ia<128))?0:255; | ||
var a = ia*(1/255); | ||
nimg[qi+0] = img[qi+0]*a; nimg[qi+1] = img[qi+1]*a; nimg[qi+2] = img[qi+2]*a; nimg[qi+3] = ia; | ||
} | ||
return nimg; | ||
} | ||
})(UPNG, pako); | ||
})(); | ||
})(); | ||
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
36406
5.29%716
5.14%1
Infinity%