At the end of May 2021, I have released Colors for After-Effects, which lets you do magnificent things with colors that are not yet possible natively. It is a color sampler that lets you sample raster images (any frame from an active comp) into a compact palette. It also lets you generate new palettes on spot without thinking about it too much, so you can quickly be inspired by many different color options and start using the one you like the most. It also lets you recolor entire comps in a breeze, as well as examine and create different gradients. It also (yes a lot of alsos) lets you drop into the comp a variety of custom elements that use colors that are based on the active palette. It also does a lot more.

Here in this little space of mine, I’ll share more about the creation process of this tool.

How I created “Colors” for Adobe After-Effects

At the end of May 2021, I have released Colors for After-Effects, which lets you do magnificent things with colors that are not yet possible natively. It is a color sampler that lets you sample raster images (any frame from an active comp) into a compact palette. It also lets you generate new palettes on spot without thinking about it too much, so you can quickly be inspired by many different color options and start using the one you like the most. It also lets you recolor entire comps in a breeze, as well as examine and create different gradients. It also (yes a lot of alsos) lets you drop into the comp a variety of custom elements that use colors that are based on the active palette. It also does a lot more.

Here in this little space of mine, I’ll share more about the creation process of this tool.

What’s a Rich Text element?

What’s a Rich Text element?

What’s a Rich Text element?

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

Static and dynamic content editing

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

How it started

I was very much inspired by procreate’s ability to drop in an image and it will convert it to a palette for you. This is not a new concept by any means, but procreate is always magical in the way it does things, so I was very eager to find a way to do the same thing inside After-Effects.

However, the road there wasn’t very straight forward. As far as scripting goes, your best bet is to use “sampleImage”, which is an expression built into After-Effects that lets you sample pixels from the image. However, this expression has a history of being a little quirky, as it can sometimes evaluate independently after the rest of the current frame is already rendered. Adobe did fix some bugs related to this issue before, but upon my first prototype, I still found it to be a little buggy and return very unreliable results, especially when the script is launched from the ScriptUI Panel folder, as a dockable panel.

However, when it did work it was magnificent af :) 

The very first prototype back in March 2021 was solely based on this feature, as I was trying to figure out if this can be done or not. I was able to harvest colors from all around the image with what I would say about a 75% rate of success. When it didn’t work, the expression would return an array of black pixels at best.

The results were pretty crazy though and gave me MS Paint vibes, which I don’t know if is a good thing, but I definitely felt the nostalgia of using the array of colors blocks at the bottom of the software to pick my colors and was charmed when I was able to get a similar grid of colors in a script, so I kept going.

Overcoming the sampling issues

This actually came much later in the process of creating the Script because for a long time I was having fun exploring different ideas of what this script could do besides just sampling colors. But I did come back to improve the sampling process later on. One of the ways I did it was by forcing the script to check if the sampleImage result is an array of black pixels. If it is, keep trying to harvest the result. Eventually, After-Effects returns the correct sample, it’s just a matter of time. If after multiple tries it still doesn’t work the script does stop trying, but this is a very high number and is very unlikely to happen if at all. From all of my tests, this method seems to work reliably.

What kind of sorcery is this? 🧙

Follow the Good Boy Ninja on Twitter for After-Effects tips and tricks
Follow

Creating a palette from an image

So sampling colors from an image is working, but it is not enough.

When you use Colors you can tell that colors are pretty good at catching the most dominant colors of the image, while ignoring/removing different shades of the same color. This was a process that was really fun to figure out. So the sampling process returns hundreds / potentially thousands of different colors. If I would just give you all those colors the script would result in way too many blocks for it to be usable. I needed to figure out a way to isolate only the most important colors and leave you with a simple compact palette.


The method I ended up using was clustering all the different colors into groups. The script loops through the colors and based on a magic threshold it divides them into arrays of similar colors. While there’s some more magic going on, for the most part, it then looks at each group of colors and tried to figure out which color in this group best represents its buddies. Then it picks at least one from each group and builds a palette only out of those, and you end up with a compact palette that represents most areas of the image and leaves you without duplicate colors/colors of the same shade.

Sampling colors from shape layers, and other color properties

One of the other cool things about Colors is the ability to sample contextually. If you try to sample colors with no layers selected, it will sample the comp as a raster image. However, for vector works, illustrations, and a lot of other workflows, we end up with a custom design that already holds all the colors that we see in the viewer. Color properties, like fill, stroke, gradients, and such already exist in After-Effects.

