Получение доминируещего цвета из изображения
colorImages(src, opts)
-
Передаем сслуку на изображения и опции(?) (ignore?: string[]; scale?: number; skipTransparentPixels?: boolean;), получаем массив всех цветов от большему к меньшему
export interface Opts { ignore?: string[]; scale?: number; skipTransparentPixels?: boolean;}
function getContext(width: string, height: string) { const canvas = document.createElement("canvas"); canvas.setAttribute("width", width); canvas.setAttribute("height", height); return canvas.getContext("2d");}
function getImageData(src: string, scale: number) { if (scale === void 0) scale = 1;
const img = new Image(); if (!src.startsWith("data")) img.crossOrigin = "Anonymous";
return new Promise((resolve, reject) => { img.onload = () => { const width = img.width * scale; const height = img.height * scale; const context = getContext(String(width), String(height)); context?.drawImage(img, 0, 0, width, height); const ref = context?.getImageData(0, 0, width, height); const data = ref?.data; resolve(data); };
const errorHandler = () => reject(new Error("An error occurred attempting to load image"));
img.onerror = errorHandler; img.onabort = errorHandler; img.src = src; });}
function getCounts(data: any, ignore?: string[]) { const countMap: { [key: string]: any } = {};
for (let i = 0; i < data.length; i += 4) { const alpha = data[i + 3]; if (+alpha === 0) continue;
const rgbComponents = Array.from(data.subarray(i, i + 3)); if (rgbComponents.indexOf(undefined) !== -1) continue;
const color = alpha && alpha !== 255 ? "rgba(" + rgbComponents.concat([alpha]).join(",") + ")" : "rgb(" + rgbComponents.join(",") + ")";
if (ignore?.indexOf(color) !== -1) continue;
if (countMap[color]) countMap[color].count++; else countMap[color] = { color: color, count: 1 }; }
const counts = Object.values(countMap); return counts.sort((a, b) => b.count - a.count);}
const defaultOpts = { ignore: [], scale: 1 };
export default async function colorImages(src: string, opts?: Opts) { if (opts === void 0) opts = defaultOpts;
try { opts = Object.assign({}, defaultOpts, opts); const ignore = opts.ignore; const scale = opts.scale;
if ((!!scale && scale > 1) || (!!scale && scale <= 0)) { console.warn( "You set scale to " + scale + ", which isn't between 0-1. This is either pointless (> 1) or a no-op (≤ 0)" ); }
const data = await Promise.resolve(getImageData(src, Number(scale))); return getCounts(data, ignore); } catch (e) { return Promise.reject(e); }}