UNPKG

extract-colors

Version:

Extract color palettes from images

1 lines 42.9 kB
{"version":3,"file":"extract-colors.mjs","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/color/FinalColor.ts","../src/helpers.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 { 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 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 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":["distance","hueDistance","total","width","height","canvas","image"],"mappings":"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"}