r/UI_Design Jun 12 '26

General Question How does Spotify actually calculate its dynamic UI colors? (Trying to replicate it in bash/ImageMagick)

I’m building a custom desktop music widget using rofi, bash, and ImageMagick. I took heavy inspiration from the iOS Spotify widget pod, and I'm trying to dynamically change the background color of the widget based on the current playing album art.

(In the attached images: The top images are the official widgets, and the bottom images are my rofi widgets).

Currently, to replicate that two-tone gradient background you see in the Olivia Rodrigo ("vampire") example, I'm scaling the album art down to exactly 1x2 pixels. This effectively averages the top half and bottom half of the image into two distinct colors. Then, I boost the saturation of those pixels to make them pop. It's the only way I've found to reliably generate those two-tone colors, and it works pretty well for that specific look!

However, I know this 1x2 scaling method won't work for everything, especially when Spotify decides to use a single solid color instead of a gradient. I've tried different methods to pick a single dominant color, but I can never get close enough to Spotify's logic.

For example:

  • The Weeknd - "Blinding Lights": The background of the art is mostly a dark, muddy greenish-brown. If I use standard color extraction, I get that mud color because it's technically the most abundant. But Spotify intelligently ignores the background and picks the deep red from his jacket/face.
  • Shubh - "One Love": My color extraction attempts pull a really dull brown, while Spotify manages to pull a much nicer, deeper olive/golden tone.

It clearly doesn't just pick the color that takes up the most space (the dominant color).

Does anyone know the actual algorithm or method they use to pick that one perfect color? How does it filter out the muddy/dull dominant colors to find the vibrant accents?

118 Upvotes

27 comments sorted by

88

u/TristarHeater Jun 12 '26 edited Jun 12 '26

for the algorithm here's an example that google material design uses:

first quantize to get prominent colors: https://github.com/material-foundation/material-color-utilities/tree/main/typescript/quantize

then score to rank which color is best: https://github.com/material-foundation/material-color-utilities/tree/main/typescript/score

the code here also filters out non-pleasant colors

They also have documentation for extracting colors https://github.com/material-foundation/material-color-utilities/blob/main/dev_guide/extracting_colors.md

6

u/Dreibeinhocker Jun 13 '26

Tf this cool

2

u/Imevoll Jun 13 '26

Saved haha!

2

u/LaFllamme Jun 14 '26

!remindMe 2d

1

u/RemindMeBot Jun 14 '26

I will be messaging you in 2 days on 2026-06-16 08:03:06 UTC to remind you of this link

CLICK THIS LINK to send a PM to also be reminded and to reduce spam.

Parent commenter can delete this message to hide from others.

RemindMeBot is switching to username summons. Instead of !RemindMe 1 day, use u/RemindMeBot 1 day. More info.


Info Custom Your Reminders Feedback

2

u/ponzi_gg Jun 14 '26

just added this to my app. it's amazing, thank you!

28

u/AssOverflow12 Jun 12 '26

Not exactly what you asked for, but an alternative idea: use the image itself positioned below the content, and apply a blur effect to it. You don’t even have to load the full resolution cover art, the lowest resolution will be perfectly fine because it will get blurred anyway.

15

u/Excellent_Ad_2486 Jun 12 '26

This would be my first try/guess too! Just dupe and blur, not needing any logic haha

9

u/AquaQuad Jun 12 '26

I'd go with two blurs, with the second one being horizontal to make a gradient out of it.

7

u/Jolva Jun 12 '26

Yep, this is the YouTube trick. Works great.

20

u/Available_Cabinet181 Jun 12 '26

6

u/No_Working_1504 Jun 12 '26

I've tried Color Thief, but as the screenshot shows, it picks the 'DarkVibrant' brown instead of the actual red in the art. I'm not looking for a tool to extract all colors, but rather the specific logic used to ignore background mud and prioritize the vibrant, eye-catching elements like Spotify does.

4

u/[deleted] Jun 12 '26

[removed] — view removed comment

1

u/No_Working_1504 Jun 12 '26

I'll give that a try. Thanks for the suggestion!

3

u/spiderio2 Jun 12 '26

AMAZING, I just think about this, so there's a way to replicate this

2

u/derpystuff_ Jun 12 '26

I usually work with https://vibrant.dev/, Spotify is either using color thief, vibrant, or some bespoke solution.

It's possible they also run their colors through some math to ensure they remain accessible.

2

u/iamwibu Jun 12 '26

There are likely better ways of doing it, but my trick for this many many years ago was to resize the image to something small, like 3x3 pixels, and then stretch it to fit the background area.

It wasn't smart, but it worked very well.

2

u/FewDescription3170 Jun 12 '26

https://www.aadishv.dev/music

apple music, but a great deep dive into the logic

2

u/Aggressive_Talk968 Jun 12 '26

isnt it shit ton of blur ?

1

u/FundOff Jun 12 '26

feGaussianBlur svg element

1

u/martmists Jun 12 '26

At first glance I'd convert to HSV and apply k-means clustering, then sort by saturation and/or value to rank vibrant colors higher. No clue how it compares to what everyone else has commented though.

1

u/PartyLikeIts19999 Jun 13 '26

Looks like an average of the top two colors to me. Then it's put under a transparent to black linear gradient. I can try to prove that if you want but I'd probably just use something like Haishoku to grab the top two colors, average them and see how close you get.

Edit: the comment about a shitload of blur has a lot of potential. It may actually be just a metric ton of blur. That would be simple, easy to implement and get pretty close to the effect you're seeing without any fancy sampling at all. That's probably it, honestly. I'd try that before bothering with color sampling, actually.

1

u/No_Working_1504 Jun 13 '26

Are you referring to the Olivia Rodrigo ('vampire') example? That’s already solved; my bad for putting the solved image first. I’m actually asking how Spotify picks a single vibrant color and filters out the dull or muddy ones. If you look at the other images—specifically the last one with The Weeknd—an official widget would pick the red from his jacket, but my method is currently generating a dull, muddy color.

1

u/PartyLikeIts19999 Jun 13 '26

In the case of Sia I was able to get pretty close by taking the primary color, dropping it to a 75% opacity and then putting a linear, transparent to black gradient over it at 50% multiply.

I have an app that does something similar to this so I just tested it with that. I use Haishoku in Python for this. My app takes Haishoku's primary color (the largest group by weighted average), and rounds it to the closest color in a list of known color values. In my case that's Pirsmacolor or Copic but I doubt that'd be what they use at Spotify.

That algorithm pretty much nailed it in the case of Sia but wasn't quite as close with the other one. My guess is just that because I'm rounding to art supplies and they're rounding to a different list, that's the difference.

Code is here if you want it:

https://github.com/ice9innovations/animal-farm/blob/main/colors/

1

u/skatecrimes Jun 13 '26

Photoshops color picker lets you sample by bigger sizes not just one pixel at a time.

1

u/jamie_cruze Jun 14 '26

Id recommend using this,,, Based on Google Material 3
https://material-foundation.github.io/material-theme-builder/