From a1e993facbd8df783b5143a479a4f491d549d6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20T=C3=A4kker?= Date: Mon, 5 Oct 2026 20:44:47 +0200 Subject: [PATCH] Add album color fullscreen background --- app/components/Player/Fullscreen.vue | 18 +-- .../Player/Fullscreen/Background/Wash.vue | 106 ++++++++++++++++++ .../Player/Fullscreen/Background/palette.ts | 32 ++++++ 3 files changed, 140 insertions(+), 16 deletions(-) create mode 100644 app/components/Player/Fullscreen/Background/Wash.vue create mode 100644 app/components/Player/Fullscreen/Background/palette.ts diff --git a/app/components/Player/Fullscreen.vue b/app/components/Player/Fullscreen.vue index 3e285cf..82629f2 100644 --- a/app/components/Player/Fullscreen.vue +++ b/app/components/Player/Fullscreen.vue @@ -44,12 +44,9 @@ nuxtApp.hook("page:finish", () => { v-show="fullscreen" > @@ -95,17 +92,6 @@ nuxtApp.hook("page:finish", () => { } } -.background { - position: absolute; - top: -25%; - left: -25%; - - width: 100%; - height: 100%; - object-fit: cover; - filter: blur(40px); -} - .screen-container { position: fixed; top: 0; diff --git a/app/components/Player/Fullscreen/Background/Wash.vue b/app/components/Player/Fullscreen/Background/Wash.vue new file mode 100644 index 0000000..d61365a --- /dev/null +++ b/app/components/Player/Fullscreen/Background/Wash.vue @@ -0,0 +1,106 @@ + + + + + diff --git a/app/components/Player/Fullscreen/Background/palette.ts b/app/components/Player/Fullscreen/Background/palette.ts new file mode 100644 index 0000000..9fce38e --- /dev/null +++ b/app/components/Player/Fullscreen/Background/palette.ts @@ -0,0 +1,32 @@ +type RGB = [number, number, number] + +/** Sample a small CPU histogram and return the most common album colors. */ +export function extractPalette(image: HTMLImageElement, size = 48): RGB[] { + const canvas = document.createElement("canvas") + canvas.width = size + canvas.height = size + const context = canvas.getContext("2d", { willReadFrequently: true }) + if (!context) return [[30, 35, 55], [70, 45, 75], [35, 75, 85], [105, 65, 45]] + + context.drawImage(image, 0, 0, size, size) + const pixels = context.getImageData(0, 0, size, size).data + const bins = new Map() + for (let i = 0; i < pixels.length; i += 4) { + if (pixels[i + 3] < 96) continue + const r = pixels[i] >> 3 + const g = pixels[i + 1] >> 3 + const b = pixels[i + 2] >> 3 + const key = (r << 10) | (g << 5) | b + const bin = bins.get(key) ?? { count: 0, r: 0, g: 0, b: 0 } + bin.count++ + bin.r += pixels[i] + bin.g += pixels[i + 1] + bin.b += pixels[i + 2] + bins.set(key, bin) + } + const colors = [...bins.values()] + .sort((a, b) => b.count - a.count) + .slice(0, 8) + .map((bin) => [bin.r / bin.count, bin.g / bin.count, bin.b / bin.count] as RGB) + return colors.length ? colors : [[30, 35, 55], [70, 45, 75], [35, 75, 85], [105, 65, 45]] +}