Use sampleImage() to create a color picker

Understand the code
Post Reply
User avatar
Disciple
Posts: 137
Joined: June 5th, 2004, 8:05 am
Location: Los Angeles, CA
Contact:

In this tutorial I will explain how to use the awesome new sampleImage() command (CS3 only) to create a simple color picker effect.

Thanks to Mylenium, Dan Ebberts and Paul Tuersley for helping me figure this out in crunch time!

I worked on a project for which we had to create a color picker that allowed you to change the color of an object "interactively".
We needed to create a fake mouse arrow pointing at certain colors, which in turn would change the color of another object in the composition.

In this tutorial Dan Ebberts explains how to use sampleImage() to read the color information of a layer and apply that information to another layer. This was the starting point of my project.

However in this case the color information is passed directly to the layer sampling the data itself. What I needed was a way to use one layer as my "reader", and another layer as a display of the sampled color.

So I have three elements in my main comp :
A background layer that will display the sampled color
A pre-comp containing a color gradient that I will sample from
A "color picker" which in this case will be a small square (a solid layer).
Image

I will do a simple position animation of the square, to make it hover over the color gradient. Now I need to pass the "sampling" data from the square to the background.
If we take a look at the sampleImage() expression, it takes the following parameters :

Code: Select all

sampleImage(point, radius = [.5, .5], postEffect=true, t=time)
Where "point" is where the data is coming from (a position array), "radius" is the size of the pixel sample (thing of a color picker radius), "postEffect" allows you to define if the color sampling occurs AFTER all masks and effects, and I'm assuming "time" would allow you to specify a time offset. In our case we won't be concerned about the last two parameters,and they are optional anyways.

In my case, I'm reading data from one layer, and sending it to another. The sampleImage() expression will be placed on the background layer. To make it effective, I will have to use it in a Fill effect or any other effect that will be able to translate the color information.
(You could use the color information to drive other things, but we won't get into that here). What we want is the exact color of one layer to appear on another layer.

First I need to determine what my "point" will be. Since it is in fact not an actual location, but the changing position of my color picker, I need to use pipe that into my "point" argument.
I create a variable called "Target" and I assign it to my color grid.

Code: Select all

target = thisComp.layer("Color_gradient");
Remember we are adding this to the"color" parameter of the "Fill" effect on the Background layer.

Now we need to create another variable for our color picker layer.

Code: Select all

colorpicker = thisComp.layer("ColorPicker");
Of course all these names will be relative to what you called your layers.

Now it is time to add the actual sampleImage() expression
It will look like this :

Code: Select all

target = thisComp.layer("Color_gradient");
colorpicker = thisComp.layer("ColorPicker");
target.sampleImage(target.fromWorld(colorpicker.position), [0.5,0.5], true, time) 
So to break it down, the variables are assigned, the sampleImage() expression knows it has to read the data from the Color_gradient layer, but it has to do it via the ColorPicker position.
The

Code: Select all

[0.5,0.5]
means that we are actually reading data pixel per pixel. You can create a larger radius if you want to average data a little more. This could be useful if you wanted to average the data from a greenscreen for example (à la Shake).

And here is the final result.

Image

One note : be careful with your color picker. Correct me if I'm wrong, but I believe the data is being sampled from the center of the layer/comp, so if you are using a precomp that is comp size, but with a small layer in the center, it could get confusing...

I hope this helps

All the best
Alex
warsmurf
Posts: 1
Joined: December 2nd, 2008, 5:27 pm

Great tutorial! Having tried your expression, it's led me to a question about taking it a step further. Say I want to demonstrate the possible color variations of a paint job on a car. How would I go about taking the sampled color from my color picker and remapping that value to a color image (ie - the car)? I was able to fake it using your expression on a duplicate car layer using a combination of the fill effect with the "Hue" layer mode. I'd like to know if it's possible to do this directly to the layer.

Thanks!
Michael
nfrancisj
Posts: 2
Joined: January 18th, 2011, 6:05 am

Awesome work! I have a few questions. :) I'm trying to do something similar and am stuck in a black hole. Im trying to create a tool to get stereoscopic depth info.

you used "sampleImage(point, radius = [.5, .5], postEffect=true, t=time)" to sample the color info. What I am trying to do is find the location (X,Y) of a pixel with a certain color.
So I have a comp thats 500x500 and I have 2 footage each containing 1 pixel. Footage#1 has a RED pixel and Footage#2 has a BLUE pixel. What my goal is to find the distance in pixels between the RED and BLUE.

Is there a way to use sampleImage() to scan the comp for a pixel with the value <<255,0,0>> and report the location of this pixel?

Any help would be greatly appreciated :)
User avatar
Disciple
Posts: 137
Joined: June 5th, 2004, 8:05 am
Location: Los Angeles, CA
Contact:

Sorry, that goes beyond my knowledge, maybe Dan or Paul or Lloyd can help with this. My assumption is that you would have to get some kind of boolean (true/false) out of the sampleImage function and then use that to read the position value. But I unfortunately don't have time to play around with that to figure it out.

Let us know if you find the solution

Alex
User avatar
lloydalvarez
Enhancement master
Posts: 460
Joined: June 17th, 2004, 9:27 am
Location: New York City, NY
Contact:

You would need to use some for loops to scan every pixel in the image which will take for ever using sampleImage(). I think this is a job better suited for a PixelBender plugin.

-Lloyd
rogozyk
Posts: 2
Joined: October 25th, 2004, 3:01 pm

Hey guys,
how would you write this expression to take the position of the layer it's applied on.
(a no-color picker version).

Thanks for any help,
Vincent
Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

I think that would be like this (not tested):

target = thisComp.layer("Color_gradient");
target.sampleImage(target.fromWorld(toWorld(anchorPoint)), [0.5,0.5], true, time)


Dan
pm87
Posts: 1
Joined: March 10th, 2023, 4:41 am

Hello,

this expression works perfectly, and I wonder if somebody knew how to link this sampled color value to "Source Text" and display the RGB value.

Thanks in advance

Dan Ebberts
Posts: 320
Joined: June 26th, 2004, 10:01 am
Location: Folsom, CA
Contact:

I'm not sure what you're looking for exactly, but maybe something like this:

Code: Select all

target = thisComp.layer("Color_gradient");
s = target.sampleImage(target.fromWorld(toWorld(anchorPoint)), [0.5,0.5], true, time);
Math.round(s[0]*255) + ", " + Math.round(s[1]*255) + ", " + Math.round(s[2]*255)
Post Reply