extract-colors
Version:
Extract color palettes from images
1 lines • 42.2 kB
Source Map (JSON)
{"version":3,"file":"extract-colors.cjs","sources":["../src/extract/cleanInputs.ts","../src/color/Color.ts","../src/color/LeafGroup.ts","../src/color/RootGroup.ts","../src/extract/extractor.ts","../src/sort/AverageGroup.ts","../src/sort/AverageManager.ts","../src/sort/sortColors.ts","../src/helpers.ts","../src/color/FinalColor.ts","../src/extractColors.ts"],"sourcesContent":["import { BrowserOptions, OptionsCleaned } from \"../types/Options\";\n\n/**\n * Default extractor values\n */\nexport const EXTRACTOR_PIXELS_DEFAULT = 64000;\nexport const EXTRACTOR_DISTANCE_DEFAULT = 0.22;\n\n/**\n * Default average values\n */\nexport const AVERAGE_HUE_DEFAULT = 1 / 12;\nexport const AVERAGE_SATURATION_DEFAULT = 1 / 5;\nexport const AVERAGE_LIGHTNESS_DEFAULT = 1 / 5;\n\nexport function testInputs({\n pixels = EXTRACTOR_PIXELS_DEFAULT,\n distance = EXTRACTOR_DISTANCE_DEFAULT,\n colorValidator = (\n _red: number,\n _green: number,\n _blue: number,\n _alpha?: number\n ) => (_alpha ?? 255) > 250,\n hueDistance = AVERAGE_HUE_DEFAULT,\n saturationDistance = AVERAGE_LIGHTNESS_DEFAULT,\n lightnessDistance = AVERAGE_SATURATION_DEFAULT,\n crossOrigin = \"\",\n requestMode = \"cors\",\n}: BrowserOptions = {}) {\n /**\n * Test if value is an integer.\n */\n const testUint = (\n label: string,\n val: number,\n min = 0,\n max = Number.MAX_SAFE_INTEGER\n ) => {\n if (!Number.isInteger(val)) {\n throw new Error(`${label} is not a valid number (${val})`);\n }\n\n if (val < min) {\n console.warn(`${label} can not be less than ${min} (it's ${val})`);\n }\n\n if (val > max) {\n console.warn(`${label} can not be more than ${max} (it's ${val})`);\n }\n\n return Math.min(Math.max(val, min), max);\n };\n\n /**\n * Test if value is a number.\n */\n const testNumber = (\n label: string,\n val: number,\n min = 0,\n max = Number.MAX_VALUE\n ) => {\n if (Number(val) !== val) {\n throw new Error(`${label} is not a valid number (${val})`);\n }\n\n if (val < min) {\n console.warn(`${label} can not be less than ${min} (it's ${val})`);\n }\n\n if (val > max) {\n console.warn(`${label} can not be more than ${max} (it's ${val})`);\n }\n\n return Math.min(Math.max(val, min), max);\n };\n\n /**\n * Test if value is a function.\n */\n const testFunction = <T = () => void>(label: string, val: T) => {\n if (!val || {}.toString.call(val) !== \"[object Function]\") {\n throw new Error(`${label} is not a function (${val})`);\n }\n\n return val;\n };\n\n /**\n * Test if value is in the list of values\n */\n const testValueInList = <T>(label: string, val: T, list: T[]) => {\n if (list.indexOf(val) < 0) {\n console.warn(\n `${label} can be one of this values ${list\n .map((v) => `\"${v}\"`)\n .join(\", \")} (it's \"${val}\")`\n );\n }\n };\n\n testUint(\"pixels\", pixels || 0, 1);\n testNumber(\"distance\", distance, 0, 1);\n testFunction(\"colorValidator\", colorValidator);\n testNumber(\"hueDistance\", hueDistance, 0, 1);\n testNumber(\"saturationDistance\", saturationDistance, 0, 1);\n testNumber(\"lightnessDistance\", lightnessDistance, 0, 1);\n testValueInList(\"crossOrigin\", crossOrigin, [\n \"\",\n \"anonymous\",\n \"use-credentials\",\n ]);\n testValueInList(\"requestMode\", requestMode, [\n \"cors\",\n \"navigate\",\n \"no-cors\",\n \"same-origin\",\n ]);\n}\n\nexport default ({\n pixels = EXTRACTOR_PIXELS_DEFAULT,\n distance = EXTRACTOR_DISTANCE_DEFAULT,\n colorValidator = (\n _red: number,\n _green: number,\n _blue: number,\n _alpha?: number\n ) => (_alpha ?? 255) > 250,\n hueDistance = AVERAGE_HUE_DEFAULT,\n saturationDistance = AVERAGE_LIGHTNESS_DEFAULT,\n lightnessDistance = AVERAGE_SATURATION_DEFAULT,\n crossOrigin = \"\",\n requestMode = \"cors\",\n}: BrowserOptions = {}): OptionsCleaned => {\n return [\n Math.max(pixels, 1),\n Math.min(Math.max(distance, 0), 1),\n colorValidator,\n Math.min(Math.max(hueDistance, 0), 1),\n Math.min(Math.max(saturationDistance, 0), 1),\n Math.min(Math.max(lightnessDistance, 0), 1),\n crossOrigin,\n requestMode,\n ];\n};\n","/**\n * Informations like saturation or count of pixels in image.\n *\n * @class\n * @classdesc Calculate some informations and store data about color.\n */\nexport default class Color {\n _red: number;\n _green: number;\n _blue: number;\n _hex: number;\n _count = 1;\n\n private __saturation = -1;\n private __hue = -1;\n private __lightness = -1;\n private __intensity = -1;\n\n /**\n * Set red, green and blue colors to create the Color object.\n */\n constructor(\n red: number,\n green: number,\n blue: number,\n hex = (red << 16) | (green << 8) | blue\n ) {\n this._red = red;\n this._green = green;\n this._blue = blue;\n this._hex = hex;\n }\n\n /**\n * Distance between two colors.\n * - Minimum is 0 (between two same colors)\n * - Maximum is 1 (for example between black and white)\n */\n static distance(colorA: Color, colorB: Color) {\n return (\n (Math.abs(colorB._red - colorA._red) +\n Math.abs(colorB._green - colorA._green) +\n Math.abs(colorB._blue - colorA._blue)) /\n (3 * 0xff)\n );\n }\n\n clone() {\n const color = new Color(this._red, this._green, this._blue, this._hex);\n color._count = this._count;\n return color;\n }\n\n updateHSL() {\n const red = this._red / 255;\n const green = this._green / 255;\n const blue = this._blue / 255;\n\n const max = Math.max(red, green, blue);\n const min = Math.min(red, green, blue);\n\n this.__lightness = (max + min) / 2;\n\n // achromatic\n if (max === min) {\n this.__hue = 0;\n this.__saturation = 0;\n this.__intensity = 0;\n } else {\n const distance = max - min;\n\n this.__saturation =\n this.__lightness > 0.5\n ? distance / (2 - max - min)\n : distance / (max + min);\n this.__intensity =\n this.__saturation * ((0.5 - Math.abs(0.5 - this.__lightness)) * 2);\n switch (max) {\n case red:\n this.__hue = ((green - blue) / distance + (green < blue ? 6 : 0)) / 6;\n break;\n case green:\n this.__hue = ((blue - red) / distance + 2) / 6;\n break;\n case blue:\n this.__hue = ((red - green) / distance + 4) / 6;\n break;\n }\n }\n }\n\n /**\n * Hue from 0 to 1\n */\n get _hue() {\n if (this.__hue === -1) {\n this.updateHSL();\n }\n return this.__hue;\n }\n\n /**\n * Saturation from 0 to 1\n */\n get _saturation() {\n if (this.__saturation === -1) {\n this.updateHSL();\n }\n return this.__saturation;\n }\n\n /**\n * Lightness from 0 to 1\n */\n get _lightness() {\n if (this.__lightness === -1) {\n this.updateHSL();\n }\n return this.__lightness;\n }\n\n /**\n * Color intensity from 0 to 1\n */\n get _intensity() {\n if (this.__intensity === -1) {\n this.updateHSL();\n }\n return this.__intensity;\n }\n}\n","import Color from \"./Color\";\n\n/**\n * Manage list of colors to optimize and merge neighbors colors.\n *\n * @export\n * @class LeafGroup\n */\nexport default class LeafGroup {\n _count: number;\n _children: Record<number, Color>;\n\n /**\n * Store colors or groups and _count similiar groups in the image.\n */\n constructor() {\n this._count = 0;\n this._children = {};\n }\n\n /**\n * Add color to the group.\n *\n * @param _hex Hexadecimal value of the color\n * @param _red Red chanel amount of the color\n * @param _green Green chanel amount of the color\n * @param _blue Blue chanel amount of the color\n * @returns The color\n */\n addColor(_hex: number, _red: number, _green: number, _blue: number) {\n this._count++;\n if (this._children[_hex]) {\n this._children[_hex]._count++;\n } else {\n this._children[_hex] = new Color(_red, _green, _blue, _hex);\n }\n return this._children[_hex];\n }\n\n /**\n * Get list of groups of list of colors.\n *\n * @returns List of colors\n */\n getList() {\n return (Object.keys(this._children) as unknown[] as number[]).map(\n (key) => this._children[key]\n );\n }\n\n /**\n * Representative color of leaf.\n *\n * @returns Main color of the leaf\n */\n createMainColor() {\n const list = this.getList();\n const biggest = list.reduce((a, b) => (a._count >= b._count ? a : b));\n const main = biggest.clone();\n main._count = this._count;\n return main;\n }\n}\n","import Color from \"./Color\";\nimport LeafGroup from \"./LeafGroup\";\n\n/**\n * RootGroup colors with algorithms to optimize and merge neighbors colors.\n *\n * @class\n * @classdesc Manage list of colors or groups.\n */\nexport default class RootGroup {\n _count: number;\n _children: Record<number, LeafGroup>;\n\n /**\n * Store colors or groups and _count similiar groups in the image.\n */\n constructor() {\n this._count = 0;\n this._children = {};\n }\n\n /**\n * Get list of groups of list of colors.\n */\n getList() {\n return (Object.keys(this._children) as unknown[] as number[]).map(\n (key) => this._children[key]\n );\n }\n\n addColor(r: number, g: number, b: number) {\n const full = (r << 16) | (g << 8) | b;\n const loss =\n (((r >> 4) & 0xf) << 8) | (((g >> 4) & 0xf) << 4) | ((b >> 4) & 0xf);\n this._count++;\n return this.getLeafGroup(loss).addColor(full, r, g, b);\n }\n\n /**\n * Add a key for a color, this key is a simplification to find neighboring colors.\n * Neighboring colors has same key.\n */\n getLeafGroup(key: number) {\n if (!this._children[key]) {\n this._children[key] = new LeafGroup();\n }\n return this._children[key] as LeafGroup;\n }\n\n /**\n * List of colors sorted by importance (neighboring hare calculated by distance and removed).\n * Importance is calculated with the saturation and _count of neighboring colors.\n */\n getColors(_distance: number) {\n const list = this.getList().map((child) => child.createMainColor());\n\n list.sort((a, b) => b._count - a._count);\n\n const newList: Color[] = [];\n while (list.length) {\n const current = list.shift() as Color;\n list\n .filter((color) => Color.distance(current, color) < _distance)\n .forEach((near) => {\n current._count += near._count;\n const i = list.findIndex((color) => color === near);\n list.splice(i, 1);\n });\n\n newList.push(current);\n }\n\n return newList;\n }\n}\n","import RootGroup from \"../color/RootGroup\";\n\n/**\n * Run extract process and get list of colors.\n */\nexport default (\n {\n data,\n width,\n height,\n }:\n | ImageData\n | { data: Uint8ClampedArray | number[]; width?: number; height?: number },\n _pixels: number,\n _distance: number,\n _colorValidator: (\n red: number,\n green: number,\n blue: number,\n alpha: number\n ) => boolean\n) => {\n const colorGroup = new RootGroup();\n const reducer =\n width && height ? Math.floor((width * height) / _pixels) || 1 : 1;\n let ignoredColorsCount = 0;\n\n for (let i = 0; i < data.length; i += 4 * reducer) {\n const r = data[i]; // 0 -> 255\n const g = data[i + 1];\n const b = data[i + 2];\n const a = data[i + 3];\n\n if (_colorValidator(r, g, b, a)) {\n colorGroup.addColor(r, g, b);\n } else {\n ignoredColorsCount++;\n }\n }\n\n return {\n colors: colorGroup.getColors(_distance),\n count: colorGroup._count + ignoredColorsCount,\n };\n};\n","import Color from \"../color/Color\";\n\nconst distance = (a: number, b: number) => Math.abs(a - b);\nconst hueDistance = (a: number, b: number) =>\n Math.min(distance(a, b), distance((a + 0.5) % 1, (b + 0.5) % 1));\n\nexport class AverageGroup {\n colors: Color[] = [];\n private _average: Color | null = null;\n\n addColor(color: Color) {\n this.colors.push(color);\n this._average = null;\n }\n\n isSamePalette(\n color: Color,\n hue: number,\n saturation: number,\n lightness: number\n ) {\n for (const currentColor of this.colors) {\n const isSame =\n hueDistance(currentColor._hue, color._hue) < hue &&\n distance(currentColor._saturation, color._saturation) < saturation &&\n distance(currentColor._lightness, color._lightness) < lightness;\n\n if (!isSame) {\n return false;\n }\n }\n return true;\n }\n\n get average() {\n if (!this._average) {\n const { r, g, b } = this.colors.reduce(\n (total, color) => {\n total.r += color._red;\n total.g += color._green;\n total.b += color._blue;\n return total;\n },\n { r: 0, g: 0, b: 0 }\n );\n\n const total = this.colors.reduce(\n (_count, color) => _count + color._count,\n 0\n );\n this._average = new Color(\n Math.round(r / this.colors.length),\n Math.round(g / this.colors.length),\n Math.round(b / this.colors.length)\n );\n this._average._count = total;\n }\n return this._average;\n }\n}\n","import Color from \"../color/Color\";\nimport { AverageGroup } from \"./AverageGroup\";\n\nexport class AverageManager {\n _hue: number;\n _saturation: number;\n _lightness: number;\n\n private _groups: AverageGroup[] = [];\n\n constructor(hue: number, saturation: number, lightness: number) {\n this._hue = hue;\n this._saturation = saturation;\n this._lightness = lightness;\n }\n\n addColor(color: Color) {\n const samePalette = this._groups.find((averageGroup) =>\n averageGroup.isSamePalette(\n color,\n this._hue,\n this._saturation,\n this._lightness\n )\n );\n if (samePalette) {\n samePalette.addColor(color);\n } else {\n const averageGroup = new AverageGroup();\n averageGroup.addColor(color);\n this._groups.push(averageGroup);\n }\n }\n\n getGroups() {\n return this._groups.map((averageGroup) => averageGroup.average);\n }\n}\n","import Color from \"../color/Color\";\nimport { AverageManager } from \"./AverageManager\";\n\nexport default (\n list: Color[],\n _pixels: number,\n _hueDistance: number,\n _saturationDistance: number,\n _lightnessDistance: number\n) => {\n const averageManager = new AverageManager(\n _hueDistance,\n _saturationDistance,\n _lightnessDistance\n );\n list.forEach((color) => averageManager.addColor(color));\n\n const sorted = averageManager.getGroups();\n\n sorted.sort((a, b) => {\n const bPower = (b._intensity + 0.1) * (0.9 - b._count / _pixels);\n const aPower = (a._intensity + 0.1) * (0.9 - a._count / _pixels);\n return bPower - aPower;\n });\n return sorted;\n};\n","import Color from \"./color/Color\";\nimport sortColors from \"./sort/sortColors\";\nimport { createFinalColor } from \"./color/FinalColor\";\n\n/**\n * Browser context detection\n *\n * @returns Is a browser context\n */\nexport const checkIsBrowser = () =>\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\n/**\n * Worker in Browser context detection\n *\n * @returns Is a worker browser context\n */\nexport const checkIsWorker = () =>\n typeof self === \"object\" &&\n self.constructor &&\n self.constructor.name === \"DedicatedWorkerGlobalScope\";\n\n/**\n * Node.js context detection\n *\n * @returns Is Node.js context\n */\nexport const checkIsNode = () =>\n typeof window === \"undefined\" &&\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n typeof process !== \"undefined\" &&\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n process.versions != null &&\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n process.versions.node != null;\n\n/**\n * Sort colors and generate standard list of colors.\n *\n * @param _colors List of colors\n * @param _pixels Count of pixels in the image\n * @param _hueDistance Maximal HUE distance between pixel before pixel merging\n * @param _saturationDistance Maximal saturation distance between pixel before pixel merging\n * @param _lightnessDistance Maximal lightness distance between pixel before pixel merging\n * @returns Sorted colors list\n */\nexport const sortFinalColors = (\n _colors: Color[],\n _pixels: number,\n _hueDistance: number,\n _saturationDistance: number,\n _lightnessDistance: number,\n) => {\n const list = sortColors(\n _colors,\n _pixels,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance,\n );\n return list.map((color) => createFinalColor(color, _pixels));\n};\n\n/**\n * Extract ImageData from image.\n * Reduce image to a pixel count.\n * Browser only\n *\n * @param _image HTML image element or Image Bitmap\n * @param _pixels Count of maximum pixels accepted for the calculation\n * @returns Data of the reduced image\n */\nexport const extractImageData = (\n _image: HTMLImageElement | ImageBitmap,\n _pixels: number,\n) => {\n const currentPixels = _image.width * _image.height;\n const width =\n currentPixels < _pixels\n ? _image.width\n : Math.round(_image.width * Math.sqrt(_pixels / currentPixels));\n const height =\n currentPixels < _pixels\n ? _image.height\n : Math.round(_image.height * Math.sqrt(_pixels / currentPixels));\n\n const canvas = ((width: number, height: number) => {\n if (checkIsWorker()) {\n return new OffscreenCanvas(width, height);\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n return canvas;\n })(width, height);\n\n const context = canvas.getContext(\"2d\") as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D;\n context.drawImage(\n _image,\n 0,\n 0,\n _image.width,\n _image.height,\n 0,\n 0,\n width,\n height,\n );\n\n return context.getImageData(0, 0, width, height);\n};\n","import { FinalColor } from \"../types/Color\";\nimport Color from \"./Color\";\n\n/**\n * Normalize color\n *\n * @param color Initial color\n * @param pixels Pixel count of this color\n *\n * @returns Normalized color\n */\nexport const createFinalColor = (color: Color, pixels: number): FinalColor => {\n return {\n hex: `#${\"0\".repeat(\n 6 - color._hex.toString(16).length\n )}${color._hex.toString(16)}`,\n red: color._red,\n green: color._green,\n blue: color._blue,\n area: color._count / pixels,\n hue: color._hue,\n saturation: color._saturation,\n lightness: color._lightness,\n intensity: color._intensity,\n };\n};\n","import cleanInputs, { testInputs } from \"./extract/cleanInputs\";\nimport extractor from \"./extract/extractor\";\nimport {\n checkIsBrowser,\n checkIsNode,\n checkIsWorker,\n extractImageData,\n sortFinalColors,\n} from \"./helpers\";\nimport { FinalColor } from \"./types/Color\";\nimport { BrowserOptions, ImageDataAlt, NodeOptions } from \"./types/Options\";\n\n/**\n * Extract colors from an ImageData object.\n *\n * @param imageData Data of the image\n * @param options Process configuration\n * @param options.pixels Total pixel number of the resized picture for calculation\n * @param options.distance From 0 to 1 is the color distance to not have near colors (1 distance is between white and black)\n * @param options.colorValidator Test function to enable only some colors\n * @param options.saturationDistance Minimum saturation value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.lightnessDistance inimum lightness value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.hueDistance inimum hue value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.crossOrigin support for CORS (only for browser)\n * @param options.requestMode support for CORS (only for Web Workers in browser)\n *\n * @returns List of extracted colors\n */\nexport const extractColorsFromImageData = (\n imageData: ImageData | ImageDataAlt,\n options: NodeOptions | BrowserOptions = {}\n) => {\n if (__DEV__) {\n testInputs(options);\n }\n\n const [\n _pixels,\n _distance,\n _colorValidator,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance,\n ] = cleanInputs(options);\n const { colors, count } = extractor(\n imageData,\n _pixels,\n _distance,\n _colorValidator\n );\n return sortFinalColors(\n colors,\n count,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance\n );\n};\n\n/**\n * Extract colors from an HTMLImageElement.\n * Browser only\n *\n * @param image HTML image element\n * @param options Process configuration\n * @param options.pixels Total pixel number of the resized picture for calculation\n * @param options.distance From 0 to 1 is the color distance to not have near colors (1 distance is between white and black)\n * @param options.colorValidator Test function to enable only some colors\n * @param options.saturationDistance Minimum saturation value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.lightnessDistance inimum lightness value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.hueDistance inimum hue value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.crossOrigin support for CORS (only for browser)\n * @param options.requestMode support for CORS (only for Web Workers in browser)\n *\n * @returns List of extracted colors\n */\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nexport const extractColorsFromImage = async (\n image: HTMLImageElement,\n options: BrowserOptions = {}\n): Promise<FinalColor[]> => {\n // Node.js version\n if (checkIsNode()) {\n if (__DEV__) {\n throw new Error(\n \"Use extractColors instead extractColorsFromImage for Node.js\"\n );\n }\n return [];\n }\n\n if (__DEV__) {\n testInputs(options);\n }\n\n // Browser version\n const [\n _pixels,\n _distance,\n _colorValidator,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance,\n _crossOrigin,\n ] = cleanInputs(options);\n image.crossOrigin = _crossOrigin;\n return new Promise((resolve: (value: FinalColor[]) => void) => {\n const extract = (image: HTMLImageElement) => {\n const imageData = extractImageData(image, _pixels);\n const { colors, count } = extractor(\n imageData,\n _pixels,\n _distance,\n _colorValidator\n );\n resolve(\n sortFinalColors(\n colors,\n count,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance\n )\n );\n };\n\n if (image.complete) {\n extract(image);\n } else {\n const imageLoaded = () => {\n image.removeEventListener(\"load\", imageLoaded);\n extract(image);\n };\n image.addEventListener(\"load\", imageLoaded);\n }\n });\n};\n\nexport const extractColorsFromImageBitmap = async (\n image: ImageBitmap,\n options: BrowserOptions = {}\n): Promise<FinalColor[]> => {\n // Node.js version\n if (checkIsNode()) {\n if (__DEV__) {\n throw new Error(\n \"Use extractColors instead extractColorsFromImageBitmap for Node.js\"\n );\n }\n return [];\n }\n\n if (__DEV__) {\n testInputs(options);\n }\n\n const [\n _pixels,\n _distance,\n _colorValidator,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance,\n ] = cleanInputs(options);\n\n const imageData = extractImageData(image, _pixels);\n const { colors, count } = extractor(\n imageData,\n _pixels,\n _distance,\n _colorValidator\n );\n\n return sortFinalColors(\n colors,\n count,\n _hueDistance,\n _saturationDistance,\n _lightnessDistance\n );\n};\n\n/**\n * Extract colors from a path.\n * The image will be downloaded.\n *\n * @param src Image source\n * @param options Process configuration\n * @param options.pixels Total pixel number of the resized picture for calculation\n * @param options.distance From 0 to 1 is the color distance to not have near colors (1 distance is between white and black)\n * @param options.colorValidator Test function to enable only some colors\n * @param options.saturationDistance Minimum saturation value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.lightnessDistance inimum lightness value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.hueDistance inimum hue value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.crossOrigin support for CORS (only for browser)\n * @param options.requestMode support for CORS (only for Web Workers in browser)\n *\n * @returns List of extracted colors\n */\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nexport const extractColorsFromSrc = async (\n src: string,\n options: BrowserOptions = {}\n): Promise<FinalColor[]> => {\n // Node.js version\n if (checkIsNode()) {\n if (__DEV__) {\n throw new Error(\"Can not use extractColorsFromSrc for Node.js\");\n }\n return [];\n }\n\n if (__DEV__) {\n testInputs(options);\n }\n\n // Web Worker version\n if (checkIsWorker()) {\n const inputs = cleanInputs(options);\n const response = await fetch(src, { mode: inputs[7] });\n const blob = await response.blob();\n const bitmap = await createImageBitmap(blob);\n const colors = await extractColorsFromImageBitmap(bitmap, options);\n bitmap.close();\n return colors;\n }\n\n // Browser version\n const image = new Image();\n image.src = src;\n return extractColorsFromImage(image, options);\n};\n\n/**\n * Extract colors from a picture.\n *\n * @param picture Image, image source or image data (node.js context only support image data)\n * @param options Process configuration\n * @param options.pixels Total pixel number of the resized picture for calculation\n * @param options.distance From 0 to 1 is the color distance to not have near colors (1 distance is between white and black)\n * @param options.colorValidator Test function to enable only some colors\n * @param options.saturationDistance Minimum saturation value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.lightnessDistance inimum lightness value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.hueDistance inimum hue value between two colors otherwise the colors will be merged (from 0 to 1)\n * @param options.crossOrigin support for CORS (only for browser)\n * @param options.requestMode support for CORS (only for Web Workers in browser)\n *\n * @returns List of extracted colors\n */\nexport const extractColors = (\n picture: string | HTMLImageElement | ImageData | ImageDataAlt,\n options?: BrowserOptions\n) => {\n // Browser version\n if (checkIsBrowser()) {\n if (__DEV__) {\n if (options?.requestMode) {\n console.warn(\n \"options.requestMode not supported in Browser, use options.crossOrigin instead\"\n );\n }\n }\n\n if (picture instanceof Image) {\n return extractColorsFromImage(picture, options);\n }\n\n if (\n picture instanceof ImageData ||\n (picture instanceof Object && picture.data)\n ) {\n return new Promise((resolve: (value: FinalColor[]) => void) => {\n resolve(extractColorsFromImageData(picture, options));\n });\n }\n\n if (typeof picture === \"string\") {\n return extractColorsFromSrc(picture, options);\n }\n }\n\n // Worker version\n if (checkIsWorker()) {\n if (__DEV__) {\n if (options?.crossOrigin) {\n console.warn(\n \"options.crossOrigin not supported in Web Worker, use options.requestMode instead\"\n );\n }\n }\n\n if (\n picture instanceof ImageData ||\n (picture instanceof Object && (picture as ImageDataAlt).data)\n ) {\n return new Promise((resolve: (value: FinalColor[]) => void) => {\n resolve(\n extractColorsFromImageData(\n picture as ImageData | ImageDataAlt,\n options\n )\n );\n });\n }\n\n if (typeof picture === \"string\") {\n return extractColorsFromSrc(picture, options);\n }\n\n // HTMLImageElement not enable on Worker, switch to src fallback\n if ((picture as HTMLImageElement).src) {\n if (__DEV__) {\n console.warn(\n \"HTMLImageElement not enable on worker, a fallback is used to extract src from your HTMLImageElement, please send 'src' instead HTMLImageElement\"\n );\n }\n return extractColorsFromSrc((picture as HTMLImageElement).src, options);\n }\n }\n\n // Node.js version\n if (checkIsNode()) {\n if (__DEV__) {\n if (picture instanceof String) {\n throw new Error(\n \"Send imageData to extractColors (Image src or HTMLImageElement not supported in Nodejs)\"\n );\n }\n\n if (!(picture as ImageData).data) {\n throw new Error(\"Send imageData to extractColors\");\n }\n\n if (options?.crossOrigin) {\n console.warn(\"options.crossOrigin not supported in Node.js\");\n }\n }\n\n return new Promise((resolve: (value: FinalColor[]) => void) => {\n resolve(\n extractColorsFromImageData(picture as ImageData | ImageDataAlt, options)\n );\n });\n }\n\n throw new Error(`Can not analyse picture`);\n};\n"],"names":["testInputs","pixels","distance","colorValidator","_red","_green","_blue","_alpha","hueDistance","AVERAGE_HUE_DEFAULT","saturationDistance","lightnessDistance","crossOrigin","requestMode","testNumber","label","val","min","max","Number","MAX_VALUE","Error","console","warn","Math","testValueInList","list","indexOf","map","v","join","MAX_SAFE_INTEGER","isInteger","testUint","toString","call","testFunction","cleanInputs","Color","constructor","red","green","blue","hex","this","_count","__saturation","__hue","__lightness","__intensity","_hex","colorA","colorB","abs","clone","color","updateHSL","_hue","_saturation","_lightness","_intensity","LeafGroup","_children","addColor","getList","Object","keys","key","createMainColor","main","reduce","a","b","RootGroup","r","g","full","loss","getLeafGroup","getColors","_distance","child","sort","newList","length","current","shift","filter","forEach","near","i","findIndex","splice","push","extractor","data","width","height","_pixels","_colorValidator","colorGroup","reducer","floor","ignoredColorsCount","colors","count","AverageGroup","_average","isSamePalette","hue","saturation","lightness","currentColor","average","total","round","AverageManager","_groups","samePalette","find","averageGroup","getGroups","checkIsWorker","self","name","checkIsNode","window","process","versions","node","sortFinalColors","_colors","_hueDistance","_saturationDistance","_lightnessDistance","averageManager","sorted","sortColors","repeat","area","intensity","createFinalColor","extractImageData","_image","currentPixels","sqrt","context","OffscreenCanvas","canvas","document","createElement","getContext","drawImage","getImageData","extractColorsFromImageData","imageData","options","__DEV__","S","extractColorsFromImage","async","image","_crossOrigin","Promise","resolve","extract","complete","imageLoaded","removeEventListener","addEventListener","extractColorsFromImageBitmap","extractColorsFromSrc","src","inputs","response","fetch","mode","blob","bitmap","createImageBitmap","close","Image","picture","ImageData","String"],"mappings":"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"}