UPNG.js 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226
  1. var UPNG = (function() {
  2. var _bin = {
  3. nextZero : function(data,p) { while(data[p]!=0) p++; return p; },
  4. readUshort : function(buff,p) { return (buff[p]<< 8) | buff[p+1]; },
  5. writeUshort: function(buff,p,n){ buff[p] = (n>>8)&255; buff[p+1] = n&255; },
  6. readUint : function(buff,p) { return (buff[p]*(256*256*256)) + ((buff[p+1]<<16) | (buff[p+2]<< 8) | buff[p+3]); },
  7. 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; },
  8. readASCII : function(buff,p,l){ var s = ""; for(var i=0; i<l; i++) s += String.fromCharCode(buff[p+i]); return s; },
  9. writeASCII : function(data,p,s){ for(var i=0; i<s.length; i++) data[p+i] = s.charCodeAt(i); },
  10. readBytes : function(buff,p,l){ var arr = []; for(var i=0; i<l; i++) arr.push(buff[p+i]); return arr; },
  11. pad : function(n) { return n.length < 2 ? "0" + n : n; },
  12. readUTF8 : function(buff, p, l) {
  13. var s = "", ns;
  14. for(var i=0; i<l; i++) s += "%" + _bin.pad(buff[p+i].toString(16));
  15. try { ns = decodeURIComponent(s); }
  16. catch(e) { return _bin.readASCII(buff, p, l); }
  17. return ns;
  18. }
  19. }
  20. function toRGBA8(out)
  21. {
  22. var w = out.width, h = out.height;
  23. if(out.tabs.acTL==null) return [decodeImage(out.data, w, h, out).buffer];
  24. var frms = [];
  25. if(out.frames[0].data==null) out.frames[0].data = out.data;
  26. var len = w*h*4, img = new Uint8Array(len), empty = new Uint8Array(len), prev=new Uint8Array(len);
  27. for(var i=0; i<out.frames.length; i++)
  28. {
  29. var frm = out.frames[i];
  30. var fx=frm.rect.x, fy=frm.rect.y, fw = frm.rect.width, fh = frm.rect.height;
  31. var fdata = decodeImage(frm.data, fw,fh, out);
  32. if(i!=0) for(var j=0; j<len; j++) prev[j]=img[j];
  33. if (frm.blend==0) _copyTile(fdata, fw, fh, img, w, h, fx, fy, 0);
  34. else if(frm.blend==1) _copyTile(fdata, fw, fh, img, w, h, fx, fy, 1);
  35. frms.push(img.buffer.slice(0));
  36. if (frm.dispose==0) {}
  37. else if(frm.dispose==1) _copyTile(empty, fw, fh, img, w, h, fx, fy, 0);
  38. else if(frm.dispose==2) for(var j=0; j<len; j++) img[j]=prev[j];
  39. }
  40. return frms;
  41. }
  42. function decodeImage(data, w, h, out)
  43. {
  44. var area = w*h, bpp = _getBPP(out);
  45. var bpl = Math.ceil(w*bpp/8); // bytes per line
  46. var bf = new Uint8Array(area*4), bf32 = new Uint32Array(bf.buffer);
  47. var ctype = out.ctype, depth = out.depth;
  48. var rs = _bin.readUshort;
  49. //console.log(ctype, depth);
  50. var time = Date.now();
  51. if (ctype==6) { // RGB + alpha
  52. var qarea = area<<2;
  53. if(depth== 8) for(var i=0; i<qarea;i+=4) { bf[i] = data[i]; bf[i+1] = data[i+1]; bf[i+2] = data[i+2]; bf[i+3] = data[i+3]; }
  54. if(depth==16) for(var i=0; i<qarea;i++ ) { bf[i] = data[i<<1]; }
  55. }
  56. else if(ctype==2) { // RGB
  57. var ts=out.tabs["tRNS"];
  58. if(ts==null) {
  59. if(depth== 8) for(var i=0; i<area; i++) { var ti=i*3; bf32[i] = (255<<24)|(data[ti+2]<<16)|(data[ti+1]<<8)|data[ti]; }
  60. if(depth==16) for(var i=0; i<area; i++) { var ti=i*6; bf32[i] = (255<<24)|(data[ti+4]<<16)|(data[ti+2]<<8)|data[ti]; }
  61. }
  62. else { var tr=ts[0], tg=ts[1], tb=ts[2];
  63. if(depth== 8) for(var i=0; i<area; i++) { var qi=i<<2, ti=i*3; bf32[i] = (255<<24)|(data[ti+2]<<16)|(data[ti+1]<<8)|data[ti];
  64. if(data[ti] ==tr && data[ti+1] ==tg && data[ti+2] ==tb) bf[qi+3] = 0; }
  65. if(depth==16) for(var i=0; i<area; i++) { var qi=i<<2, ti=i*6; bf32[i] = (255<<24)|(data[ti+4]<<16)|(data[ti+2]<<8)|data[ti];
  66. if(rs(data,ti)==tr && rs(data,ti+2)==tg && rs(data,ti+4)==tb) bf[qi+3] = 0; }
  67. }
  68. }
  69. else if(ctype==3) { // palette
  70. var p=out.tabs["PLTE"], ap=out.tabs["tRNS"], tl=ap?ap.length:0;
  71. //console.log(p, ap);
  72. if(depth==1) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w;
  73. 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; }
  74. }
  75. if(depth==2) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w;
  76. 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; }
  77. }
  78. if(depth==4) for(var y=0; y<h; y++) { var s0 = y*bpl, t0 = y*w;
  79. 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; }
  80. }
  81. 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; }
  82. }
  83. else if(ctype==4) { // gray + alpha
  84. 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]; }
  85. 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]; }
  86. }
  87. else if(ctype==0) { // gray
  88. var tr = out.tabs["tRNS"] ? out.tabs["tRNS"] : -1;
  89. for(var y=0; y<h; y++) {
  90. var off = y*bpl, to = y*w;
  91. if (depth== 1) for(var x=0; x<w; x++) { var gr=255*((data[off+(x>>>3)]>>>(7 -((x&7) )))& 1), al=(gr==tr*255)?0:255; bf32[to+x]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
  92. else if(depth== 2) for(var x=0; x<w; x++) { var gr= 85*((data[off+(x>>>2)]>>>(6 -((x&3)<<1)))& 3), al=(gr==tr* 85)?0:255; bf32[to+x]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
  93. else if(depth== 4) for(var x=0; x<w; x++) { var gr= 17*((data[off+(x>>>1)]>>>(4 -((x&1)<<2)))&15), al=(gr==tr* 17)?0:255; bf32[to+x]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
  94. else if(depth== 8) for(var x=0; x<w; x++) { var gr=data[off+ x], al=(gr ==tr)?0:255; bf32[to+x]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
  95. else if(depth==16) for(var x=0; x<w; x++) { var gr=data[off+(x<<1)], al=(rs(data,off+(x<<1))==tr)?0:255; bf32[to+x]=(al<<24)|(gr<<16)|(gr<<8)|gr; }
  96. }
  97. }
  98. //console.log(Date.now()-time);
  99. return bf;
  100. }
  101. function decode(buff)
  102. {
  103. var data = new Uint8Array(buff), offset = 8, bin = _bin, rUs = bin.readUshort, rUi = bin.readUint;
  104. var out = {tabs:{}, frames:[]};
  105. var dd = new Uint8Array(data.length), doff = 0; // put all IDAT data into it
  106. var fd, foff = 0; // frames
  107. var mgck = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
  108. for(var i=0; i<8; i++) if(data[i]!=mgck[i]) throw "The input is not a PNG file!";
  109. while(offset<data.length)
  110. {
  111. var len = bin.readUint(data, offset); offset += 4;
  112. var type = bin.readASCII(data, offset, 4); offset += 4;
  113. //console.log(type,len);
  114. if (type=="IHDR") { _IHDR(data, offset, out); }
  115. else if(type=="iCCP") {
  116. var off = offset; while(data[off]!=0) off++;
  117. var nam = bin.readASCII(data,offset,off-offset);
  118. var cpr = data[off+1];
  119. var fil = data.slice(off+2,offset+len);
  120. var res = null;
  121. try { res = _inflate(fil); } catch(e) { res = inflateRaw(fil); }
  122. out.tabs[type] = res;
  123. }
  124. else if(type=="CgBI") { out.tabs[type] = data.slice(offset,offset+4); }
  125. else if(type=="IDAT") {
  126. for(var i=0; i<len; i++) dd[doff+i] = data[offset+i];
  127. doff += len;
  128. }
  129. else if(type=="acTL") {
  130. out.tabs[type] = { num_frames:rUi(data, offset), num_plays:rUi(data, offset+4) };
  131. fd = new Uint8Array(data.length);
  132. }
  133. else if(type=="fcTL") {
  134. if(foff!=0) { var fr = out.frames[out.frames.length-1];
  135. fr.data = _decompress(out, fd.slice(0,foff), fr.rect.width, fr.rect.height); foff=0;
  136. }
  137. var rct = {x:rUi(data, offset+12),y:rUi(data, offset+16),width:rUi(data, offset+4),height:rUi(data, offset+8)};
  138. var del = rUs(data, offset+22); del = rUs(data, offset+20) / (del==0?100:del);
  139. var frm = {rect:rct, delay:Math.round(del*1000), dispose:data[offset+24], blend:data[offset+25]};
  140. //console.log(frm);
  141. out.frames.push(frm);
  142. }
  143. else if(type=="fdAT") {
  144. for(var i=0; i<len-4; i++) fd[foff+i] = data[offset+i+4];
  145. foff += len-4;
  146. }
  147. else if(type=="pHYs") {
  148. out.tabs[type] = [bin.readUint(data, offset), bin.readUint(data, offset+4), data[offset+8]];
  149. }
  150. else if(type=="cHRM") {
  151. out.tabs[type] = [];
  152. for(var i=0; i<8; i++) out.tabs[type].push(bin.readUint(data, offset+i*4));
  153. }
  154. else if(type=="tEXt" || type=="zTXt") {
  155. if(out.tabs[type]==null) out.tabs[type] = {};
  156. var nz = bin.nextZero(data, offset);
  157. var keyw = bin.readASCII(data, offset, nz-offset);
  158. var text, tl=offset+len-nz-1;
  159. if(type=="tEXt") text = bin.readASCII(data, nz+1, tl);
  160. else {
  161. var bfr = _inflate(data.slice(nz+2,nz+2+tl));
  162. text = bin.readUTF8(bfr,0,bfr.length);
  163. }
  164. out.tabs[type][keyw] = text;
  165. }
  166. else if(type=="iTXt") {
  167. if(out.tabs[type]==null) out.tabs[type] = {};
  168. var nz = 0, off = offset;
  169. nz = bin.nextZero(data, off);
  170. var keyw = bin.readASCII(data, off, nz-off); off = nz + 1;
  171. var cflag = data[off], cmeth = data[off+1]; off+=2;
  172. nz = bin.nextZero(data, off);
  173. var ltag = bin.readASCII(data, off, nz-off); off = nz + 1;
  174. nz = bin.nextZero(data, off);
  175. var tkeyw = bin.readUTF8(data, off, nz-off); off = nz + 1;
  176. var text, tl=len-(off-offset);
  177. if(cflag==0) text = bin.readUTF8(data, off, tl);
  178. else {
  179. var bfr = _inflate(data.slice(off,off+tl));
  180. text = bin.readUTF8(bfr,0,bfr.length);
  181. }
  182. out.tabs[type][keyw] = text;
  183. }
  184. else if(type=="PLTE") {
  185. out.tabs[type] = bin.readBytes(data, offset, len);
  186. }
  187. else if(type=="hIST") {
  188. var pl = out.tabs["PLTE"].length/3;
  189. out.tabs[type] = []; for(var i=0; i<pl; i++) out.tabs[type].push(rUs(data, offset+i*2));
  190. }
  191. else if(type=="tRNS") {
  192. if (out.ctype==3) out.tabs[type] = bin.readBytes(data, offset, len);
  193. else if(out.ctype==0) out.tabs[type] = rUs(data, offset);
  194. else if(out.ctype==2) out.tabs[type] = [ rUs(data,offset),rUs(data,offset+2),rUs(data,offset+4) ];
  195. //else console.log("tRNS for unsupported color type",out.ctype, len);
  196. }
  197. else if(type=="gAMA") out.tabs[type] = bin.readUint(data, offset)/100000;
  198. else if(type=="sRGB") out.tabs[type] = data[offset];
  199. else if(type=="bKGD")
  200. {
  201. if (out.ctype==0 || out.ctype==4) out.tabs[type] = [rUs(data, offset)];
  202. else if(out.ctype==2 || out.ctype==6) out.tabs[type] = [rUs(data, offset), rUs(data, offset+2), rUs(data, offset+4)];
  203. else if(out.ctype==3) out.tabs[type] = data[offset];
  204. }
  205. else if(type=="IEND") {
  206. break;
  207. }
  208. //else { console.log("unknown chunk type", type, len); out.tabs[type]=data.slice(offset,offset+len); }
  209. offset += len;
  210. var crc = bin.readUint(data, offset); offset += 4;
  211. }
  212. if(foff!=0) { var fr = out.frames[out.frames.length-1];
  213. fr.data = _decompress(out, fd.slice(0,foff), fr.rect.width, fr.rect.height);
  214. }
  215. out.data = _decompress(out, dd, out.width, out.height);
  216. delete out.compress; delete out.interlace; delete out.filter;
  217. return out;
  218. }
  219. function _decompress(out, dd, w, h) {
  220. var time = Date.now();
  221. var bpp = _getBPP(out), bpl = Math.ceil(w*bpp/8), buff = new Uint8Array((bpl+1+out.interlace)*h);
  222. if(out.tabs["CgBI"]) dd = inflateRaw(dd,buff);
  223. else dd = _inflate(dd,buff);
  224. //console.log(dd.length, buff.length);
  225. //console.log(Date.now()-time);
  226. var time=Date.now();
  227. if (out.interlace==0) dd = _filterZero(dd, out, 0, w, h);
  228. else if(out.interlace==1) dd = _readInterlace(dd, out);
  229. //console.log(Date.now()-time);
  230. return dd;
  231. }
  232. function _inflate(data, buff) { var out=inflateRaw(new Uint8Array(data.buffer, 2,data.length-6),buff); return out; }
  233. var inflateRaw=function(){var D=function(){var o=Uint16Array,j=Uint32Array;return{m:new o(16),v:new o(16),
  234. d:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],o:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],
  235. z:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],B:new o(32),
  236. p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],
  237. w:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],h:new j(32),g:new o(512),s:[],A:new o(32),t:[],k:new o(32768),c:[],
  238. a:[],n:new o(32768),e:[],C:new o(512),b:[],i:new o(1<<15),r:new j(286),f:new j(30),l:new j(19),u:new j(15e3),q:new o(1<<16),j:new o(1<<15)}}();
  239. function C(o,j){var I=o.length,A,r,i,y,G,f=D.v;for(var y=0;y<=j;y++)f[y]=0;for(y=1;y<I;y+=2)f[o[y]]++;
  240. var a=D.m;A=0;f[0]=0;for(r=1;r<=j;r++){A=A+f[r-1]<<1;a[r]=A}for(i=0;i<I;i+=2){G=o[i+1];if(G!=0){o[i]=a[G];
  241. a[G]++}}}function t(o,j,I){var A=o.length,r=D.i;for(var i=0;i<A;i+=2)if(o[i+1]!=0){var y=i>>1,G=o[i+1],f=y<<4|G,a=j-G,k=o[i]<<a,N=k+(1<<a);
  242. while(k!=N){var x=r[k]>>>15-j;I[x]=f;k++}}}function g(o,j){var I=D.i,A=15-j;for(var r=0;r<o.length;r+=2){var i=o[r]<<j-o[r+1];
  243. o[r]=I[i]>>>A}}(function(){var o=1<<15;for(var j=0;j<o;j++){var I=j;I=(I&2863311530)>>>1|(I&1431655765)<<1;
  244. I=(I&3435973836)>>>2|(I&858993459)<<2;I=(I&4042322160)>>>4|(I&252645135)<<4;I=(I&4278255360)>>>8|(I&16711935)<<8;
  245. D.i[j]=(I>>>16|I<<16)>>>17}function A(r,i,y){while(i--!=0)r.push(0,y)}for(var j=0;j<32;j++){D.B[j]=D.o[j]<<3|D.z[j];
  246. D.h[j]=D.p[j]<<4|D.w[j]}A(D.s,144,8);A(D.s,255-143,9);A(D.s,279-255,7);A(D.s,287-279,8);C(D.s,9);t(D.s,9,D.g);
  247. g(D.s,9);A(D.t,32,5);C(D.t,5);t(D.t,5,D.A);g(D.t,5);A(D.b,19,0);A(D.c,286,0);A(D.e,30,0);A(D.a,320,0)}());
  248. function F(o,j,I){return(o[j>>>3]|o[(j>>>3)+1]<<8)>>>(j&7)&(1<<I)-1}function s(o,j,I){return(o[j>>>3]|o[(j>>>3)+1]<<8|o[(j>>>3)+2]<<16)>>>(j&7)&(1<<I)-1}
  249. function w(o,j){return(o[j>>>3]|o[(j>>>3)+1]<<8|o[(j>>>3)+2]<<16)>>>(j&7)}function b(o,j){return(o[j>>>3]|o[(j>>>3)+1]<<8|o[(j>>>3)+2]<<16|o[(j>>>3)+3]<<24)>>>(j&7)}
  250. function v(o,j){var I=Uint8Array,r=0,i=0,y=0,G=0,f=0,a=0,k=0,N=0,x=0,P,J;
  251. if(o[0]==3&&o[1]==0)return j?j:new I(0);var A=j==null;if(A)j=new I(o.length>>>2<<3);while(r==0){r=s(o,x,1);
  252. i=s(o,x+1,2);x+=3;if(i==0){if((x&7)!=0)x+=8-(x&7);var K=(x>>>3)+4,m=o[K-4]|o[K-3]<<8;if(A)j=H(j,N+m);
  253. j.set(new I(o.buffer,o.byteOffset+K,m),N);x=K+m<<3;N+=m;continue}if(A)j=H(j,N+(1<<17));if(i==1){P=D.g;
  254. J=D.A;a=(1<<9)-1;k=(1<<5)-1}if(i==2){y=F(o,x,5)+257;G=F(o,x+5,5)+1;f=F(o,x+10,4)+4;x+=14;var O=x,Q=1;
  255. for(var p=0;p<38;p+=2){D.b[p]=0;D.b[p+1]=0}for(var p=0;p<f;p++){var l=F(o,x+p*3,3);D.b[(D.d[p]<<1)+1]=l;
  256. if(l>Q)Q=l}x+=3*f;C(D.b,Q);t(D.b,Q,D.C);P=D.k;J=D.n;x=B(D.C,(1<<Q)-1,y+G,o,x,D.a);var u=d(D.a,0,y,D.c);
  257. a=(1<<u)-1;var n=d(D.a,y,G,D.e);k=(1<<n)-1;C(D.c,u);t(D.c,u,P);C(D.e,n);t(D.e,n,J)}while(!0){var h=P[w(o,x)&a];
  258. x+=h&15;var L=h>>>4;if(L>>>8==0){j[N++]=L}else if(L==256){break}else{var M=N+L-254;if(L>264){var z=D.B[L-257];
  259. M=N+(z>>>3)+F(o,x,z&7);x+=z&7}var e=J[w(o,x)&k];x+=e&15;var E=e>>>4,c=D.h[E],q=(c>>>4)+s(o,x,c&15);x+=c&15;
  260. if(A)j=H(j,N+(1<<17));while(N<M){j[N]=j[N++-q];j[N]=j[N++-q];j[N]=j[N++-q];j[N]=j[N++-q]}N=M}}}return j.length==N?j:j.slice(0,N)}function H(o,j){var I=o.length;
  261. if(j<=I)return o;var A=new Uint8Array(Math.max(I<<1,j));A.set(o,0);return A}function B(o,j,I,A,r,i){var y=0;
  262. while(y<I){var G=o[w(A,r)&j];r+=G&15;var f=G>>>4;if(f<=15){i[y]=f;y++}else{var a=0,k=0;if(f==16){k=3+F(A,r,2);
  263. r+=2;a=i[y-1]}else if(f==17){k=3+F(A,r,3);r+=3}else if(f==18){k=11+F(A,r,7);r+=7}var N=y+k;while(y<N){i[y]=a;
  264. y++}}}return r}function d(o,j,I,A){var r=0,i=0,y=A.length>>>1;while(i<I){var G=o[i+j];A[i<<1]=0;A[(i<<1)+1]=G;
  265. if(G>r)r=G;i++}while(i<y){A[i<<1]=0;A[(i<<1)+1]=0;i++}return r}return v}();
  266. function _readInterlace(data, out)
  267. {
  268. var w = out.width, h = out.height;
  269. var bpp = _getBPP(out), cbpp = bpp>>3, bpl = Math.ceil(w*bpp/8);
  270. var img = new Uint8Array( h * bpl );
  271. var di = 0;
  272. var starting_row = [ 0, 0, 4, 0, 2, 0, 1 ];
  273. var starting_col = [ 0, 4, 0, 2, 0, 1, 0 ];
  274. var row_increment = [ 8, 8, 8, 4, 4, 2, 2 ];
  275. var col_increment = [ 8, 8, 4, 4, 2, 2, 1 ];
  276. var pass=0;
  277. while(pass<7)
  278. {
  279. var ri = row_increment[pass], ci = col_increment[pass];
  280. var sw = 0, sh = 0;
  281. var cr = starting_row[pass]; while(cr<h) { cr+=ri; sh++; }
  282. var cc = starting_col[pass]; while(cc<w) { cc+=ci; sw++; }
  283. var bpll = Math.ceil(sw*bpp/8);
  284. _filterZero(data, out, di, sw, sh);
  285. var y=0, row = starting_row[pass];
  286. while(row<h)
  287. {
  288. var col = starting_col[pass];
  289. var cdi = (di+y*bpll)<<3;
  290. while(col<w)
  291. {
  292. if(bpp==1) {
  293. var val = data[cdi>>3]; val = (val>>(7-(cdi&7)))&1;
  294. img[row*bpl + (col>>3)] |= (val << (7-((col&7)<<0)));
  295. }
  296. if(bpp==2) {
  297. var val = data[cdi>>3]; val = (val>>(6-(cdi&7)))&3;
  298. img[row*bpl + (col>>2)] |= (val << (6-((col&3)<<1)));
  299. }
  300. if(bpp==4) {
  301. var val = data[cdi>>3]; val = (val>>(4-(cdi&7)))&15;
  302. img[row*bpl + (col>>1)] |= (val << (4-((col&1)<<2)));
  303. }
  304. if(bpp>=8) {
  305. var ii = row*bpl+col*cbpp;
  306. for(var j=0; j<cbpp; j++) img[ii+j] = data[(cdi>>3)+j];
  307. }
  308. cdi+=bpp; col+=ci;
  309. }
  310. y++; row += ri;
  311. }
  312. if(sw*sh!=0) di += sh * (1 + bpll);
  313. pass = pass + 1;
  314. }
  315. return img;
  316. }
  317. function _getBPP(out) {
  318. var noc = [1,null,3,1,2,null,4][out.ctype];
  319. return noc * out.depth;
  320. }
  321. function _filterZero(data, out, off, w, h)
  322. {
  323. var bpp = _getBPP(out), bpl = Math.ceil(w*bpp/8);
  324. bpp = Math.ceil(bpp/8);
  325. var i,di, type=data[off], x=0;
  326. if(type>1) data[off]=[0,0,1][type-2];
  327. if(type==3) for(x=bpp; x<bpl; x++) data[x+1] = (data[x+1] + (data[x+1-bpp]>>>1) )&255;
  328. for(var y=0; y<h; y++) {
  329. i = off+y*bpl; di = i+y+1;
  330. type = data[di-1]; x=0;
  331. if (type==0) for(; x<bpl; x++) data[i+x] = data[di+x];
  332. else if(type==1) { for(; x<bpp; x++) data[i+x] = data[di+x];
  333. for(; x<bpl; x++) data[i+x] = (data[di+x] + data[i+x-bpp]); }
  334. else if(type==2) { for(; x<bpl; x++) data[i+x] = (data[di+x] + data[i+x-bpl]); }
  335. else if(type==3) { for(; x<bpp; x++) data[i+x] = (data[di+x] + ( data[i+x-bpl]>>>1));
  336. for(; x<bpl; x++) data[i+x] = (data[di+x] + ((data[i+x-bpl]+data[i+x-bpp])>>>1) ); }
  337. else { for(; x<bpp; x++) data[i+x] = (data[di+x] + _paeth(0, data[i+x-bpl], 0));
  338. for(; x<bpl; x++) data[i+x] = (data[di+x] + _paeth(data[i+x-bpp], data[i+x-bpl], data[i+x-bpp-bpl]) ); }
  339. }
  340. return data;
  341. }
  342. function _paeth(a,b,c)
  343. {
  344. var p = a+b-c, pa = (p-a), pb = (p-b), pc = (p-c);
  345. if (pa*pa <= pb*pb && pa*pa <= pc*pc) return a;
  346. else if (pb*pb <= pc*pc) return b;
  347. return c;
  348. }
  349. function _IHDR(data, offset, out)
  350. {
  351. out.width = _bin.readUint(data, offset); offset += 4;
  352. out.height = _bin.readUint(data, offset); offset += 4;
  353. out.depth = data[offset]; offset++;
  354. out.ctype = data[offset]; offset++;
  355. out.compress = data[offset]; offset++;
  356. out.filter = data[offset]; offset++;
  357. out.interlace = data[offset]; offset++;
  358. }
  359. function _copyTile(sb, sw, sh, tb, tw, th, xoff, yoff, mode)
  360. {
  361. var w = Math.min(sw,tw), h = Math.min(sh,th);
  362. var si=0, ti=0;
  363. for(var y=0; y<h; y++)
  364. for(var x=0; x<w; x++)
  365. {
  366. if(xoff>=0 && yoff>=0) { si = (y*sw+x)<<2; ti = (( yoff+y)*tw+xoff+x)<<2; }
  367. else { si = ((-yoff+y)*sw-xoff+x)<<2; ti = (y*tw+x)<<2; }
  368. 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]; }
  369. else if(mode==1) {
  370. var fa = sb[si+3]*(1/255), fr=sb[si]*fa, fg=sb[si+1]*fa, fb=sb[si+2]*fa;
  371. var ba = tb[ti+3]*(1/255), br=tb[ti]*ba, bg=tb[ti+1]*ba, bb=tb[ti+2]*ba;
  372. var ifa=1-fa, oa = fa+ba*ifa, ioa = (oa==0?0:1/oa);
  373. tb[ti+3] = 255*oa;
  374. tb[ti+0] = (fr+br*ifa)*ioa;
  375. tb[ti+1] = (fg+bg*ifa)*ioa;
  376. tb[ti+2] = (fb+bb*ifa)*ioa;
  377. }
  378. else if(mode==2){ // copy only differences, otherwise zero
  379. var fa = sb[si+3], fr=sb[si], fg=sb[si+1], fb=sb[si+2];
  380. var ba = tb[ti+3], br=tb[ti], bg=tb[ti+1], bb=tb[ti+2];
  381. if(fa==ba && fr==br && fg==bg && fb==bb) { tb[ti]=0; tb[ti+1]=0; tb[ti+2]=0; tb[ti+3]=0; }
  382. else { tb[ti]=fr; tb[ti+1]=fg; tb[ti+2]=fb; tb[ti+3]=fa; }
  383. }
  384. else if(mode==3){ // check if can be blended
  385. var fa = sb[si+3], fr=sb[si], fg=sb[si+1], fb=sb[si+2];
  386. var ba = tb[ti+3], br=tb[ti], bg=tb[ti+1], bb=tb[ti+2];
  387. if(fa==ba && fr==br && fg==bg && fb==bb) continue;
  388. //if(fa!=255 && ba!=0) return false;
  389. if(fa<220 && ba>20) return false;
  390. }
  391. }
  392. return true;
  393. }
  394. return {
  395. decode:decode,
  396. toRGBA8:toRGBA8,
  397. _paeth:_paeth,
  398. _copyTile:_copyTile,
  399. _bin:_bin
  400. };
  401. })();
  402. (function() {
  403. var _copyTile = UPNG._copyTile, _bin=UPNG._bin, paeth = UPNG._paeth;
  404. var crcLib = {
  405. table : ( function() {
  406. var tab = new Uint32Array(256);
  407. for (var n=0; n<256; n++) {
  408. var c = n;
  409. for (var k=0; k<8; k++) {
  410. if (c & 1) c = 0xedb88320 ^ (c >>> 1);
  411. else c = c >>> 1;
  412. }
  413. tab[n] = c; }
  414. return tab; })(),
  415. update : function(c, buf, off, len) {
  416. for (var i=0; i<len; i++) c = crcLib.table[(c ^ buf[off+i]) & 0xff] ^ (c >>> 8);
  417. return c;
  418. },
  419. crc : function(b,o,l) { return crcLib.update(0xffffffff,b,o,l) ^ 0xffffffff; }
  420. }
  421. function addErr(er, tg, ti, f) {
  422. tg[ti]+=(er[0]*f)>>4; tg[ti+1]+=(er[1]*f)>>4; tg[ti+2]+=(er[2]*f)>>4; tg[ti+3]+=(er[3]*f)>>4;
  423. }
  424. function N(x) { return Math.max(0, Math.min(255, x)); }
  425. function D(a,b) { var dr=a[0]-b[0], dg=a[1]-b[1], db=a[2]-b[2], da=a[3]-b[3]; return (dr*dr + dg*dg + db*db + da*da); }
  426. // MTD: 0: None, 1: floyd-steinberg, 2: Bayer
  427. function dither(sb, w, h, plte, tb, oind, MTD) {
  428. if(MTD==null) MTD=1;
  429. var pc=plte.length, nplt = [], rads=[];
  430. for(var i=0; i<pc; i++) {
  431. var c = plte[i];
  432. nplt.push([((c>>>0)&255), ((c>>>8)&255), ((c>>>16)&255), ((c>>>24)&255)]);
  433. }
  434. for(var i=0; i<pc; i++) {
  435. var ne=0xffffffff, ni=0;
  436. for(var j=0; j<pc; j++) { var ce=D(nplt[i],nplt[j]); if(j!=i && ce<ne) { ne=ce; ni=j; } }
  437. var hd = Math.sqrt(ne)/2;
  438. rads[i] = ~~(hd*hd);
  439. }
  440. var tb32 = new Uint32Array(tb.buffer);
  441. var err = new Int16Array(w*h*4);
  442. /*
  443. var S=2, M = [
  444. 0,2,
  445. 3,1]; //*/
  446. //*
  447. var S=4, M = [
  448. 0, 8, 2,10,
  449. 12, 4,14, 6,
  450. 3,11, 1, 9,
  451. 15, 7,13, 5 ]; //*/
  452. for(var i=0; i<M.length; i++) M[i] = 255*(-0.5 + (M[i]+0.5)/(S*S));
  453. for(var y=0; y<h; y++) {
  454. for(var x=0; x<w; x++) {
  455. var i = (y*w+x)*4;
  456. var cc;
  457. if(MTD!=2) cc = [N(sb[i]+err[i]), N(sb[i+1]+err[i+1]), N(sb[i+2]+err[i+2]), N(sb[i+3]+err[i+3])];
  458. else {
  459. var ce = M[(y&(S-1))*S+(x&(S-1))];
  460. cc = [N(sb[i]+ce), N(sb[i+1]+ce), N(sb[i+2]+ce), N(sb[i+3]+ce)];
  461. }
  462. var ni=0, nd = 0xffffff;
  463. for(var j=0; j<pc; j++) {
  464. var cd = D(cc,nplt[j]);
  465. if(cd<nd) { nd=cd; ni=j; }
  466. }
  467. var nc = nplt[ni];
  468. var er = [cc[0]-nc[0], cc[1]-nc[1], cc[2]-nc[2], cc[3]-nc[3]];
  469. if(MTD==1) {
  470. //addErr(er, err, i+4, 16);
  471. if(x!=w-1) addErr(er, err, i+4 , 7);
  472. if(y!=h-1) {
  473. if(x!= 0) addErr(er, err, i+4*w-4, 3);
  474. addErr(er, err, i+4*w , 5);
  475. if(x!=w-1) addErr(er, err, i+4*w+4, 1);
  476. }//*/
  477. }
  478. oind[i>>2] = ni; tb32[i>>2] = plte[ni];
  479. }
  480. }
  481. }
  482. function encode(bufs, w, h, ps, dels, tabs, forbidPlte)
  483. {
  484. if(ps==null) ps=0;
  485. if(forbidPlte==null) forbidPlte = false;
  486. var nimg = compress(bufs, w, h, ps, [false, false, false, 0, forbidPlte,false]);
  487. compressPNG(nimg, -1);
  488. return _main(nimg, w, h, dels, tabs);
  489. }
  490. function encodeLL(bufs, w, h, cc, ac, depth, dels, tabs) {
  491. var nimg = { ctype: 0 + (cc==1 ? 0 : 2) + (ac==0 ? 0 : 4), depth: depth, frames: [] };
  492. var time = Date.now();
  493. var bipp = (cc+ac)*depth, bipl = bipp * w;
  494. for(var i=0; i<bufs.length; i++)
  495. nimg.frames.push({ rect:{x:0,y:0,width:w,height:h}, img:new Uint8Array(bufs[i]), blend:0, dispose:1, bpp:Math.ceil(bipp/8), bpl:Math.ceil(bipl/8) });
  496. compressPNG(nimg, 0, true);
  497. var out = _main(nimg, w, h, dels, tabs);
  498. return out;
  499. }
  500. function _main(nimg, w, h, dels, tabs) {
  501. if(tabs==null) tabs={};
  502. var crc = crcLib.crc, wUi = _bin.writeUint, wUs = _bin.writeUshort, wAs = _bin.writeASCII;
  503. var offset = 8, anim = nimg.frames.length>1, pltAlpha = false;
  504. var cicc;
  505. var leng = 8 + (16+5+4) /*+ (9+4)*/ + (anim ? 20 : 0);
  506. if(tabs["sRGB"]!=null) leng += 8+1+4;
  507. if(tabs["pHYs"]!=null) leng += 8+9+4;
  508. if(tabs["iCCP"]!=null) { cicc = pako.deflate(tabs["iCCP"]); leng += 8 + 11 + 2 + cicc.length + 4; }
  509. if(nimg.ctype==3) {
  510. var dl = nimg.plte.length;
  511. for(var i=0; i<dl; i++) if((nimg.plte[i]>>>24)!=255) pltAlpha = true;
  512. leng += (8 + dl*3 + 4) + (pltAlpha ? (8 + dl*1 + 4) : 0);
  513. }
  514. for(var j=0; j<nimg.frames.length; j++)
  515. {
  516. var fr = nimg.frames[j];
  517. if(anim) leng += 38;
  518. leng += fr.cimg.length + 12;
  519. if(j!=0) leng+=4;
  520. }
  521. leng += 12;
  522. var data = new Uint8Array(leng);
  523. var wr=[0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
  524. for(var i=0; i<8; i++) data[i]=wr[i];
  525. wUi(data,offset, 13); offset+=4;
  526. wAs(data,offset,"IHDR"); offset+=4;
  527. wUi(data,offset,w); offset+=4;
  528. wUi(data,offset,h); offset+=4;
  529. data[offset] = nimg.depth; offset++; // depth
  530. data[offset] = nimg.ctype; offset++; // ctype
  531. data[offset] = 0; offset++; // compress
  532. data[offset] = 0; offset++; // filter
  533. data[offset] = 0; offset++; // interlace
  534. wUi(data,offset,crc(data,offset-17,17)); offset+=4; // crc
  535. // 13 bytes to say, that it is sRGB
  536. if(tabs["sRGB"]!=null) {
  537. wUi(data,offset, 1); offset+=4;
  538. wAs(data,offset,"sRGB"); offset+=4;
  539. data[offset] = tabs["sRGB"]; offset++;
  540. wUi(data,offset,crc(data,offset-5,5)); offset+=4; // crc
  541. }
  542. if(tabs["iCCP"]!=null) {
  543. var sl = 11+2+cicc.length;
  544. wUi(data,offset, sl); offset+=4;
  545. wAs(data,offset,"iCCP"); offset+=4;
  546. wAs(data,offset,"ICC profile"); offset+=11; offset+=2;
  547. data.set(cicc, offset); offset+=cicc.length;
  548. wUi(data,offset,crc(data,offset-(sl+4),sl+4)); offset+=4; // crc
  549. }
  550. if(tabs["pHYs"]!=null) {
  551. wUi(data,offset, 9); offset+=4;
  552. wAs(data,offset,"pHYs"); offset+=4;
  553. wUi(data,offset, tabs["pHYs"][0]); offset+=4;
  554. wUi(data,offset, tabs["pHYs"][1]); offset+=4;
  555. data[offset]=tabs["pHYs"][2]; offset++;
  556. wUi(data,offset,crc(data,offset-13,13)); offset+=4; // crc
  557. }
  558. if(anim) {
  559. wUi(data,offset, 8); offset+=4;
  560. wAs(data,offset,"acTL"); offset+=4;
  561. wUi(data,offset, nimg.frames.length); offset+=4;
  562. wUi(data,offset, tabs["loop"]!=null?tabs["loop"]:0); offset+=4;
  563. wUi(data,offset,crc(data,offset-12,12)); offset+=4; // crc
  564. }
  565. if(nimg.ctype==3) {
  566. var dl = nimg.plte.length;
  567. wUi(data,offset, dl*3); offset+=4;
  568. wAs(data,offset,"PLTE"); offset+=4;
  569. for(var i=0; i<dl; i++){
  570. var ti=i*3, c=nimg.plte[i], r=(c)&255, g=(c>>>8)&255, b=(c>>>16)&255;
  571. data[offset+ti+0]=r; data[offset+ti+1]=g; data[offset+ti+2]=b;
  572. }
  573. offset+=dl*3;
  574. wUi(data,offset,crc(data,offset-dl*3-4,dl*3+4)); offset+=4; // crc
  575. if(pltAlpha) {
  576. wUi(data,offset, dl); offset+=4;
  577. wAs(data,offset,"tRNS"); offset+=4;
  578. for(var i=0; i<dl; i++) data[offset+i]=(nimg.plte[i]>>>24)&255;
  579. offset+=dl;
  580. wUi(data,offset,crc(data,offset-dl-4,dl+4)); offset+=4; // crc
  581. }
  582. }
  583. var fi = 0;
  584. for(var j=0; j<nimg.frames.length; j++)
  585. {
  586. var fr = nimg.frames[j];
  587. if(anim) {
  588. wUi(data, offset, 26); offset+=4;
  589. wAs(data, offset,"fcTL"); offset+=4;
  590. wUi(data, offset, fi++); offset+=4;
  591. wUi(data, offset, fr.rect.width ); offset+=4;
  592. wUi(data, offset, fr.rect.height); offset+=4;
  593. wUi(data, offset, fr.rect.x); offset+=4;
  594. wUi(data, offset, fr.rect.y); offset+=4;
  595. wUs(data, offset, dels[j]); offset+=2;
  596. wUs(data, offset, 1000); offset+=2;
  597. data[offset] = fr.dispose; offset++; // dispose
  598. data[offset] = fr.blend ; offset++; // blend
  599. wUi(data,offset,crc(data,offset-30,30)); offset+=4; // crc
  600. }
  601. var imgd = fr.cimg, dl = imgd.length;
  602. wUi(data,offset, dl+(j==0?0:4)); offset+=4;
  603. var ioff = offset;
  604. wAs(data,offset,(j==0)?"IDAT":"fdAT"); offset+=4;
  605. if(j!=0) { wUi(data, offset, fi++); offset+=4; }
  606. data.set(imgd,offset);
  607. offset += dl;
  608. wUi(data,offset,crc(data,ioff,offset-ioff)); offset+=4; // crc
  609. }
  610. wUi(data,offset, 0); offset+=4;
  611. wAs(data,offset,"IEND"); offset+=4;
  612. wUi(data,offset,crc(data,offset-4,4)); offset+=4; // crc
  613. return data.buffer;
  614. }
  615. function compressPNG(out, filter, levelZero) {
  616. for(var i=0; i<out.frames.length; i++) {
  617. var frm = out.frames[i], nw=frm.rect.width, nh=frm.rect.height;
  618. var fdata = new Uint8Array(nh*frm.bpl+nh);
  619. frm.cimg = _filterZero(frm.img,nh,frm.bpp,frm.bpl,fdata, filter, levelZero);
  620. }
  621. }
  622. function compress(bufs, w, h, ps, prms) // prms: onlyBlend, minBits, forbidPlte
  623. {
  624. //var time = Date.now();
  625. var onlyBlend = prms[0], evenCrd = prms[1], forbidPrev = prms[2], minBits = prms[3], forbidPlte = prms[4], dith=prms[5];
  626. var ctype = 6, depth = 8, alphaAnd=255
  627. for(var j=0; j<bufs.length; j++) { // when not quantized, other frames can contain colors, that are not in an initial frame
  628. var img = new Uint8Array(bufs[j]), ilen = img.length;
  629. for(var i=0; i<ilen; i+=4) alphaAnd &= img[i+3];
  630. }
  631. var gotAlpha = (alphaAnd!=255);
  632. //console.log("alpha check", Date.now()-time); time = Date.now();
  633. //var brute = gotAlpha && forGIF; // brute : frames can only be copied, not "blended"
  634. var frms = framize(bufs, w, h, onlyBlend, evenCrd, forbidPrev);
  635. //console.log("framize", Date.now()-time); time = Date.now();
  636. var cmap={}, plte=[], inds=[];
  637. if(ps!=0) {
  638. var nbufs = []; for(var i=0; i<frms.length; i++) nbufs.push(frms[i].img.buffer);
  639. var abuf = concatRGBA(nbufs), qres = quantize(abuf, ps);
  640. for(var i=0; i<qres.plte.length; i++) plte.push(qres.plte[i].est.rgba);
  641. var cof = 0;
  642. for(var i=0; i<frms.length; i++) {
  643. var frm=frms[i], bln=frm.img.length, ind = new Uint8Array(qres.inds.buffer, cof>>2, bln>>2); inds.push(ind);
  644. var bb = new Uint8Array(qres.abuf,cof,bln);
  645. //console.log(frm.img, frm.width, frm.height);
  646. //var time = Date.now();
  647. if(dith) dither(frm.img, frm.rect.width, frm.rect.height, plte, bb, ind);
  648. //console.log(Date.now()-time);
  649. frm.img.set(bb); cof+=bln;
  650. }
  651. //console.log("quantize", Date.now()-time); time = Date.now();
  652. }
  653. else {
  654. // what if ps==0, but there are <=256 colors? we still need to detect, if the palette could be used
  655. for(var j=0; j<frms.length; j++) { // when not quantized, other frames can contain colors, that are not in an initial frame
  656. var frm = frms[j], img32 = new Uint32Array(frm.img.buffer), nw=frm.rect.width, ilen = img32.length;
  657. var ind = new Uint8Array(ilen); inds.push(ind);
  658. for(var i=0; i<ilen; i++) {
  659. var c = img32[i];
  660. if (i!=0 && c==img32[i- 1]) ind[i]=ind[i-1];
  661. else if(i>nw && c==img32[i-nw]) ind[i]=ind[i-nw];
  662. else {
  663. var cmc = cmap[c];
  664. if(cmc==null) { cmap[c]=cmc=plte.length; plte.push(c); if(plte.length>=300) break; }
  665. ind[i]=cmc;
  666. }
  667. }
  668. }
  669. //console.log("make palette", Date.now()-time); time = Date.now();
  670. }
  671. var cc=plte.length; //console.log("colors:",cc);
  672. if(cc<=256 && forbidPlte==false) {
  673. if(cc<= 2) depth=1; else if(cc<= 4) depth=2; else if(cc<=16) depth=4; else depth=8;
  674. depth = Math.max(depth, minBits);
  675. }
  676. for(var j=0; j<frms.length; j++)
  677. {
  678. var frm = frms[j], nx=frm.rect.x, ny=frm.rect.y, nw=frm.rect.width, nh=frm.rect.height;
  679. var cimg = frm.img, cimg32 = new Uint32Array(cimg.buffer);
  680. var bpl = 4*nw, bpp=4;
  681. if(cc<=256 && forbidPlte==false) {
  682. bpl = Math.ceil(depth*nw/8);
  683. var nimg = new Uint8Array(bpl*nh);
  684. var inj = inds[j];
  685. for(var y=0; y<nh; y++) { var i=y*bpl, ii=y*nw;
  686. if (depth==8) for(var x=0; x<nw; x++) nimg[i+(x) ] = (inj[ii+x] );
  687. else if(depth==4) for(var x=0; x<nw; x++) nimg[i+(x>>1)] |= (inj[ii+x]<<(4-(x&1)*4));
  688. else if(depth==2) for(var x=0; x<nw; x++) nimg[i+(x>>2)] |= (inj[ii+x]<<(6-(x&3)*2));
  689. else if(depth==1) for(var x=0; x<nw; x++) nimg[i+(x>>3)] |= (inj[ii+x]<<(7-(x&7)*1));
  690. }
  691. cimg=nimg; ctype=3; bpp=1;
  692. }
  693. else if(gotAlpha==false && frms.length==1) { // some next "reduced" frames may contain alpha for blending
  694. var nimg = new Uint8Array(nw*nh*3), area=nw*nh;
  695. 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]; }
  696. cimg=nimg; ctype=2; bpp=3; bpl=3*nw;
  697. }
  698. frm.img=cimg; frm.bpl=bpl; frm.bpp=bpp;
  699. }
  700. //console.log("colors => palette indices", Date.now()-time); time = Date.now();
  701. return {ctype:ctype, depth:depth, plte:plte, frames:frms };
  702. }
  703. function framize(bufs,w,h,alwaysBlend,evenCrd,forbidPrev) {
  704. /* DISPOSE
  705. - 0 : no change
  706. - 1 : clear to transparent
  707. - 2 : retstore to content before rendering (previous frame disposed)
  708. BLEND
  709. - 0 : replace
  710. - 1 : blend
  711. */
  712. var frms = [];
  713. for(var j=0; j<bufs.length; j++) {
  714. var cimg = new Uint8Array(bufs[j]), cimg32 = new Uint32Array(cimg.buffer);
  715. var nimg;
  716. var nx=0, ny=0, nw=w, nh=h, blend=alwaysBlend?1:0;
  717. if(j!=0) {
  718. var tlim = (forbidPrev || alwaysBlend || j==1 || frms[j-2].dispose!=0)?1:2, tstp = 0, tarea = 1e9;
  719. for(var it=0; it<tlim; it++)
  720. {
  721. var pimg = new Uint8Array(bufs[j-1-it]), p32 = new Uint32Array(bufs[j-1-it]);
  722. var mix=w,miy=h,max=-1,may=-1;
  723. for(var y=0; y<h; y++) for(var x=0; x<w; x++) {
  724. var i = y*w+x;
  725. if(cimg32[i]!=p32[i]) {
  726. if(x<mix) mix=x; if(x>max) max=x;
  727. if(y<miy) miy=y; if(y>may) may=y;
  728. }
  729. }
  730. if(max==-1) mix=miy=max=may=0;
  731. if(evenCrd) { if((mix&1)==1)mix--; if((miy&1)==1)miy--; }
  732. var sarea = (max-mix+1)*(may-miy+1);
  733. if(sarea<tarea) {
  734. tarea = sarea; tstp = it;
  735. nx = mix; ny = miy; nw = max-mix+1; nh = may-miy+1;
  736. }
  737. }
  738. // alwaysBlend: pokud zjistím, že blendit nelze, nastavím předchozímu snímku dispose=1. Zajistím, aby obsahoval můj obdélník.
  739. var pimg = new Uint8Array(bufs[j-1-tstp]);
  740. if(tstp==1) frms[j-1].dispose = 2;
  741. nimg = new Uint8Array(nw*nh*4);
  742. _copyTile(pimg,w,h, nimg,nw,nh, -nx,-ny, 0);
  743. blend = _copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 3) ? 1 : 0;
  744. if(blend==1) _prepareDiff(cimg,w,h,nimg,{x:nx,y:ny,width:nw,height:nh});
  745. else _copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, 0);
  746. }
  747. else nimg = cimg.slice(0); // img may be rewritten further ... don't rewrite input
  748. frms.push({rect:{x:nx,y:ny,width:nw,height:nh}, img:nimg, blend:blend, dispose:0});
  749. }
  750. if(alwaysBlend) for(var j=0; j<frms.length; j++) {
  751. var frm = frms[j]; if(frm.blend==1) continue;
  752. var r0 = frm.rect, r1 = frms[j-1].rect
  753. var miX = Math.min(r0.x, r1.x), miY = Math.min(r0.y, r1.y);
  754. var maX = Math.max(r0.x+r0.width, r1.x+r1.width), maY = Math.max(r0.y+r0.height, r1.y+r1.height);
  755. var r = {x:miX, y:miY, width:maX-miX, height:maY-miY};
  756. frms[j-1].dispose = 1;
  757. if(j-1!=0)
  758. _updateFrame(bufs, w,h,frms, j-1,r, evenCrd);
  759. _updateFrame(bufs, w,h,frms, j ,r, evenCrd);
  760. }
  761. var area = 0;
  762. if(bufs.length!=1) for(var i=0; i<frms.length; i++) {
  763. var frm = frms[i];
  764. area += frm.rect.width*frm.rect.height;
  765. //if(i==0 || frm.blend!=1) continue;
  766. //var ob = new Uint8Array(
  767. //console.log(frm.blend, frm.dispose, frm.rect);
  768. }
  769. //if(area!=0) console.log(area);
  770. return frms;
  771. }
  772. function _updateFrame(bufs, w,h, frms, i, r, evenCrd) {
  773. var U8 = Uint8Array, U32 = Uint32Array;
  774. var pimg = new U8(bufs[i-1]), pimg32 = new U32(bufs[i-1]), nimg = i+1<bufs.length ? new U8(bufs[i+1]):null;
  775. var cimg = new U8(bufs[i]), cimg32 = new U32(cimg.buffer);
  776. var mix=w,miy=h,max=-1,may=-1;
  777. for(var y=0; y<r.height; y++) for(var x=0; x<r.width; x++) {
  778. var cx = r.x+x, cy = r.y+y;
  779. var j = cy*w+cx, cc = cimg32[j];
  780. // no need to draw transparency, or to dispose it. Or, if writing the same color and the next one does not need transparency.
  781. if(cc==0 || (frms[i-1].dispose==0 && pimg32[j]==cc && (nimg==null || nimg[j*4+3]!=0))/**/) {}
  782. else {
  783. if(cx<mix) mix=cx; if(cx>max) max=cx;
  784. if(cy<miy) miy=cy; if(cy>may) may=cy;
  785. }
  786. }
  787. if(max==-1) mix=miy=max=may=0;
  788. if(evenCrd) { if((mix&1)==1)mix--; if((miy&1)==1)miy--; }
  789. r = {x:mix, y:miy, width:max-mix+1, height:may-miy+1};
  790. var fr = frms[i]; fr.rect = r; fr.blend = 1; fr.img = new Uint8Array(r.width*r.height*4);
  791. if(frms[i-1].dispose==0) {
  792. _copyTile(pimg,w,h, fr.img,r.width,r.height, -r.x,-r.y, 0);
  793. _prepareDiff(cimg,w,h,fr.img,r);
  794. }
  795. else
  796. _copyTile(cimg,w,h, fr.img,r.width,r.height, -r.x,-r.y, 0);
  797. }
  798. function _prepareDiff(cimg, w,h, nimg, rec) {
  799. _copyTile(cimg,w,h, nimg,rec.width,rec.height, -rec.x,-rec.y, 2);
  800. }
  801. function _filterZero(img,h,bpp,bpl,data, filter, levelZero)
  802. {
  803. var fls = [], ftry=[0,1,2,3,4];
  804. if (filter!=-1) ftry=[filter];
  805. else if(h*bpl>500000 || bpp==1) ftry=[0];
  806. var opts; if(levelZero) opts={level:0};
  807. var CMPR = (data.length>10e6 && window.UZIP!=null) ? window.UZIP : pako;
  808. var time = Date.now();
  809. for(var i=0; i<ftry.length; i++) {
  810. for(var y=0; y<h; y++) _filterLine(data, img, y, bpl, bpp, ftry[i]);
  811. //var nimg = new Uint8Array(data.length);
  812. //var sz = UZIP.F.deflate(data, nimg); fls.push(nimg.slice(0,sz));
  813. //var dfl = pako["deflate"](data), dl=dfl.length-4;
  814. //var crc = (dfl[dl+3]<<24)|(dfl[dl+2]<<16)|(dfl[dl+1]<<8)|(dfl[dl+0]<<0);
  815. //console.log(crc, UZIP.adler(data,2,data.length-6));
  816. fls.push(CMPR["deflate"](data,opts));
  817. }
  818. var ti, tsize=1e9;
  819. for(var i=0; i<fls.length; i++) if(fls[i].length<tsize) { ti=i; tsize=fls[i].length; }
  820. return fls[ti];
  821. }
  822. function _filterLine(data, img, y, bpl, bpp, type)
  823. {
  824. var i = y*bpl, di = i+y;
  825. data[di]=type; di++;
  826. if(type==0) {
  827. if(bpl<500) for(var x=0; x<bpl; x++) data[di+x] = img[i+x];
  828. else data.set(new Uint8Array(img.buffer,i,bpl),di);
  829. }
  830. else if(type==1) {
  831. for(var x= 0; x<bpp; x++) data[di+x] = img[i+x];
  832. for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]-img[i+x-bpp]+256)&255;
  833. }
  834. else if(y==0) {
  835. for(var x= 0; x<bpp; x++) data[di+x] = img[i+x];
  836. if(type==2) for(var x=bpp; x<bpl; x++) data[di+x] = img[i+x];
  837. if(type==3) for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x] - (img[i+x-bpp]>>1) +256)&255;
  838. 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;
  839. }
  840. else {
  841. if(type==2) { for(var x= 0; x<bpl; x++) data[di+x] = (img[i+x]+256 - img[i+x-bpl])&255; }
  842. if(type==3) { for(var x= 0; x<bpp; x++) data[di+x] = (img[i+x]+256 - (img[i+x-bpl]>>1))&255;
  843. for(var x=bpp; x<bpl; x++) data[di+x] = (img[i+x]+256 - ((img[i+x-bpl]+img[i+x-bpp])>>1))&255; }
  844. 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;
  845. 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; }
  846. }
  847. }
  848. function quantize(abuf, ps, doKmeans)
  849. {
  850. var time = Date.now();
  851. var sb = new Uint8Array(abuf), tb = sb.slice(0), tb32 = new Uint32Array(tb.buffer);
  852. var KD = getKDtree(tb, ps);
  853. var root = KD[0], leafs = KD[1], K=leafs.length;
  854. //console.log(Date.now()-time, "tree made"); time = Date.now();
  855. var cl32 = new Uint32Array(K), clr8=new Uint8Array(cl32.buffer);
  856. for(var i=0; i<K; i++) cl32[i]=leafs[i].est.rgba;
  857. var len=sb.length;
  858. var inds = new Uint8Array(len>>2), nd;
  859. if(K<=60) { findNearest(sb,inds,clr8); remap(inds,tb32,cl32); }
  860. else if(sb.length<32e6) // precise, but slow :(
  861. //for(var j=0; j<4; j++)
  862. for(var i=0; i<len; i+=4) {
  863. var r=sb[i]*(1/255), g=sb[i+1]*(1/255), b=sb[i+2]*(1/255), a=sb[i+3]*(1/255);
  864. nd = getNearest(root, r, g, b, a);
  865. inds[i>>2] = nd.ind; tb32[i>>2] = nd.est.rgba;
  866. }
  867. else
  868. for(var i=0; i<len; i+=4) {
  869. var r=sb[i]*(1/255), g=sb[i+1]*(1/255), b=sb[i+2]*(1/255), a=sb[i+3]*(1/255);
  870. nd = root; while(nd.left) nd = (planeDst(nd.est,r,g,b,a)<=0) ? nd.left : nd.right;
  871. inds[i>>2] = nd.ind; tb32[i>>2] = nd.est.rgba;
  872. }
  873. //console.log(Date.now()-time, "nearest found"); time = Date.now();
  874. if(doKmeans || sb.length*K<10*4e6) {
  875. var le = 1e9;
  876. for(var i=0; i<10; i++) {
  877. var ce = kmeans(sb, inds, clr8); //console.log(i,ce);
  878. if(ce/le>0.997) break; le=ce;
  879. }
  880. for(var i=0; i<K; i++) leafs[i].est.rgba = cl32[i];
  881. remap(inds,tb32,cl32);
  882. //console.log(Date.now()-time, "k-means");
  883. }
  884. return { abuf:tb.buffer, inds:inds, plte:leafs };
  885. }
  886. function remap(inds,tb32,pl32) { for(var i=0; i<inds.length; i++) tb32[i]=pl32[inds[i]]; }
  887. function kmeans(sb,inds,plte) {
  888. updatePalette(sb,inds,plte);
  889. var err = findNearest(sb,inds,plte);
  890. return err;
  891. }
  892. function updatePalette(sb,inds,plte) {
  893. var K = plte.length>>>2;
  894. var sums = new Uint32Array(K*4), cnts = new Uint32Array(K);
  895. for(var i=0; i<sb.length; i+=4) {
  896. var ind = inds[i>>>2], qi=ind*4;
  897. cnts[ind]++;
  898. sums[qi ]+=sb[i ]; sums[qi+1]+=sb[i+1];
  899. sums[qi+2]+=sb[i+2]; sums[qi+3]+=sb[i+3];
  900. }
  901. for(var i=0; i<plte.length; i++) plte[i]=Math.round(sums[i]/cnts[i>>>2]);
  902. }
  903. function findNearest(sb,inds,plte) {
  904. var terr = 0, K=plte.length>>>2;
  905. var nd = []; // squared half-distance to the nearest color
  906. for(var i=0; i<K; i++) {
  907. var qi=i*4;
  908. var r=plte[qi], g=plte[qi+1], b=plte[qi+2], a=plte[qi+3], ti=0, te=1e9;
  909. for(var j=0; j<K; j++) {
  910. if(i==j) continue;
  911. var qj=j*4, dr=r-plte[qj], dg=g-plte[qj+1], db=b-plte[qj+2], da=a-plte[qj+3];
  912. var err = dr*dr+dg*dg+db*db+da*da;
  913. if(err<te) {te=err; ti=j;}
  914. }
  915. nd[i] = Math.sqrt(te)*0.5; nd[i]=nd[i]*nd[i];
  916. }
  917. for(var i=0; i<sb.length; i+=4) {
  918. var r=sb[i ], g=sb[i+1], b=sb[i+2], a=sb[i+3];
  919. var ti=inds[i>>>2], qi=ti*4, dr=r-plte[qi], dg=g-plte[qi+1], db=b-plte[qi+2], da=a-plte[qi+3], te = dr*dr+dg*dg+db*db+da*da;
  920. if(te>nd[ti]) for(var j=0; j<K; j++) {
  921. qi=j*4; dr=r-plte[qi]; dg=g-plte[qi+1]; db=b-plte[qi+2]; da=a-plte[qi+3];
  922. var err = dr*dr+dg*dg+db*db+da*da;
  923. if(err<te) {te=err; ti=j; if(te<nd[j]) break; }
  924. }
  925. inds[i>>>2]=ti;
  926. terr+=te;
  927. }
  928. return terr/(sb.length>>>2);
  929. }
  930. function getKDtree(nimg, ps, err) {
  931. if(err==null) err = 0.0001;
  932. var nimg32 = new Uint32Array(nimg.buffer);
  933. var root = {i0:0, i1:nimg.length, bst:null, est:null, tdst:0, left:null, right:null }; // basic statistic, extra statistic
  934. root.bst = stats( nimg,root.i0, root.i1 ); root.est = estats( root.bst );
  935. var leafs = [root];
  936. while(leafs.length<ps)
  937. {
  938. var maxL = 0, mi=0;
  939. for(var i=0; i<leafs.length; i++) if(leafs[i].est.L > maxL) { maxL=leafs[i].est.L; mi=i; }
  940. if(maxL<err) break;
  941. var node = leafs[mi];
  942. var s0 = splitPixels(nimg,nimg32, node.i0, node.i1, node.est.e, node.est.eMq255);
  943. var s0wrong = (node.i0>=s0 || node.i1<=s0);
  944. //console.log(maxL, leafs.length, mi);
  945. if(s0wrong) { node.est.L=0; continue; }
  946. var ln = {i0:node.i0, i1:s0, bst:null, est:null, tdst:0, left:null, right:null }; ln.bst = stats( nimg, ln.i0, ln.i1 );
  947. ln.est = estats( ln.bst );
  948. 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};
  949. for(var i=0; i<16; i++) rn.bst.R[i] = node.bst.R[i]-ln.bst.R[i];
  950. for(var i=0; i< 4; i++) rn.bst.m[i] = node.bst.m[i]-ln.bst.m[i];
  951. rn.est = estats( rn.bst );
  952. node.left = ln; node.right = rn;
  953. leafs[mi]=ln; leafs.push(rn);
  954. }
  955. leafs.sort(function(a,b) { return b.bst.N-a.bst.N; });
  956. for(var i=0; i<leafs.length; i++) leafs[i].ind=i;
  957. return [root, leafs];
  958. }
  959. function getNearest(nd, r,g,b,a)
  960. {
  961. if(nd.left==null) { nd.tdst = dist(nd.est.q,r,g,b,a); return nd; }
  962. var pd = planeDst(nd.est,r,g,b,a);
  963. var node0 = nd.left, node1 = nd.right;
  964. if(pd>0) { node0=nd.right; node1=nd.left; }
  965. var ln = getNearest(node0, r,g,b,a);
  966. if(ln.tdst<=pd*pd) return ln;
  967. var rn = getNearest(node1, r,g,b,a);
  968. return rn.tdst<ln.tdst ? rn : ln;
  969. }
  970. function planeDst(est, r,g,b,a) { var e = est.e; return e[0]*r + e[1]*g + e[2]*b + e[3]*a - est.eMq; }
  971. function dist (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; }
  972. function splitPixels(nimg, nimg32, i0, i1, e, eMq)
  973. {
  974. i1-=4;
  975. var shfs = 0;
  976. while(i0<i1)
  977. {
  978. while(vecDot(nimg, i0, e)<=eMq) i0+=4;
  979. while(vecDot(nimg, i1, e)> eMq) i1-=4;
  980. if(i0>=i1) break;
  981. var t = nimg32[i0>>2]; nimg32[i0>>2] = nimg32[i1>>2]; nimg32[i1>>2]=t;
  982. i0+=4; i1-=4;
  983. }
  984. while(vecDot(nimg, i0, e)>eMq) i0-=4;
  985. return i0+4;
  986. }
  987. function vecDot(nimg, i, e)
  988. {
  989. return nimg[i]*e[0] + nimg[i+1]*e[1] + nimg[i+2]*e[2] + nimg[i+3]*e[3];
  990. }
  991. function stats(nimg, i0, i1){
  992. var R = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
  993. var m = [0,0,0,0];
  994. var N = (i1-i0)>>2;
  995. for(var i=i0; i<i1; i+=4)
  996. {
  997. var r = nimg[i]*(1/255), g = nimg[i+1]*(1/255), b = nimg[i+2]*(1/255), a = nimg[i+3]*(1/255);
  998. //var r = nimg[i], g = nimg[i+1], b = nimg[i+2], a = nimg[i+3];
  999. m[0]+=r; m[1]+=g; m[2]+=b; m[3]+=a;
  1000. R[ 0] += r*r; R[ 1] += r*g; R[ 2] += r*b; R[ 3] += r*a;
  1001. R[ 5] += g*g; R[ 6] += g*b; R[ 7] += g*a;
  1002. R[10] += b*b; R[11] += b*a;
  1003. R[15] += a*a;
  1004. }
  1005. R[4]=R[1]; R[8]=R[2]; R[9]=R[6]; R[12]=R[3]; R[13]=R[7]; R[14]=R[11];
  1006. return {R:R, m:m, N:N};
  1007. }
  1008. function estats(stats){
  1009. var R = stats.R, m = stats.m, N = stats.N;
  1010. // when all samples are equal, but N is large (millions), the Rj can be non-zero ( 0.0003.... - precission error)
  1011. var m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], iN = (N==0 ? 0 : 1/N);
  1012. var Rj = [
  1013. R[ 0] - m0*m0*iN, R[ 1] - m0*m1*iN, R[ 2] - m0*m2*iN, R[ 3] - m0*m3*iN,
  1014. R[ 4] - m1*m0*iN, R[ 5] - m1*m1*iN, R[ 6] - m1*m2*iN, R[ 7] - m1*m3*iN,
  1015. R[ 8] - m2*m0*iN, R[ 9] - m2*m1*iN, R[10] - m2*m2*iN, R[11] - m2*m3*iN,
  1016. R[12] - m3*m0*iN, R[13] - m3*m1*iN, R[14] - m3*m2*iN, R[15] - m3*m3*iN
  1017. ];
  1018. var A = Rj, M = M4;
  1019. var b = [Math.random(),Math.random(),Math.random(),Math.random()], mi = 0, tmi = 0;
  1020. if(N!=0)
  1021. for(var i=0; i<16; i++) {
  1022. b = M.multVec(A, b); tmi = Math.sqrt(M.dot(b,b)); b = M.sml(1/tmi, b);
  1023. if(i!=0 && Math.abs(tmi-mi)<1e-9) break; mi = tmi;
  1024. }
  1025. //b = [0,0,1,0]; mi=N;
  1026. var q = [m0*iN, m1*iN, m2*iN, m3*iN];
  1027. var eMq255 = M.dot(M.sml(255,q),b);
  1028. return { Cov:Rj, q:q, e:b, L:mi, eMq255:eMq255, eMq : M.dot(b,q),
  1029. rgba: (((Math.round(255*q[3])<<24) | (Math.round(255*q[2])<<16) | (Math.round(255*q[1])<<8) | (Math.round(255*q[0])<<0))>>>0) };
  1030. }
  1031. var M4 = {
  1032. multVec : function(m,v) {
  1033. return [
  1034. m[ 0]*v[0] + m[ 1]*v[1] + m[ 2]*v[2] + m[ 3]*v[3],
  1035. m[ 4]*v[0] + m[ 5]*v[1] + m[ 6]*v[2] + m[ 7]*v[3],
  1036. m[ 8]*v[0] + m[ 9]*v[1] + m[10]*v[2] + m[11]*v[3],
  1037. m[12]*v[0] + m[13]*v[1] + m[14]*v[2] + m[15]*v[3]
  1038. ];
  1039. },
  1040. dot : function(x,y) { return x[0]*y[0]+x[1]*y[1]+x[2]*y[2]+x[3]*y[3]; },
  1041. sml : function(a,y) { return [a*y[0],a*y[1],a*y[2],a*y[3]]; }
  1042. }
  1043. function concatRGBA(bufs) {
  1044. var tlen = 0;
  1045. for(var i=0; i<bufs.length; i++) tlen += bufs[i].byteLength;
  1046. var nimg = new Uint8Array(tlen), noff=0;
  1047. for(var i=0; i<bufs.length; i++) {
  1048. var img = new Uint8Array(bufs[i]), il = img.length;
  1049. for(var j=0; j<il; j+=4) {
  1050. var r=img[j], g=img[j+1], b=img[j+2], a = img[j+3];
  1051. if(a==0) r=g=b=0;
  1052. nimg[noff+j]=r; nimg[noff+j+1]=g; nimg[noff+j+2]=b; nimg[noff+j+3]=a; }
  1053. noff += il;
  1054. }
  1055. return nimg.buffer;
  1056. }
  1057. UPNG.encode = encode;
  1058. UPNG.encodeLL = encodeLL;
  1059. UPNG.encode.compress = compress;
  1060. UPNG.encode.dither = dither;
  1061. UPNG.quantize = quantize;
  1062. UPNG.quantize.findNearest=findNearest;
  1063. UPNG.quantize.getKDtree=getKDtree;
  1064. UPNG.quantize.getNearest=getNearest;
  1065. })();
  1066. window.UPNG = UPNG