class R{constructor(t,e){this.pixels=t,this.opts=e;const{sigBits:i}=e,n=(x,k,f)=>(x<<2*i)+(k<<i)+f;this.getColorIndex=n;const s=8-i,a=1<<3*i,o=new Uint32Array(a);let h,u,l,m,_,b,c,g,d,M;h=l=_=0,u=m=b=Number.MAX_VALUE;const L=t.length/4;let y=0;for(;y<L;){const x=y*4;if(y++,c=t[x+0],g=t[x+1],d=t[x+2],M=t[x+3],M===0)continue;c=c>>s,g=g>>s,d=d>>s;const k=n(c,g,d);o[k]===void 0&&(o[k]=0),o[k]+=1,c>h&&(h=c),c<u&&(u=c),g>l&&(l=g),g<m&&(m=g),d>_&&(_=d),d<b&&(b=d)}this._colorCount=o.reduce((x,k)=>k>0?x+1:x,0),this.hist=o,this.rmax=h,this.rmin=u,this.gmax=l,this.gmin=m,this.bmax=_,this.bmin=b}get colorCount(){return this._colorCount}}class Q{scaleDown(t){const e=this.getWidth(),i=this.getHeight();let n=1;if(t.maxDimension>0){const s=Math.max(e,i);s>t.maxDimension&&(n=t.maxDimension/s)}else n=1/t.quality;n<1&&this.resize(e*n,i*n,n)}}function G(r,t){var e;if(t.length>0){const i=r.data,n=i.length/4;let s,a,o,h,u;for(let l=0;l<n;l++){s=l*4,a=i[s+0],o=i[s+1],h=i[s+2],u=i[s+3];for(let m=0;m<t.length;m++)if(!((e=t[m])!=null&&e.call(t,a,o,h,u))){i[s+3]=0;break}}}return r}function Y(r){const t=new URL(r,location.href);return t.protocol===location.protocol&&t.host===location.host&&t.port===location.port}function J(r,t){const e=new URL(r),i=new URL(t);return e.protocol===i.protocol&&e.hostname===i.hostname&&e.port===i.port}class X extends Q{_getCanvas(){if(!this._canvas)throw new Error("Canvas is not initialized");return this._canvas}_getContext(){if(!this._context)throw new Error("Context is not initialized");return this._context}_getWidth(){if(!this._width)throw new Error("Width is not initialized");return this._width}_getHeight(){if(!this._height)throw new Error("Height is not initialized");return this._height}_initCanvas(){const t=this.image;if(!t)throw new Error("Image is not initialized");const e=this._canvas=document.createElement("canvas"),i=e.getContext("2d");if(!i)throw new ReferenceError("Failed to create canvas context");this._context=i,e.className="@vibrant/canvas",e.style.display="none",this._width=e.width=t.width,this._height=e.height=t.height,i.drawImage(t,0,0),document.body.appendChild(e)}load(t){let e,i;if(typeof t=="string")e=document.createElement("img"),i=t,!Y(i)&&!J(window.location.href,i)&&(e.crossOrigin="anonymous"),e.src=i;else if(t instanceof HTMLImageElement)e=t,i=t.src;else return Promise.reject(new Error("Cannot load buffer as an image in browser"));return this.image=e,new Promise((n,s)=>{const a=()=>{this._initCanvas(),n(this)};e.complete?a():(e.onload=a,e.onerror=o=>s(new Error(`Fail to load image: ${i}`)))})}clear(){this._getContext().clearRect(0,0,this._getWidth(),this._getHeight())}update(t){this._getContext().putImageData(t,0,0)}getWidth(){return this._getWidth()}getHeight(){return this._getHeight()}resize(t,e,i){if(!this.image)throw new Error("Image is not initialized");this._width=this._getCanvas().width=t,this._height=this._getCanvas().height=e,this._getContext().scale(i,i),this._getContext().drawImage(this.image,0,0)}getPixelCount(){return this._getWidth()*this._getHeight()}getImageData(){return this._getContext().getImageData(0,0,this._getWidth(),this._getHeight())}remove(){this._canvas&&this._canvas.parentNode&&this._canvas.parentNode.removeChild(this._canvas)}}function I(r,...t){return t.forEach(e=>{if(e){for(const i in e)if(e.hasOwnProperty(i)){const n=e[i];Array.isArray(n)?r[i]=n.slice(0):typeof n=="object"?(r[i]||(r[i]={}),I(r[i],n)):r[i]=n}}}),r}function $(r,t){const{colorCount:e,quantizer:i,generators:n,filters:s}=r,a={colorCount:e},o=typeof i=="string"?{name:i,options:{}}:i;return o.options=I({},a,o.options),I({},{quantizer:o,generators:n,filters:s},t)}class K{constructor(t,e={}){this._src=t,this._opts=I({},S.DefaultOpts,e)}maxColorCount(t){return this._opts.colorCount=t,this}maxDimension(t){return this._opts.maxDimension=t,this}addFilter(t){return this._opts.filters?this._opts.filters.push(t):this._opts.filters=[t],this}removeFilter(t){if(this._opts.filters){const e=this._opts.filters.indexOf(t);e>0&&this._opts.filters.splice(e)}return this}clearFilters(){return this._opts.filters=[],this}quality(t){return this._opts.quality=t,this}useImageClass(t){return this._opts.ImageClass=t,this}useGenerator(t,e){return this._opts.generators||(this._opts.generators=[]),this._opts.generators.push(e?{name:t,options:e}:t),this}useQuantizer(t,e){return this._opts.quantizer=e?{name:t,options:e}:t,this}build(){return new S(this._src,this._opts)}getPalette(){return this.build().getPalette()}}class E{constructor(t){this.pipeline=t,this._map={}}names(){return Object.keys(this._map)}has(t){return!!this._map[t]}get(t){return this._map[t]}register(t,e){return this._map[t]=e,this.pipeline}}class Z{constructor(){this.filter=new E(this),this.quantizer=new E(this),this.generator=new E(this)}_buildProcessTasks({filters:t,quantizer:e,generators:i}){return i.length===1&&i[0]==="*"&&(i=this.generator.names()),{filters:t.map(s=>n(this.filter,s)),quantizer:n(this.quantizer,e),generators:i.map(s=>n(this.generator,s))};function n(s,a){let o,h;return typeof a=="string"?o=a:(o=a.name,h=a.options),{name:o,fn:s.get(o),options:h}}}async process(t,e){const{filters:i,quantizer:n,generators:s}=this._buildProcessTasks(e),a=await this._filterColors(i,t),o=await this._generateColors(n,a),h=await this._generatePalettes(s,o);return{colors:o,palettes:h}}_filterColors(t,e){return Promise.resolve(G(e,t.map(({fn:i})=>i)))}_generateColors(t,e){return Promise.resolve(t.fn(e.data,t.options))}async _generatePalettes(t,e){const i=await Promise.all(t.map(({fn:n,options:s})=>Promise.resolve(n(e,s))));return Promise.resolve(i.reduce((n,s,a)=>(n[t[a].name]=s,n),{}))}}function tt(r,t,e){return"#"+((1<<24)+(r<<16)+(t<<8)+e).toString(16).slice(1,7)}function et(r,t,e){r/=255,t/=255,e/=255;const i=Math.max(r,t,e),n=Math.min(r,t,e);let s=0,a=0;const o=(i+n)/2;if(i!==n){const h=i-n;switch(a=o>.5?h/(2-i-n):h/(i+n),i){case r:s=(t-e)/h+(t<e?6:0);break;case t:s=(e-r)/h+2;break;case e:s=(r-t)/h+4;break}s/=6}return[s,a,o]}function p(r,t,e){let i,n,s;function a(o,h,u){return u<0&&(u+=1),u>1&&(u-=1),u<1/6?o+(h-o)*6*u:u<1/2?h:u<2/3?o+(h-o)*(2/3-u)*6:o}if(t===0)i=n=s=e;else{const o=e<.5?e*(1+t):e+t-e*t,h=2*e-o;i=a(h,o,r+1/3),n=a(h,o,r),s=a(h,o,r-1/3)}return[i*255,n*255,s*255]}class V{static applyFilters(t,e){return e.length>0?t.filter(({r:i,g:n,b:s})=>{var a;for(let o=0;o<e.length;o++)if(!((a=e[o])!=null&&a.call(e,i,n,s,255)))return!1;return!0}):t}static clone(t){return new V(t._rgb,t._population)}get r(){return this._rgb[0]}get g(){return this._rgb[1]}get b(){return this._rgb[2]}get rgb(){return this._rgb}get hsl(){if(!this._hsl){const[t,e,i]=this._rgb;this._hsl=et(t,e,i)}return this._hsl}get hex(){if(!this._hex){const[t,e,i]=this._rgb;this._hex=tt(t,e,i)}return this._hex}get population(){return this._population}toJSON(){return{rgb:this.rgb,population:this.population}}getYiq(){if(!this._yiq){const t=this._rgb;this._yiq=(t[0]*299+t[1]*587+t[2]*114)/1e3}return this._yiq}get titleTextColor(){return this._titleTextColor||(this._titleTextColor=this.getYiq()<200?"#fff":"#000"),this._titleTextColor}get bodyTextColor(){return this._bodyTextColor||(this._bodyTextColor=this.getYiq()<150?"#fff":"#000"),this._bodyTextColor}constructor(t,e){this._rgb=t,this._population=e}}const B=class T{constructor(t,e){this._src=t,this.opts=I({},T.DefaultOpts,e)}static use(t){this._pipeline=t}static from(t){return new K(t)}get result(){return this._result}_process(t,e){t.scaleDown(this.opts);const i=$(this.opts,e);return T._pipeline.process(t.getImageData(),i)}async getPalette(){const t=new this.opts.ImageClass;try{const e=await t.load(this._src),i=await this._process(e,{generators:["default"]});this._result=i;const n=i.palettes.default;if(!n)throw new Error("Something went wrong and a palette was not found, please file a bug against our GitHub repo: https://github.com/vibrant-Colors/node-vibrant/");return t.remove(),n}catch(e){return t.remove(),Promise.reject(e)}}async getPalettes(){const t=new this.opts.ImageClass;try{const e=await t.load(this._src),i=await this._process(e,{generators:["*"]});this._result=i;const n=i.palettes;return t.remove(),n}catch(e){return t.remove(),Promise.reject(e)}}};B.DefaultOpts={colorCount:64,quality:5,filters:[]};let S=B;S.DefaultOpts.quantizer="mmcq";S.DefaultOpts.generators=["default"];S.DefaultOpts.filters=["default"];S.DefaultOpts.ImageClass=X;const N=5,O=8-N;class P{constructor(t,e,i,n,s,a,o){this.histogram=o,this._volume=-1,this._avg=null,this._count=-1,this.dimension={r1:t,r2:e,g1:i,g2:n,b1:s,b2:a}}static build(t){const e=new R(t,{sigBits:N}),{rmin:i,rmax:n,gmin:s,gmax:a,bmin:o,bmax:h}=e;return new P(i,n,s,a,o,h,e)}invalidate(){this._volume=this._count=-1,this._avg=null}volume(){if(this._volume<0){const{r1:t,r2:e,g1:i,g2:n,b1:s,b2:a}=this.dimension;this._volume=(e-t+1)*(n-i+1)*(a-s+1)}return this._volume}count(){if(this._count<0){const{hist:t,getColorIndex:e}=this.histogram,{r1:i,r2:n,g1:s,g2:a,b1:o,b2:h}=this.dimension;let u=0;for(let l=i;l<=n;l++)for(let m=s;m<=a;m++)for(let _=o;_<=h;_++){const b=e(l,m,_);t[b]&&(u+=t[b])}this._count=u}return this._count}clone(){const{histogram:t}=this,{r1:e,r2:i,g1:n,g2:s,b1:a,b2:o}=this.dimension;return new P(e,i,n,s,a,o,t)}avg(){if(!this._avg){const{hist:t,getColorIndex:e}=this.histogram,{r1:i,r2:n,g1:s,g2:a,b1:o,b2:h}=this.dimension;let u=0;const l=1<<8-N;let m,_,b;m=_=b=0;for(let c=i;c<=n;c++)for(let g=s;g<=a;g++)for(let d=o;d<=h;d++){const M=e(c,g,d),L=t[M];L&&(u+=L,m+=L*(c+.5)*l,_+=L*(g+.5)*l,b+=L*(d+.5)*l)}u?this._avg=[~~(m/u),~~(_/u),~~(b/u)]:this._avg=[~~(l*(i+n+1)/2),~~(l*(s+a+1)/2),~~(l*(o+h+1)/2)]}return this._avg}contains(t){let[e,i,n]=t;const{r1:s,r2:a,g1:o,g2:h,b1:u,b2:l}=this.dimension;return e>>=O,i>>=O,n>>=O,e>=s&&e<=a&&i>=o&&i<=h&&n>=u&&n<=l}split(){const{hist:t,getColorIndex:e}=this.histogram,{r1:i,r2:n,g1:s,g2:a,b1:o,b2:h}=this.dimension,u=this.count();if(!u)return[];if(u===1)return[this.clone()];const l=n-i+1,m=a-s+1,_=h-o+1,b=Math.max(l,m,_);let c=null,g,d;g=d=0;let M=null;if(b===l){M="r",c=new Uint32Array(n+1);for(let f=i;f<=n;f++){g=0;for(let w=s;w<=a;w++)for(let v=o;v<=h;v++){const D=e(f,w,v);t[D]&&(g+=t[D])}d+=g,c[f]=d}}else if(b===m){M="g",c=new Uint32Array(a+1);for(let f=s;f<=a;f++){g=0;for(let w=i;w<=n;w++)for(let v=o;v<=h;v++){const D=e(w,f,v);t[D]&&(g+=t[D])}d+=g,c[f]=d}}else{M="b",c=new Uint32Array(h+1);for(let f=o;f<=h;f++){g=0;for(let w=i;w<=n;w++)for(let v=s;v<=a;v++){const D=e(w,v,f);t[D]&&(g+=t[D])}d+=g,c[f]=d}}let L=-1;const y=new Uint32Array(c.length);for(let f=0;f<c.length;f++){const w=c[f];w&&(L<0&&w>d/2&&(L=f),y[f]=d-w)}const x=this;function k(f){const w=f+"1",v=f+"2",D=x.dimension[w];let C=x.dimension[v];const q=x.clone(),H=x.clone(),A=L-D,U=C-L;for(A<=U?(C=Math.min(C-1,~~(L+U/2)),C=Math.max(0,C)):(C=Math.max(D,~~(L-1-A/2)),C=Math.min(x.dimension[v],C));!c[C];)C++;let F=y[C];for(;!F&&c[C-1];)F=y[--C];return q.dimension[v]=C,H.dimension[w]=C+1,[q,H]}return k(M)}}class W{_sort(){this._sorted||(this.contents.sort(this._comparator),this._sorted=!0)}constructor(t){this._comparator=t,this.contents=[],this._sorted=!1}push(t){this.contents.push(t),this._sorted=!1}peek(t){return this._sort(),t=typeof t=="number"?t:this.contents.length-1,this.contents[t]}pop(){return this._sort(),this.contents.pop()}size(){return this.contents.length}map(t){return this._sort(),this.contents.map(t)}}const it=.75;function j(r,t){let e=r.size();for(;r.size()<t;){const i=r.pop();if(i&&i.count()>0){const[n,s]=i.split();if(!n||(r.push(n),s&&s.count()>0&&r.push(s),r.size()===e))break;e=r.size()}else break}}const rt=(r,t)=>{if(r.length===0||t.colorCount<2||t.colorCount>256)throw new Error("Wrong MMCQ parameters");const e=P.build(r);e.histogram.colorCount;const i=new W((s,a)=>s.count()-a.count());i.push(e),j(i,it*t.colorCount);const n=new W((s,a)=>s.count()*s.volume()-a.count()*a.volume());return n.contents=i.contents,j(n,t.colorCount-n.size()),nt(n)};function nt(r){const t=[];for(;r.size();){const e=r.pop(),i=e.avg();t.push(new V(i,e.count()))}return t}const st={targetDarkLuma:.26,maxDarkLuma:.45,minLightLuma:.55,targetLightLuma:.74,minNormalLuma:.3,targetNormalLuma:.5,maxNormalLuma:.7,targetMutesSaturation:.3,maxMutesSaturation:.4,targetVibrantSaturation:1,minVibrantSaturation:.35,weightSaturation:3,weightLuma:6.5,weightPopulation:.5};function ot(r){let t=0;return r.forEach(e=>{t=Math.max(t,e.population)}),t}function at(r,t){return r.Vibrant===t||r.DarkVibrant===t||r.LightVibrant===t||r.Muted===t||r.DarkMuted===t||r.LightMuted===t}function ht(r,t,e,i,n,s,a){function o(...u){let l=0,m=0;for(let _=0;_<u.length;_+=2){const b=u[_],c=u[_+1];!b||!c||(l+=b*c,m+=c)}return l/m}function h(u,l){return 1-Math.abs(u-l)}return o(h(r,t),a.weightSaturation,h(e,i),a.weightLuma,n/s,a.weightPopulation)}function z(r,t,e,i,n,s,a,o,h,u){let l=null,m=0;return t.forEach(_=>{const[,b,c]=_.hsl;if(b>=o&&b<=h&&c>=n&&c<=s&&!at(r,_)){const g=ht(b,a,c,i,_.population,e,u);(l===null||g>m)&&(l=_,m=g)}}),l}function ut(r,t,e){const i={Vibrant:null,DarkVibrant:null,LightVibrant:null,Muted:null,DarkMuted:null,LightMuted:null};return i.Vibrant=z(i,r,t,e.targetNormalLuma,e.minNormalLuma,e.maxNormalLuma,e.targetVibrantSaturation,e.minVibrantSaturation,1,e),i.LightVibrant=z(i,r,t,e.targetLightLuma,e.minLightLuma,1,e.targetVibrantSaturation,e.minVibrantSaturation,1,e),i.DarkVibrant=z(i,r,t,e.targetDarkLuma,0,e.maxDarkLuma,e.targetVibrantSaturation,e.minVibrantSaturation,1,e),i.Muted=z(i,r,t,e.targetNormalLuma,e.minNormalLuma,e.maxNormalLuma,e.targetMutesSaturation,0,e.maxMutesSaturation,e),i.LightMuted=z(i,r,t,e.targetLightLuma,e.minLightLuma,1,e.targetMutesSaturation,0,e.maxMutesSaturation,e),i.DarkMuted=z(i,r,t,e.targetDarkLuma,0,e.maxDarkLuma,e.targetMutesSaturation,0,e.maxMutesSaturation,e),i}function lt(r,t,e){if(!r.Vibrant&&!r.DarkVibrant&&!r.LightVibrant){if(!r.DarkVibrant&&r.DarkMuted){let[i,n,s]=r.DarkMuted.hsl;s=e.targetDarkLuma,r.DarkVibrant=new V(p(i,n,s),0)}if(!r.LightVibrant&&r.LightMuted){let[i,n,s]=r.LightMuted.hsl;s=e.targetDarkLuma,r.DarkVibrant=new V(p(i,n,s),0)}}if(!r.Vibrant&&r.DarkVibrant){let[i,n,s]=r.DarkVibrant.hsl;s=e.targetNormalLuma,r.Vibrant=new V(p(i,n,s),0)}else if(!r.Vibrant&&r.LightVibrant){let[i,n,s]=r.LightVibrant.hsl;s=e.targetNormalLuma,r.Vibrant=new V(p(i,n,s),0)}if(!r.DarkVibrant&&r.Vibrant){let[i,n,s]=r.Vibrant.hsl;s=e.targetDarkLuma,r.DarkVibrant=new V(p(i,n,s),0)}if(!r.LightVibrant&&r.Vibrant){let[i,n,s]=r.Vibrant.hsl;s=e.targetLightLuma,r.LightVibrant=new V(p(i,n,s),0)}if(!r.Muted&&r.Vibrant){let[i,n,s]=r.Vibrant.hsl;s=e.targetMutesSaturation,r.Muted=new V(p(i,n,s),0)}if(!r.DarkMuted&&r.DarkVibrant){let[i,n,s]=r.DarkVibrant.hsl;s=e.targetMutesSaturation,r.DarkMuted=new V(p(i,n,s),0)}if(!r.LightMuted&&r.LightVibrant){let[i,n,s]=r.LightVibrant.hsl;s=e.targetMutesSaturation,r.LightMuted=new V(p(i,n,s),0)}}const ct=(r,t)=>{t=Object.assign({},st,t);const e=ot(r),i=ut(r,e,t);return lt(i,e,t),i},gt=new Z().filter.register("default",(r,t,e,i)=>i>=125&&!(r>250&&t>250&&e>250)).quantizer.register("mmcq",rt).generator.register("default",ct);S.use(gt);export{S as V}; | |