first commit
This commit is contained in:
21
build/node_modules/upng-js/LICENSE
generated
vendored
Normal file
21
build/node_modules/upng-js/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Photopea
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
55
build/node_modules/upng-js/README.md
generated
vendored
Normal file
55
build/node_modules/upng-js/README.md
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# UPNG.js
|
||||
A small, fast and advanced PNG / APNG encoder and decoder. It is the main PNG engine for [Photopea image editor](https://www.photopea.com).
|
||||
|
||||
* [Examples of PNGs minified by UPNG.js](https://blog.photopea.com/png-minifier-inside-photopea.html#examples)
|
||||
* [Try UPNG.js in Photopea](https://www.photopea.com) - open an image and press File - Save for web, play with the Quality
|
||||
* [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%40kuckir%2ecom&lc=CZ&item_name=UPNG%2ejs¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted).
|
||||
|
||||
Download and include the `UPNG.js` file in your code, or get it from NPM:
|
||||
|
||||
```sh
|
||||
npm install upng-js
|
||||
```
|
||||
|
||||
## Encoder
|
||||
|
||||
UPNG.js supports APNG and the interface expects "frames". Regular PNG is just a single-frame animation (single-item array).
|
||||
|
||||
#### `UPNG.encode(imgs, w, h, cnum, [dels])`
|
||||
* `imgs`: array of frames. A frame is an ArrayBuffer containing the pixel data (RGBA, 8 bits per channel)
|
||||
* `w`, `h` : width and height of the image
|
||||
* `cnum`: number of colors in the result; 0: all colors (lossless PNG)
|
||||
* `dels`: array of delays for each frame (only when 2 or more frames)
|
||||
* returns an ArrayBuffer with binary data of a PNG file
|
||||
|
||||
UPNG.js can do a lossy minification of PNG files, similar to [TinyPNG](https://tinypng.com/) and other tools. It performs color quantization using the [k-means algorithm](https://en.wikipedia.org/wiki/K-means_clustering).
|
||||
|
||||
Lossy compression is allowed by the last parameter `cnum`. Set it to zero for a lossless compression, or write the number of allowed colors in the image. Smaller values produce smaller files. **Or just use 0 for lossless / 256 for lossy.**
|
||||
|
||||
## Decoder
|
||||
|
||||
Supports all color types (including Grayscale and Palettes), all channel depths (1, 2, 4, 8, 16), interlaced images etc. Opens PNGs which other libraries can not open (tested with [PngSuite](http://www.schaik.com/pngsuite/)).
|
||||
|
||||
#### `UPNG.decode(buffer)`
|
||||
* `buffer`: ArrayBuffer containing the PNG file
|
||||
* returns an image object with following properties:
|
||||
* * `width`: the width of the image
|
||||
* * `height`: the height of the image
|
||||
* * `depth`: number of bits per channel
|
||||
* * `ctype`: color type of the file (Truecolor, Grayscale, Palette ...)
|
||||
* * `frames`: additional info about frames (frame delays etc.)
|
||||
* * `tabs`: additional chunks of the PNG file
|
||||
* * `data`: pixel data of the image
|
||||
|
||||
PNG files may have a various number of channels and a various color depth. The interpretation of `data` depends on the current color type and color depth (see the [PNG specification](https://www.w3.org/TR/PNG/)).
|
||||
|
||||
#### `UPNG.toRGBA8(img)`
|
||||
* `img`: PNG image object (returned by UPNG.decode())
|
||||
* returns an array of frames. A frame is ArrayBuffer of the image in RGBA format, 8 bits per channel.
|
||||
|
||||
### Example
|
||||
var img = UPNG.decode(buff); // put ArrayBuffer of the PNG file into UPNG.decode
|
||||
var rgba = UPNG.toRGBA8(img)[0]; // UPNG.toRGBA8 returns array of frames, size: width * height * 4 bytes.
|
||||
|
||||
PNG format uses the Inflate algorithm. Right now, UPNG.js calls [Pako.js](https://github.com/nodeca/pako) for the Inflate and Deflate method.
|
||||
820
build/node_modules/upng-js/UPNG.js
generated
vendored
Normal file
820
build/node_modules/upng-js/UPNG.js
generated
vendored
Normal file
@@ -0,0 +1,820 @@
|
||||
|
||||
;(function(){
|
||||
var UPNG = {};
|
||||
|
||||
// Make available for import by `require()`
|
||||
var pako;
|
||||
if (typeof module == "object") {module.exports = UPNG;} else {window.UPNG = UPNG;}
|
||||
if (typeof require == "function") {pako = require("pako");} else {pako = window.pako;}
|
||||
function log() { if (typeof process=="undefined" || process.env.NODE_ENV=="development") console.log.apply(console, arguments); }
|
||||
(function(UPNG, pako){
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
UPNG.toRGBA8 = function(out)
|
||||
{
|
||||
var w = out.width, h = out.height;
|
||||
if(out.tabs.acTL==null) return [UPNG.toRGBA8.decodeImage(out.data, w, h, out).buffer];
|
||||
|
||||
var frms = [];
|
||||
if(out.frames[0].data==null) out.frames[0].data = out.data;
|
||||
|
||||
var img, empty = new Uint8Array(w*h*4);
|
||||
for(var i=0; i<out.frames.length; i++)
|
||||
{
|
||||
var frm = out.frames[i];
|
||||
var fx=frm.rect.x, fy=frm.rect.y, fw = frm.rect.width, fh = frm.rect.height;
|
||||
var fdata = UPNG.toRGBA8.decodeImage(frm.data, fw,fh, out);
|
||||
|
||||
if(i==0) img = fdata;
|
||||
else if(frm.blend ==0) UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy, 0);
|
||||
else if(frm.blend ==1) UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy, 1);
|
||||
|
||||
frms.push(img.buffer); img = img.slice(0);
|
||||
|
||||
if (frm.dispose==0) {}
|
||||
else if(frm.dispose==1) UPNG._copyTile(empty, fw, fh, img, w, h, fx, fy, 0);
|
||||
else if(frm.dispose==2) {
|
||||
var pi = i-1;
|
||||
while(out.frames[pi].dispose==2) pi--;
|
||||
img = new Uint8Array(frms[pi]).slice(0);
|
||||
}
|
||||
}
|
||||
return frms;
|
||||
}
|
||||
UPNG.toRGBA8.decodeImage = function(data, w, h, out)
|
||||
{
|
||||
var area = w*h, bpp = UPNG.decode._getBPP(out);
|
||||
var bpl = Math.ceil(w*bpp/8); // bytes per line
|
||||
|
||||
var bf = new Uint8Array(area*4), bf32 = new Uint32Array(bf.buffer);
|
||||
var ctype = out.ctype, depth = out.depth;
|
||||
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 && data[i]!=0) bf[i]=255;*/ }
|
||||
if(depth==16) for(var i=0; i<qarea;i++) { bf[i] = data[i<<1]; }
|
||||
}
|
||||
else if(ctype==2) { // RGB
|
||||
var ts=out.tabs["tRNS"], tr=-1, tg=-1, tb=-1;
|
||||
if(ts) { tr=ts[0]; tg=ts[1]; tb=ts[2]; }
|
||||
if(depth== 8) for(var i=0; i<area; i++) { var qi=i<<2, ti=i*3; bf[qi] = data[ti]; bf[qi+1] = data[ti+1]; bf[qi+2] = data[ti+2]; bf[qi+3] = 255;
|
||||
if(tr!=-1 && data[ti] ==tr && data[ti+1] ==tg && data[ti+2] ==tb) bf[qi+3] = 0; }
|
||||
if(depth==16) for(var i=0; i<area; i++) { var qi=i<<2, ti=i*6; bf[qi] = data[ti]; bf[qi+1] = data[ti+2]; bf[qi+2] = data[ti+4]; bf[qi+3] = 255;
|
||||
if(tr!=-1 && rs(data,ti)==tr && rs(data,ti+2)==tg && rs(data,ti+4)==tb) bf[qi+3] = 0; }
|
||||
}
|
||||
else if(ctype==3) { // palette
|
||||
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;
|
||||
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; }
|
||||
}
|
||||
if(depth==2) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w;
|
||||
for(var i=0; i<w; i++) { var qi=(t0+i)<<2, j=((data[s0+(i>>2)]>>(6-((i&3)<<1)))& 3), 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; }
|
||||
}
|
||||
if(depth==4) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w;
|
||||
for(var i=0; i<w; i++) { var qi=(t0+i)<<2, j=((data[s0+(i>>1)]>>(4-((i&1)<<2)))&15), 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; }
|
||||
}
|
||||
if(depth==8) for(var i=0; i<area; i++ ) { var qi=i<<2, j=data[i] , 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; }
|
||||
}
|
||||
else if(ctype==4) { // gray + alpha
|
||||
if(depth== 8) for(var i=0; i<area; i++) { var qi=i<<2, di=i<<1, gr=data[di]; bf[qi]=gr; bf[qi+1]=gr; bf[qi+2]=gr; bf[qi+3]=data[di+1]; }
|
||||
if(depth==16) for(var i=0; i<area; i++) { var qi=i<<2, di=i<<2, gr=data[di]; bf[qi]=gr; bf[qi+1]=gr; bf[qi+2]=gr; bf[qi+3]=data[di+2]; }
|
||||
}
|
||||
else if(ctype==0) { // gray
|
||||
var tr = out.tabs["tRNS"] ? out.tabs["tRNS"] : -1;
|
||||
if(depth== 1) for(var i=0; i<area; i++) { var gr=255*((data[i>>3]>>(7 -((i&7) )))& 1), al=(gr==tr*255)?0:255; bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
|
||||
if(depth== 2) for(var i=0; i<area; i++) { var gr= 85*((data[i>>2]>>(6 -((i&3)<<1)))& 3), al=(gr==tr* 85)?0:255; bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
|
||||
if(depth== 4) for(var i=0; i<area; i++) { var gr= 17*((data[i>>1]>>(4 -((i&1)<<2)))&15), al=(gr==tr* 17)?0:255; bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
|
||||
if(depth== 8) for(var i=0; i<area; i++) { var gr=data[i ] , al=(gr ==tr)?0:255; bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
|
||||
if(depth==16) for(var i=0; i<area; i++) { var gr=data[i<<1], al=(rs(data,i<<1)==tr)?0:255; bf32[i]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
|
||||
}
|
||||
return bf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UPNG.decode = function(buff)
|
||||
{
|
||||
var data = new Uint8Array(buff), offset = 8, bin = UPNG._bin, rUs = bin.readUshort, rUi = bin.readUint;
|
||||
var out = {tabs:{}, frames:[]};
|
||||
var dd = new Uint8Array(data.length), doff = 0; // put all IDAT data into it
|
||||
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(offset<data.length)
|
||||
{
|
||||
var len = bin.readUint(data, offset); offset += 4;
|
||||
var type = bin.readASCII(data, offset, 4); offset += 4;
|
||||
//log(type,len);
|
||||
|
||||
if (type=="IHDR") { UPNG.decode._IHDR(data, offset, out); }
|
||||
else if(type=="IDAT") {
|
||||
for(var i=0; i<len; i++) dd[doff+i] = data[offset+i];
|
||||
doff += len;
|
||||
}
|
||||
else if(type=="acTL") {
|
||||
out.tabs[type] = { num_frames:rUi(data, offset), num_plays:rUi(data, offset+4) };
|
||||
fd = new Uint8Array(data.length);
|
||||
}
|
||||
else if(type=="fcTL") {
|
||||
if(foff!=0) { var fr = out.frames[out.frames.length-1];
|
||||
fr.data = UPNG.decode._decompress(out, fd.slice(0,foff), fr.rect.width, fr.rect.height); foff=0;
|
||||
}
|
||||
var rct = {x:rUi(data, offset+12),y:rUi(data, offset+16),width:rUi(data, offset+4),height:rUi(data, offset+8)};
|
||||
var del = rUs(data, offset+22); del = rUs(data, offset+20) / (del==0?100:del);
|
||||
var frm = {rect:rct, delay:Math.round(del*1000), dispose:data[offset+24], blend:data[offset+25]};
|
||||
//console.log(frm);
|
||||
out.frames.push(frm);
|
||||
}
|
||||
else if(type=="fdAT") {
|
||||
for(var i=0; i<len-4; i++) fd[foff+i] = data[offset+i+4];
|
||||
foff += len-4;
|
||||
}
|
||||
else if(type=="pHYs") {
|
||||
out.tabs[type] = [bin.readUint(data, offset), bin.readUint(data, offset+4), data[offset+8]];
|
||||
}
|
||||
else if(type=="cHRM") {
|
||||
out.tabs[type] = [];
|
||||
for(var i=0; i<8; i++) out.tabs[type].push(bin.readUint(data, offset+i*4));
|
||||
}
|
||||
else if(type=="tEXt") {
|
||||
if(out.tabs[type]==null) out.tabs[type] = {};
|
||||
var nz = bin.nextZero(data, offset);
|
||||
var keyw = bin.readASCII(data, offset, nz-offset);
|
||||
var text = bin.readASCII(data, nz+1, offset+len-nz-1);
|
||||
out.tabs[type][keyw] = text;
|
||||
}
|
||||
else if(type=="iTXt") {
|
||||
if(out.tabs[type]==null) out.tabs[type] = {};
|
||||
var nz = 0, off = offset;
|
||||
nz = bin.nextZero(data, off);
|
||||
var keyw = bin.readASCII(data, off, nz-off); off = nz + 1;
|
||||
var cflag = data[off], cmeth = data[off+1]; off+=2;
|
||||
nz = bin.nextZero(data, off);
|
||||
var ltag = bin.readASCII(data, off, nz-off); off = nz + 1;
|
||||
nz = bin.nextZero(data, off);
|
||||
var tkeyw = bin.readUTF8(data, off, nz-off); off = nz + 1;
|
||||
var text = bin.readUTF8(data, off, len-(off-offset));
|
||||
out.tabs[type][keyw] = text;
|
||||
}
|
||||
else if(type=="PLTE") {
|
||||
out.tabs[type] = bin.readBytes(data, offset, len);
|
||||
}
|
||||
else if(type=="hIST") {
|
||||
var pl = out.tabs["PLTE"].length/3;
|
||||
out.tabs[type] = []; for(var i=0; i<pl; i++) out.tabs[type].push(rUs(data, offset+i*2));
|
||||
}
|
||||
else if(type=="tRNS") {
|
||||
if (out.ctype==3) out.tabs[type] = bin.readBytes(data, offset, len);
|
||||
else if(out.ctype==0) out.tabs[type] = rUs(data, offset);
|
||||
else if(out.ctype==2) out.tabs[type] = [ rUs(data,offset),rUs(data,offset+2),rUs(data,offset+4) ];
|
||||
//else console.log("tRNS for unsupported color type",out.ctype, len);
|
||||
}
|
||||
else if(type=="gAMA") out.tabs[type] = bin.readUint(data, offset)/100000;
|
||||
else if(type=="sRGB") out.tabs[type] = data[offset];
|
||||
else if(type=="bKGD")
|
||||
{
|
||||
if (out.ctype==0 || out.ctype==4) out.tabs[type] = [rUs(data, offset)];
|
||||
else if(out.ctype==2 || out.ctype==6) out.tabs[type] = [rUs(data, offset), rUs(data, offset+2), rUs(data, offset+4)];
|
||||
else if(out.ctype==3) out.tabs[type] = data[offset];
|
||||
}
|
||||
else if(type=="IEND") {
|
||||
if(foff!=0) { var fr = out.frames[out.frames.length-1];
|
||||
fr.data = UPNG.decode._decompress(out, fd.slice(0,foff), fr.rect.width, fr.rect.height); foff=0;
|
||||
}
|
||||
out.data = UPNG.decode._decompress(out, dd, out.width, out.height); break;
|
||||
}
|
||||
//else { log("unknown chunk type", type, len); }
|
||||
offset += len;
|
||||
var crc = bin.readUint(data, offset); offset += 4;
|
||||
}
|
||||
delete out.compress; delete out.interlace; delete out.filter;
|
||||
return out;
|
||||
}
|
||||
|
||||
UPNG.decode._decompress = function(out, dd, w, h) {
|
||||
if(out.compress ==0) dd = UPNG.decode._inflate(dd);
|
||||
|
||||
if (out.interlace==0) dd = UPNG.decode._filterZero(dd, out, 0, w, h);
|
||||
else if(out.interlace==1) dd = UPNG.decode._readInterlace(dd, out);
|
||||
return dd;
|
||||
}
|
||||
|
||||
UPNG.decode._inflate = function(data) { return pako["inflate"](data); }
|
||||
|
||||
UPNG.decode._readInterlace = function(data, out)
|
||||
{
|
||||
var w = out.width, h = out.height;
|
||||
var bpp = UPNG.decode._getBPP(out), cbpp = bpp>>3, bpl = Math.ceil(w*bpp/8);
|
||||
var img = new Uint8Array( h * bpl );
|
||||
var di = 0;
|
||||
|
||||
var starting_row = [ 0, 0, 4, 0, 2, 0, 1 ];
|
||||
var starting_col = [ 0, 4, 0, 2, 0, 1, 0 ];
|
||||
var row_increment = [ 8, 8, 8, 4, 4, 2, 2 ];
|
||||
var col_increment = [ 8, 8, 4, 4, 2, 2, 1 ];
|
||||
|
||||
var pass=0;
|
||||
while(pass<7)
|
||||
{
|
||||
var ri = row_increment[pass], ci = col_increment[pass];
|
||||
var sw = 0, sh = 0;
|
||||
var cr = starting_row[pass]; while(cr<h) { cr+=ri; sh++; }
|
||||
var cc = starting_col[pass]; while(cc<w) { cc+=ci; sw++; }
|
||||
var bpll = Math.ceil(sw*bpp/8);
|
||||
UPNG.decode._filterZero(data, out, di, sw, sh);
|
||||
|
||||
var y=0, row = starting_row[pass];
|
||||
while(row<h)
|
||||
{
|
||||
var col = starting_col[pass];
|
||||
var cdi = (di+y*bpll)<<3;
|
||||
|
||||
while(col<w)
|
||||
{
|
||||
if(bpp==1) {
|
||||
var val = data[cdi>>3]; val = (val>>(7-(cdi&7)))&1;
|
||||
img[row*bpl + (col>>3)] |= (val << (7-((col&3)<<0)));
|
||||
}
|
||||
if(bpp==2) {
|
||||
var val = data[cdi>>3]; val = (val>>(6-(cdi&7)))&3;
|
||||
img[row*bpl + (col>>2)] |= (val << (6-((col&3)<<1)));
|
||||
}
|
||||
if(bpp==4) {
|
||||
var val = data[cdi>>3]; val = (val>>(4-(cdi&7)))&15;
|
||||
img[row*bpl + (col>>1)] |= (val << (4-((col&1)<<2)));
|
||||
}
|
||||
if(bpp>=8) {
|
||||
var ii = row*bpl+col*cbpp;
|
||||
for(var j=0; j<cbpp; j++) img[ii+j] = data[(cdi>>3)+j];
|
||||
}
|
||||
cdi+=bpp; col+=ci;
|
||||
}
|
||||
y++; row += ri;
|
||||
}
|
||||
if(sw*sh!=0) di += sh * (1 + bpll);
|
||||
pass = pass + 1;
|
||||
}
|
||||
return img;
|
||||
}
|
||||
|
||||
UPNG.decode._getBPP = function(out) {
|
||||
var noc = [1,null,3,1,2,null,4][out.ctype];
|
||||
return noc * out.depth;
|
||||
}
|
||||
|
||||
UPNG.decode._filterZero = function(data, out, off, w, h)
|
||||
{
|
||||
var bpp = UPNG.decode._getBPP(out), bpl = Math.ceil(w*bpp/8), paeth = UPNG.decode._paeth;
|
||||
bpp = Math.ceil(bpp/8);
|
||||
|
||||
for(var y=0; y<h; y++) {
|
||||
var i = off+y*bpl, di = i+y+1;
|
||||
var type = data[di-1];
|
||||
|
||||
if (type==0) for(var x= 0; x<bpl; x++) data[i+x] = data[di+x];
|
||||
else if(type==1) {
|
||||
for(var x= 0; x<bpp; x++) data[i+x] = data[di+x];
|
||||
for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x] + data[i+x-bpp])&255;
|
||||
}
|
||||
else if(y==0) {
|
||||
for(var x= 0; x<bpp; x++) data[i+x] = data[di+x];
|
||||
if(type==2) for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x])&255;
|
||||
if(type==3) for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x] + (data[i+x-bpp]>>1) )&255;
|
||||
if(type==4) for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x] + paeth(data[i+x-bpp], 0, 0) )&255;
|
||||
}
|
||||
else {
|
||||
if(type==2) { for(var x= 0; x<bpl; x++) data[i+x] = (data[di+x] + data[i+x-bpl])&255; }
|
||||
|
||||
if(type==3) { for(var x= 0; x<bpp; x++) data[i+x] = (data[di+x] + (data[i+x-bpl]>>1))&255;
|
||||
for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x] + ((data[i+x-bpl]+data[i+x-bpp])>>1) )&255; }
|
||||
|
||||
if(type==4) { for(var x= 0; x<bpp; x++) data[i+x] = (data[di+x] + paeth(0, data[i+x-bpl], 0))&255;
|
||||
for(var x=bpp; x<bpl; x++) data[i+x] = (data[di+x] + paeth(data[i+x-bpp], data[i+x-bpl], data[i+x-bpp-bpl]) )&255; }
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
UPNG.decode._paeth = function(a,b,c)
|
||||
{
|
||||
var p = a+b-c, pa = Math.abs(p-a), pb = Math.abs(p-b), pc = Math.abs(p-c);
|
||||
if (pa <= pb && pa <= pc) return a;
|
||||
else if (pb <= pc) return b;
|
||||
return c;
|
||||
}
|
||||
|
||||
UPNG.decode._IHDR = function(data, offset, out)
|
||||
{
|
||||
var bin = UPNG._bin;
|
||||
out.width = bin.readUint(data, offset); offset += 4;
|
||||
out.height = bin.readUint(data, offset); offset += 4;
|
||||
out.depth = data[offset]; offset++;
|
||||
out.ctype = data[offset]; offset++;
|
||||
out.compress = data[offset]; offset++;
|
||||
out.filter = data[offset]; offset++;
|
||||
out.interlace = data[offset]; offset++;
|
||||
}
|
||||
|
||||
UPNG._bin = {
|
||||
nextZero : function(data,p) { while(data[p]!=0) p++; return p; },
|
||||
readUshort : function(buff,p) { return (buff[p]<< 8) | buff[p+1]; },
|
||||
writeUshort: function(buff,p,n){ buff[p] = (n>>8)&255; buff[p+1] = n&255; },
|
||||
readUint : function(buff,p) { return (buff[p]*(256*256*256)) + ((buff[p+1]<<16) | (buff[p+2]<< 8) | buff[p+3]); },
|
||||
writeUint : function(buff,p,n){ buff[p]=(n>>24)&255; buff[p+1]=(n>>16)&255; buff[p+2]=(n>>8)&255; buff[p+3]=n&255; },
|
||||
readASCII : function(buff,p,l){ var s = ""; for(var i=0; i<l; i++) s += String.fromCharCode(buff[p+i]); return s; },
|
||||
writeASCII : function(data,p,s){ for(var i=0; i<s.length; i++) data[p+i] = s.charCodeAt(i); },
|
||||
readBytes : function(buff,p,l){ var arr = []; for(var i=0; i<l; i++) arr.push(buff[p+i]); return arr; },
|
||||
pad : function(n) { return n.length < 2 ? "0" + n : n; },
|
||||
readUTF8 : function(buff, p, l) {
|
||||
var s = "", ns;
|
||||
for(var i=0; i<l; i++) s += "%" + UPNG._bin.pad(buff[p+i].toString(16));
|
||||
try { ns = decodeURIComponent(s); }
|
||||
catch(e) { return UPNG._bin.readASCII(buff, p, l); }
|
||||
return ns;
|
||||
}
|
||||
}
|
||||
UPNG._copyTile = function(sb, sw, sh, tb, tw, th, xoff, yoff, mode)
|
||||
{
|
||||
var w = Math.min(sw,tw), h = Math.min(sh,th);
|
||||
var si=0, ti=0;
|
||||
for(var y=0; y<h; y++)
|
||||
for(var x=0; x<w; x++)
|
||||
{
|
||||
if(xoff>=0 && yoff>=0) { si = (y*sw+x)<<2; ti = (( yoff+y)*tw+xoff+x)<<2; }
|
||||
else { si = ((-yoff+y)*sw-xoff+x)<<2; ti = (y*tw+x)<<2; }
|
||||
|
||||
if (mode==0) { tb[ti] = sb[si]; tb[ti+1] = sb[si+1]; tb[ti+2] = sb[si+2]; tb[ti+3] = sb[si+3]; }
|
||||
else if(mode==1) {
|
||||
var fa = sb[si+3]*(1/255), fr=sb[si]*fa, fg=sb[si+1]*fa, fb=sb[si+2]*fa;
|
||||
var ba = tb[ti+3]*(1/255), br=tb[ti]*ba, bg=tb[ti+1]*ba, bb=tb[ti+2]*ba;
|
||||
|
||||
var ifa=1-fa, oa = fa+ba*ifa, ioa = (oa==0?0:1/oa);
|
||||
tb[ti+3] = 255*oa;
|
||||
tb[ti+0] = (fr+br*ifa)*ioa;
|
||||
tb[ti+1] = (fg+bg*ifa)*ioa;
|
||||
tb[ti+2] = (fb+bb*ifa)*ioa;
|
||||
}
|
||||
else if(mode==2){ // copy only differences, otherwise zero
|
||||
var fa = sb[si+3], fr=sb[si], fg=sb[si+1], fb=sb[si+2];
|
||||
var ba = tb[ti+3], br=tb[ti], bg=tb[ti+1], bb=tb[ti+2];
|
||||
if(fa==ba && fr==br && fg==bg && fb==bb) { tb[ti]=0; tb[ti+1]=0; tb[ti+2]=0; tb[ti+3]=0; }
|
||||
else { tb[ti]=fr; tb[ti+1]=fg; tb[ti+2]=fb; tb[ti+3]=fa; }
|
||||
}
|
||||
else if(mode==3){ // check if can be blended
|
||||
var fa = sb[si+3], fr=sb[si], fg=sb[si+1], fb=sb[si+2];
|
||||
var ba = tb[ti+3], br=tb[ti], bg=tb[ti+1], bb=tb[ti+2];
|
||||
if(fa==ba && fr==br && fg==bg && fb==bb) continue;
|
||||
//if(fa!=255 && ba!=0) return false;
|
||||
if(fa<220 && ba>20) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
})();
|
||||
|
||||
59
build/node_modules/upng-js/package.json
generated
vendored
Normal file
59
build/node_modules/upng-js/package.json
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"_from": "upng-js@^2.1.0",
|
||||
"_id": "upng-js@2.1.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-d3xzZzpMP64YkjP5pr8gNyvBt7dLk/uGI67EctzDuVp4lCZyVMo0aJO6l/VDlgbInJYDY6cnClLoBp29eKWI6g==",
|
||||
"_location": "/upng-js",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "upng-js@^2.1.0",
|
||||
"name": "upng-js",
|
||||
"escapedName": "upng-js",
|
||||
"rawSpec": "^2.1.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^2.1.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/imagemin-upng"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/upng-js/-/upng-js-2.1.0.tgz",
|
||||
"_shasum": "7176e73973db361ca95d0fa14f958385db6b9dd2",
|
||||
"_spec": "upng-js@^2.1.0",
|
||||
"_where": "/Users/asciidisco/Desktop/asciidisco.com/build/node_modules/imagemin-upng",
|
||||
"author": {
|
||||
"name": "photopea",
|
||||
"url": "https://github.com/photopea"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/photopea/UPNG.js/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Scimonster",
|
||||
"url": "https://github.com/Scimonster"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"pako": "^1.0.5"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Small, fast and advanced PNG / APNG encoder and decoder",
|
||||
"homepage": "https://github.com/photopea/UPNG.js",
|
||||
"keywords": [
|
||||
"png",
|
||||
"apng",
|
||||
"image",
|
||||
"conversion"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "UPNG",
|
||||
"name": "upng-js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/photopea/UPNG.js.git"
|
||||
},
|
||||
"version": "2.1.0"
|
||||
}
|
||||
Reference in New Issue
Block a user