Therefore, using the same sample button when a layer is selected will send Colors to find the color properties from the layer that you meant to sample. This way you can actually quickly create custom color palettes from already existing objects. Just select them and click sample.

While this sounds simple it actually has a level of complexity that hopefully, you don’t care about because it just works.

Scripts in After-Effects don’t have a way to access colors only. In other words, no command gives the script only the selected color properties. Moreover, we are lazy (and proud of it). We don’t like to select out color properties specifically, we often end up selecting the parent object, like the shape layer, the shape group, or even the effect itself.

Colors deals with that as well and is trying to be as smart as possible about your selection, and compensate for your laziness. It usually looks through the scope of your selection and scans all the sub-properties to find the nearest color properties. 


Solids and texts

What is usually easy to miss is the fact that text properties don’t have any exposed color properties as well as solid layers. Through scripts, you can use the textDocument object to change the color of a text, but this gets rather complex when using the previous approach of scanning for colors, as this is a completely different type of object. This gets more complex with solids because the color of a solid is stored in the source of the layer, and not in the layer itself. It gets even more complex when you realize that every time you duplicate a solid and change its colors, After-Effects replaces your solid with a new solid (there’s a little checkbox for that that is automatically selected in the Solid Settings dialog). Without that feature, you’d end up changing the colors of multiple solids in your timeline that are sharing the same source. Users usually don’t even understand that this is happening.

Through scripting, however, you have to do this manually, so this just makes the whole deal even more annoying.

My solution was pretty fun though, I ended up creating a new class of properties that is similar to how other color properties are built. For example, when encountering a sourceText property, the script creates a new “sourceText Fill Color” pseudo property which is very similar to how regular color properties behave in after effects. I did the same with solids. This allows me eventually to streamline the process of coloring multiple stuff at the same time. With regular properties you can use the “setValue()” method. With my pseudo properties, I mimic the same behavior with a custom “setValue()” function. Honestly, I wish After-Effects would simply have all these properties exposed instead of making it harder for everybody. It would be neat to be able to toggle the sourceText property and open up a list of properties such as colors and text size etc and would make it much easier for scripts to handle.

Generating Color Palettes

This was fun as hell. First from a learning point of view, and also scripting wise it was a fun thing to make. So there are many traditional ways to get harmonious color palettes, most tools like Adobe Color and other palette generation websites will actually visually preview the relationship between color ‘nodes’ or areas on the color wheel. The key is to find harmonious ratios and distances between colors.

However, all my experiments with similar methods left me unsatisfied. Not to say these methods don’t work, but I felt like the results I ended up with were pretty meh. I gave many algorithms a try and a lot of them were pretty boring.

My vision for colors was for it to be a buddy you can call for inspiration. If you want to make something out of nothing you can quickly generate a lot of color palettes and once you see something inspiring you can use it to quickly build something up.

The way I ended up implementing this was quite interesting. What I did was sampling a lot of beautiful existing palettes from around the web, but then instead of taking the colors themselves, I stored arrays of color differences, or in other words the spaces between the colors. With a collection of such arrays I am able to start with one color, then build the rest of the colors one by one based on the differences. Sometimes I also mix between those arrays to create exciting and unpredictable options. When I first implemented it I was quite surprised to learn that it works much better than all my previous experiments, and I am delighted with most palettes that Colors ends up generating for me.

Undo and redo

Once the color generating system was in place, I realized that it’s really fun to click the generate button like crazy a million times and trust your instincts to stop when you see one you like. However we are slow with our instincts so more often than not I ended up liking something, but in practice stopped clicking the mouse a palette or two after I saw it. There was no question that Colors needed a way to scroll back through your palettes, so I implemented an undo system that stores a number of palettes in memory. You can use the arrows at the bottom left side of the script to scroll back and forward your palette's history.

Colors library

Saving a color palette also ended up being important, but also a pain in the ass to implement. Not out of complexity, but scope-wise. It’s a bigger project than it seems. I’m happy with the current implementation, mostly because I worked on it multiple times to make it future-proof. Right now, all colors are stored in one collection, but the system is built in a way that could potentially let me expand this to multiple collections, or in other words let the user create different categories of colors, perhaps for different projects, etc.


An early prototype of Colors

A grid is a grid is a grid

If you’re making scripts, or new to javascript / ExtendScript, I can’t emphasize enough how much the concept of a class is important. You can get away with creating a lot of similar different things using a function, but ultimately the potential you unlock when creating your own types of objects is really vast. 

