diff --git a/packages/core-service/src/core/expert-profile/profile-export.service.ts b/packages/core-service/src/core/expert-profile/profile-export.service.ts index 8e3584c..a2589b9 100644 --- a/packages/core-service/src/core/expert-profile/profile-export.service.ts +++ b/packages/core-service/src/core/expert-profile/profile-export.service.ts @@ -218,6 +218,13 @@ export class ProfileExportService { } } } catch { /* Einstellungen nicht verfügbar */ } + + // Akzentfarbe dynamisch aus Logo extrahieren + if (platformLogo) { + const extracted = await this.extractDominantColor(platformLogo); + if (extracted) accentColor = extracted; + } + const fullName = `${data.firstName} ${data.lastName}`; const { firstName, lastName } = data; @@ -953,4 +960,45 @@ export class ProfileExportService { const base64Data = dataUrl.includes(',') ? dataUrl.split(',')[1] : dataUrl; return Buffer.from(base64Data, 'base64'); } + + /** + * Extrahiert die dominante Akzentfarbe aus einem Logo-Bild. + * Strategie: 20x20 Pixel resizen, transparenten Alpha gegen Weiss flatten, + * dann alle "bunten" Pixel (nicht weiss/schwarz/grau) mitteln. + * Gibt null zurück wenn keine ausreichend gesättigte Farbe gefunden wird. + */ + private async extractDominantColor(imageBuffer: Buffer): Promise { + try { + const { data, info } = await sharp(imageBuffer) + .resize(20, 20, { fit: 'fill' }) + .flatten({ background: { r: 255, g: 255, b: 255 } }) + .raw() + .toBuffer({ resolveWithObject: true }); + + let rSum = 0, gSum = 0, bSum = 0, count = 0; + for (let i = 0; i < info.width * info.height; i++) { + const r = data[i * 3]!; + const g = data[i * 3 + 1]!; + const b = data[i * 3 + 2]!; + const avg = (r + g + b) / 3; + const range = Math.max(r, g, b) - Math.min(r, g, b); + // Nur gesättigte Pixel: nicht zu hell, nicht zu dunkel, genug Farbabstand + if (avg > 25 && avg < 225 && range > 35) { + rSum += r; + gSum += g; + bSum += b; + count++; + } + } + + if (count === 0) return null; + + const r = Math.round(rSum / count); + const g = Math.round(gSum / count); + const b = Math.round(bSum / count); + return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`; + } catch { + return null; + } + } }