0


微信小程序 | 人脸识别的最终解决方案

📌个人主页:个人主页
​🧀 推荐专栏:小程序开发成神之路 --(**这是一个为想要

入门和进阶小程序开发专门开启的精品专栏

!从

个人到商业的全套开发教程

,实打实的干货分享,确定不来看看?** 😻😻)
📝作者简介:一个读研中创业、打工中学习的能搞全栈、也搞算法、目前在搞大数据的奋斗者。
⭐️

您的小小关注是我持续输出的动力!

⭐️


在这里插入图片描述


干货内容推荐

🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :

  • 《吐血整理的几十款小程序登陆界面【附完整代码】》
  • 《你真的会做小程序按钮吗?看了字节35K前端的样式设计,悟了》
  • 《来接私活吧?玩转小程序开发之丝滑拆红包【附完整代码】》
  • 《来接私活吧?小程序接私活必备功能-婚恋交友【附完整代码】》

一、人脸识别功能现状

1.1 微信原生接口篇

在这里插入图片描述
微信原生的人脸识别接口可以完美的结合小程序所采集到的图像,可以达到实时帧级别的识别,是高效开发人脸识别功能的首选!

但是,由于人脸数据是个人的敏感数据,微信在开放该接口出来时,就是为了方便各行各业的业务开展。所以,我们要用它,就必须具备相应的资质。后续才能通过审核并发布上线。

资质说明链接:微信开放能力文档
在这里插入图片描述


1.2 百度接口篇

百度人脸识别SDK的服务模式是用户在平台开通好相应的权限以及获取到appId等一系列操作之后,再到我们开发端是采用对百度人脸验证平台的相应接口进行发送验证请求才能实现服务的调用。

也就是说:百度已经人脸验证服务帮你全部搭建好了,你只需要发起请求进行调即可。

百度人脸识别服务地址
在这里插入图片描述

可以按量收费,目前根据你的业务量的QPS进行计费统计。

如果您的业务并发支持要求较高,免费测试 QPS 不能满足,您可以随时购买扩充 QPS ,QPS 可包月购买,也可按天购买,灵活多样,适应多场景需求。


1.3 虹软接口篇

在这里插入图片描述

平台链接地址:虹软接口平台

虹软 和 百度 这两者之间的区别在于:

  • 百度直接替你部署好了识别用的服务,你只需要按照文档指引向其特定的 接口发送数据即可获得你的结果,在某些主前端开发轻后端服务的应用来说还是很有优势的。
  • 虹软所走的模式是不管你是离线还是在线都能让你运行,他把搭建服务端的工作留给你自己去做。在这样的模式下,你可以实时把控用户的人脸数据,对其进行自定义操作,从而构造更为灵活的人脸设别方式,对业务场景的开发也可以有更多操作的空间!

二、人脸识别功能流程

在这里插入图片描述


三、微信接口解析

3.1 微信摄像头组件的使用

  • 小程序中要使用到摄像头的功能在于使用<camera>标签:
<camerav-if='isAuthCamera'device-position="front"class="camera"flash="off"resolution='high'/>

**对于

<camera>

标签核心的参数如下:**
属性类型必填说明可选值默认值modestring否应用模式,只在初始化时有效,不能动态变更

normal: 相机模式

】【

scanCode:扫码模式

】normal属性类型必填说明可选值默认值resolutionstring否分辨率,不支持动态修改

low 低

】【

medium 中

】【

high 高

】medium属性类型必填说明可选值默认值device-positionstring否摄像头朝向

front 前置

】【

back 后置

】back属性类型必填说明可选值默认值flashstring否闪光灯,值为 auto , on, off

auto 自动

】【

on 打开

】【

off 关闭

】【

torch 常亮

】auto

3.2 微信小程序实时视频帧获取

对如何调用和开启微信小程序中的摄像头摄像和拍照功能进行学习:微信小程序–摄像头接口详解

  • 首先需要调用CameraContext wx.createCameraContext()方法创建camera操作对象。
  • 然后在camera对象之后调用onCameraFrame(function callback),该方法用于实时获取摄像头所捕捉的相片帧,从而用于与后端人脸识别引擎进行交互。
const context = wx.createCameraContext()const listener = context.onCameraFrame((frame)=>{
      console.log(frame.data instanceofArrayBuffer, frame.width, frame.height)})
listener.start()

四、工具包的准备

4.1 将帧数据转为

Base64
  • 针对onCameraFrame()方法,获取到的是相机所捕捉的图片帧数据,这个时候我们需要将其转为Base64格式的图片数据,这是为了让其传输到后端能够被人脸识别引擎所使用!
  • 在微信所开放的用于将帧数据转化为base 64接口中wx.arrayBufferToBase64(已弃用),项目中需要用摄像头获取人脸并将获取的ArrayBuffer数据转化为base64,就需要经过一下流程:在这里插入图片描述代码如下:
let pngData = ToPNG.encode([frame.data], frame.width, frame.height),  
            base64 = Base64Util.arrayBufferToBase64(pngData)
  • 所以先准备ArrayBuffer数据转化为PNG数据的工具包ToPNG.js
