I like playing around with colors, and have many articles on this site featuring various techniques. This one is an experiment I’ve been working on to derive colors and color mixtures based on textual content. To start with, I’ll be using a spreadsheet to provide the content but in later articles I might move on to Docs and Slides.
Color from content
The first type of content is where text itself mentions colors. Imagine you have this list of song titles and you want to color the background according to their titles.
We’ll try to interpret the content to look for colors. Some have multiple colors mentioned in a song title – so let’s mix all of the colors mentioned into 1. Notice that the font color has also been adjusted to contrast the background color.
Sort titles by color derived from content
Then sorting it by the combined colors, magically gives a much more interestingly organized list.
Color Saturation to represent content prevalance
Changing the color saturation by how many times a color is mentioned in the content, might be nice too – so Green, Green Grass will be ‘greener’ than say, Green Onions. It’s pretty subtle, but you can see the saturated hex code is a little different – the Green,green,really green green grass would be even greener.
Alternative lists
Of course, you may want to organize content by color that doesn’t itself contain any specific color name references.
You could create alternative lists which reference other lists which are themselves color based. Imagine you had a recipe book, where the ingredients were color coded, and the overall recipe itself could be assigned a color based on the ingredients in it.
Ingredients
Here’s a list of ingredients, sorted by colors. Using the same technique as with the list of song titles, we can approximate the color of an ingredient by listing the colors that seem to make it up. For example an aubergine (eggplant) has both purple and darkgreen shades. I’ll talk about the weight column later.
Recipes
Now here’s a list of recipes, this time showing the ingredients by color, and combining them to provide 2 final colors for the finished recipe.
Weighted mixing
The mix column is all the colors of the ingredients mixed as if they were equal in volume, whereas the mix-saturated column takes account of the volume by multiplying any numbers it finds in the ingredients by the weight in the ingredient column. For example 2 tbsp of olive oil = 2 x 15 = 30g and 300g of mushrooms = 300 x 1 = 300g. It’s far from perfect, but it’s just a proof of concept.
Other applications
Using this concept, any content could be mapped to a list which has color text to be used as a reference. For example, a document with sentiment analysis applied or paragraphs that reference particular subjects and so on.
Code samples
You’ll need to set a few things up first.
bmChroma
To get started you’ll need my bmChroma library. Reference is below.
1zjBPTX8meADK6W2tbw-sNB0479OMN2hhT1O5MGna7v5liAj7paj-W8QE
PreFiddler
I’m using PreFiddler and Fiddler for sheet manipulation as usual. bmPreFiddler id is below (it has its own reference to Fiddler built in).
13JUFGY18RHfjjuKmIRRfvmGlCYrEkEtN6uUm-iLUcxOUFRJD-WBX-tkR
Exports
If you’ve used my libaries before, you’ll probably know I usually add an exports layer like this which not only abstracts whether or not we are using libraries away from the main code, but also deals with the problems you sometimes get with the ordering of script files in project.
As a bonus, it’ll throw an error if you accidentally try to access an unknown property or method. I recommend it for all your projects. This is the one you’ll to add to your project for this article.
Chroma
Most of the heavy color maths is done using a version of the excellent chroma.js, which is wrapped inside the bmChroma library. Let’s look at creating the list of songs – the first example in this article.
The code
You can take a copy of my test sheet, or make your own. In any case, just update the PreFiddler spec to your own id and sheetName.
Most of the code is related to populating the sheet, which you can read about in the write ups for PreFiddler and Fiddler.
bmChroma
In this article, I’ll concentrate on the methods available from bmChroma
discover ( text ) : ColorNames
Pass a string which may or may not contain various words that can be recognized as colors. Currently this is any hex code, or any of the standard X11 color names. In a future article I’ll add Material colors to the list if there’s any interest in this library.
It will return a TextToColors object, which looks like this.
/**
* @typedef ColorNames
* @property {string} text the original text
* @property {string[]} colorNames the words in the string that could be colors
*/
getColorPack (color) : ColorPack
Pass a color in any format to and receive a ColorPack, which contains extended information about the color, as well as a property which is chroma color object.
/**
* @typedef ColorPack
* @property {object} base a chroma color
* @property {string} hex version of the based (same as base.hex())
* @property {string} contrast the contrast color in hex
* @property {string} name the name of the color (or a hex code if it cant be named)
*/
You can use the base property to access all the chroma.color native if you need to tweak the standard returns
getContrast (color, {dark = ‘#000000’, light = ‘#ffffff’, mode =”rgb”, minLuminance = 0.5} )
A ColorPack already has a contrast property – the hex value to use for contrasting text, and you can always use getColorPack to create one. You can also use getContrast directly if you want to change the luminance threshold (between 0 and 1 – the point at which it flips from providing a dark color to a light color), the mode (the color system used to calculate the luminance eg ‘lch’ or ‘hsl’), or the values to use for light or dark.
getChroma () : chroma
You may want to have direct access to the chroma API. getChroma() will return an instance you can use directly.
mixer ({colors, weights, mode=’rgb’}) : ColorPack
You can use this to mix an array of colors an end up with a single color that blends them all. Weights is an optional array the same length as the colors array, which allows you to weight the blending process to certain colors. If there are no weights provided, all colors are treated as equal. The mode picks the color space to use to guide the blending, eg ‘lch’.
getColors (text)
This is the main interface used to process documents.
Text contains a series of colors for example
const result = getColors("The green, green grass of home")
will produce this result
Result properties
text
A repeat of the original text
colorNames
An array of all the recognized color names
colorPacks
An array of ColorPacks corresponding with the colorNames array
mentions
A consolidated array of each unique color mentioned
mentions.color
A ColorPack of each color mentioned
mentions.noticed
An array of ColorPacks corresponding to each time the the mentions.color has been noticed
mix
A ColorPack with an unweighted mix of all colors mentioned
saturated
A ColorPack with a mix of all colors mentioned weighted by how often they occur.
Links
bmChroma 1zjBPTX8meADK6W2tbw-sNB0479OMN2hhT1O5MGna7v5liAj7paj-W8QE (github)
bmPreFiddler 13JUFGY18RHfjjuKmIRRfvmGlCYrEkEtN6uUm-iLUcxOUFRJD-WBX-tkR (github)
testBmYiq Github
Next
If there’s an interest in this library, I’ll add features such as material color recognition and examples using formats other than spreadsheets, or other interesting suggestions you may have.
Related
Contrast colors with Yiq
PreFiddler and Fiddler