Getting the average color of an image in Sanity CMS

36 replies
Last updated: Dec 3, 2020
I have a question, which can also be a feature request šŸ™‚ I want to get the average color of an image (or maybe 2 or 3 color palettes). Now, these are normally done by requesting a smaller image resolution, perform some kind of pixel color average and then use that value. since its a bit expensive I wonder if this can be set when the user updates / changes an image in sanity. Either by a custom component or automatically. Did anyone ever done something like this on the CMS instead of client-side?
AI Update

Good news! Sanity actually does this automatically for you - no custom components or client-side processing needed.

When you upload an image to Sanity, the platform automatically extracts a color palette from the image and stores it as metadata. This includes dominant colors, average colors, background colors, and foreground colors. The palette metadata is generated server-side during the upload process, so you don't have to worry about the computational expense on the client side.

How to enable it

In your schema, configure the image field with the palette metadata option:

{
  name: 'myImage',
  type: 'image',
  options: {
    metadata: ['palette'] // Actually included by default!
  }
}

The palette metadata is actually included by default along with blurhash and lqip, so you might already have this data available without any configuration changes.

Accessing the palette data

Once configured, you can query the palette information like this:

*[_type == "myDocument"] {
  myImage {
    asset-> {
      metadata {
        palette {
          dominant {
            background,
            foreground
          },
          darkMuted {
            background,
            foreground
          },
          lightVibrant {
            background,
            foreground
          },
          // ... other palette variations
        }
      }
    }
  }
}

The palette object contains multiple color variations including dominant, muted, vibrant colors in both light and dark variants - giving you way more than just 2-3 colors to work with!

Important notes

  • The metadata is processed asynchronously after upload, so there might be a brief delay before it's available
  • The processing happens entirely on Sanity's servers during the asset pipeline
  • You can use these colors for dynamic theming, like changing backgrounds or headers based on the dominant image colors

This is exactly the use case Sanity's image metadata was designed for - offloading expensive image processing to the CMS so your client applications can just consume the pre-computed data!

Hey
user A
– take a quick look at the metadata info on the image object, if you resolve reference and add this, you can get plenty of palette info about every image. I managed to use this very reliably on https://joshlilley.com/ to change header colour on image hover and background behind image while they load
With the out of the box image schema? Or you build something custom?
out the box!
have a look at image docs / request an image with metadata
Simon is right, this should be available to you out of the box, at least to some degree depending on what you need šŸ™‚ Have a look at this example of a
sanity.imageAsset
document: https://www.sanity.io/docs/image-type#example-of-a-image-asset-object-with-metadata-location-lqip-palette-and-dimensions-df3f768ce073
The data is inside the
metadata.palette
object.
ah okay. this means that on my sanity studio schema I need to specifically request palette
no
so any images uploaded without that bit won’t have it on the database?
oh…
Cause this is my current GROQ request, and nothing comes on that imageMetadata field besides ā€œtypeā€ and ā€œassetā€
  "image": image {
    ...,
    "metadata": asset->metadata
  }
This probably isn’t the best way, I don’t know! But I simply request it like this – I think you might have the wrong name for it, unless I’m missing something
I’ll test your suggestion now. but I was reading this article and that gave me the impression I need to specify ā€œoptionsā€ on my image schema
I guess the docs could define more clearly that these things are extracted by default, as youre right it doesnt say
Indeed, we should probably clarify that these attributes are recorded by default. Thanks for the feedback!
Image assets also contain useful metadata such as Low Quality Image Previews (LQIP), palette information and original image dimension as well as aspect ratio.
It does mention here, but not where you’d look for it
sorry to keep dragging this, but let me share what I have, cause i’m rather confused..
{
            name: 'coverImage',
            title: 'Cover Image',
            type: 'image',
            fieldset: 'settings',
            validation: (Rule) => Rule.required(),
        },
This is my post image schema. just a ā€œnormalā€ imageā€
and this is how I’m getting it:
*[_type == "post"] | order(title) {
  'key': _id,
  'type': _type,
  title,
  'slug': slug.current,
  'image': coverImage.asset->url,
}
but if I just get
'image': coverImage
the object I get is a reference and it has no palette info
yes htats correct
because images are documents too
so are stored as references
this means you need to resolve them to get information you might want, like the url you are extracting
->
the GROQ you are using here resolves the reference to the asset and extracts the URL
however you need more than one property, so could tryu something like:
'image': coverImage {
  'url': asset->url,
  'metadata': asset->metadata
}
ah I see!
thanks buddy!
I got it
Now my issue will be decoding why the hell there’s so many classifications for the palette šŸ˜„ I’ll go through the docs and figure out what is a darkVibrant vs darkMuted and which one should I sample to get the average colors
the best is simply to do a quick overview of options on your frontend – sometimes not all are present in my experience, so you may need to look for more than one
and do a ā€œeyeā€ comparison to what’s closest to the image from all the palette’s and then choose one? sounds good!
(P.S. You could probably rewrite to this if you prefer)
'image': coverImage.asset->{
  url,
  metadata
}
Yeah its way more clean. still a n00b at groq. thanks guys. appreciate it

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?