Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 45x 45x 10x 6x 6x 1x 5x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 400x 400x 300x 300x 300x 300x 300x 100x 100x 100x 100x 100x 1x 1x 100x 4x 4x 4x 1x 1x 1x 4x 4x 1x 4x 4x 4x | import { Dispatch, SetStateAction } from "react"; import { rgbToHex } from "utils"; const cache: Record<string, string> = {}; export function getMainColorFromImage( imageId: string, callback: Dispatch<SetStateAction<string>> | ((color: string) => void), config?: { sampleSize?: number; qualityReduction?: number }, document: Document = window.document ): void { const img = document.querySelector(`#${imageId}`) as HTMLImageElement; if (!img) { return; } if (cache[img.src]) { callback(cache[img.src]); return; } const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); Iif (!ctx) return; const image = new Image(); image.crossOrigin = "anonymous"; image.src = img.src; image.onload = () => { const sampleSize = config?.sampleSize || 100; const qualityReduction = config?.qualityReduction || 10; const scaledWidth = Math.max(1, Math.floor(image.width / qualityReduction)); const scaledHeight = Math.max( 1, Math.floor(image.height / qualityReduction) ); canvas.width = scaledWidth; canvas.height = scaledHeight; ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight); const imageData = ctx.getImageData(0, 0, scaledWidth, scaledHeight).data; const colorCounts: Record<string, number> = {}; const colorValues: Record<string, { r: number; g: number; b: number }> = {}; for (let i = 0; i < sampleSize; i++) { const randomIndex = Math.floor(Math.random() * (scaledWidth * scaledHeight)) * 4; if (imageData[randomIndex + 3] === 0) continue; const r = imageData[randomIndex]; const g = imageData[randomIndex + 1]; const b = imageData[randomIndex + 2]; const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; if (luma > 240 || luma < 15) continue; const simplifiedR = Math.floor(r / 8) * 8; const simplifiedG = Math.floor(g / 8) * 8; const simplifiedB = Math.floor(b / 8) * 8; const colorKey = `${simplifiedR},${simplifiedG},${simplifiedB}`; if (!colorCounts[colorKey]) { colorCounts[colorKey] = 0; colorValues[colorKey] = { r, g, b }; } colorCounts[colorKey]++; } let dominantColorKey = Object.keys(colorCounts)[0]; let maxCount = 0; for (const colorKey in colorCounts) { if (colorCounts[colorKey] > maxCount) { maxCount = colorCounts[colorKey]; dominantColorKey = colorKey; } } let dominantColor = { r: 122, g: 122, b: 122 }; if (dominantColorKey) { dominantColor = colorValues[dominantColorKey]; } const hex = rgbToHex(dominantColor); cache[img.src] = hex; callback(hex); }; } |