So I dove into Pixel Bender in my previous post ( see Pixel Bender ).

What we will dive into in this tutorial are basics in variables and hardcore pixel manipulation.

When you open Pixel Bender, a lot of basics are already filled out for you, this is known as the Kernal Syntax.

The first portion is the information about the Kernal’s metadata:

kernel NewFilter
< namespace : "Your Namespace";
vendor : "Joshua";
version : 1;
description : "My First Basic Pixel Bender Manipulation Filter";
>

You can indicate in the kernal a set of name value metadata for your Pixel Bender Filter. In our case we can just the name and description of what we are doing.

The second part of the Pixel Bender Kernal is where all of our code is declared. When you start a new Pixel Bender Kernal Filter it looks like this

{
input image4 src;
output pixel4 dst;

void
evaluatePixel()
{
dst = sampleNearest(src,outCoord());
}
}

With Pixel Bender, we need to indicate a source, and in this case we are loading an image and storing the image in a variable called src. We are typing the variable as an image4. An image4 type indicates that this image would contain the 4 different types of pixel colour values ( Red, Green, Blue, Alpha ). We also have an output called dst which returns our manipulated pixels ( again using the 4 different types of pixel colour values ) so we can view the manipulated image. We have a function called evaluatePixel which runs through all of the pixels and where we can manipulate the data accordingly.

If we load an image( Select File > Load Image 1 – or press ctrl + 1 / command + 1 ). And hit run, at the bottom right corner. We have our first running Pixel Bender Filter. It currently does nothing, but load the image.

Now let’s manipulate some colour. Say I want to adjust the red in the photo. Lets add this code.

pixel4 pix = sampleNearest( src, outCoord() );
pix *= pixel4( 2, 1, 1, 1 ); //R, G, B, A
dst = pix;

What we have done is taken each pixel and multiplied the red value by 2. I have stored each pixel in a variable called pix, and I multiplied the red value by 2. I set the output dst to my variable pix and now we have an image that has the red’s more prominent. This is just a static example, now we want to dynamically adjust these values to our own discretion. What we would need to do is create a parameter.


parameter float red
<
maxValue: float( 5 );
minValue: float( 0 );
defaultValue: float( 1 );
>;

parameter float green
<
maxValue: float( 5 );
minValue: float( 0 );
defaultValue: float( 1 );
>;

parameter float blue
<
maxValue: float( 5 );
minValue: float( 0 );
defaultValue: float( 1 );
>;

parameter float alpha
<
maxValue: float( 1 );
minValue: float( 0 );
defaultValue: float( 1 );
>;

These are 4 parameters that we can now adjust. We are proving each parameter with a set of rules – a maxmium value, a minmium value and a default value. We need to make one adjustment to our evaluatePixel() and we should be good to go.


pixel4 pix = sampleNearest( src, outCoord() );
pix *= pixel4( red, green, blue, alpha ); //R, G, B, A
dst = pix;

Now we have variables tied to the red, green, blue, and alpha channels. The cool thing about pixel bender is that it can be exported and loaded into AS3 – Min requirements: Flash player 10. Adobe created 2 special classes that tie in with Pixel Bender – Shader (http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/display/Shader.html) and ShaderFilter (http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/filters/ShaderFilter.html).

Pixel Bender files can be loaded with URLLoaders. Once the pixel bender is loaded, you can cast the data as a Shader Class. Shader’s can access the variables inside of Pixel Bender and adjust the values. Once the values are adjusted you can load the shader through a ShaderFilter filter and apply that on any DisplayObjects to view your result.

Below is a quick example of applying the above pixel bender filter onto a webcam feed and adjust the Red in the webcam feed.

private var video:Video;
var camera:Camera;
video = new Video( 320, 240 );
var i:uint = Camera.names.length;
while ( i-- ) {
if ( Camera.names[i] == "USB Video Class Video" ) {
break;
}
}

if ( i == uint.MAX_VALUE ) {
camera = Camera.getCamera();
} else {
camera = Camera.getCamera( i.toString() );
}

camera.setMode( 320, 240, 30 );
video.attachCamera( camera );

var loader:URLLoader = new URLLoader( new URLRequest( "MyPixelBender.pbj" ) );
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener( Event.COMPLETE, loadShader );

private function loadShader( evt:Event ):void {
var shader:Shader = new Shader( evt.target.data );
shader.data.red.value = [0.5];
var shaderFilter:ShaderFilter = new ShaderFilter( shader );
video.filters = [shaderFilter];
addChild( video );


This post is tagged , , , ,

Leave a Reply

Categories