Expression Shorts Sample Images Part 1

March 26th 2012 08:00:03am

This week we dive into the sampleImage expression. I show you how to read the values it outputs and how to use those values to drive the intensity of a lens flare.

SOURCE CODE:

sourceLayer = thisComp.layer("RGBA");
controlLayer = thisComp.layer("MASTER CONTROLLER");
sampleSize = [controlLayer.effect("Sample width")("Slider"), controlLayer.effect("Sample height")("Slider")];
samplePoint = controlLayer.effect("Sample Point")("Point");
maxBright = controlLayer.effect("Brightness Max")("Slider");
minBright = controlLayer.effect("Brightness Min")("Slider");
minInputVal = controlLayer.effect("Min input value")("Slider");
maxInputVal = controlLayer.effect("Max input value")("Slider");
c = parseInt(controlLayer.effect("Channel")("Slider"));
sourceChannelValue = 255*sourceLayer.sampleImage(samplePoint, sampleSize)[c];
linear(sourceChannelValue, minInputVal, maxInputVal, minBright, maxBright);

NOTE: The above expression can be used to control almost any property. The expression assumes that Expression Control effect plugins are also applied to the “MASTER CONTROLLER” layer. Point, and Slider controls are needed.

sampleImage() – The sampleImage() expression is used to read color and alpha information of a layer. You need to fill in two arguments for it, the first being the sample point to look at and the second the sample area size, sampleImage(samplepoint, samplesize).

The sample point needs to be a vector array like so, [1, 1]. The two numbers correspond to the X and Y coordinates of the comp viewer. The sample size refers to the size of the search area. Think of the GPS icons on maps, you are the center point and the circle that shows up on your phone around that point is the search area. Roughly, but you get the idea. sampleImage() will return an array of four values, something like this, 0.81960791349411,0.90196084976196,0.93333339691162,1. One for each of the color channels, Red, Green, Blue and Alpha.

It’s very confusing looking and that’s because the values are on a scale of 0 to 1, not 0 to 255 like you may expect. To convert the values into something more familiar like 0 to 255, you will need to do a little math on each channel. To do this, you multiply 255 times the channel result, 255*channel result. To access the individual array items we use each items index number, [0], [1], [2] and [3]. See my previous explanation of how arrays work here.

Here is the RGBA image that I use for this tutorial. Just right click and “Save Image As” to download the pic.

CODE BREAKDOWN:

sourceLayer = thisComp.layer("RGBA");
controlLayer = thisComp.layer("MASTER CONTROLLER");
sampleSize = [controlLayer.effect("Sample width")("Slider"), controlLayer.effect("Sample height")("Slider")];
samplePoint = controlLayer.effect("Sample Point")("Point");
maxBright = controlLayer.effect("Brightness Max")("Slider");
minBright = controlLayer.effect("Brightness Min")("Slider");
minInputVal = controlLayer.effect("Min input value")("Slider");
maxInputVal = controlLayer.effect("Max input value")("Slider");
c = parseInt(controlLayer.effect("Channel")("Slider"));
sourceChannelValue = 255*sourceLayer.sampleImage(samplePoint, sampleSize)[c];
linear(sourceChannelValue, minInputVal, maxInputVal, minBright, maxBright);

Line 1: We start our expression by setting some variables, the first being one called sourceLayer, to which we assign the our source image. In this case we used the RGBA still.

sourceLayer = thisComp.layer("RGBA");

Line 2: We now create a variable called controlLayer and assign it our null called MASTER CONTROLLER.

controlLayer = thisComp.layer("MASTER CONTROLLER");

Line 3: The next variable is called sampleSize and is a vector array, which requires and open and close bracket around it, [ ]. Inside that we assign the first item our Sample width slider and the second item the Sample height slider from our Master Controller null.

sampleSize = [controlLayer.effect("Sample width")("Slider"), controlLayer.effect("Sample height")("Slider")];

Line 4: In this line, we create a variable called samplePoint and assign it the Sample Point slider on our Master Controller null.

samplePoint = controlLayer.effect("Sample Point")("Point");

Line 5: We create a variable called maxBright and assign it the Brightness Max slider on our Master Controller null.

maxBright = controlLayer.effect("Brightness Max")("Slider");

Line 6: We do the same here for the minimum brightness.

minBright = controlLayer.effect("Brightness Min")("Slider");

Line 7: For this variable we are creating a link for the minimum input value to map to. related to the linear() expression on line 11. The variable name is minValInput and it is assigned the Min input value slider on our Master Controller null.

minInputVal = controlLayer.effect("Min input value")("Slider");

Line 8: We then create the maxInputVal variable and assign it the Max input value slider on our Master Controller null.

maxInputVal = controlLayer.effect("Max input value")("Slider");

Line 9: Next we create another variable and call it c. We the type parseInt(), this will convert our value to an Integer number. So 3.0 will become 3. This is important since we are wanting variable c to represent a specific color channel. Those channels are labeled as 0, 1, 2 and 3. Any other number, like 3.0, will not work and cause an error. Next we assign the Channel slider from our Master Controller null, making sure it is inside the the parenthesis of the parseInt().

c = parseInt(controlLayer.effect("Channel")("Slider"));

Line 10: This line is where we are getting our source values from. The variable is called sourceChannelValue and we assign it our sourceLayer variable from before. We then add .sampleImage() and inside the parenthesis we place our two arguments, the first being samplePoint and the second being sampleSize. At the end of this we add the channel index by using brackets, [ ] and placing our c variable in them, [c]. To convert the final value we multiply it by 255.

sourceChannelValue = 255*sourceLayer.sampleImage(samplePoint, sampleSize)[c];

Line 11: And now the final line that does gives us our final values. We use the linear() expression to track the values and adjust our flare accordingly. I did a full explanation of how linear() works here. We start with placing our first argument, this will be the source input that we want to use, in this case it is a color channel. More specifically, our variable sourceChannelValue.

The next two arguments are the min and max values of our source input that we want to use, so we place our min and max variables, minInputVal and maxInputVal. The final two arguments are the min and max values of the current property, flare brightness, that we want to map to the source input values. Here’s a quick comparison:

sourceChannelValue (our color channel)
0, 255 (min and max of color channel)
0, 100 (min and max of flare brightness)

When color channel value is at 0, flare brightness is at 0.
When color channel value is at 127.5, flare brightness is at 50.
When color channel value is at 255, flare brightness is at 100.

So, if you wanted to have the flare be 100 when your color channel is at 50% (127.5), you only need to adjust the color channel max to be lower, say 127.5 instead of 255.

linear(sourceChannelValue, minInputVal, maxInputVal, minBright, maxBright);

Hope it all makes sense. Check out part 2 here.

Checkout more:
After Effects ExtendScript Training: Ep. 4
X-Particles Self-feeding Particle System
Mastering TurbulenceFD Volume 1
After Effects ExtendScript Training: Ep. 1
After Effects ExtendScript Training: Ep. 6