import pako from'pako'varUPNG={};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 len = w * h *4,
        img =newUint8Array(len),
        empty =newUint8Array(len),
        prev =newUint8Array(len);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)for(var j =0; j < len; j++) prev[j]= img[j];if(frm.blend ==0)UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy,0);elseif(frm.blend ==1)UPNG._copyTile(fdata, fw, fh, img, w, h, fx, fy,1);

        frms.push(img.buffer.slice(0));if(frm.dispose ==0){}elseif(frm.dispose ==1)UPNG._copyTile(empty, fw, fh, img, w, h, fx, fy,0);elseif(frm.dispose ==2)for(var j =0; j < len; j++) img[j]= prev[j];}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 linevar bf =newUint8Array(area *4),
        bf32 =newUint32Array(bf.buffer);var ctype = out.ctype,
        depth = out.depth;var rs =UPNG._bin.readUshort;//console.log(ctype, depth);var time = Date.now();if(ctype ==6){// RGB + alphavar qarea = area <<2;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];}if(depth ==16)for(var i =0; i < qarea; i++){
                bf[i]= data[i <<1];}}elseif(ctype ==2){// RGBvar ts = out.tabs["tRNS"];if(ts ==null){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];}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];}}else{var 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;
                    bf32[i]=(255<<24)|(data[ti +2]<<16)|(data[ti +1]<<8)| data[ti];if(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;
                    bf32[i]=(255<<24)|(data[ti +4]<<16)|(data[ti +2]<<8)| data[ti];if(rs(data, ti)== tr &&rs(data, ti +2)== tg &&rs(data, ti +4)== tb) bf[qi +3]=0;}}}elseif(ctype ==3){// palettevar 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;}}elseif(ctype ==4){// gray + alphaif(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];}}elseif(ctype ==0){// grayvar tr = out.tabs["tRNS"]? out.tabs["tRNS"]:-1;for(var y =0; y < h; y++){var off = y * bpl,
                to = y * w;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;}elseif(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;}elseif(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;}elseif(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;}elseif(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;}}}//console.log(Date.now()-time);return bf;}UPNG.decode=function(buff){var data =newUint8Array(buff),
        offset =8,
        bin =UPNG._bin,
        rUs = bin.readUshort,
        rUi = bin.readUint;var out ={tabs:{},frames:[]};var dd =newUint8Array(data.length),
        doff =0;// put all IDAT data into itvar fd, foff =0;// framesvar 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;//console.log(type,len);if(type =="IHDR"){UPNG.decode._IHDR(data, offset, out);}elseif(type =="CgBI"){
            out.tabs[type]= data.slice(offset, offset +4);}elseif(type =="IDAT"){for(var i =0; i < len; i++) dd[doff + i]= data[offset + i];
            doff += len;}elseif(type =="acTL"){
            out.tabs[type]={num_frames:rUi(data, offset),num_plays:rUi(data, offset +4)};
            fd =newUint8Array(data.length);}elseif(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);}elseif(type =="fdAT"){for(var i =0; i < len -4; i++) fd[foff + i]= data[offset + i +4];
            foff += len -4;}elseif(type =="pHYs"){
            out.tabs[type]=[bin.readUint(data, offset), bin.readUint(data, offset +4), data[offset +8]];}elseif(type =="cHRM"){
            out.tabs[type]=[];for(var i =0; i <8; i++) out.tabs[type].push(bin.readUint(data, offset + i *4));}elseif(type =="tEXt"|| type =="zTXt"){if(out.tabs[type]==null) out.tabs[type]={};var nz = bin.nextZero(data, offset);var keyw = bin.readASCII(data, offset, nz - offset);var text, tl = offset + len - nz -1;if(type =="tEXt") text = bin.readASCII(data, nz +1, tl);else{var bfr =UPNG.decode._inflate(data.slice(nz +2, nz +2+ tl));
                text = bin.readUTF8(bfr,0, bfr.length);}
            out.tabs[type][keyw]= text;}elseif(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, tl = len -(off - offset);if(cflag ==0) text = bin.readUTF8(data, off, tl);else{var bfr =UPNG.decode._inflate(data.slice(off, off + tl));
                text = bin.readUTF8(bfr,0, bfr.length);}
            out.tabs[type][keyw]= text;}elseif(type =="PLTE"){
            out.tabs[type]= bin.readBytes(data, offset, len);}elseif(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));}elseif(type =="tRNS"){if(out.ctype ==3) out.tabs[type]= bin.readBytes(data, offset, len);elseif(out.ctype ==0) out.tabs[type]=rUs(data, offset);elseif(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);}elseif(type =="gAMA") out.tabs[type]= bin.readUint(data, offset)/100000;elseif(type =="sRGB") out.tabs[type]= data[offset];elseif(type =="bKGD"){if(out.ctype ==0|| out.ctype ==4) out.tabs[type]=[rUs(data, offset)];elseif(out.ctype ==2|| out.ctype ==6) out.tabs[type]=[rUs(data, offset),rUs(data, offset +2),rUs(data, offset +4)];elseif(out.ctype ==3) out.tabs[type]= data[offset];}elseif(type =="IEND"){break;}//else {  console.log("unknown chunk type", type, len);  out.tabs[type]=data.slice(offset,offset+len);  }
        offset += len;var crc = bin.readUint(data, offset);
        offset +=4;}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);}
    out.data =UPNG.decode._decompress(out, dd, out.width, out.height);delete out.compress;delete out.interlace;delete out.filter;return out;}UPNG.decode._decompress=function(out, dd, w, h){var time = Date.now();var bpp =UPNG.decode._getBPP(out),
        bpl = Math.ceil(w * bpp /8),
        buff =newUint8Array((bpl +1+ out.interlace)* h);if(out.tabs["CgBI"]) dd =UPNG.inflateRaw(dd, buff);else dd =UPNG.decode._inflate(dd, buff);//console.log(dd.length, buff.length);//console.log(Date.now()-time);var time = Date.now();if(out.interlace ==0) dd =UPNG.decode._filterZero(dd, out,0, w, h);elseif(out.interlace ==1) dd =UPNG.decode._readInterlace(dd, out);//console.log(Date.now()-time);return dd;}UPNG.decode._inflate=function(data, buff){var out =UPNG["inflateRaw"](newUint8Array(data.buffer,2, data.length -6), buff);return out;}UPNG.inflateRaw=function(){varH={};H.H={};H.H.N=function(N,W){varR= Uint8Array,
            i =0,
            m =0,J=0,
            h =0,Q=0,X=0,
            u =0,
            w =0,
            d =0,
            v,C;if(N[0]==3&&N[1]==0)returnW?W:newR(0);varV=H.H,
            n =V.b,A=V.e,
            l =V.R,M=V.n,I=V.A,
            e =V.Z,
            b =V.m,Z=W==null;if(Z)W=newR(N.length >>>2<<5);while(i ==0){
            i =n(N, d,1);
            m =n(N, d +1,2);
            d +=3;if(m ==0){if((d &7)!=0) d +=8-(d &7);varD=(d >>>3)+4,
                    q =N[D-4]|N[D-3]<<8;if(Z)W=H.H.W(W, w + q);W.set(newR(N.buffer,N.byteOffset +D, q), w);
                d =D+ q <<3;
                w += q;continue}if(Z)W=H.H.W(W, w +(1<<17));if(m ==1){
                v = b.J;C= b.h;X=(1<<9)-1;
                u =(1<<5)-1}if(m ==2){J=A(N, d,5)+257;
                h =A(N, d +5,5)+1;Q=A(N, d +10,4)+4;
                d +=14;varE= d,
                    j =1;for(var c =0; c <38; c +=2){
                    b.Q[c]=0;
                    b.Q[c +1]=0}for(var c =0; c <Q; c++){varK=A(N, d + c *3,3);
                    b.Q[(b.X[c]<<1)+1]=K;if(K> j) j =K}
                d +=3*Q;M(b.Q, j);I(b.Q, j, b.u);
                v = b.w;C= b.d;
                d =l(b.u,(1<< j)-1,J+ h,N, d, b.v);var r =V.V(b.v,0,J, b.C);X=(1<< r)-1;varS=V.V(b.v,J, h, b.D);
                u =(1<<S)-1;M(b.C, r);I(b.C, r, v);M(b.D,S);I(b.D,S,C)}while(!0){varT= v[e(N, d)&X];
                d +=T&15;var p =T>>>4;if(p >>>8==0){W[w++]= p
                }elseif(p ==256){break}else{var z = w + p -254;if(p >264){var _ = b.q[p -257];
                        z = w +(_ >>>3)+A(N, d, _ &7);
                        d += _ &7}var $ =C[e(N, d)& u];
                    d += $ &15;var s = $ >>>4,Y= b.c[s],
                        a =(Y>>>4)+n(N, d,Y&15);
                    d +=Y&15;while(w < z){W[w]=W[w++- a];W[w]=W[w++- a];W[w]=W[w++- a];W[w]=W[w++- a]}
                    w = z
                }}}returnW.length == w ?W:W.slice(0, w)};H.H.W=function(N,W){varR=N.length;if(W<=R)returnN;varV=newUint8Array(R<<1);V.set(N,0);returnV};H.H.R=function(N,W,R,V, n,A){var l =H.H.e,M=H.H.Z,I=0;while(I<R){var e =N[M(V, n)&W];
            n += e &15;var b = e >>>4;if(b <=15){A[I]= b;I++}else{varZ=0,
                    m =0;if(b ==16){
                    m =3+l(V, n,2);
                    n +=2;Z=A[I-1]}elseif(b ==17){
                    m =3+l(V, n,3);
                    n +=3}elseif(b ==18){
                    m =11+l(V, n,7);
                    n +=7}varJ=I+ m;while(I<J){A[I]=Z;I++}}}return n
    };H.H.V=function(N,W,R,V){var n =0,A=0,
            l =V.length >>>1;while(A<R){varM=N[A+W];V[A<<1]=0;V[(A<<1)+1]=M;if(M> n) n =M;A++}while(A< l){V[A<<1]=0;V[(A<<1)+1]=0;A++}return n
    };H.H.n=function(N,W){varR=H.H.m,V=N.length,
            n,A, l,M,I, e =R.j;for(varM=0;M<=W;M++) e[M]=0;for(M=1;M<V;M+=2) e[N[M]]++;var b =R.K;
        n =0;
        e[0]=0;for(A=1;A<=W;A++){
            n = n + e[A-1]<<1;
            b[A]= n
        }for(l =0; l <V; l +=2){I=N[l +1];if(I!=0){N[l]= b[I];
                b[I]++}}};H.H.A=function(N,W,R){varV=N.length,
            n =H.H.m,A= n.r;for(var l =0; l <V; l +=2)if(N[l +1]!=0){varM= l >>1,I=N[l +1],
                    e =M<<4|I,
                    b =W-I,Z=N[l]<< b,
                    m =Z+(1<< b);while(Z!= m){varJ=A[Z]>>>15-W;R[J]= e;Z++}}};H.H.l=function(N,W){varR=H.H.m.r,V=15-W;for(var n =0; n <N.length; n +=2){varA=N[n]<<W-N[n +1];N[n]=R[A]>>>V}};H.H.M=function(N,W,R){R=R<<(W&7);varV=W>>>3;N[V]|=R;N[V+1]|=R>>>8};H.H.I=function(N,W,R){R=R<<(W&7);varV=W>>>3;N[V]|=R;N[V+1]|=R>>>8;N[V+2]|=R>>>16};H.H.e=function(N,W,R){return(N[W>>>3]|N[(W>>>3)+1]<<8)>>>(W&7)&(1<<R)-1};H.H.b=function(N,W,R){return(N[W>>>3]|N[(W>>>3)+1]<<8|N[(W>>>3)+2]<<16)>>>(W&7)&(1<<R)-1};H.H.Z=function(N,W){return(N[W>>>3]|N[(W>>>3)+1]<<8|N[(W>>>3)+2]<<16)>>>(W&7)};H.H.i=function(N,W){return(N[W>>>3]|N[(W>>>3)+1]<<8|N[(W>>>3)+2]<<16|N[(W>>>3)+3]<<24)>>>(W&7)};H.H.m=function(){varN= Uint16Array,W= Uint32Array;return{K:newN(16),j:newN(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[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],T:[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],q:newN(32),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],z:[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],c:newW(32),J:newN(512),_:[],h:newN(32),$:[],w:newN(32768),C:[],v:[],d:newN(32768),D:[],u:newN(512),Q:[],r:newN(1<<15),s:newW(286),Y:newW(30),a:newW(19),t:newW(15e3),k:newN(1<<16),g:newN(1<<15)}}();(function(){varN=H.H.m,W=1<<15;for(varR=0;R<W;R++){varV=R;V=(V&2863311530)>>>1|(V&1431655765)<<1;V=(V&3435973836)>>>2|(V&858993459)<<2;V=(V&4042322160)>>>4|(V&252645135)<<4;V=(V&4278255360)>>>8|(V&16711935)<<8;N.r[R]=(V>>>16|V<<16)>>>17}functionn(A, l,M){while(l--!=0)A.push(0,M)}for(varR=0;R<32;R++){N.q[R]=N.S[R]<<3|N.T[R];N.c[R]=N.p[R]<<4|N.z[R]}n(N._,144,8);n(N._,255-143,9);n(N._,279-255,7);n(N._,287-279,8);H.H.n(N._,9);H.H.A(N._,9,N.J);H.H.l(N._,9);n(N.$,32,5);H.H.n(N.$,5);H.H.A(N.$,5,N.h);H.H.l(N.$,5);n(N.Q,19,0);n(N.C,286,0);n(N.D,30,0);n(N.v,320,0)}());returnH.H.N}()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 =newUint8Array(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 &7)<<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);var i, di, type = data[off],
        x =0;if(type >1) data[off]=[0,0,1][type -2];if(type ==3)for(x = bpp; x < bpl; x++) data[x +1]=(data[x +1]+(data[x +1- bpp]>>>1))&255;for(var y =0; y < h; y++){
        i = off + y * bpl;
        di = i + y +1;
        type = data[di -1];
        x =0;if(type ==0)for(; x < bpl; x++) data[i + x]= data[di + x];elseif(type ==1){for(; x < bpp; x++) data[i + x]= data[di + x];for(; x < bpl; x++) data[i + x]=(data[di + x]+ data[i + x - bpp]);}elseif(type ==2){for(; x < bpl; x++) data[i + x]=(data[di + x]+ data[i + x - bpl]);}elseif(type ==3){for(; x < bpp; x++) data[i + x]=(data[di + x]+(data[i + x - bpl]>>>1));for(; x < bpl; x++) data[i + x]=(data[di + x]+((data[i + x - bpl]+ data[i + x - bpp])>>>1));}else{for(; x < bpp; x++) data[i + x]=(data[di + x]+paeth(0, data[i + x - bpl],0));for(; x < bpl; x++) data[i + x]=(data[di + x]+paeth(data[i + x - bpp], data[i + x - bpl], data[i + x - bpp - bpl]));}}return data;}UPNG.decode._paeth=function(a, b, c){var p = a + b - c,
        pa =(p - a),
        pb =(p - b),
        pc =(p - c);if(pa * pa <= pb * pb && pa * pa <= pc * pc)return a;elseif(pb * pb <= pc * 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){returnUPNG._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];}elseif(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;}elseif(mode ==2){// copy only differences, otherwise zerovar 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;}}elseif(mode ==3){// check if can be blendedvar 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)returnfalse;}}returntrue;}UPNG.encode=function(bufs, w, h, ps, dels, tabs, forbidPlte){if(ps ==null) ps =0;if(forbidPlte ==null) forbidPlte =false;var nimg =UPNG.encode.compress(bufs, w, h, ps,[false,false,false,0, forbidPlte,false]);UPNG.encode.compressPNG(nimg,-1);returnUPNG.encode._main(nimg, w, h, dels, tabs);}UPNG.encodeLL=function(bufs, w, h, cc, ac, depth, dels, tabs){var nimg ={ctype:0+(cc ==1?0:2)+(ac ==0?0:4),depth: depth,frames:[]};var time = Date.now();var bipp =(cc + ac)* depth,
        bipl = bipp * w;for(var i =0; i < bufs.length; i++)
        nimg.frames.push({rect:{x:0,y:0,width: w,height: h
            },img:newUint8Array(bufs[i]),blend:0,dispose:1,bpp: Math.ceil(bipp /8),bpl: Math.ceil(bipl /8)});UPNG.encode.compressPNG(nimg,0,true);var out =UPNG.encode._main(nimg, w, h, dels, tabs);return out;}UPNG.encode._main=function(nimg, w, h, dels, tabs){if(tabs ==null) tabs ={};var crc =UPNG.crc.crc,
        wUi =UPNG._bin.writeUint,
        wUs =UPNG._bin.writeUshort,
        wAs =UPNG._bin.writeASCII;var offset =8,
        anim = nimg.frames.length >1,
        pltAlpha =false;var leng =8+(16+5+4)/*+ (9+4)*/+(anim ?20:0);if(tabs["sRGB"]!=null) leng +=8+1+4;if(tabs["pHYs"]!=null) leng +=8+9+4;if(nimg.ctype ==3){var dl = nimg.plte.length;for(var i =0; i < dl; i++)if((nimg.plte[i]>>>24)!=255) pltAlpha =true;
        leng +=(8+ dl *3+4)+(pltAlpha ?(8+ dl *1+4):0);}for(var j =0; j < nimg.frames.length; j++){var fr = nimg.frames[j];if(anim) leng +=38;
        leng += fr.cimg.length +12;if(j !=0) leng +=4;}
    leng +=12;var data =newUint8Array(leng);var wr =[0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a];for(var i =0; i <8; i++) data[i]= wr[i];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++;// interlacewUi(data, offset,crc(data, offset -17,17));
    offset +=4;// crc// 13 bytes to say, that it is sRGBif(tabs["sRGB"]!=null){wUi(data, offset,1);
        offset +=4;wAs(data, offset,"sRGB");
        offset +=4;
        data[offset]= tabs["sRGB"];
        offset++;wUi(data, offset,crc(data, offset -5,5));
        offset +=4;// crc}if(tabs["pHYs"]!=null){wUi(data, offset,9);
        offset +=4;wAs(data, offset,"pHYs");
        offset +=4;wUi(data, offset, tabs["pHYs"][0]);
        offset +=4;wUi(data, offset, tabs["pHYs"][1]);
        offset +=4;
        data[offset]= tabs["pHYs"][2];
        offset++;wUi(data, offset,crc(data, offset -13,13));
        offset +=4;// crc}if(anim){wUi(data, offset,8);
        offset +=4;wAs(data, offset,"acTL");
        offset +=4;wUi(data, offset, nimg.frames.length);
        offset +=4;wUi(data, offset, tabs["loop"]!=null? tabs["loop"]: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;// crcif(pltAlpha){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++;// blendwUi(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;}
        data.set(imgd, offset);
        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;// crcreturn data.buffer;}UPNG.encode.compressPNG=function(out, filter, levelZero){for(var i =0; i < out.frames.length; i++){var frm = out.frames[i],
            nw = frm.rect.width,
            nh = frm.rect.height;var fdata =newUint8Array(nh * frm.bpl + nh);
        frm.cimg =UPNG.encode._filterZero(frm.img, nh, frm.bpp, frm.bpl, fdata, filter, levelZero);}}UPNG.encode.compress=function(bufs, w, h, ps, prms)// prms:  onlyBlend, minBits, forbidPlte{//var time = Date.now();var onlyBlend = prms[0],
        evenCrd = prms[1],
        forbidPrev = prms[2],
        minBits = prms[3],
        forbidPlte = prms[4],
        dither = prms[5];var ctype =6,
        depth =8,
        alphaAnd =255for(var j =0; j < bufs.length; j++){// when not quantized, other frames can contain colors, that are not in an initial framevar img =newUint8Array(bufs[j]),
            ilen = img.length;for(var i =0; i < ilen; i +=4) alphaAnd &= img[i +3];}var gotAlpha =(alphaAnd !=255);//console.log("alpha check", Date.now()-time);  time = Date.now();//var brute = gotAlpha && forGIF;        // brute : frames can only be copied, not "blended"var frms =UPNG.encode.framize(bufs, w, h, onlyBlend, evenCrd, forbidPrev);//console.log("framize", Date.now()-time);  time = Date.now();var cmap ={},
        plte =[],
        inds =[];if(ps !=0){var nbufs =[];for(var i =0; i < frms.length; i++) nbufs.push(frms[i].img.buffer);var abuf =UPNG.encode.concatRGBA(nbufs),
            qres =UPNG.quantize(abuf, ps);for(var i =0; i < qres.plte.length; i++) plte.push(qres.plte[i].est.rgba);var cof =0;for(var i =0; i < frms.length; i++){var frm = frms[i],
                bln = frm.img.length,
                ind =newUint8Array(qres.inds.buffer, cof >>2, bln >>2);
            inds.push(ind);var bb =newUint8Array(qres.abuf, cof, bln);//console.log(frm.img, frm.width, frm.height);//var time = Date.now();if(dither)UPNG.encode.dither(frm.img, frm.rect.width, frm.rect.height, plte, bb, ind);//console.log(Date.now()-time);
            frm.img.set(bb);
            cof += bln;}//console.log("quantize", Date.now()-time);  time = Date.now();}else{// what if ps==0, but there are <=256 colors?  we still need to detect, if the palette could be usedfor(var j =0; j < frms.length; j++){// when not quantized, other frames can contain colors, that are not in an initial framevar frm = frms[j],
                img32 =newUint32Array(frm.img.buffer),
                nw = frm.rect.width,
                ilen = img32.length;var ind =newUint8Array(ilen);
            inds.push(ind);for(var i =0; i < ilen; i++){var c = img32[i];if(i !=0&& c == img32[i -1]) ind[i]= ind[i -1];elseif(i > nw && c == img32[i - nw]) ind[i]= ind[i - nw];else{var cmc = cmap[c];if(cmc ==null){
                        cmap[c]= cmc = plte.length;
                        plte.push(c);if(plte.length >=300)break;}
                    ind[i]= cmc;}}}//console.log("make palette", Date.now()-time);  time = Date.now();}var cc = plte.length;//console.log("colors:",cc);if(cc <=256&& forbidPlte ==false){if(cc <=2) depth =1;elseif(cc <=4) depth =2;elseif(cc <=16) depth =4;else depth =8;
        depth = Math.max(depth, minBits);}for(var j =0; j < frms.length; j++){var frm = frms[j],
            nx = frm.rect.x,
            ny = frm.rect.y,
            nw = frm.rect.width,
            nh = frm.rect.height;var cimg = frm.img,
            cimg32 =newUint32Array(cimg.buffer);var bpl =4* nw,
            bpp =4;if(cc <=256&& forbidPlte ==false){
            bpl = Math.ceil(depth * nw /8);var nimg =newUint8Array(bpl * nh);var inj = inds[j];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)]=(inj[ii + x]);elseif(depth ==4)for(var x =0; x < nw; x++) nimg[i +(x >>1)]|=(inj[ii + x]<<(4-(x &1)*4));elseif(depth ==2)for(var x =0; x < nw; x++) nimg[i +(x >>2)]|=(inj[ii + x]<<(6-(x &3)*2));elseif(depth ==1)for(var x =0; x < nw; x++) nimg[i +(x >>3)]|=(inj[ii + x]<<(7-(x &7)*1));}
            cimg = nimg;
            ctype =3;
            bpp =1;}elseif(gotAlpha ==false&& frms.length ==1){// some next "reduced" frames may contain alpha for blendingvar nimg =newUint8Array(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;}
        frm.img = cimg;
        frm.bpl = bpl;
        frm.bpp = bpp;}//console.log("colors => palette indices", Date.now()-time);  time = Date.now();return{ctype: ctype,depth: depth,plte: plte,frames: frms
    };}UPNG.encode.framize=function(bufs, w, h, alwaysBlend, evenCrd, forbidPrev){/*  DISPOSE
        - 0 : no change
        - 1 : clear to transparent
        - 2 : retstore to content before rendering (previous frame disposed)
        BLEND
        - 0 : replace
        - 1 : blend
    */var frms =[];for(var j =0; j < bufs.length; j++){var cimg =newUint8Array(bufs[j]),
            cimg32 =newUint32Array(cimg.buffer);var nimg;var nx =0,
            ny =0,
            nw = w,
            nh = h,
            blend = alwaysBlend ?1:0;if(j !=0){var tlim =(forbidPrev || alwaysBlend || j ==1|| frms[j -2].dispose !=0)?1:2,
                tstp =0,
                tarea =1e9;for(var it =0; it < tlim; it++){var pimg =newUint8Array(bufs[j -1- it]),
                    p32 =newUint32Array(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;}}if(max ==-1) mix = miy = max = may =0;if(evenCrd){if((mix &1)==1) mix--;if((miy &1)==1) miy--;}var sarea =(max - mix +1)*(may - miy +1);if(sarea < tarea){
                    tarea = sarea;
                    tstp = it;
                    nx = mix;
                    ny = miy;
                    nw = max - mix +1;
                    nh = may - miy +1;}}// 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.var pimg =newUint8Array(bufs[j -1- tstp]);if(tstp ==1) frms[j -1].dispose =2;

            nimg =newUint8Array(nw * nh *4);UPNG._copyTile(pimg, w, h, nimg, nw, nh,-nx,-ny,0);

            blend =UPNG._copyTile(cimg, w, h, nimg, nw, nh,-nx,-ny,3)?1:0;if(blend ==1)UPNG.encode._prepareDiff(cimg, w, h, nimg,{x: nx,y: ny,width: nw,height: nh
            });elseUPNG._copyTile(cimg, w, h, nimg, nw, nh,-nx,-ny,0);//UPNG._copyTile(cimg,w,h, nimg,nw,nh, -nx,-ny, blend==1?2:0);}else nimg = cimg.slice(0);// img may be rewritten further ... don't rewrite input

        frms.push({rect:{x: nx,y: ny,width: nw,height: nh
            },img: nimg,blend: blend,dispose:0});}if(alwaysBlend)for(var j =0; j < frms.length; j++){var frm = frms[j];if(frm.blend ==1)continue;var r0 = frm.rect,
                r1 = frms[j -1].rect
            var miX = Math.min(r0.x, r1.x),
                miY = Math.min(r0.y, r1.y);var maX = Math.max(r0.x + r0.width, r1.x + r1.width),
                maY = Math.max(r0.y + r0.height, r1.y + r1.height);var r ={x: miX,y: miY,width: maX - miX,height: maY - miY
            };

            frms[j -1].dispose =1;if(j -1!=0)UPNG.encode._updateFrame(bufs, w, h, frms, j -1, r, evenCrd);UPNG.encode._updateFrame(bufs, w, h, frms, j, r, evenCrd);}var area =0;if(bufs.length !=1)for(var i =0; i < frms.length; i++){var frm = frms[i];
            area += frm.rect.width * frm.rect.height;//if(i==0 || frm.blend!=1) continue;//var ob = new Uint8Array(//console.log(frm.blend, frm.dispose, frm.rect);}//if(area!=0) console.log(area);return frms;}UPNG.encode._updateFrame=function(bufs, w, h, frms, i, r, evenCrd){varU8= Uint8Array,U32= Uint32Array;var pimg =newU8(bufs[i -1]),
        pimg32 =newU32(bufs[i -1]),
        nimg = i +1< bufs.length ?newU8(bufs[i +1]):null;var cimg =newU8(bufs[i]),
        cimg32 =newU32(cimg.buffer);var mix = w,
        miy = h,
        max =-1,
        may =-1;for(var y =0; y < r.height; y++)for(var x =0; x < r.width; x++){var cx = r.x + x,
                cy = r.y + y;var j = cy * w + cx,
                cc = cimg32[j];// no need to draw transparency, or to dispose it. Or, if writing the same color and the next one does not need transparency.if(cc ==0||(frms[i -1].dispose ==0&& pimg32[j]== cc &&(nimg ==null|| nimg[j *4+3]!=0))/**/){}else{if(cx < mix) mix = cx;if(cx > max) max = cx;if(cy < miy) miy = cy;if(cy > may) may = cy;}}if(max ==-1) mix = miy = max = may =0;if(evenCrd){if((mix &1)==1) mix--;if((miy &1)==1) miy--;}
    r ={x: mix,y: miy,width: max - mix +1,height: may - miy +1};var fr = frms[i];
    fr.rect = r;
    fr.blend =1;
    fr.img =newUint8Array(r.width * r.height *4);if(frms[i -1].dispose ==0){UPNG._copyTile(pimg, w, h, fr.img, r.width, r.height,-r.x,-r.y,0);UPNG.encode._prepareDiff(cimg, w, h, fr.img, r);//UPNG._copyTile(cimg,w,h, fr.img,r.width,r.height, -r.x,-r.y, 2);}elseUPNG._copyTile(cimg, w, h, fr.img, r.width, r.height,-r.x,-r.y,0);}UPNG.encode._prepareDiff=function(cimg, w, h, nimg, rec){UPNG._copyTile(cimg, w, h, nimg, rec.width, rec.height,-rec.x,-rec.y,2);/*
    var n32 = new Uint32Array(nimg.buffer);
    var og = new Uint8Array(rec.width*rec.height*4), o32 = new Uint32Array(og.buffer);
    UPNG._copyTile(cimg,w,h, og,rec.width,rec.height, -rec.x,-rec.y, 0);
    for(var i=4; i<nimg.length; i+=4) {
        if(nimg[i-1]!=0 && nimg[i+3]==0 && o32[i>>>2]==o32[(i>>>2)-1]) {
            n32[i>>>2]=o32[i>>>2];
            //var j = i, c=p32[(i>>>2)-1];
            //while(p32[j>>>2]==c) {  n32[j>>>2]=c;  j+=4;  }
        }
    }
    for(var i=nimg.length-8; i>0; i-=4) {
        if(nimg[i+7]!=0 && nimg[i+3]==0 && o32[i>>>2]==o32[(i>>>2)+1]) {
            n32[i>>>2]=o32[i>>>2];
            //var j = i, c=p32[(i>>>2)-1];
            //while(p32[j>>>2]==c) {  n32[j>>>2]=c;  j+=4;  }
        }
    }*/}UPNG.encode._filterZero=function(img, h, bpp, bpl, data, filter, levelZero){var fls =[],
        ftry =[0,1,2,3,4];if(filter !=-1) ftry =[filter];elseif(h * bpl >500000|| bpp ==1) ftry =[0];var opts;if(levelZero) opts ={level:0};varCMPR=(data.length >10e6&&UZIP!=null)?UZIP: pako;var time = Date.now();for(var i =0; i < ftry.length; i++){for(var y =0; y < h; y++)UPNG.encode._filterLine(data, img, y, bpl, bpp, ftry[i]);//var nimg = new Uint8Array(data.length);//var sz = UZIP.F.deflate(data, nimg);  fls.push(nimg.slice(0,sz));//var dfl = pako["deflate"](data), dl=dfl.length-4;//var crc = (dfl[dl+3]<<24)|(dfl[dl+2]<<16)|(dfl[dl+1]<<8)|(dfl[dl+0]<<0);//console.log(crc, UZIP.adler(data,2,data.length-6));
        fls.push(CMPR["deflate"](data, opts));}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){if(bpl <500)for(var x =0; x < bpl; x++) data[di + x]= img[i + x];else data.set(newUint8Array(img.buffer, i, bpl), di);}elseif(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;}elseif(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 =newUint32Array(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){returnUPNG.crc.update(0xffffffff, b, o, l)^0xffffffff;}}UPNG.quantize=function(abuf, ps){var sb =newUint8Array(abuf),
        tb = sb.slice(0),
        tb32 =newUint32Array(tb.buffer);varKD=UPNG.quantize.getKDtree(tb, ps);var root =KD[0],
        leafs =KD[1];var planeDst =UPNG.quantize.planeDst;var len = sb.length;var inds =newUint8Array(len >>2),
        nd;if(sb.length <20e6)// precise, but slow :(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);

            nd =UPNG.quantize.getNearest(root, r, g, b, a);
            inds[i >>2]= nd.ind;
            tb32[i >>2]= nd.est.rgba;}elsefor(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);

            nd = root;while(nd.left) nd =(planeDst(nd.est, r, g, b, a)<=0)? nd.left : nd.right;
            inds[i >>2]= nd.ind;
            tb32[i >>2]= nd.est.rgba;}return{abuf: tb.buffer,inds: inds,plte: leafs
    };}UPNG.quantize.getKDtree=function(nimg, ps, err){if(err ==null) err =0.0001;var nimg32 =newUint32Array(nimg.buffer);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 < err)break;var node = leafs[mi];var s0 =UPNG.quantize.splitPixels(nimg, nimg32, node.i0, node.i1, node.est.e, node.est.eMq255);var s0wrong =(node.i0 >= s0 || node.i1 <= s0);//console.log(maxL, leafs.length, mi);if(s0wrong){
            node.est.L=0;continue;}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 i =0; i < leafs.length; i++) leafs[i].ind = i;return[root, 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){varR=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];var m =[0,0,0,0];varN=(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[9]=R[6];R[12]=R[3];R[13]=R[7];R[14]=R[11];return{R:R,m: m,N:N};}UPNG.quantize.estats=function(stats){varR= stats.R,
        m = stats.m,N= stats.N;// when all samples are equal, but N is large (millions), the Rj can be non-zero ( 0.0003.... - precission error)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
    ];varA= Rj,M=UPNG.M4;var b =[Math.random(), Math.random(), Math.random(), Math.random()],
        mi =0,
        tmi =0;if(N!=0)for(var i =0; i <16; i++){
            b =M.multVec(A, b);
            tmi = Math.sqrt(M.dot(b, b));
            b =M.sml(1/ tmi, b);if(i !=0&& 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);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])<<16)|(Math.round(255* q[1])<<8)|(Math.round(255* q[0])<<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.concatRGBA=function(bufs){var tlen =0;for(var i =0; i < bufs.length; i++) tlen += bufs[i].byteLength;var nimg =newUint8Array(tlen),
        noff =0;for(var i =0; i < bufs.length; i++){var img =newUint8Array(bufs[i]),
            il = img.length;for(var j =0; j < il; j +=4){var r = img[j],
                g = img[j +1],
                b = img[j +2],
                a = img[j +3];if(a ==0) r = g = b =0;
            nimg[noff + j]= r;
            nimg[noff + j +1]= g;
            nimg[noff + j +2]= b;
            nimg[noff + j +3]= a;}
        noff += il;}return nimg.buffer;}UPNG.encode.dither=function(sb, w, h, plte, tb, oind){functionaddErr(er, tg, ti, f){
        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;}functionN(x){return Math.max(0, Math.min(255, x));}functionD(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);}var pc = plte.length,
        nplt =[],
        rads =[];for(var i =0; i < pc; i++){var c = plte[i];
        nplt.push([((c >>>0)&255),((c >>>8)&255),((c >>>16)&255),((c >>>24)&255)]);}for(var i =0; i < pc; i++){var ne =0xffffffff,
            ni =0;for(var j =0; j < pc; j++){var ce =D(nplt[i], nplt[j]);if(j != i && ce < ne){
                ne = ce;
                ni = j;}}var hd = Math.sqrt(ne)/2;
        rads[i]=~~(hd * hd);}var tb32 =newUint32Array(tb.buffer);var err =newInt16Array(w * h *4);for(var y =0; y < h; y++){for(var x =0; x < w; x++){var i =(y * w + x)*4;var 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])];var ni =0,
                nd =0xffffff;for(var j =0; j < pc; j++){var cd =D(cc, nplt[j]);if(cd < nd){
                    nd = cd;
                    ni = j;}}//ni = oind[i>>2];var nc = nplt[ni];var er =[cc[0]- nc[0], cc[1]- nc[1], cc[2]- nc[2], cc[3]- nc[3]];//addErr(er, err, i+4, 16);//*if(x != w -1)addErr(er, err, i +4,7);if(y != h -1){if(x !=0)addErr(er, err, i +4* w -4,3);addErr(er, err, i +4* w,5);if(x != w -1)addErr(er, err, i +4* w +4,1);//*/}

            oind[i >>2]= ni;
            tb32[i >>2]= plte[ni];}}}

