edgeit.js
Version:
基于Canvas的智能图片描边处理库
2 lines (1 loc) • 2.4 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).EdgeIt=t()}(this,(function(){"use strict";const e={strokeColor:"#000000",strokeWidth:2,cache:!0,willReadFrequently:!0,imageSmoothing:!0};class t{static#e=new Map;constructor(t={}){this.config={...e,...t}}async process(e){try{const t=await this.#t(e),{naturalWidth:n,naturalHeight:i}=t,a=this.#n(n,i),{canvas:o,context:s}=this.#i(a.width,a.height);this.#a(s,t,a);const r=s.getImageData(0,0,a.width,a.height),h=this.#o(r),c=this.#s(t,h,a);return this.#r(c)}catch(e){throw e}}#n(e,t){const{width:n,height:i}=this.config,a=e/t;return{width:n||(i?i*a:e),height:i||(n?n/a:t)}}async#t(e){return e instanceof Image?e:t.#e.has(e)?t.#e.get(e):new Promise(((n,i)=>{const a=new Image;a.crossOrigin="anonymous",a.src=e,a.onload=()=>{this.config.cache&&t.#e.set(e,a),n(a)},a.onerror=i}))}#i(e,t){const n="undefined"!=typeof OffscreenCanvas?new OffscreenCanvas(e,t):document.createElement("canvas");n.width=e,n.height=t;const i=n.getContext("2d",{willReadFrequently:this.config.willReadFrequently});return i.imageSmoothingEnabled=this.config.imageSmoothing,{canvas:n,context:i}}#a(e,t,n){e.clearRect(0,0,n.width,n.height),e.drawImage(t,0,0,t.naturalWidth,t.naturalHeight,0,0,n.width,n.height)}#o(e){const t=e.data,n=[],{width:i,height:a}=e;for(let e=0;e<a;e++)for(let o=0;o<i;o++){0!==t[4*(e*i+o)+3]&&(this.#h(o,e,i,a,t)&&n.push(o,e))}return n}#h(e,t,n,i,a){return[[-1,-1],[0,-1],[1,-1],[-1,0],[1,0],[-1,1],[0,1],[1,1]].some((([o,s])=>{const r=e+o,h=t+s;if(r<0||r>=n||h<0||h>=i)return!0;return 0===a[4*(h*n+r)+3]}))}#s(e,t,n){const{canvas:i,context:a}=this.#i(n.width+2*this.config.strokeWidth,n.height+2*this.config.strokeWidth);return a.save(),a.translate(this.config.strokeWidth,this.config.strokeWidth),a.beginPath(),a.strokeStyle=this.config.strokeColor,a.lineWidth=this.config.strokeWidth,a.lineJoin="round",a.lineCap="round",t.forEach(((e,n)=>{n%2==0&&(a.moveTo(e,t[n+1]),a.lineTo(e+1,t[n+1]))})),a.stroke(),a.restore(),a.drawImage(e,this.config.strokeWidth,this.config.strokeWidth,n.width,n.height),i}#r(e){return new Promise((async t=>{const n=new Image;n.onload=()=>t(n),n.src=await this.#c(e)}))}#c(e){return e instanceof OffscreenCanvas?e.convertToBlob().then(URL.createObjectURL):e.toDataURL()}}return t}));