Initially, I expected the colors grid to only be used in the main script panel, so I have created functions around the concept of a grid that are being utilized to build it into the panel. However as the development of the script progressed, I realized that the same concept of a colors grid will be used in many other places, such as the palette preview in the library, the drag&drop palette in Recolor, as well as the editor which lets you reorder and change the grid. But eventually, they are all the same grid.

This is where classes come in really handy and also make the code much more readable. Creating a “Grid” class helped me quickly bring the same grid into multiple windows anywhere in the script without any groundwork being redone over and over again. This is also quite versatile. Because different grids are meant to do different things (library grids are not interactive, editor grid gives you the option to delete and move swatches around, and the main grid lets you apply colors to After-Effects properties), with a class it was easy to create all these conditions. Some are implemented into the class itself, and others are added as a new grid is created. For example, you can make an “onClick” function for a swatch (which is, by the way, a class as well) inside the Grid class, then use JavaScript “.apply()” to integrate the actual onClick functionality once you build a grid. This also made sense code-wise, as you make a grid, define what it does and then build it.

Drag and Drop in Recolor

Recolor is wonderful and it also lets you drag and drop colors from the palette onto a set of existing color properties. This was a little difficult to implement using ScriptUI and extendscript. The solution for me was to have a transparent group that covers the entire drag and drops section by having that section orientation set to “stack”, and the alignment of the drag and drop group set to ["fill", "fill"]. This sheet is hidden until being called. Once you click a color from the palette, it takes the color and passes it to the drag and dropper, which then shows up and draws the little color preview next to the mouse. As you move the mouse the Drag and Drop sheet is calculated based on proximity to which group you are planning to apply the color to and highlights it if the mouse is close enough. As you let your finger off the mouse it applies the new color to this group and the drag and drop sheet is hidden again. So it is only shown when being called. It actually works really well.

Once I got that working, I also implemented something similar in the editor. While there is no color preview as you drag colors around, the same concept of a “Drag and Drop” object that takes care of what is happening as you move the mouse is implemented.

Tidbits

So to wrap things up, it was fun as heck to work on this script. I am super proud of it and what it can do, as well as how much I managed to learn from one project. There’s a lot happening behind the scenes that I haven’t talked about, but here are some fun concepts I learned along the way.

  • There is no one way to sort colors. You can sort by hue, saturation, eh… whatever. You will always have colors that feel out of place. For example, if you sort a lot of blues by hue, and one of them is super dark, close to black dark, but all the other ones are light, you might end up with a weird dark blue color in the middle of a bunch of lighter ones. These exemptions happen in other sorting ways as well, so in other words, there are only preferences.
  • Colors can be “uncompelling” by themselves, but as part of a palette, they can be mega beautiful. In other words, we are suckers for harmonies. The poop-greeny color we all know and love can feel spot on with the right colors around it.
  • Scripts can be powerful. It’s true that the potential is much greater with CEP panels, let alone plug-ins. However, there is a lot of room for creativity within the limitations of a script. Important to note that if you want to learn how to make CEP panels you should probably do it as the technologies are newer and possibilities are much broader. If you are just starting out with scripting, there’s still a lot that can be done with good old ExtendScript. Trust your mind and have fun with the process.
  • Keep track of the code you write and make your own libraries! This project was a turning point for me (I am always learning!). I took a week pause at some point and rearranged my entire workflow and made my own library of functions and commonly used thingies I reuse a lot. I can work under my own mess as I build a mental image in my head of where things are in my code, but as the Good Boy Ninja is becoming the home for more and more tools it only makes sense to have greater order, and a library I can finally re-use and expand on as I keep developing more stuff. Even if you are not planning to reuse stuff, be organized, learn how to work with classes, and build your own javascript libraries. Separate your scripts into different files and treat your script like a project somebody else will end up working on. It pays off and will save you lots of time in the long run.
  • I want more tools that help me be creative. While the sampling option in the script is amazing, I enjoy the most shuffling through dozens of color palettes and find one I like. I am LAZY! I very much enjoy picking my own colors, but I don’t always have the time to when I work with clients. When you have too much stuff to worry about, it’s really fun to have this entity in your software that’s there to be your buddy and save your ass. If you have to come up with something quick, finding a compelling palette first and building up from it is super handy. This notion is something I want to put more emphasis on in upcoming tools and future projects.

That’s it for now, thanks for reading my brain dump. You can get Colors from here and I’m very excited by the impact it can make on your workflow, the responses so far have been amazing, so feel free to share your thoughts with me on Twitter.

See you next time.
Good Boy Ninja

Good Boy Ninja
Motion Designer since 2008.
Maker of tools for Adobe After-Effects
Quick jump:
June 6, 2021
 
Similar Posts