-
Colore Brand (media palette):
-
-
+
Colore Brand (media palette):
+
+
-
Palette estratta:
+
Palette estratta:
@@ -727,153 +751,227 @@
reader.readAsDataURL(file);
},
-
-extractDominantColor(imageData) {
- const img = new Image();
- img.onload = () => {
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- canvas.width = img.width;
- canvas.height = img.height;
- ctx.drawImage(img, 0, 0);
+ extractDominantColor(imageData) {
+ const img = new Image();
+ img.onload = () => {
+ const canvas = document.createElement("canvas");
+ const ctx = canvas.getContext("2d");
+ canvas.width = img.width;
+ canvas.height = img.height;
+ ctx.drawImage(img, 0, 0);
- try {
- const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
- const data = imgData.data;
+ try {
+ const imgData = ctx.getImageData(
+ 0,
+ 0,
+ canvas.width,
+ canvas.height,
+ );
+ const data = imgData.data;
- // Step 1: Collect all valid colors
- const colors = [];
- for (let i = 0; i < data.length; i += 16) {
- const r = data[i];
- const g = data[i + 1];
- const b = data[i + 2];
- const a = data[i + 3];
+ // Step 1: Collect all valid colors
+ const colors = [];
+ for (let i = 0; i < data.length; i += 16) {
+ const r = data[i];
+ const g = data[i + 1];
+ const b = data[i + 2];
+ const a = data[i + 3];
- // Skip transparent
- if (a < 125) continue;
+ // Skip transparent
+ if (a < 125) continue;
- // Skip whites (> 235)
- if (r > 235 && g > 235 && b > 235) continue;
+ // Skip whites (> 235)
+ if (r > 235 && g > 235 && b > 235) continue;
- // Skip blacks (< 20)
- if (r < 20 && g < 20 && b < 20) continue;
+ // Skip blacks (< 20)
+ if (r < 20 && g < 20 && b < 20) continue;
- // Calculate saturation to skip grays
- const max = Math.max(r, g, b);
- const min = Math.min(r, g, b);
- const saturation = max === 0 ? 0 : (max - min) / max;
- if (saturation < 0.2) continue; // Skip grays
+ // Calculate saturation to skip grays
+ const max = Math.max(r, g, b);
+ const min = Math.min(r, g, b);
+ const saturation =
+ max === 0 ? 0 : (max - min) / max;
+ if (saturation < 0.2) continue; // Skip grays
- colors.push({ r, g, b });
- }
+ colors.push({ r, g, b });
+ }
- if (colors.length === 0) {
- this.logoColor = "#10b981";
- this.colorPalette = [];
- console.log("No valid colors found, using fallback");
- return;
- }
+ if (colors.length === 0) {
+ this.logoColor = "#10b981";
+ this.colorPalette = [];
+ console.log(
+ "No valid colors found, using fallback",
+ );
+ return;
+ }
- // Step 2: K-means clustering to extract palette (5-7 colors)
- const numClusters = Math.min(6, Math.max(3, Math.floor(colors.length / 50)));
- const palette = this.kMeansClustering(colors, numClusters);
+ // Step 2: K-means clustering to extract palette (5-7 colors)
+ const numClusters = Math.min(
+ 6,
+ Math.max(3, Math.floor(colors.length / 50)),
+ );
+ const palette = this.kMeansClustering(
+ colors,
+ numClusters,
+ );
- // Step 3: Filter palette colors by lightness
- const filteredPalette = palette.filter(color => {
- const max = Math.max(color.r, color.g, color.b);
- const min = Math.min(color.r, color.g, color.b);
- const l = (max + min) / 2 / 255;
- return l > 0.25 && l < 0.80; // Keep mid-range lightness
- });
+ // Step 3: Filter palette colors by lightness
+ const filteredPalette = palette.filter(
+ (color) => {
+ const max = Math.max(
+ color.r,
+ color.g,
+ color.b,
+ );
+ const min = Math.min(
+ color.r,
+ color.g,
+ color.b,
+ );
+ const l = (max + min) / 2 / 255;
+ return l > 0.25 && l < 0.8; // Keep mid-range lightness
+ },
+ );
- if (filteredPalette.length === 0) {
- this.logoColor = "#10b981";
- this.colorPalette = [];
- console.log("No suitable colors in palette, using fallback");
- return;
- }
+ if (filteredPalette.length === 0) {
+ this.logoColor = "#10b981";
+ this.colorPalette = [];
+ console.log(
+ "No suitable colors in palette, using fallback",
+ );
+ return;
+ }
- // Step 4: Calculate average color from palette
- const avgR = Math.round(filteredPalette.reduce((sum, c) => sum + c.r, 0) / filteredPalette.length);
- const avgG = Math.round(filteredPalette.reduce((sum, c) => sum + c.g, 0) / filteredPalette.length);
- const avgB = Math.round(filteredPalette.reduce((sum, c) => sum + c.b, 0) / filteredPalette.length);
+ // Step 4: Calculate average color from palette
+ const avgR = Math.round(
+ filteredPalette.reduce(
+ (sum, c) => sum + c.r,
+ 0,
+ ) / filteredPalette.length,
+ );
+ const avgG = Math.round(
+ filteredPalette.reduce(
+ (sum, c) => sum + c.g,
+ 0,
+ ) / filteredPalette.length,
+ );
+ const avgB = Math.round(
+ filteredPalette.reduce(
+ (sum, c) => sum + c.b,
+ 0,
+ ) / filteredPalette.length,
+ );
- // Store results
- this.logoColor = this.rgbToHex(avgR, avgG, avgB);
- this.colorPalette = filteredPalette.map(c => this.rgbToHex(c.r, c.g, c.b));
+ // Store results
+ this.logoColor = this.rgbToHex(
+ avgR,
+ avgG,
+ avgB,
+ );
+ this.colorPalette = filteredPalette.map((c) =>
+ this.rgbToHex(c.r, c.g, c.b),
+ );
- console.log("Extracted palette:", this.colorPalette);
- console.log("Average brand color:", this.logoColor);
- } catch (err) {
- console.error("Error extracting color:", err);
- this.logoColor = "#10b981";
- this.colorPalette = [];
- }
- };
- img.src = imageData;
-},
+ console.log(
+ "Extracted palette:",
+ this.colorPalette,
+ );
+ console.log(
+ "Average brand color:",
+ this.logoColor,
+ );
+ } catch (err) {
+ console.error("Error extracting color:", err);
+ this.logoColor = "#10b981";
+ this.colorPalette = [];
+ }
+ };
+ img.src = imageData;
+ },
-kMeansClustering(colors, k) {
- // Initialize centroids randomly
- let centroids = [];
- const shuffled = [...colors].sort(() => Math.random() - 0.5);
- for (let i = 0; i < k; i++) {
- centroids.push({ ...shuffled[i % shuffled.length] });
- }
+ kMeansClustering(colors, k) {
+ // Initialize centroids randomly
+ let centroids = [];
+ const shuffled = [...colors].sort(
+ () => Math.random() - 0.5,
+ );
+ for (let i = 0; i < k; i++) {
+ centroids.push({
+ ...shuffled[i % shuffled.length],
+ });
+ }
- // K-means iterations
- for (let iter = 0; iter < 10; iter++) {
- // Assign colors to nearest centroid
- const clusters = Array(k).fill(null).map(() => []);
+ // K-means iterations
+ for (let iter = 0; iter < 10; iter++) {
+ // Assign colors to nearest centroid
+ const clusters = Array(k)
+ .fill(null)
+ .map(() => []);
- colors.forEach(color => {
- let minDist = Infinity;
- let closestIdx = 0;
+ colors.forEach((color) => {
+ let minDist = Infinity;
+ let closestIdx = 0;
- centroids.forEach((centroid, idx) => {
- const dist = Math.sqrt(
- Math.pow(color.r - centroid.r, 2) +
- Math.pow(color.g - centroid.g, 2) +
- Math.pow(color.b - centroid.b, 2)
- );
- if (dist < minDist) {
- minDist = dist;
- closestIdx = idx;
- }
- });
+ centroids.forEach((centroid, idx) => {
+ const dist = Math.sqrt(
+ Math.pow(color.r - centroid.r, 2) +
+ Math.pow(color.g - centroid.g, 2) +
+ Math.pow(color.b - centroid.b, 2),
+ );
+ if (dist < minDist) {
+ minDist = dist;
+ closestIdx = idx;
+ }
+ });
- clusters[closestIdx].push(color);
- });
+ clusters[closestIdx].push(color);
+ });
- // Update centroids
- const newCentroids = clusters.map(cluster => {
- if (cluster.length === 0) return centroids[0]; // Fallback
+ // Update centroids
+ const newCentroids = clusters.map((cluster) => {
+ if (cluster.length === 0) return centroids[0]; // Fallback
- const avgR = Math.round(cluster.reduce((sum, c) => sum + c.r, 0) / cluster.length);
- const avgG = Math.round(cluster.reduce((sum, c) => sum + c.g, 0) / cluster.length);
- const avgB = Math.round(cluster.reduce((sum, c) => sum + c.b, 0) / cluster.length);
+ const avgR = Math.round(
+ cluster.reduce((sum, c) => sum + c.r, 0) /
+ cluster.length,
+ );
+ const avgG = Math.round(
+ cluster.reduce((sum, c) => sum + c.g, 0) /
+ cluster.length,
+ );
+ const avgB = Math.round(
+ cluster.reduce((sum, c) => sum + c.b, 0) /
+ cluster.length,
+ );
- return { r: avgR, g: avgG, b: avgB };
- });
+ return { r: avgR, g: avgG, b: avgB };
+ });
- // Check convergence
- const converged = centroids.every((c, i) =>
- c.r === newCentroids[i].r &&
- c.g === newCentroids[i].g &&
- c.b === newCentroids[i].b
- );
+ // Check convergence
+ const converged = centroids.every(
+ (c, i) =>
+ c.r === newCentroids[i].r &&
+ c.g === newCentroids[i].g &&
+ c.b === newCentroids[i].b,
+ );
- centroids = newCentroids;
- if (converged) break;
- }
+ centroids = newCentroids;
+ if (converged) break;
+ }
- // Sort by saturation (most saturated first)
- return centroids.sort((a, b) => {
- const satA = (Math.max(a.r, a.g, a.b) - Math.min(a.r, a.g, a.b)) / Math.max(a.r, a.g, a.b);
- const satB = (Math.max(b.r, b.g, b.b) - Math.min(b.r, b.g, b.b)) / Math.max(b.r, b.g, b.b);
- return satB - satA;
- });
-},
+ // Sort by saturation (most saturated first)
+ return centroids.sort((a, b) => {
+ const satA =
+ (Math.max(a.r, a.g, a.b) -
+ Math.min(a.r, a.g, a.b)) /
+ Math.max(a.r, a.g, a.b);
+ const satB =
+ (Math.max(b.r, b.g, b.b) -
+ Math.min(b.r, b.g, b.b)) /
+ Math.max(b.r, b.g, b.b);
+ return satB - satA;
+ });
+ },
rgbToHex(r, g, b) {
return (