module.exports =UPNG
  • 再将png数据转化为Base64数据,所使用的工具包Base64Util:
exportdefault{arrayBufferToBase64(buffer){var binary ='';var bytes =newUint8Array(buffer);var len = bytes.byteLength;for(var i =0; i < len; i++){
    binary += String.fromCharCode(bytes[i]);}varbtoa=function(string){var b64 ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    string =String(string);var bitmap, a, b, c,
        result ="", i =0,
        rest = string.length %3;// To determine the final paddingfor(; i < string.length;){if((a = string.charCodeAt(i++))>255||(b = string.charCodeAt(i++))>255||(c = string.charCodeAt(i++))>255)thrownewTypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");

        bitmap =(a <<16)|(b <<8)| c;
        result += b64.charAt(bitmap >>18&63)+ b64.charAt(bitmap >>12&63)+ b64.charAt(bitmap >>6&63)+ b64.charAt(bitmap &63);}// If there's need of padding, replace the last 'A's with equal signsreturn rest ? result.slice(0, rest -3)+"===".substring(rest): result;}return"data:image/png;base64,"+btoa(binary);}}

4.2 控制帧数据采集频率

  • 特别注意:对于微信的这个数据帧采集接口onCameraFrame,它是处于一个以60ms采集一次用户的数据的频率运行的,很多时候我们用不到这么高的频率!我们可以通过setInteerval定时器来控制摄像头采集用户数据的频率。
let task =setInterval(function(){var timeStart = Date.now();//在此处处理store[0](图像的数据);// store.shift();var frame = that.frameQueue.shift()
console.log("开始运行===",frame,that.flag);
that.flag =true;if(frame !=undefined){let pngData =UPNG.encode([frame.data], frame.width, frame.height),  
        base64 = Base64Util.arrayBufferToBase64(pngData)
                                                        
    uni.request({url:'http://127.0.0.1:8000/miniapp/faceEngine/faceLogin',method:'post',data:{openId:uni.getStorageSync("openId"),base64Img:base64},dataType:'json',header:{'content-type':'application/json'//自定义请求头信息},success:(res)=>{
                console.log("====执行成功===",res)if(res.statusCode !=undefined){clearInterval(task)
                    that.isAuthCamera =false
                    uni.navigateTo({url:'./login'})}},fail:(err)=>{
                console.log("====执行失败===",err)clearInterval(task)
                that.isAuthCamera =false
                uni.navigateTo({url:'./login'})}})}

五、实时人脸采集功能实现

在这里插入图片描述



本文转载自: https://blog.csdn.net/weixin_37797592/article/details/127626580
版权归原作者 陶人超有料 所有, 如有侵权,请联系我们删除。

“微信小程序 | 人脸识别的最终解决方案”的评论:

还没有评论