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