fast-average-color
Version:
A simple library that calculates the average color of images, videos and canvas in browser environment.
2 lines • 6.63 kB
JavaScript
/*! Fast Average Color | © 2026 Denis Seleznev | MIT License | https://github.com/fast-average-color/fast-average-color */
!function(){"use strict";function t(t){var e=t.toString(16);return 1===e.length?"0"+e:e}function e(e){return"#"+e.map(t).join("")}function r(t){return t?(e=t,Array.isArray(e[0])?t:[t]):[];var e}function n(t,e,r){for(var n=0;n<r.length;n++)if(i(t,e,r[n]))return!0;return!1}function i(t,e,r){switch(r.length){case 3:if(function(t,e,r){if(255!==t[e+3])return!0;if(t[e]===r[0]&&t[e+1]===r[1]&&t[e+2]===r[2])return!0;return!1}(t,e,r))return!0;break;case 4:if(function(t,e,r){if(t[e+3]&&r[3])return t[e]===r[0]&&t[e+1]===r[1]&&t[e+2]===r[2]&&t[e+3]===r[3];return t[e+3]===r[3]}(t,e,r))return!0;break;case 5:if(function(t,e,r){var n=r[0],i=r[1],a=r[2],s=r[3],u=r[4],c=t[e+3],d=o(c,s,u);if(!s)return d;if(!c&&d)return!0;if(o(t[e],n,u)&&o(t[e+1],i,u)&&o(t[e+2],a,u)&&d)return!0;return!1}(t,e,r))return!0;break;default:return!1}}function o(t,e,r){return t>=e-r&&t<=e+r}function a(t,e,r){for(var i={},o=r.dominantDivider||24,a=r.ignoredColor,s=r.step,u=[0,0,0,0,0],c=0;c<e;c+=s){var d=t[c],h=t[c+1],f=t[c+2],l=t[c+3];if(!a||!n(t,c,a)){var v=Math.round(d/o)+","+Math.round(h/o)+","+Math.round(f/o);i[v]?i[v]=[i[v][0]+d*l,i[v][1]+h*l,i[v][2]+f*l,i[v][3]+l,i[v][4]+1]:i[v]=[d*l,h*l,f*l,l,1],u[4]<i[v][4]&&(u=i[v])}}var g=u[0],p=u[1],m=u[2],C=u[3],w=u[4];return C?[Math.round(g/C),Math.round(p/C),Math.round(m/C),Math.round(C/w)]:r.defaultColor}function s(t,e,r){for(var i=0,o=0,a=0,s=0,u=0,c=r.ignoredColor,d=r.step,h=0;h<e;h+=d){var f=t[h+3],l=t[h]*f,v=t[h+1]*f,g=t[h+2]*f;c&&n(t,h,c)||(i+=l,o+=v,a+=g,s+=f,u++)}return s?[Math.round(i/s),Math.round(o/s),Math.round(a/s),Math.round(s/u)]:r.defaultColor}function u(t,e,r){for(var i=0,o=0,a=0,s=0,u=0,c=r.ignoredColor,d=r.step,h=0;h<e;h+=d){var f=t[h],l=t[h+1],v=t[h+2],g=t[h+3];c&&n(t,h,c)||(i+=f*f*g,o+=l*l*g,a+=v*v*g,s+=g,u++)}return s?[Math.round(Math.sqrt(i/s)),Math.round(Math.sqrt(o/s)),Math.round(Math.sqrt(a/s)),Math.round(s/u)]:r.defaultColor}function c(t){return d(t,"defaultColor",[0,0,0,0])}function d(t,e,r){return void 0===t[e]?r:t[e]}function h(t){if(l(t)){var e=t.naturalWidth,r=t.naturalHeight;return t.naturalWidth||-1===t.src.search(/\.svg(\?|$)/i)||(e=r=100),{width:e,height:r}}return function(t){return"undefined"!=typeof HTMLVideoElement&&t instanceof HTMLVideoElement}(t)?{width:t.videoWidth,height:t.videoHeight}:g(t)?{width:t.codedWidth,height:t.codedHeight}:{width:t.width,height:t.height}}function f(t){return function(t){return"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement}(t)?"canvas":function(t){return v&&t instanceof OffscreenCanvas}(t)?"offscreencanvas":g(t)?"videoframe":function(t){return"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap}(t)?"imagebitmap":t.src}function l(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement}var v="undefined"!=typeof OffscreenCanvas;function g(t){return"undefined"!=typeof VideoFrame&&t instanceof VideoFrame}var p="undefined"==typeof window;function m(t){return Error("FastAverageColor: "+t)}function C(t,e){e||console.error(t)}var w=function(){function t(){this.canvas=null,this.ctx=null}return t.prototype.getColorAsync=function(t,e){if(!t)return Promise.reject(m("call .getColorAsync() without resource"));if("string"==typeof t){if("undefined"==typeof Image)return Promise.reject(m("resource as string is not supported in this environment"));var r=new Image;r.crossOrigin=e&&e.crossOrigin||"";var n=this.bindImageEvents(r,e);return r.src=t,n}if(l(t)&&!t.complete)return this.bindImageEvents(t,e);var i=this.getColor(t,e);return i.error?Promise.reject(i.error):Promise.resolve(i)},t.prototype.getColor=function(t,e){var r=c(e=e||{});if(!t)return C(o=m("call .getColor() without resource"),e.silent),this.prepareResult(r,o);var n=function(t,e){var r,n=d(e,"left",0),i=d(e,"top",0),o=d(e,"width",t.width),a=d(e,"height",t.height),s=o,u=a;return"precision"===e.mode||(o>a?(r=o/a,s=100,u=Math.round(s/r)):(r=a/o,u=100,s=Math.round(u/r)),(s>o||u>a||s<10||u<10)&&(s=o,u=a)),{srcLeft:n,srcTop:i,srcWidth:o,srcHeight:a,destWidth:s,destHeight:u}}(h(t),e);if(!(n.srcWidth&&n.srcHeight&&n.destWidth&&n.destHeight))return C(o=m('incorrect sizes for resource "'.concat(f(t),'"')),e.silent),this.prepareResult(r,o);if(!this.canvas&&(this.canvas=p?v?new OffscreenCanvas(1,1):null:document.createElement("canvas"),!this.canvas))return C(o=m("OffscreenCanvas is not supported in this browser"),e.silent),this.prepareResult(r,o);if(!this.ctx){if(this.ctx=this.canvas.getContext("2d",{willReadFrequently:!0}),!this.ctx)return C(o=m("Canvas Context 2D is not supported in this browser"),e.silent),this.prepareResult(r,o);this.ctx.imageSmoothingEnabled=!1}this.canvas.width=n.destWidth,this.canvas.height=n.destHeight;try{this.ctx.clearRect(0,0,n.destWidth,n.destHeight),this.ctx.drawImage(t,n.srcLeft,n.srcTop,n.srcWidth,n.srcHeight,0,0,n.destWidth,n.destHeight);var i=this.ctx.getImageData(0,0,n.destWidth,n.destHeight).data;return this.prepareResult(this.getColorFromArray4(i,e))}catch(n){var o;return C(o=m("security error (CORS) for resource ".concat(f(t),".\nDetails: https://developer.mozilla.org/en/docs/Web/HTML/CORS_enabled_image")),e.silent),e.silent||console.error(n),this.prepareResult(r,o)}},t.prototype.getColorFromArray4=function(t,e){e=e||{};var n=t.length,i=c(e);if(n<4)return i;var o,d=n-n%4,h=4*(e.step||1);switch(e.algorithm||"sqrt"){case"simple":o=s;break;case"sqrt":o=u;break;case"dominant":o=a;break;default:throw m("".concat(e.algorithm," is unknown algorithm"))}return o(t,d,{defaultColor:i,ignoredColor:r(e.ignoredColor),step:h,dominantDivider:e.dominantDivider})},t.prototype.prepareResult=function(t,r){var n,i=t.slice(0,3),o=[t[0],t[1],t[2],t[3]/255],a=(299*(n=t)[0]+587*n[1]+114*n[2])/1e3<128;return{value:[t[0],t[1],t[2],t[3]],rgb:"rgb("+i.join(",")+")",rgba:"rgba("+o.join(",")+")",hex:e(i),hexa:e(t),isDark:a,isLight:!a,error:r}},t.prototype.destroy=function(){this.canvas&&(this.canvas.width=1,this.canvas.height=1,this.canvas=null),this.ctx=null},t.prototype.bindImageEvents=function(t,e){var r=this;return new Promise(function(n,i){var o=function(){t.removeEventListener("load",a),t.removeEventListener("error",s),t.removeEventListener("abort",u)},a=function(){o();var a=r.getColor(t,e);a.error?i(a.error):n(a)},s=function(){o(),i(m('Error loading image "'.concat(t.src,'"')))},u=function(){o(),i(m('Image "'.concat(t.src,'" loading aborted')))};t.addEventListener("load",a),t.addEventListener("error",s),t.addEventListener("abort",u),t.complete&&a()})},t}();("undefined"!=typeof window?window:self).FastAverageColor=w}();